summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1999-12-11 12:24:21 +0000
committerpeter <peter@FreeBSD.org>1999-12-11 12:24:21 +0000
commitb38569ff99f04a0eff4c8387273fafe38bb58c43 (patch)
tree2ed56a5cb810a4c08d41ea1babfef0e4a2c88b3e /contrib/cvs/src
parent25155fc40f43750917e9621b6e4b57f72e19a29c (diff)
parent784ea5066cbea73d04e8ce5783dd0eb842e3ac1f (diff)
downloadFreeBSD-src-b38569ff99f04a0eff4c8387273fafe38bb58c43.zip
FreeBSD-src-b38569ff99f04a0eff4c8387273fafe38bb58c43.tar.gz
This commit was generated by cvs2svn to compensate for changes in r54427,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'contrib/cvs/src')
-rw-r--r--contrib/cvs/src/ChangeLog1518
-rw-r--r--contrib/cvs/src/Makefile.in6
-rw-r--r--contrib/cvs/src/add.c77
-rw-r--r--contrib/cvs/src/admin.c81
-rw-r--r--contrib/cvs/src/checkout.c2
-rw-r--r--contrib/cvs/src/client.c628
-rw-r--r--contrib/cvs/src/client.h5
-rw-r--r--contrib/cvs/src/create_adm.c6
-rw-r--r--contrib/cvs/src/cvsrc.c7
-rw-r--r--contrib/cvs/src/edit.c42
-rw-r--r--contrib/cvs/src/entries.c41
-rw-r--r--contrib/cvs/src/error.c165
-rw-r--r--contrib/cvs/src/expand_path.c9
-rw-r--r--contrib/cvs/src/fileattr.h20
-rw-r--r--contrib/cvs/src/find_names.c63
-rw-r--r--contrib/cvs/src/hardlink.c2
-rw-r--r--contrib/cvs/src/history.c14
-rw-r--r--contrib/cvs/src/ignore.c19
-rw-r--r--contrib/cvs/src/log.c19
-rw-r--r--contrib/cvs/src/modules.c92
-rw-r--r--contrib/cvs/src/myndbm.c6
-rw-r--r--contrib/cvs/src/no_diff.c9
-rw-r--r--contrib/cvs/src/options.h.in11
-rw-r--r--contrib/cvs/src/parseinfo.c15
-rw-r--r--contrib/cvs/src/patch.c16
-rw-r--r--contrib/cvs/src/release.c73
-rw-r--r--contrib/cvs/src/remove.c8
-rw-r--r--contrib/cvs/src/root.c97
-rw-r--r--contrib/cvs/src/rtag.c15
-rw-r--r--contrib/cvs/src/run.c109
-rwxr-xr-xcontrib/cvs/src/sanity.sh5410
-rw-r--r--contrib/cvs/src/server.h60
-rw-r--r--contrib/cvs/src/status.c73
-rw-r--r--contrib/cvs/src/subr.c100
-rw-r--r--contrib/cvs/src/tag.c38
-rw-r--r--contrib/cvs/src/vers_ts.c20
-rw-r--r--contrib/cvs/src/version.c3
-rw-r--r--contrib/cvs/src/watch.c22
-rw-r--r--contrib/cvs/src/wrapper.c13
-rw-r--r--contrib/cvs/src/zlib.c84
40 files changed, 7878 insertions, 1120 deletions
diff --git a/contrib/cvs/src/ChangeLog b/contrib/cvs/src/ChangeLog
index 8077ce8..0d18891 100644
--- a/contrib/cvs/src/ChangeLog
+++ b/contrib/cvs/src/ChangeLog
@@ -1,3 +1,1517 @@
+1999-07-28 Eric Sink <eric@sourcegear.com>
+
+ * sanity.sh: before running basicc-11, we need to see if
+ the cwd has been deleted (by basicc-8). If so, we
+ recreate it to allow basicc-11 to proceed. This may be
+ something that only happens under the Linux 2.2 kernel.
+
+1999-07-18 Karl Fogel <kfogel@floss.red-bean.com>
+
+ * edit.c (notify_do): chop newline, if any, from the value
+ obtained from CVSROOT/users. Otherwise it just gets passed along
+ in the argument to the notification program (usually mail), which
+ will misinterpret it as signifying the end of the command.
+
+1999-07-19 Larry Jones <larry.jones@sdrc.com>
+
+ * rcs.c (RCS_delete_revs): In the WIN32 kludge, be sure that the result
+ of RCS_getexpand is not NULL before trying to use what it points to.
+ (Patch submitted by Timothy L. Taylor <ttaylor@mitre.org>.)
+
+1999-07-16 Tom Tromey <tromey@cygnus.com>
+
+ * admin.c (admin): Allow `-k' options to be used unrestricted.
+
+1999-06-23 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (symlinks2): New test, for symlinks in working
+ directory without PreservePermissions. This test (modulo a few
+ details not relevant to testing whether we are following symlinks)
+ worked remote as of now, or either remote or local for CVS 1.9.
+ * subr.c (get_file): Revert 1998-02-15 change to special-case
+ symlinks. This makes the above test work local too.
+ * rcs.c (RCS_checkin): Move the logic to handle special-case
+ symlinks (and other files other than regular files) here, and make
+ it only happen if PreservePermissions is on.
+
+1999-06-18 Larry Jones <larry.jones@sdrc.com>
+
+ * sanity.sh (devcom3-9a): Be less specific about the expected
+ error message (BSD/OS 4.0 has a bug that can cause exec* to fail
+ with EACCES instead of ENOENT).
+
+1999-06-08 Larry Jones <larry.jones@sdrc.com>
+
+ * sanity.sh (diff-4, dirs2-10, tagf-13, importc-7, conflicts2-142b8):
+ Use ${PROG} instead of "cvs".
+
+1999-06-05 Jim Kingdon <http://www.cyclic.com>
+
+ * recurse.c (do_recursion, do_dir_proc): Make the SERVER_ACTIVE
+ #ifdef be only around the check for server_active. Modulo a few
+ cosmetic tweaks, same as a patch submitted by Johannes Stezenbach
+ of propack-data.de.
+
+1999-06-01 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh: Add comment about rcs2-7 failures on certain days.
+
+ Make "cvs status -v" on a removed file work:
+ * status.c (cvsstatus): Reindent the client code.
+ (status_fileproc): Don't need a CVS/Entries listing to show the
+ tags.
+ * sanity.sh (rmadd2): New test rmadd2-16 tests the existing
+ behavior with "cvs log"; new test rmadd2-17 tests the new behavior
+ with "cvs status".
+
+ * sanity.sh (basicc): To match no output in dotest, put the empty
+ regexp first. Remove tests which check that first-dir exists,
+ since that isn't true in the case where the OS let us delete it.
+ (dotest_internal): Fix so that things work with two regexps, with
+ an empty one first.
+
+1999-05-28 Larry Jones <larry.jones@sdrc.com>
+
+ * sanity.sh (server-4): Replace bogus directory with real one since
+ the server now checks it.
+
+1999-05-27 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (spacefiles): Clean up -c, top, and -b at end.
+ (spacefiles, files): Fix bad references to CVSROOT_DIRNAME.
+
+ Fix two problems pointed out by Olaf Kirch of swb.de/caldera.de:
+ * server.c (outside_root): New function, contains expanded version
+ of code from serve_directory.
+ (serve_directory): Call outside_root.
+ (outside_dir): New function
+ (serve_modified, serve_is_modified, serve_notify,
+ serve_questionable, serve_unchanged): Call outside_dir.
+ * sanity.sh (server2): New tests, for these fixes.
+
+1999-05-26 Jim Kingdon <http://www.cyclic.com>
+
+ * cvs.h, subr.c (xmalloc): Return void* not char*, like xrealloc
+ has done for some time.
+ * modules.c (do_module): If we find the module as a directory/file
+ (rather than in the modules file), skip a bunch of processing
+ which was unnecessary and also broken in most of the cases
+ now tested for by the spacefiles sanity.sh test.
+ * sanity.sh (spacefiles): New test, for specifying filenames
+ (containing spaces, or starting with '-', or starting with '/') to
+ "cvs co".
+
+1999-05-25 Jim Kingdon <http://www.cyclic.com>
+
+ * client.c (update_entries): Make the old DONT_USE_PATCH code the
+ only code. This means that if people are still on CVS 1.9
+ servers, then CVS will fall back to transferring entire files.
+ This is better than looking for an external "patch" program which
+ causes no end of troubles (especially on Windows, but someone just
+ posted to info-cvs about a problem with the Solaris patch). (This
+ change was run by devel-cvs and feedback was positive).
+
+ * subr.c (xmalloc, xrealloc): The new error.c does not support
+ %lu; use sprintf instead.
+
+1999-05-25 Derek Price
+ <http://www-personal.engin.umich.edu/~oberon/resume.html>
+
+ * sanity.sh (server): Escaped a few more newlines in
+ another awk script. Solaris awk still don't like 'em.
+
+1999-05-25 Derek Price
+ <http://www-personal.engin.umich.edu/~oberon/resume.html>
+ and Jim Kingdon
+
+ * log.c: Remove comment which said "you can delete [this line]"
+ and which stuck around for over 3 years.
+ * sanity.sh (errmsg2 & tagdate): Added tests to prove the
+ current functionality with respect to combining -r and -D.
+
+1999-05-20 Larry Jones <larry.jones@sdrc.com>
+
+ * server.c (pserver_authenticate_connection): Previous changes
+ broke verify_and_exit (reported by Robert Fitzsimons, thanks).
+ * sanity.sh (pserver): New tests pserver-7 and pserver-8 for this.
+
+1999-05-18 Derek Price
+ <http://www-personal.engin.umich.edu/~oberon/resume.html>
+
+ * sanity.sh (keyword2): Escaped a newline in an awk script.
+ Apparently Solaris awk don't like 'em.
+
+1999-05-18 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (basicc): Allow the behavior whereby unlink(".")
+ succeeds. Reported by Jeremy Buhler and Pavel Roskin.
+
+1999-05-17 Steve Cameron of Compaq
+
+ * sanity.sh: Modified to no longer use "test -e" for existence
+ test as it has turned out to be not portable enough. Instead use
+ "test -f", "test -d", etc.
+ [SCO Unixware 7 apparently doesn't always support it -kingdon]
+
+1999-05-17 Jim Kingdon <http://www.cyclic.com>
+
+ * version.c: Push version number to 1.10.6.1.
+
+ * version.c: Version 1.10.6.
+
+1999-05-16 Jim Kingdon <http://www.cyclic.com>
+
+ * update.c (patch_file): When we are passing vn_rcs to
+ RCS_checkout, pass vn_tag as well.
+ * sanity.sh (keyword): In test keyword-22, test for the fixed
+ behavior rather than the buggy behavior. Adjust keyword-23. Add
+ test keyword-24, to see whether keyword-23 really worked.
+
+1999-05-12 Larry Jones <larry.jones@sdrc.com>
+
+ * sanity.sh (pserver-4, pserver-5): Bogus error messages from
+ non-root initgroups on some 4.4BSD derived systems now show up
+ in different places in the output.
+
+1999-05-12 Jim Kingdon <http://www.cyclic.com>
+
+ * import.c (import): Don't allow the user to supply a repository
+ directory which takes us out of the cvsroot.
+ * sanity.sh (importc): New tests importc-10 to importc-12, for this.
+
+1999-05-11 Larry Jones <larry.jones@sdrc.com>
+
+ * server.c (serve_notify): Allocate enough memory to hold the
+ "misformed Notify request" message in pending_error_text.
+
+1999-05-11 Jim Kingdon <http://www.cyclic.com>
+
+ * server.c (switch_to_user): Ignore EPERM from initgroups. Fixes
+ pserver-4 in testsuite.
+ (pserver_authenticate_connection): Only print "I LOVE YOU" after
+ switch_to_user has come back successfully.
+
+ * server.c (pserver_authenticate_connection): Call error_exit
+ rather than reinventing the wheel ourselves.
+ (switch_to_user): Check for errors from setuid, setgid, and
+ initgroups. Fix the #ifdef's (the previous code would skip the
+ setuid call if SETXID_SUPPORT).
+
+1999-05-10 Jim Kingdon <http://www.cyclic.com>
+
+ * server.c (serve_notify), edit.c (notify_do): Check for
+ and reject characters which will get confused with delimiters.
+ * sanity.sh (server): New tests server-7 through server-15 test
+ for this and for other notify behaviors.
+
+ * rcs.c (RCS_tag2rev): Also look for a physical branch with
+ RCS_getversion.
+ * sanity.sh (tagf): Adjust tagf-12 and following tests to test for
+ the fixed behavior rather than the broken behavior.
+
+1999-05-07 Jim Kingdon <http://www.cyclic.com>
+
+ * server.c (server_notify): Also set last_node to NULL.
+ * sanity.sh (server): New tests server-6 and server-7, for this.
+
+1999-05-05 Jim Kingdon <http://www.cyclic.com>
+
+ * rcs.c (rcs_internal_lockfile): Remove unused variable lockfile.
+
+ * add.c (add): Look for directories with the same name in a
+ different case where appropriate (analogous to fopen_case).
+ In client code, add comment about how this doesn't do quite
+ everything.
+
+1999-05-03 Jim Meyering <meyering@ascend.com>
+
+ Remove rcs-style ,file, lock files upon signal.
+ * rcs.c (rcs_lockfile): New file-scoped global.
+ (rcs_cleanup): New function (similar to patch_cleanup).
+ (rcs_internal_lockfile): Register rcs_cleanup the first time this
+ function is called. Rename uses of local `lockfile' to refer to new
+ global, `rcs_lockfile'. Don't free the lock file name string, now
+ that it's global.
+ (rcs_internal_unlockfile): Rename `lockfile', as above, and carefully
+ free and NULL-out the global, rcs_lockfile.
+
+1999-04-30 Jim Kingdon <http://www.cyclic.com>
+
+ * rcs.c (annotate_fileproc): Don't cast NULL in passing it to
+ RCS_deltas. Because there is a prototype in scope the cast is
+ unnecessary (per HACKING's ANSI C or SunOS4 rule), and in fact it
+ was causing failures on UNICOS because it cast to size_t instead
+ of size_t*. (Thanks to Dean Kopesky for reporting this).
+
+1999-04-29 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh: If invoked without any arguments, print a usage
+ message (thanks to Pavel Roskin for a report/patch).
+
+ * run.c (piped_child): Make the error messages more verbose.
+ (close_on_exec): Reindent.
+ * sanity.sh (devcom3): Several errors are possible in devcom3-9a.
+ Adjust for change to piped_child error message.
+
+1999-04-28 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (devcom3): Add some tests of the CVS/Notify file and
+ disconnected "cvs edit".
+
+ * main.c (opt_usage): Remove -b.
+
+1999-04-20 Derek Price
+ <http://www-personal.engin.umich.edu/~oberon/resume.html>
+
+ * rcs.c (RCS_delete_revs): RCS_delete_revs uses an
+ RCS_checkout call to get a new copy of a revision to be
+ used internally after old revisions were deleted and it was
+ performing keyword substitutions. This munged all the
+ the revisions of the file on the branch containing the
+ deleted revisions and its sub-branches, as the original they
+ were being patched from was incorrect. Corrected this by
+ passing in "-ko" as an option to RCS_checkout.
+ * sanity.sh (keywordlog): modified this test to verify the
+ correct behavior of 'cvs admin -o'.
+ [Fixed use of \$ in keywordlog test; added code in RCS_delete_revs
+ to abort on binary file on Windows -kingdon]
+
+1999-04-21 Derek Price
+ <http://www-personal.engin.umich.edu/~oberon/resume.html>
+ and Jim Kingdon
+
+ * tag.c (tag_check_valid): A bug was causing CVS to spin
+ indefinately when -j:<date> was specified. CVS now returns
+ an error.
+ * sanity.sh: Added a test (tagdate-12) to test this.
+
+1999-04-19 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (backuprecover): Clean up the repository at the end.
+
+1999-04-18 Derek Price
+ <http://www-personal.engin.umich.edu/~oberon/resume.html>
+
+ * sanity.sh added a test (backuprecover) to test cvs behavior
+ with a repository that is out of date relative to the
+ developer's workspaces.
+ [Fix --keep code; move test to "Repository Storage" section since
+ it doesn't really exercise the diff/diff3 library. -kingdon]
+
+1999-04-13 Derek Price
+ <http://www-personal.engin.umich.edu/~oberon/resume.html>
+
+ * sanity.sh (diff): Tests to verify correct operation of
+ the --ifdef parameter to cvs diff.
+ [indentation fixed -kingdon].
+
+1999-04-13 Derek Price
+ <http://www-personal.engin.umich.edu/~oberon/resume.html>
+ for Noah Friedman <friedman@splode.com>
+
+ * diff.c (diff): Put "--ifdef=" in opts string, not "-D"; the
+ latter is confused by pserver for a date spec.
+
+1999-04-14 Jim Kingdon <http://www.cyclic.com>
+
+ * fileattr.h: Adjust comments to reflect the official version of
+ the fileattr format now being in cvs.texinfo.
+
+1999-04-05 Jim Kingdon
+
+ * sanity.sh (watch5): Remove nonstandard --keep code. Don't pass
+ -f to rm when cleaning up (that tends to mask bugs). Add watch5
+ to list of tests at start. Add comment explaining why we consider
+ the behavior we test for the right one. Rename a few tests which
+ had been erroneously named watch6* instead of watch5*.
+ * client.c (update_entries): Add comment with brief discussion of
+ whether there is a better way.
+
+1999-04-05 Derek Price
+ <http://www-personal.engin.umich.edu/~oberon/resume.html>
+
+ * client.c (update_entries): Only call mark_up_to_date
+ (which deletes the CVS/Base/<filename> file for watched
+ and edited files) on commit.
+ * sanity.sh: Make sure the CVS/Base/<filename> file for
+ a watched and edited file is not removed on a status or
+ update of a touched/unmodfied file.
+
+1999-03-30 Larry Jones <larry.jones@sdrc.com>
+
+ * client.c (get_responses_and_close), commit.c (commit),
+ update.c (do_update): If the sleep(1) call returns prematurely
+ (due to the way wakeup is scheduled or receiving a signal), do
+ it again.
+
+1999-03-26 Jim Kingdon <http://www.cyclic.com>
+
+ * server.c (server): Add comment about Gzip-stream vs. RQ_ROOTLESS.
+
+ * sanity.sh (modules3-11b): Adjust exact text of error message to
+ reflect 1999-03-24 change to dirswitch.
+
+1999-03-25 Jim Kingdon <http://www.cyclic.com>
+
+ * admin.c (admin): Make argument to -e optional, to match the
+ documentation.
+ * sanity.sh (admin-19a-2): Test for this.
+
+ * server.c (serve_root): Update comment about checking for missing
+ Root request.
+
+1999-03-24 Jim Kingdon <http://www.cyclic.com>
+
+ * server.c (dirswitch): Also check dir here, similar to
+ what server_pathname_check does for other cases.
+ * sanity.sh (files): Adjust files-14 to test for this.
+
+1999-03-24 Derek Price
+ <http://www-personal.engin.umich.edu/~oberon/resume.html>
+ and Jim Kingdon
+
+ * sanity.sh: added a test (files-13) to test .. indirection
+ in a path and another (files-14) to make sure we still fail
+ out when the '..' indirection takes us into the $CVSROOT
+ directory or beyond.
+
+1999-03-24 Larry Jones <larry.jones@sdrc.com>
+
+ * rcs.c: Change enum constants ADD and DELETE to something less
+ likely to run into conflicts.
+
+1999-03-21 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (tagf): New test, tests for moving a branch tag to a
+ non-branch tag and trying to recover.
+
+1999-03-12 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (branches): Tweak test branches-5 to test the case in
+ which one modifies a file and then branches it.
+
+1999-03-09 John Bley of duke.edu
+
+ * mkmodules.c (filelist): Missed a NULL in this struct (should
+ have 3 members, only had 2).
+
+1999-03-07 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (Index): Rename new test from rm_CVS/Root to rmroot
+ (we don't have a formal rule about funky punctuation in test names
+ but both underscore and a slash is too funky for me :-)).
+ Reindent a few tests which were off.
+
+ * root.c: Remove the sentence which had the improper English;
+ there isn't really a need for that sentence and it isn't
+ particularly accurate any more.
+
+1999-02-27 Derek Price
+ <http://www-personal.engin.umich.edu/~oberon/resume.html>
+
+ * sanity.sh: Added rm_CVS/Root test to test that CVS uses
+ $CVSROOT rather than dumping core when running remotely and
+ the admin file CVS/Root is deleted from the workspace.
+
+ Also, altered a few 'cvs commit' 's in regular expressions to
+ fit the .${PROG} commit. portability syntax.
+
+ * recurse.c: Stopped CVS from dumping core in the case tested
+ above.
+
+ * root.c: Fixed somebody's improper english.
+
+1999-02-25 Larry Jones <larry.jones@sdrc.com>
+
+ * sanity.sh (keyword2-12): Use ${QUESTION} instead of ? in the
+ expected result.
+
+1999-02-24 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (keyword2): Restore the original \\\$ instead of $.
+ The latter ends up working due to various kludgy semantics in the
+ shell and regular expressions, but the former is cleaner.
+
+ * sanity.sh (keyword2): Protect keywords against accidental
+ expansion in sanity.sh itself (most occurrences had this, but not
+ all).
+
+1999-02-23 Derek Price <http://www.cyclic.com>
+ and Jim Kingdon.
+
+ * sanity.sh (keyword2): New test, tests for merging with -kk.
+
+1999-02-22 Jim Kingdon <http://www.cyclic.com>
+
+ * version.c: Ease version number to 1.10.5.1.
+
+ * version.c: Version 1.10.5.
+
+1999-02-18 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (files): New test, for a relatively obscure spurious
+ "Up-to-date check failed" in client/server.
+
+ * main.c (lookup_command_attribute): Don't check for "history"
+ twice.
+
+1999-02-17 Jim Kingdon <http://www.cyclic.com>
+ and Hallvard B Furuseth
+
+ * root.c (parse_cvsroot): Rearrange ifdefs to squelch possible
+ warnings about statement not reached.
+
+1999-02-16 Jim Kingdon <http://www.cyclic.com>
+
+ * recurse.c (start_recursion): If we are skipping the current
+ directory (due to it being from the wrong repository), also adjust
+ the arguments we send to the server accordingly (like we already
+ do for the case in which there is no CVS directory).
+ * sanity.sh (multiroot4): New test, for this. All these tests had
+ passed locally, but remote multiroot4-12 tests for this fix.
+ (multiroot): Adjust multiroot-diff-1, multiroot-update-2,
+ multiroot-tag-1, multiroot-status-1, multiroot-update-3, and
+ multiroot-log-1 to reflect the cosmetic change this produces (one
+ less "Diffing ." message).
+ (multiroot2): multiroot2-8 likewise.
+
+1999-02-10 Jim Kingdon <http://www.cyclic.com>
+
+ * tag.c (cvstag): Don't pass SEND_NO_CONTENTS if -c specified.
+ * sanity.sh (tagc): New test, for various tag -c behaviors.
+ Test tagc-6 tests for this fix.
+
+1999-02-09 Jim Kingdon <http://www.cyclic.com>
+
+ * error.c (error): Rewrite to no longer use vasprintf (see
+ ../lib/ChangeLog for rationale). Note the slight change in
+ interface - callers which want %8.8s or similar formats need to
+ call sprintf.
+ * lock.c (lock_wait, lock_obtained): Use sprintf.
+
+1999-02-08 Jim Kingdon <http://www.cyclic.com>
+
+ * rcs.c (RCS_delete_revs): Pass -a to diff_exec.
+ * sanity.sh (binfiles3): New tests binfiles3-9 through
+ binfiles3-13 test for this fix.
+ * sanity.sh (binfiles): New tests binfiles-o4 and binfiles-o5
+ (which don't test this bug, just on general principles).
+
+1999-02-04 Jim Kingdon <http://www.cyclic.com>
+
+ * lock.c (lock_name): Permissions of directories in LockDir
+ shouldn't depend on the umask.
+ * sanity.sh (lockfiles): Set umask and CVSUMASK, to test for this.
+
+1999-02-01 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (keywordlog): New tests keywordlog-22 and
+ keywordlog-23 test keyword expansion and $Log. Adjust other tests
+ so that revisions differ more from each other, so this is a
+ better test.
+
+1999-01-29 Jim Kingdon <http://www.cyclic.com>
+
+ * commit.c (checkaddfile): If options is "", treat it the same as
+ NULL. Centralize this check, and the one for it starting with
+ "-k", at the start of the function.
+
+ * rcs.c, rcs.h (RCS_setexpand): New function.
+ * admin.c (admin_fileproc): Access keyword expansion field via
+ RCS_getexpand and RCS_setexpand, rather than directly.
+ * commit.c (checkaddfile): When resurrecting, set the keyword
+ expansion mode.
+ * sanity.sh (binfiles3): Adjust tests binfiles3-7 and binfiles3-8
+ for the new behavior.
+
+1999-01-27 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (multiroot3): Add new variant of multiroot3-10 test
+ for RELATIVE_REPOS. Move multiroot3-11 test out of the
+ conditionals; it works the same for remote or local,
+ RELATIVE_REPOS or no.
+
+ * options.h.in: Make RELATIVE_REPOS the default, as has been
+ announced as a future direction since 1997-10-11.
+ * sanity.sh (multiroot): Tweak multiroot-update-1a and
+ multiroot-update-1b tests to work with either RELATIVE_REPOS or
+ non-RELATIVE_REPOS.
+
+ * sanity.sh (client-9): Don't assume the time zone.
+
+1999-01-26 Jim Kingdon <http://www.cyclic.com>
+
+ Fix one facet of the "cvs add -kb" re-adding problem (the other
+ known facet is tested for by binfiles3-8).
+ * add.c (add): When re-adding a file, set the keyword expansion
+ as we normally would.
+ * sanity.sh (binfiles3): New test binfiles3-6a tests for this.
+
+1999-01-22 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (rmadd2): New tests, for undoing a commit.
+
+1999-01-21 Eric Mumpower <nocturne@cygnus.com>
+
+ * sanity.sh (reposmv): Actually modify CVSROOT in current
+ environment when calling functions, rather than trying to achieve
+ the same effect with "CVSROOT=foo functionname". (Many common
+ bourne shells, including those in SunOS and Solaris 2.4-2.7,
+ do not properly handle "ENVVAR=foo command" when "command" is
+ a user-defined shell function rather than an actual executable.)
+
+1999-01-15 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (rcs3): Redirect awk's stdin to /dev/null like all the
+ other awk invocations. GNU awk seems not to read stdin in this
+ case, but that behavior is hard to reconcile with the Single Unix
+ Spec and some awks don't do it.
+
+ * sanity.sh (binfiles, binfiles2, binfiles3, server): Use the same
+ tr trick as in rcs3. People don't seem to have been complaining,
+ and this should fix server-4 for HPUX.
+
+1999-01-14 Jim Kingdon <http://www.cyclic.com>
+
+ * client.c (recv_line): If the line we are reading contains a
+ character which would sign-extend to EOF, don't treat it as end of
+ file. recv() doesn't report end of file this way and this might
+ fix bugs with 0xff characters.
+
+1999-01-14 Larry Jones <larry.jones@sdrc.com>
+
+ * client.c (recv_line): Handle EOF from server.
+
+ * sanity.sh (importc-8, importc-9): Accept anything in the seconds
+ fields of the timestamps since touch doesn't set it reliably.
+ (This isn't great, but it's better than nothing.)
+
+1999-01-14 Jim Kingdon <http://www.cyclic.com>
+
+ * run.c (run_exec): Adjust comment about vfork; this isn't the place
+ to get into a treatise about fork performance vs. vfork
+ performance but it isn't quite as simple as whether one has
+ copy-on-write.
+
+1999-01-13 Larry Jones <larry.jones@sdrc.com>
+
+ * sanity.sh (dotest_fail): Handle spurrious output from assert better.
+
+ * sanity.sh (rcs3-4, rcs3-5a): Handle even more variants of the
+ assertion failure message.
+
+1999-01-12 Larry Jones <larry.jones@sdrc.com>
+
+ * sanity.sh (mtfr-3): ls behavior varies wildly on nonexistant files,
+ just use echo instead.
+
+1999-01-11 Jim Meyering <meyering@ascend.com>
+
+ * sanity.sh (mkmodules-temp-file-removal): New test, for this.
+ * mkmodules.c (mkmodules): Remove each `CVSROOT/.#[0-9]*' temporary
+ file that's used to check out files listed in CVSROOT/checkoutlist.
+ Remove extra semicolon at end of line.
+
+1999-01-11 Larry Jones <larry.jones@sdrc.com>
+
+ * sanity.sh (rcs3-5a): Allow for multiple lines of output before the
+ assertion failure message.
+
+ * sanity.sh (lockfiles-6, client-8): Work around bug in HP-UX chmod
+ (doesn't allow anything to follow omitted permissions).
+
+1999-01-09 Jim Kingdon <http://www.cyclic.com>
+
+ * client.c (set_sticky): Nonfatal error if we can't write it.
+ * sanity.sh (dirs2-8 through dirs2-14): New tests, for this.
+
+ * sanity.sh (rcs3): Write NUL character with tr not awk, in
+ accordance with Single Unix Specification. Hopefully will fix
+ rcs3-7 for HPUX. Will not work on SunOS4, but then again neither
+ did the old syntax.
+
+1999-01-05 Jim Kingdon <http://www.cyclic.com>
+
+ * client.c, update.c: Rename MD5* functions to cvs_MD5* per
+ corresponding change to ../lib/md5.h.
+
+1999-01-03 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (client): Give file1 a predictable mode so that the
+ output in client-9 will not depend on the umask of the user
+ running the tests.
+
+1998-12-29 Jim Kingdon <http://www.cyclic.com>
+
+ * client.c (client_senddate): Use date_to_internet rather than
+ using our own "5/26/1997 13:01:40 GMT" date format.
+ * main.c (date_to_internet): Check for errors from sscanf. Always
+ send a four digit year. Send hours, minutes, and seconds as two
+ digits per RFC822.
+ * sanity.sh (client): New tests client-8 and client-9 test for this.
+
+ * sanity.sh (rcs2): New tests rcs2-6 through rcs2-8 test for fix
+ to lib/getdate.y (before the fix, "100 months" or "8 years" would
+ tend to mean the year 1969, thus the tests would give "cvs update:
+ file1 is no longer in the repository").
+
+1998-12-28 Larry Jones <larry.jones@sdrc.com>
+
+ * entries.c (Register): Return if unable to open log file to avoid
+ referencing the invalid file pointer.
+ * sanity.sh (dirs2-7): With above change, no longer fails.
+ * sanity.sh (rcs3-5a): Another assertion failure message.
+ * sanity.sh (pserver-4, pserver-5): Some 4.4BSD derived systems spit
+ out bogus error messages when initgroups is called as non-root.
+
+1998-12-23 Larry Jones <larry.jones@sdrc.com>
+
+ * sanity.sh (rcs3, dotest_fail): The assertion failure message varies
+ wildly between different systems and the resulting abort call can
+ even result in spurrious output. Fix the regexp to accept nearly
+ anything containing some kind of assertion failure and ensure that
+ any spurrious output ends up in the output file instead of on the
+ terminal.
+
+1998-12-23 Jim Kingdon <http://www.cyclic.com>
+
+ * admin.c, checkout.c, commit.c, cvsrc.c, expand_path.c,
+ history.c, ignore.c, import.c, log.c, mkmodules.c, modules.c,
+ myndbm.c, parseinfo.c, rcs.c, remove.c, rtag.c, status.c, subr.c,
+ tag.c, wrapper.c: Cast all char's to unsigned char before passing
+ them to ctype.h functions (isalpha, isgraph, isalnum, isspace,
+ isdigit, isprint, isupper). Whether using ctype.h is the right
+ thing at all is unclear to me (having the server depend on locale
+ seems wrong, as we don't necessarily have any good way to set the
+ right locale, if there even is such a concept as 'right' locale in
+ this context), but as long as we use ctype.h we might as use it
+ according to the standards (this affects systems where plain char
+ is signed but users supply characters with the 8th bit set).
+ Thanks to Paul Eggert for suggesting this.
+
+1998-12-22 Jim Kingdon <http://www.cyclic.com>
+
+ * sanity.sh (rcs3): Oops, the earlier fix for srcdir only fixed
+ the non-remote case, not the remote case. Fix the other occurrence.
+
+1998-12-22 Jim Kingdon
+
+ * sanity.sh (rcs3): The assertion failure message varies slightly
+ depending on whether CVS was built with srcdir != ".". Fix regexp.
+
+1998-12-21 Jim Kingdon
+
+ * rcs.c (RCS_getdate): Reindent Jim Meyering's change; remove
+ unused variable x_vers.
+
+ * rcs.c: When printing an unexpected character we found in the RCS
+ file, print it in hex rather than as a character (see comment for
+ rationale).
+ * sanity.sh (rcs3): Adjust rcs3-2 and rcs3-7 tests accordingly.
+
+ * sanity.sh (rcs3): New test, for some error handling cases
+ involving parsing RCS files.
+
+1998-12-16 Jim Meyering <meyering@ascend.com>
+
+ * rcs.c (RCS_getdate): Handle the case in which a file is first
+ imported after its initial version has been created.
+ * sanity.sh (import-after-initial): New test for that.
+
+1998-12-17 Jim Kingdon
+
+ * server.c (serve_root): Pserver_Repos only exists if
+ AUTH_SERVER_SUPPORT is defined.
+
+1998-12-12 Jim Kingdon, and Derek R. Price of Stortek.
+
+ * sanity.sh (multiroot): Change + to ${PLUS}.
+
+1998-12-12 Jim Kingdon, and Gary Young of Motorola
+
+ * sanity.sh (admin): In tests admin-13, admin-25, and admin-29,
+ allow 4 digit year in addition to 2 digit year.
+
+1998-12-12 Jim Kingdon
+
+ * sanity.sh (log): New tests log-14a and log-14b test for -rHEAD
+ and for HEAD as (nonexistent) file name.
+
+1998-12-02 Jim Kingdon
+
+ * version.c: Squish version number to 1.10.4.1.
+
+ * version.c: Version 1.10.4.
+
+1998-11-24 Jim Kingdon
+
+ * recurse.c (do_file_proc): Check for errors from RCS_parse.
+ * sanity.sh (rcslib-symlink-7 through rcslib-symlink-10): New
+ tests, test for this.
+
+ * sanity.sh (reposmv-2): Adjust for 22-Nov change to Find_Names.
+
+ * entries.c (Register): If we can't write Entries.Log, make it a
+ nonfatal error.
+ * sanity.sh (dirs2): Test for this fix.
+
+ * sanity.sh (dirs2): Clean up working directory at end of test.
+
+1998-11-23 Jim Kingdon
+
+ * sanity.sh (dirs2): New test, for some more cases involving
+ deleting directories and such.
+
+ * sanity.sh (dirs): Update for yesterday's change in Find_Names
+ error handling. The error in dirs-4 is fairly different now; in
+ dirs-3 and dirs-3a it is the obvious change.
+
+1998-11-22 Jim Kingdon
+
+ * sanity.sh (release): Move the commments listing "cvs release"
+ tests from modules2-6 to here.
+ * release.c (release): Update comment to reflect "? foo" case.
+
+ * find_names.c (Find_Names): If we can't read the repository, make
+ it a nonfatal error. Tell the caller whether this happened.
+ (find_rcs): Add comment regarding this behavior.
+ * recurse.c (do_recursion): If Find_Names gives an error, skip
+ the directory and print a message saying so.
+ * sanity.sh (modes3): New test, for this.
+
+1998-11-18 Jim Kingdon
+
+ * rtag.c (rtag_usage), tag.c (tag_usage): Use "-r rev"
+ consistently.
+
+ * sanity.sh (conflicts3): Tests conflicts3-24 through
+ conflicts3-28 test for another case similar to conflicts3-22.
+
+1998-11-14 Jim Kingdon
+
+ * sanity.sh (diff): New test, for now just tests for the "I know
+ nothing" message.
+
+ * sanity.sh (conflicts2-142b7 through conflicts2-142b11): New
+ tests; resurrecting doesn't work from one level up.
+
+ * sanity.sh (mwrap-7): Remote prints the messages in a different
+ order.
+
+1998-11-13 Jim Kingdon
+
+ * tag.c (check_fileproc): Log tag deletions.
+ * rtag.c (check_fileproc): Likewise.
+ * sanity.sh (taginfo-14 through taginfo-18): New tests, for
+ these behaviors.
+
+1998-11-12 Jim Kingdon
+
+ * sanity.sh (mwrap-7): Update for the noexec fix.
+
+ * server.c (server_copy_file): Add comment about noexec.
+
+ * update.c (checkout_file): Handle noexec case involving revbuf
+ and modes.
+ (update_fileproc): In case T_NEEDS_MERGE, let merge_file take care
+ of noexec, so it can tell the user if there would be conflicts.
+ (merge_file): Print "conflicts found in FILE" message
+ regardless of noexec. Add comment about checking for whether the
+ file already contained the changes, and noexec.
+ * sanity.sh (conflicts-192a): New test, for this.
+
+1998-10-20 Jim Kingdon
+
+ Use the gzip library on the server. Probably doesn't speed things
+ up as currently implemented, but does avoid hassles in terms of
+ finding an external gzip program.
+ * zlib.c, server.h (gunzip_and_write, read_and_gzip): Now returns
+ whether a fatal error occurred, rather than expecting error (1,
+ ...) to work.
+ * client.c (update_entries, send_modified): Change callers.
+ * server.c (receive_file): Rewrite gzip code to use
+ gunzip_and_write rather than filter_through_gunzip.
+ (server_updated): Likewise, use read_and_gzip rather than
+ filter_through_gzip.
+ * client.c, client.h (filter_through_gzip, filter_through_gunzip),
+ run.c, cvs.h (filter_stream_through_program): Removed; no longer used.
+ * sanity.sh (server): New tests server-4 and server-5 test
+ this feature (note that CVS 1.10 also passes these tests; the
+ behavior is supposed to be unchanged).
+
+1998-10-19 Jim Kingdon
+
+ * sanity.sh (multiroot3): New test, tests for a few more
+ multiroot cases.
+
+ * lock.c (lock_name): Set the permissions on each directory we
+ create to that of the parent directory.
+ * sanity.sh (lockfiles): New chmod and tests lockfiles-7a and
+ lockfiles-7b test for this. Adjust lockfiles-5 for new text of
+ error message.
+
+1998-10-15 Jim Kingdon
+
+ * server.c (requests): Set RQ_ROOTLESS for "Set".
+ * sanity.sh (info): Also clean up $HOME/.cvsrc.
+ (server): Test that we can send Set before Root (had been tested
+ by crerepos-6b, but only if you ran the info test first). Tests
+ for this fix.
+
+1998-10-14 Jim Kingdon
+
+ * subr.c (expand_string): Tweak the algorithm so that the size
+ that it allocates is generally a power of two.
+
+1998-10-14 Eivind Eklund and Jim Kingdon
+
+ * commit.c (commit): For the client, don't worry about whether we
+ are root.
+
+1998-10-13 Jim Kingdon
+
+ * server.h (struct request): Change status field to flags and add
+ RQ_ROOTLESS.
+ * client.c (handle_valid_requests, supported_request): Change
+ status to flags.
+ * server.c (requests): Change status to flags. Add RQ_ROOTLESS.
+ * server.c (server): If not RQ_ROOTLESS, and we haven't gotten a
+ Root request, give an error.
+
+1998-10-12 Jim Kingdon
+
+ * version.c: Slide version number to 1.10.3.1.
+
+ * Version 1.10.3.
+
+ * sanity.sh (modules2-17): Update for 9 Oct 1998 change to
+ update_dirent_proc.
+
+1998-10-11 Jim Kingdon
+
+ * commit.c (checkaddfile, commit_fileproc): A numeric value for
+ 'tag' does not mean that we are adding on a branch.
+ * sanity.sh (keywordlog): Adjust this test, to test for this
+ (replaces comment saying we should be doing it).
+ (rmadd): Likewise.
+
+ * sanity.sh (rmadd): New test, tests for various existing
+ behaviors with "cvs ci -r".
+
+1998-10-09 Jim Kingdon
+
+ * update.c (update_dirent_proc): For local CVS, if the directory
+ does not exist in the working directory nor in the repository,
+ just skip it.
+ * sanity.sh (dirs): New tests dirs-3a, dirs-7 and dirs-8 test for
+ this and related behaviors. Note that the new behavior was also
+ the previous behavior for remote; we are only changing it for local.
+
+ * wrapper.c, cvsrc.c, ignore.c: Add comments about ignoring .cvsrc
+ and friends if we can't find a home directory.
+ * expand_path.c (expand_path): If we can't find the home
+ directory, give an error rather than a coredump (or worse).
+ * login.c (construct_cvspass_filename): Don't use errno in error
+ message; get_homedir doesn't set it. Add comment about this
+ message.
+
+1998-10-07 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * diff.c (diff): Set variables to NULL at the start, and free
+ memory at the end.
+ * sanity.sh (multiroot2): Add tests for this (before the fix,
+ multiroot2-12 would abort with "no more than two revisions/dates
+ can be specified").
+
+1998-10-06 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * Makefile.in (installcheck check): Remove references to RCSBIN;
+ they don't do anything now that RCSBIN is ignored.
+
+ * client.c: Clean up horrible confusion about whether stored_mode
+ or stored_mode_valid (or nothing :-)) indicates whether
+ stored_mode is allocated. Should fix crashes (for example, on NT
+ when the server has renamed multiple files from uppercase to
+ lowercase).
+
+ * sanity.sh (dirs): New tests, tests for some cases involving
+ admins who do surgery on the repository.
+
+1998-10-03 Johannes Stezenbach <johannes.stezenbach@propack-data.de>
+
+ * vers_ts.c (Version_TS): If UTIME_EXPECTS_WRITABLE, if
+ necessary change the file to be writable temporarily to set its
+ modification time.
+
+1998-10-03 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * client.c (handle_error): Add comment about indicating which
+ errors are from the server.
+
+1998-10-01 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * sanity.sh (devcom-180): Allow one digit day.
+
+1998-09-30 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * main.c (main): Don't call Name_Root if -d specified.
+ * recurse.c (do_recursion, do_dir_proc): Don't check CVS/Root
+ if -d was specified.
+ * import.c (import): Indentation fix.
+ * sanity.sh (multiroot): Update for this change.
+ (reposmv): New test, tests for this.
+
+1998-09-28 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * sanity.sh (multiroot2): New test, tests some nested directory
+ cases.
+
+1998-09-25 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * sanity.sh (multiroot): Change a few comments which said modules
+ when they meant directories.
+
+1998-09-25 Jim Meyering <meyering@ascend.com>
+
+ * sanity.sh (devcom-180): Add 0-9 to the range of characters allowed
+ in hostname regexp.
+
+1998-09-25 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * sanity.sh (log2): New test log2-7a tests for one error handling
+ case. Add a comment about another.
+
+1998-09-24 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * sanity.sh: Change crerepos test back to :ext: (for several
+ reasons; see comments).
+
+1998-09-24 Noel Cragg <noel@swish.red-bean.com>
+
+ * sanity.sh (rcslib-symlink-5, rcslib-symlink-6): new tests to
+ check the operation of "tag" when there are symlinks in the
+ repository.
+
+ * rcs.c (RCS_checkin): remove old code that resolved the symlink
+ and call resolve_symlink instead.
+ (RCS_rewrite): call resolve_symlink before doing anything else to
+ make sure we're operating on the file and not the symlink.
+
+ * subr.c (resolve_symlink): new routine -- resolves a symbolic
+ link chain to its destination.
+ * cvs.h: add prototype.
+
+ * sanity.sh (basica-6.2, basica-6.3): changed match expressions to
+ reflect new diff output.
+
+ * rcs.c (make_file_label): generate labels for files that include
+ the pathname so that output from "cvs diff" is useable by patch.
+ Looks like I came up with the mods as Andy Piper
+ <andyp@parallax.co.uk>; his patch was on the Cyclic unofficial
+ patches page.
+
+ * sanity.sh: change remote access method from ext to fork. This
+ results in a significant speed improvement when running the
+ testsuite. The ext method on my machine (i586 120MHz Linux 2.0.35
+ with TCP wrappers installed) runs in 450% of the time of the local
+ method while the fork method runs in only 150% of the time of the
+ local method! Yow! Am I SWAPPING yet?!
+ (crerepos-6a, crerepos-6b): change to reflect different error
+ messages for fork method.
+ (modes-15): same.
+
+ * client.c (connect_to_forked_server): new routine.
+ (start_server): call the above when method is fork_method.
+
+ * root.c: add a new method named "fork". This method uses the
+ remote protocol, but does so by forking a "cvs server" process
+ directly rather than doing "rsh host cvs server" (for example).
+ This new method has few advantages for day-to-day use, but has
+ three important benefits for debugging:
+
+ 1) Most secure installations these days don't allow rsh access.
+ With this new method, we can still test the remote protocol on
+ these machines because we don't need to be able to make a local
+ TCP connection.
+
+ 2) Even if installations allow rsh access, they almost always
+ have TCP wrappers to check permissions by IP/hostname. This
+ causes a short delay for every connection. For invocations from
+ the command line, this doesn't matter much, but it adds up to a
+ significant amount of time when running the testsuite.
+
+ 3) On machines that can't (or do not usually) provide rshd
+ access (I'm thinking of WNT/W95 in particular), we can now run
+ tests of the remote protocol using this method. Indeed, we can
+ run remote protocol tests on any machine that has an
+ implementation of piped_child().
+
+ (parse_cvsroot): handle new method.
+ (error_exit, xstrdup, isabsolute): new stub functions to use when
+ compiling root.c with the DEBUG option.
+ (main): fix a few typos.
+ * cvs.h (CVSmethod): add fork_method.
+
+ * server.c (create_adm_p): use Emptydir as the placeholder
+ directory instead of "." to avoid problems with "cvs update -d" et
+ al.
+
+1998-09-22 Noel Cragg <noel@swish.red-bean.com>
+
+ * sanity.sh (devcom-180): fixed typo in regexp.
+
+ * main.c (main): remove need_to_create_root and related code
+ (including CVS_IGNORE_REMOTE_ROOT environment variable). The
+ current implementation (just removed) of rewriting the contents of
+ the CVS/Root file isn't desirable for a number of reasons:
+
+ 1) Only the top-level CVS/Root directory is updated. If we're
+ really interested in pointing our WD at another CVSROOT, we
+ should have a separate command.
+
+ 2) With the new multiroot mods, we don't ever want to rewrite
+ CVS/Root files in the way the removed code did. Consider:
+
+ cvs -d repository1 co a
+ cd a
+ cvs -d repository2 co b
+ cvs -d repository2 update b
+
+ The update command would rewrite the contents of a/CVS/Root to
+ the incorrect value. Bad. We then wouldn't be talking to the
+ correct repository for files in a.
+
+ 3) The removed code seems to be a quick hack to support working
+ directories checked out from multiple repositories. With the
+ CVS_IGNORE_REMOTE_ROOT variable set, one could perform commands
+ as in example 2, above, without worring about updating CVS/Root
+ files. While in pre-1.10.1 recursive commands wouldn't handle
+ that working directory hierarchy, one could use commands like
+ "cvs foo -l" instead. While not great, this allows you (with a
+ lot of manual interaction) to have a multiroot WD. Since we now
+ have multiroot mods checked in, we don't need this code.
+
+ (lookup_command_attribute): while we don't need the
+ CVS_CMD_USES_WORK_DIR flag anymore (since it only was supporting
+ the need_to_create_root code), I'm leaving it in. It may come in
+ handy at some later date.
+
+1998-09-18 Jim Kingdon <kingdon@pennington.cyclic.com>
+
+ * version.c: Advance version number to 1.10.2.1.
+
+ * Version 1.10.2.
+
+1998-09-13 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * client.c: Refuse to Copy-file to another directory
+ * sanity.sh (client): New test, tests for this.
+
+ * edit.c (editors_fileproc), watch.c (watchers_fileproc): Use
+ cvs_output rather than writing to stdout.
+ * sanity.sh (devcom): Use dotest for tests 178, 180, and 183
+ (tests that we preserve existing behavior on "cvs editors").
+
+ * commit.c (check_fileproc): Don't allow commits in Emptydir.
+ * sanity.sh (emptydir-8): Test for this change in behavior.
+
+ * sanity.sh: Add some compatibility tests to TODO comments at end.
+
+1998-09-10 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * wrapper.c (wrap_add): Remove obsolete comment about -m.
+
+ * server.c (server_updated): Check for error from CVS_UNLINK.
+
+1998-09-09 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * server.c (serve_root): Allocate with malloc, not xmalloc.
+
+ * root.c (set_local_cvsroot): Move memory allocation from here...
+ * server.c (serve_root): ...to here. Fixes error handling.
+
+ * root.c (parse_cvsroot): Don't call check_root_consistent;
+ parse_cvsroot is only used for local and client.
+ * root.c (set_local_cvsroot): Move check_root_consistent
+ functionality from here...
+ * server.c (serve_root): ...to here. Fixes error handling. Also
+ made the error more explicit, while I am at it.
+ * server.c (Pserver_Repos): Now static.
+ * cvs.h: Don't declare it.
+ * root.c (check_root_consistent): Removed; no longer needed.
+ * sanity.sh (pserver): New test, tests for this behavior and some
+ other basic pserver stuff.
+
+ * update.c (merge_file): Use cvs_output for "already contains the
+ differences" message. Found this one when I actually observed the
+ out-of-order bug in Real Life(TM).
+
+1998-09-09 Jim Kingdon
+
+ * find_names.c (find_dirs): Make sure to zero errno before
+ going around the loop again.
+ * find_names.c (find_rcs): Make sure to set save_errno.
+ (thanks to Alexandre Parenteau for reporting both problems).
+
+1998-09-09 Jim Kingdon <kingdon@harvey.cyclic.com> and Michael Pakovic
+
+ * edit.c (notify_do): Only free line if it is not NULL.
+
+1998-09-07 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvs.h: dirs_sent_to_server should not be inside
+ AUTH_SERVER_SUPPORT (reported by both Richard Levitte and Murray
+ Bishop, thanks).
+
+ * lock.c, cvs.h: New variable lock_dir.
+ * parseinfo.c (parse_config): New option LockDir.
+ * lock.c (lock_name): New function, abstracts out lock file naming
+ and also supports LockDir.
+ * lock.c (lock_simple_remove, Reader_Lock, write_lock, set_lock):
+ Call it (6 places, to create/remove read/write/master locks).
+ (Lock_Cleanup): Refuse to reenter this function.
+ * sanity.sh (lockfiles): New test, tests for this feature.
+
+1998-09-03 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * sanity.sh (multiroot): Expect ${TESTDIR} in output instead of
+ assuming it is /tmp/cvs-sanity (thanks to Mark D. Baushke of Cisco).
+ Clean up working directory when done (fixes apparent thinko).
+
+ * server.c (create_adm_p): Fix one "return" which didn't return a
+ value.
+ (dirswitch): Check for errors from create_adm_p.
+
+ * sanity.sh: Set LC_ALL rather than just LC_COLLATE.
+
+Wed Sep 2 02:30:22 1998 Jim Kingdon <kingdon@pennington.cyclic.com>
+
+ * version.c: Bump version number to 1.10.1.1.
+
+ * Version 1.10.1.
+
+1998-09-01 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ Administrative note regarding Noel's changes to allow one to
+ switch from one CVS root to another in a single command: The
+ ChangeLog entries for the changes which Noel just checked in
+ appear for 1998-09-01, 1998-08-28, 1998-08-25, 1998-08-19, and
+ 1998-08-18, rather than being all together.
+
+ * main.c (set_root_directory): Fix whitespace.
+ (main): Nuke new -m option and just have that message controlled
+ by -t.
+ * server.c (server): Revert the CVS_SERVER_SLEEP code back the way
+ it was in CVS 1.10. Attaching to the parent process is relatively
+ boring (you can just run "cvs server" under a debugger instead),
+ but connecting to the child process is what the old code was for.
+ * recurse.c, server.c: Remove DEBUG_NJC code.
+
+1998-09-01 Noel Cragg <noel@swish.red-bean.com>
+
+ * server.c (do_cvs_command): add another environment variable,
+ CVS_SERVER_SLEEP2, after forking to pause the program so one can
+ attach a debugger.
+
+ * sanity.sh (crerepos): clean up crerepos-18 now that multiroot
+ works in this case.
+ (multiroot): finalize tests for local vs. remote operation.
+
+ * recurse.c (start_recursion): near the beginning, save the list
+ of directories to spoof as command-line arguments, if necessary.
+ Use that list near the end and call send_file_names to send those
+ arguments to the server.
+ (do_argument_proc): removed, since we call send_file_names now.
+
+ * main.c (main): re-initialize dirs_sent_to_server on each pass
+ through the loop for each CVSROOT.
+
+ * cvs.h: add proto for global variable which keeps track of which
+ directories have been sent to the server when in client mode.
+
+ * client.c (is_arg_a_parent_or_listed_dir): new function.
+ (arg_should_not_be_sent_to_server): new function. Tries to decide
+ whether the given argument should be sent to the server, based on
+ the current CVSROOT and the list of directories sent to the
+ server.
+ (send_repository): add the directory name to the list of
+ directories sent to the server.
+ (send_file_names): call arg_should_not_be_sent_to_server.
+
+ * add.c (add): switch the order of send_files and send_file_names
+ to make multiple repository support possible. send_files needs to
+ create a list of directories being requested so that
+ send_file_names can decide which command-line arguments to send to
+ the server for the given current CVSROOT.
+ * admin.c (admin): same.
+ * commit.c (commit): same.
+ * diff.c (diff): same.
+ * edit.c (editors): same.
+ * log.c (cvslog): same.
+ * rcs.c (annotate): same.
+ * remove.c (cvsremove): same.
+ * status.c (cvsstatus): same.
+ * tag.c (cvstag): same.
+ * update.c (update): same.
+ * watch.c (watch_addremove): same.
+ (watchers): same.
+
+1998-08-31 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * sanity.sh: Remove "debug" function; it was apparently checked
+ in accidentally by Norbert Kiesel's change.
+
+1998-08-31 Norbert Kiesel <nk@iname.com>
+
+ * release.c (release): modify last patch to release so that
+ save_cwd is called only once and restore_cwd is always called when
+ neccessary. Also fixed a tiny memory leak.
+
+ * sanity.sh (release): added some more tests for "cvs release"
+ including a test with two dirs and a "no" for the first one (which
+ fails without the above patch).
+
+1998-08-28 Noel Cragg <noel@swish.red-bean.com>
+
+ * sanity.sh (crerepos-18): add new comment and change test
+ slightly to support multiroot.
+ (multiroot): add more tests.
+
+ * server.c (create_adm_p): new function.
+ (dirswitch): call create_adm_p. Modify the code to always write a
+ new CVSADM_REP file, since create_adm_p might have put a
+ placeholder there and our value is guaranteed to be correct.
+ (server): move the CVS_SERVER_SLEEP check here so we can debug
+ things at an earlier stage.
+
+ * recurse.c (start_recursion): add large comment about the ideal
+ solution to the "Argument xxx" problem.
+
+ * main.c (main): move position of debugging comment for -m flag.
+
+ * diff.c (diff): clear a static variable.
+
+ * client.c (send_file_names): check to see if we should send this
+ argument to the server based on the contents of the appropriate
+ CVSADM directory. This avoids "nothing known about foo" messages
+ and problems with duplicate modules names in multiple
+ repositories.
+ (send_a_repository): change method of calculating toplevel_repos
+ to support multiple CVSROOTs.
+ (start_server): clear some static variables.
+
+1998-08-28 Jim Meyering <meyering@ascend.com>
+
+ * sanity.sh (basicc-8, basicc-11): Use `.*' instead of explicit
+ `Operation not permitted'. Solaris2.5.1 gets a different error:
+ `Invalid argument'.
+
+1998-08-26 Eric M. Hopper
+
+ * sanity.sh: Set LC_COLLATE to "C".
+
+1998-08-25 Noel Cragg <noel@swish.red-bean.com>
+
+ * sanity.sh (multiroot): new set of tests to check the behavior of
+ multiroot.
+
+ * diff.c (diff): set options value to NULL after freeing to reset
+ the state for the next time around.
+
+1998-08-25 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ Fix problems with trying to rename an open file:
+ * rcs.c, rcs.h (RCS_setattic): New function.
+ * commit.c (remove_file, checkaddfile): Call it.
+
+1998-08-24 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * release.c (release): Use save_cwd and restore_cwd to get back to
+ where we started, rather than hoping that CVS_CHDIR ("..") will do
+ something useful. This removes the need for most of
+ release_delete, so remove that function and inline what is left.
+ * sanity.sh (basicc): Adjust tests for this fix, also some tests
+ with multiple arguments to "cvs release" (in the non-"-d"-case, it
+ would seem like the old code would CVS_CHDIR into directories and not
+ CVS_CHDIR back, but I'm not going to investigate this and it
+ should be a moot point with this fix.).
+
+ * sanity.sh (basicc): Add tests for a serious bug in "cvs release
+ -d .".
+
+ More error handling fixes:
+ * ignore.c (ignore_files): Check for errors from opendir and
+ readdir.
+ * find_names.c (Find_Names): Check for errors from find_rcs.
+ (find_rcs, find_dirs): Comment error handling better; also return
+ an error if we got one from readdir.
+ * filesubr.c (deep_remove_dir): Also check for errors from readdir.
+ * import.c (import_descend): Print message on error from opendir
+ or readdir.
+ * commit.c (remove_file): Check for errors from CVS_MKDIR and
+ CVS_RENAME.
+ (remove_file): No need to remove the file in the temporary
+ directory; server.c now informs time_stamp_server of what is going
+ on via CVS/Entries rather than a file with a kludged up timestamp.
+ * client.c, entries.c, login.c, logmsg.c, mkmodules.c, patch.c,
+ remove.c, update.c: Check for errors from unlink_file.
+ * mkmodules.c (write_dbmfile, rename_dbfile, rename_rcsfile):
+ Check for errors from fclose, CVS_RENAME, and CVS_STAT.
+ * mkmodules.c (checkout_file): Clarify error handling convention.
+ * mkmodules.c (mkmodules): Call checkout_file accordingly.
+ * entries.c (Entries_Open): Check for errors from fclose.
+
+1998-08-21 Ian Lance Taylor <ian@cygnus.com>
+
+ * import.c (import): Output suggested merge command using
+ cvs_output_tagged rather than just cvs_output. Don't put
+ CVSroot_cmdline in the log file.
+ * client.c (importmergecmd): New static struct.
+ (handle_mt): Handle +importmergecmd tag.
+ * sanity.sh (import): Use an explicit -d in importb-2, to test
+ whether it is reported in the suggested merge command.
+
+1998-08-20 Ian Lance Taylor <ian@cygnus.com>
+
+ * sanity.sh (import): Rewrite tests to use dotest.
+
+1998-08-20 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * sanity.sh: Add comments about binary files and cvs import.
+
+1998-08-19 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * sanity.sh (importc): Use ${username} in one place where I had
+ missed it.
+
+ Make import -d work client/server:
+ * client.c, client.h (client_process_import_file): Take new
+ argument, for whether -d is specified, and send Checkin-time
+ request if it is set.
+ * import.c (import_descend): Pass it.
+ * main.c, cvs.h (date_to_internet): New function.
+ * server.c (server_modtime): Call date_to_internet.
+ * server.c (serve_checkin_time): New function.
+ (requests): Add "Checkin-time" request.
+ (serve_modified): If it was sent, set the timestamp in the
+ temporary directory.
+ * import.c (import): If the client sends a -d option, complain.
+ (import): For the server, always use the timestamps from the temp
+ directory.
+ (import): Don't send a -d option to the server.
+ * sanity.sh (importc): Add tests for import -d.
+
+Wed Aug 19 15:19:13 1998 Larry Jones <larry.jones@sdrc.com>
+
+ * sanity.sh (unedit-without-baserev-5): use ${DOTSTAR} instead
+ of .* since we expect to match multiple lines.
+
+1998-08-19 Ian Lance Taylor <ian@cygnus.com>
+
+ * cvs.h (CVSroot_cmdline): Declare.
+ * root.c (CVSroot_cmdline): Define.
+ * main.c (main): Set CVSroot_cmdline if the -d option is used.
+ * import.c (import): If CVSroot_cmdline is not NULL, then mention
+ an explicit -d option in the suggested merge command line.
+
+Wed Aug 19 00:28:50 1998 Noel Cragg <noel@swish.red-bean.com>
+
+ * recurse.c (do_dir_proc): don't muck with CVS/Root directories
+ when running in server mode.
+ (do_recursion): same.
+
+ * main.c (main): add the command-line option `m' to help debug the
+ multiroot environment; it prints out the value of CVSROOT for each
+ iteration through the main loop. Also, changed the main loop so
+ that it gets executed only once when running in server mode (the
+ server will only deal with a single CVSROOT).
+
+ * recurse.c (do_recursion): change default for
+ PROCESS_THIS_DIRECTORY to true; we should always process a
+ directory's contents unless there's an existing CVS/Root file with
+ a different root than the current root to tell us otherwise.
+ (do_dir_proc): same.
+
+Tue Aug 18 14:30:59 1998 Noel Cragg <noel@swish.red-bean.com>
+
+ * recurse.c (do_recursion): check the current value of CVS/Root
+ and add it to our list of CVSROOTs if it doesn't exist. Decide
+ whether or not to process files in this directory based based on
+ the value of CURRENT_ROOT.
+ (do_dir_proc): same.
+
+ * main.c: add two new globals -- root_directories and current_root
+ -- which keep track of the values of CVSROOT we've seen and which
+ value of CVSROOT we're currently processing.
+ (main): put the main loop for stepping through cvsroot values
+ here, since we might need to send command-specific arguments for
+ every unique non-local cvsroot. Moved blocks of code around so
+ that one-time initializations happen first (outside the loop) and
+ the other stuff happens inside the loop.
+ (set_root_directory): helper function.
+
+ * cvs.h: add prototypes for root_directories and current_root, two
+ new globals for keeping track of multiple CVSROOT information.
+
+1998-08-18 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * sanity.sh: Don't assume that the shell leaves $^ unexpanded in
+ an unquoted here-document (suggested by Bart Schaefer to help when
+ zsh is the shell).
+
+1998-08-17 Ian Lance Taylor <ian@cygnus.com>
+
+ * commit.c (checkaddfile): Don't call fix_rcs_modes.
+ (fix_rcs_modes): Remove.
+
+1998-08-16 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * create_adm.c (Create_Admin): Don't condition traces on
+ SERVER_SUPPORT; SERVER_SUPPORT shouldn't do (much of) anything
+ independent of server_active.
+
+ * sanity.sh (binfiles3): New test, for yet another binary file
+ bug (sigh). Thanks to Jason Aten for reporting this one.
+
+1998-08-15 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * rcscmds.c (call_diff_write_output): Update to reflect new
+ calling convention for the write_output callback.
+
+1998-08-15 Jim Meyering <meyering@ascend.com>
+
+ * update.c (merge_file): Warn about failed unlink when not due
+ to ENOENT.
+
+ * server.h (CLIENT_SERVER_STR): New macro
+ * create_adm.c (Create_Admin): Use it.
+ * entries.c (Scratch_Entry, Register): Use it.
+ * filesubr.c (copy_file, xchmod, rename_file, unlink_file): Use it.
+ * history.c (history_write): Use it.
+ * modules.c (do_module): Use it.
+ * no_diff.c (No_Difference): Use it.
+ * run.c (run_popen): Use it.
+ * server.c (server_register): Use it.
+
+1998-08-14 Jim Meyering <meyering@ascend.com>
+
+ * hardlink.c (lookup_file_by_inode): Use existence_error rather than
+ comparing errno to ENOENT directly.
+
+ * client.c (copy_a_file): Unlink destination before doing copy.
+ * sanity.sh (join-readonly-conflict): New test for this -- it would
+ fail only in client/server mode.
+
+ * sanity.sh (rcsmerge-symlink-4): Don't use `test -L', it's not
+ portable. Instead, match against the output of `ls -l'.
+ (dotest tag8k-16): Simplify tag-construction code and at the same
+ time, avoid using expr's `length' and `substr' operators. Not
+ all versions of expr support those.
+
+1998-08-14 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * version.c: Bump version number to 1.10.0.1.
+
Thu Aug 13 11:15:24 1998 Noel Cragg <noel@swish.red-bean.com>
* version.c: Change version number to 1.10 and name to `Halibut'.
@@ -67,14 +1581,14 @@ Sun Jul 26 05:14:41 1998 Noel Cragg <noel@swish.red-bean.com>
does not create CVS directories at top-level (except for the
obvious "cvs co ."). Added a new configuration option to switch
between 1.9 and 1.9.2 behavior.
-
+
* recurse.c (do_argument_proc): new function.
(start_recursion): in the case that we've done a command from
top-level but have no CVS directory there, the behavior should be
the same as "cvs <cmd> dir1 dir2 dir3...". Make sure that the
appropriate "Argument" commands are sent to the server by calling
walklist with do_argument_proc.
-
+
* client.c (call_in_directory): only create the top-level CVS
directory when we're checking out "." explicitly. The server will
force creation of this directory in all other cases.
diff --git a/contrib/cvs/src/Makefile.in b/contrib/cvs/src/Makefile.in
index 2c93ec2..7cbdca7 100644
--- a/contrib/cvs/src/Makefile.in
+++ b/contrib/cvs/src/Makefile.in
@@ -97,14 +97,10 @@ installdirs:
.PHONY: install installdirs
installcheck:
- RCSBIN=$(bindir) ; export RCSBIN ; $(SHELL) $(srcdir)/sanity.sh $(bindir)/cvs
+ $(SHELL) $(srcdir)/sanity.sh $(bindir)/cvs
.PHONY: installcheck
check: all
- if [ -x ../../rcs/src/rcs ] ; then \
- RCSBIN=`pwd`/../../rcs/src ; \
- export RCSBIN ; \
- fi ; \
$(SHELL) $(srcdir)/sanity.sh `pwd`/cvs
.PHONY: check
diff --git a/contrib/cvs/src/add.c b/contrib/cvs/src/add.c
index a4eed40..db1f527 100644
--- a/contrib/cvs/src/add.c
+++ b/contrib/cvs/src/add.c
@@ -172,9 +172,20 @@ add (argc, argv)
}
for (i = 0; i < argc; ++i)
+ {
/* FIXME: Does this erroneously call Create_Admin in error
conditions which are only detected once the server gets its
hands on things? */
+ /* FIXME-also: if filenames are case-insensitive on the
+ client, and the directory in the repository already
+ exists and is named "foo", and the command is "cvs add
+ FOO", this call to Create_Admin puts the wrong thing in
+ CVS/Repository and so a subsequent "cvs update" will
+ give an error. The fix will be to have the server report
+ back what it actually did (e.g. use tagged text for the
+ "Directory %s added" message), and then Create_Admin,
+ which should also fix the error handling concerns. */
+
if (isdir (argv[i]))
{
char *tag;
@@ -240,8 +251,9 @@ add (argc, argv)
free (repository);
free (filedir);
}
- send_file_names (argc, argv, SEND_EXPAND_WILD);
+ }
send_files (argc, argv, 0, 0, SEND_BUILD_DIRS | SEND_NO_CONTENTS);
+ send_file_names (argc, argv, SEND_EXPAND_WILD);
send_to_server ("add\012", 0);
if (message)
free (message);
@@ -258,6 +270,9 @@ add (argc, argv)
#endif
struct file_info finfo;
char *p;
+#if defined (SERVER_SUPPORT) && !defined (FILENAMES_CASE_INSENSITIVE)
+ char *found_name;
+#endif
memset (&finfo, 0, sizeof finfo);
@@ -294,6 +309,60 @@ add (argc, argv)
finfo.repository = repository;
finfo.entries = entries;
+#if defined (SERVER_SUPPORT) && !defined (FILENAMES_CASE_INSENSITIVE)
+ if (ign_case)
+ {
+ /* Need to check whether there is a directory with the
+ same name but different case. We'll check for files
+ with the same name later (when Version_TS calls
+ RCS_parse which calls fopen_case). If CVS some day
+ records directories in the RCS files, then we should be
+ able to skip the separate check here, which would be
+ cleaner. */
+ DIR *dirp;
+ struct dirent *dp;
+
+ dirp = CVS_OPENDIR (finfo.repository);
+ if (dirp == NULL)
+ error (1, errno, "cannot read directory %s", finfo.repository);
+ found_name = NULL;
+ errno = 0;
+ while ((dp = readdir (dirp)) != NULL)
+ {
+ if (cvs_casecmp (dp->d_name, finfo.file) == 0)
+ {
+ if (found_name != NULL)
+ error (1, 0, "%s is ambiguous; could mean %s or %s",
+ finfo.file, dp->d_name, found_name);
+ found_name = xstrdup (dp->d_name);
+ }
+ }
+ if (errno != 0)
+ error (1, errno, "cannot read directory %s", finfo.repository);
+ closedir (dirp);
+
+ if (found_name != NULL)
+ {
+ /* OK, we are about to patch up the name, so patch up
+ the temporary directory too to match. The isdir
+ should "always" be true (since files have ,v), but
+ I guess we might as well make some attempt to not
+ get confused by stray files in the repository. */
+ if (isdir (finfo.file))
+ {
+ if (CVS_MKDIR (found_name, 0777) < 0
+ && errno != EEXIST)
+ error (0, errno, "cannot create %s", finfo.file);
+ }
+
+ /* OK, we found a directory with the same name, maybe in
+ a different case. Treat it as if the name were the
+ same. */
+ finfo.file = found_name;
+ }
+ }
+#endif
+
/* We pass force_tag_match as 1. If the directory has a
sticky branch tag, and there is already an RCS file which
does not have that tag, then the head revision is
@@ -420,7 +489,7 @@ file `%s' will be added on branch `%s' from version %s",
re-adding file %s (in place of dead revision %s)",
finfo.fullname, vers->vn_rcs);
Register (entries, finfo.file, "0", vers->ts_user,
- NULL,
+ vers->options,
vers->tag, NULL, NULL);
++added_files;
}
@@ -538,6 +607,10 @@ cannot resurrect %s; RCS file removed by second party", finfo.fullname);
free_cwd (&cwd);
free (finfo.fullname);
+#if defined (SERVER_SUPPORT) && !defined (FILENAMES_CASE_INSENSITIVE)
+ if (ign_case && found_name != NULL)
+ free (found_name);
+#endif
}
if (added_files)
error (0, 0, "use '%s commit' to add %s permanently",
diff --git a/contrib/cvs/src/admin.c b/contrib/cvs/src/admin.c
index 72cddac..c5af96e 100644
--- a/contrib/cvs/src/admin.c
+++ b/contrib/cvs/src/admin.c
@@ -120,35 +120,11 @@ admin (argc, argv)
struct admin_data admin_data;
int c;
int i;
+ int only_k_option;
if (argc <= 1)
usage (admin_usage);
-#ifdef CVS_ADMIN_GROUP
- grp = getgrnam(CVS_ADMIN_GROUP);
- /* skip usage right check if group CVS_ADMIN_GROUP does not exist */
- if (grp != NULL)
- {
- char *me = getcaller();
- char **grnam = grp->gr_mem;
- int denied = 1;
-
- while (*grnam)
- {
- if (strcmp(*grnam, me) == 0)
- {
- denied = 0;
- break;
- }
- grnam++;
- }
-
- if (denied)
- error (1, 0, "usage is restricted to members of the group %s",
- CVS_ADMIN_GROUP);
- }
-#endif
-
wrap_setup ();
memset (&admin_data, 0, sizeof admin_data);
@@ -157,9 +133,13 @@ admin (argc, argv)
example, admin_data->branch should be not `-bfoo' but simply `foo'. */
optind = 0;
+ only_k_option = 1;
while ((c = getopt (argc, argv,
- "+ib::c:a:A:e:l::u::LUn:N:m:o:s:t::IqxV:k:")) != -1)
+ "+ib::c:a:A:e::l::u::LUn:N:m:o:s:t::IqxV:k:")) != -1)
{
+ if (c != 'k')
+ only_k_option = 0;
+
switch (c)
{
case 'i':
@@ -211,6 +191,11 @@ admin (argc, argv)
break;
case 'e':
+ if (optarg == NULL)
+ {
+ error (1, 0,
+ "removing entire access list not yet implemented");
+ }
arg_add (&admin_data, 'e', optarg);
break;
@@ -353,6 +338,33 @@ admin (argc, argv)
argc -= optind;
argv += optind;
+#ifdef CVS_ADMIN_GROUP
+ grp = getgrnam(CVS_ADMIN_GROUP);
+ /* skip usage right check if group CVS_ADMIN_GROUP does not exist */
+ if (grp != NULL)
+ {
+ char *me = getcaller();
+ char **grnam = grp->gr_mem;
+ /* The use of `cvs admin -k' is unrestricted. However, any
+ other option is restricted. */
+ int denied = ! only_k_option;
+
+ while (*grnam)
+ {
+ if (strcmp(*grnam, me) == 0)
+ {
+ denied = 0;
+ break;
+ }
+ grnam++;
+ }
+
+ if (denied)
+ error (1, 0, "usage is restricted to members of the group %s",
+ CVS_ADMIN_GROUP);
+ }
+#endif
+
for (i = 0; i < admin_data.ac; ++i)
{
assert (admin_data.av[i][0] == '-');
@@ -375,9 +387,9 @@ admin (argc, argv)
check_numeric (admin_data.delete_revs + 2, argc, argv);
p = strchr (admin_data.delete_revs + 2, ':');
- if (p != NULL && isdigit (p[1]))
+ if (p != NULL && isdigit ((unsigned char) p[1]))
check_numeric (p + 1, argc, argv);
- else if (p != NULL && p[1] == ':' && isdigit(p[2]))
+ else if (p != NULL && p[1] == ':' && isdigit ((unsigned char) p[2]))
check_numeric (p + 2, argc, argv);
}
@@ -414,8 +426,8 @@ admin (argc, argv)
for (i = 0; i < admin_data.ac; ++i)
send_arg (admin_data.av[i]);
- send_file_names (argc, argv, SEND_EXPAND_WILD);
send_files (argc, argv, 0, 0, SEND_NO_CONTENTS);
+ send_file_names (argc, argv, SEND_EXPAND_WILD);
send_to_server ("admin\012", 0);
err = get_responses_and_close ();
goto return_it;
@@ -492,7 +504,7 @@ admin_fileproc (callerdat, finfo)
if (admin_data->branch != NULL)
{
char *branch = &admin_data->branch[2];
- if (*branch != '\0' && ! isdigit (*branch))
+ if (*branch != '\0' && ! isdigit ((unsigned char) *branch))
{
branch = RCS_whatbranch (rcs, admin_data->branch + 2);
if (branch == NULL)
@@ -604,12 +616,9 @@ admin_fileproc (callerdat, finfo)
if (admin_data->kflag != NULL)
{
char *kflag = admin_data->kflag + 2;
- if (!rcs->expand || strcmp (rcs->expand, kflag) != 0)
- {
- if (rcs->expand)
- free (rcs->expand);
- rcs->expand = xstrdup (kflag);
- }
+ char *oldexpand = RCS_getexpand (rcs);
+ if (oldexpand == NULL || strcmp (oldexpand, kflag) != 0)
+ RCS_setexpand (rcs, kflag);
}
/* Handle miscellaneous options. TODO: decide whether any or all
diff --git a/contrib/cvs/src/checkout.c b/contrib/cvs/src/checkout.c
index c6a8122..a7d942f 100644
--- a/contrib/cvs/src/checkout.c
+++ b/contrib/cvs/src/checkout.c
@@ -238,7 +238,7 @@ checkout (argc, argv)
if (!tag && !date)
error (1, 0, "must specify a tag or date");
- if (tag && isdigit (tag[0]))
+ if (tag && isdigit ((unsigned char) tag[0]))
error (1, 0, "tag `%s' must be a symbolic tag", tag);
}
diff --git a/contrib/cvs/src/client.c b/contrib/cvs/src/client.c
index 222e7f2..748132a 100644
--- a/contrib/cvs/src/client.c
+++ b/contrib/cvs/src/client.c
@@ -148,6 +148,139 @@ static void handle_notified PROTO((char *, int));
static size_t try_read_from_server PROTO ((char *, size_t));
#endif /* CLIENT_SUPPORT */
+#ifdef CLIENT_SUPPORT
+
+/* We need to keep track of the list of directories we've sent to the
+ server. This list, along with the current CVSROOT, will help us
+ decide which command-line arguments to send. */
+List *dirs_sent_to_server = NULL;
+
+static int is_arg_a_parent_or_listed_dir PROTO((Node *, void *));
+
+static int
+is_arg_a_parent_or_listed_dir (n, d)
+ Node *n;
+ void *d;
+{
+ char *directory = n->key; /* name of the dir sent to server */
+ char *this_argv_elem = (char *) d; /* this argv element */
+
+ /* Say we should send this argument if the argument matches the
+ beginning of a directory name sent to the server. This way,
+ the server will know to start at the top of that directory
+ hierarchy and descend. */
+
+ if (strncmp (directory, this_argv_elem, strlen (this_argv_elem)) == 0)
+ return 1;
+
+ return 0;
+}
+
+static int arg_should_not_be_sent_to_server PROTO((char *));
+
+/* Return nonzero if this argument should not be sent to the
+ server. */
+
+static int
+arg_should_not_be_sent_to_server (arg)
+ char *arg;
+{
+ /* Decide if we should send this directory name to the server. We
+ should always send argv[i] if:
+
+ 1) the list of directories sent to the server is empty (as it
+ will be for checkout, etc.).
+
+ 2) the argument is "."
+
+ 3) the argument is a file in the cwd and the cwd is checked out
+ from the current root
+
+ 4) the argument lies within one of the paths in
+ dirs_sent_to_server.
+
+ 4) */
+
+ if (list_isempty (dirs_sent_to_server))
+ return 0; /* always send it */
+
+ if (strcmp (arg, ".") == 0)
+ return 0; /* always send it */
+
+ /* We should send arg if it is one of the directories sent to the
+ server or the parent of one; this tells the server to descend
+ the hierarchy starting at this level. */
+ if (isdir (arg))
+ {
+ if (walklist (dirs_sent_to_server, is_arg_a_parent_or_listed_dir, arg))
+ return 0;
+
+ /* If arg wasn't a parent, we don't know anything about it (we
+ would have seen something related to it during the
+ send_files phase). Don't send it. */
+ return 1;
+ }
+
+ /* Try to decide whether we should send arg to the server by
+ checking the contents of the corresponding CVSADM directory. */
+ {
+ char *t, *this_root;
+
+ /* Calculate "dirname arg" */
+ for (t = arg + strlen (arg) - 1; t >= arg; t--)
+ {
+ if (ISDIRSEP(*t))
+ break;
+ }
+
+ /* Now we're either poiting to the beginning of the
+ string, or we found a path separator. */
+ if (t >= arg)
+ {
+ /* Found a path separator. */
+ char c = *t;
+ *t = '\0';
+
+ /* First, check to see if we sent this directory to the
+ server, because it takes less time than actually
+ opening the stuff in the CVSADM directory. */
+ if (walklist (dirs_sent_to_server, is_arg_a_parent_or_listed_dir,
+ arg))
+ {
+ *t = c; /* make sure to un-truncate the arg */
+ return 0;
+ }
+
+ /* Since we didn't find it in the list, check the CVSADM
+ files on disk. */
+ this_root = Name_Root (arg, (char *) NULL);
+ *t = c;
+ }
+ else
+ {
+ /* We're at the beginning of the string. Look at the
+ CVSADM files in cwd. */
+ this_root = Name_Root ((char *) NULL, (char *) NULL);
+ }
+
+ /* Now check the value for root. */
+ if (this_root && current_root
+ && (strcmp (this_root, current_root) != 0))
+ {
+ /* Don't send this, since the CVSROOTs don't match. */
+ free (this_root);
+ return 1;
+ }
+ free (this_root);
+ }
+
+ /* OK, let's send it. */
+ return 0;
+}
+
+
+#endif /* CLIENT_SUPPORT */
+
#if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT)
/* Shared with server. */
@@ -710,25 +843,6 @@ int gzip_level;
*/
int file_gzip_level;
-int filter_through_gzip (fd, dir, level, pidp)
- int fd, dir, level;
- pid_t *pidp;
-{
- static char buf[5] = "-";
- static char *gzip_argv[3] = { "gzip", buf };
-
- sprintf (buf+1, "%d", level);
- return filter_stream_through_program (fd, dir, &gzip_argv[0], pidp);
-}
-
-int filter_through_gunzip (fd, dir, pidp)
- int fd, dir;
- pid_t *pidp;
-{
- static char *gunzip_argv[3] = { "gzip", "-d" };
- return filter_stream_through_program (fd, dir, &gunzip_argv[0], pidp);
-}
-
#endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
#ifdef CLIENT_SUPPORT
@@ -737,7 +851,7 @@ int filter_through_gunzip (fd, dir, pidp)
* The Repository for the top level of this command (not necessarily
* the CVSROOT, just the current directory at the time we do it).
*/
-static char *toplevel_repos;
+static char *toplevel_repos = NULL;
/* Working directory when we first started. Note: we could speed things
up on some systems by using savecwd.h here instead of just always
@@ -770,6 +884,13 @@ handle_error (args, len)
return;
}
++p;
+
+ /* Next we print the text of the message from the server. We
+ probably should be prefixing it with "server error" or some
+ such, because if it is something like "Out of memory", the
+ current behavior doesn't say which machine is out of
+ memory. */
+
len -= p - args;
something_printed = 0;
for (; len > 0; --len)
@@ -807,7 +928,7 @@ handle_valid_requests (args, len)
;
else
{
- if (rq->status == rq_enableme)
+ if (rq->flags & RQ_ENABLEME)
{
/*
* Server wants to know if we have this, to enable the
@@ -817,16 +938,17 @@ handle_valid_requests (args, len)
send_to_server ("\012", 0);
}
else
- rq->status = rq_supported;
+ rq->flags |= RQ_SUPPORTED;
}
p = q;
} while (q != NULL);
for (rq = requests; rq->name != NULL; ++rq)
{
- if (rq->status == rq_essential)
+ if ((rq->flags & RQ_SUPPORTED)
+ || (rq->flags & RQ_ENABLEME))
+ continue;
+ if (rq->flags & RQ_ESSENTIAL)
error (1, 0, "request `%s' not supported by server", rq->name);
- else if (rq->status == rq_optional)
- rq->status = rq_not_supported;
}
}
@@ -1210,7 +1332,14 @@ copy_a_file (data, ent_list, short_pathname, filename)
for(p = newname; *p; p++)
if(*p == '.' || *p == '#') *p = '_';
#endif
-
+ /* cvsclient.texi has said for a long time that newname must be in the
+ same directory. Wouldn't want a malicious or buggy server overwriting
+ ~/.profile, /etc/passwd, or anything like that. */
+ if (last_component (newname) != newname)
+ error (1, 0, "protocol error: Copy-file tried to specify directory");
+
+ if (unlink_file (newname) && !existence_error (errno))
+ error (0, errno, "unable to remove %s", newname);
copy_file (filename, newname);
free (newname);
}
@@ -1317,6 +1446,23 @@ static int updated_seen;
/* Filename from an "fname" tagged response within +updated/-updated. */
static char *updated_fname;
+/* This struct is used to hold data when reading the +importmergecmd
+ and -importmergecmd tags. We put the variables in a struct only
+ for namespace issues. FIXME: As noted above, we need to develop a
+ more systematic approach. */
+static struct
+{
+ /* Nonzero if we have seen +importmergecmd and not -importmergecmd. */
+ int seen;
+ /* Number of conflicts, from a "conflicts" tagged response. */
+ int conflicts;
+ /* First merge tag, from a "mergetag1" tagged response. */
+ char *mergetag1;
+ /* Second merge tag, from a "mergetag2" tagged response. */
+ char *mergetag2;
+ /* Repository, from a "repository" tagged response. */
+ char *repository;
+} importmergecmd;
/* Nonzero if we should arrange to return with a failure exit status. */
static int failure_exit;
@@ -1367,7 +1513,7 @@ handle_checksum (args, len)
stored_checksum_valid = 1;
}
-static int stored_mode_valid;
+/* Mode that we got in a "Mode" response (malloc'd), or NULL if none. */
static char *stored_mode;
static void handle_mode PROTO ((char *, int));
@@ -1377,12 +1523,9 @@ handle_mode (args, len)
char *args;
int len;
{
- if (stored_mode_valid)
- error (1, 0, "protocol error: duplicate Mode");
if (stored_mode != NULL)
- free (stored_mode);
+ error (1, 0, "protocol error: duplicate Mode");
stored_mode = xstrdup (args);
- stored_mode_valid = 1;
}
/* Nonzero if time was specified in Mod-time. */
@@ -1547,8 +1690,8 @@ update_entries (data_arg, ent_list, short_pathname, filename)
free (size_string);
/* Note that checking this separately from writing the file is
- a race condition: if the existing or lack thereof of the
- file changes between now and the actually calls which
+ a race condition: if the existence or lack thereof of the
+ file changes between now and the actual calls which
operate on it, we lose. However (a) there are so many
cases, I'm reluctant to try to fix them all, (b) in some
cases the system might not even have a system call which
@@ -1622,9 +1765,11 @@ update_entries (data_arg, ent_list, short_pathname, filename)
/* The Mode, Mod-time, and Checksum responses should not carry
over to a subsequent Created (or whatever) response, even
in the error case. */
- stored_mode_valid = 0;
if (stored_mode != NULL)
+ {
free (stored_mode);
+ stored_mode = NULL;
+ }
stored_modtime_valid = 0;
stored_checksum_valid = 0;
@@ -1701,7 +1846,10 @@ update_entries (data_arg, ent_list, short_pathname, filename)
read_from_server (buf, size);
if (use_gzip)
- gunzip_and_write (fd, short_pathname, buf, size);
+ {
+ if (gunzip_and_write (fd, short_pathname, buf, size))
+ error (1, 0, "aborting due to compression error");
+ }
else if (write (fd, buf, size) != size)
error (1, errno, "writing %s", short_pathname);
}
@@ -1734,82 +1882,14 @@ update_entries (data_arg, ent_list, short_pathname, filename)
}
else if (data->contents == UPDATE_ENTRIES_PATCH)
{
-#ifdef DONT_USE_PATCH
- /* Hmm. We support only Rcs-diff, and the server supports
- only Patched (or else it would have sent Rcs-diff instead).
+ /* You might think we could just leave Patched out of
+ Valid-responses and not get this response. However, if
+ memory serves, the CVS 1.9 server bases this on -u
+ (update-patches), and there is no way for us to send -u
+ or not based on whether the server supports "Rcs-diff".
+
Fall back to transmitting entire files. */
patch_failed = 1;
-#else /* Use patch. */
- int retcode;
- char *backup;
- struct stat s;
-
- backup = xmalloc (strlen (filename) + 5);
- strcpy (backup, filename);
- strcat (backup, "~");
- (void) unlink_file (backup);
- if (!isfile (filename))
- error (1, 0, "patch original file %s does not exist",
- short_pathname);
- if ( CVS_STAT (temp_filename, &s) < 0)
- error (1, errno, "can't stat patch file %s", temp_filename);
- if (s.st_size == 0)
- retcode = 0;
- else
- {
- /* This behavior (in which -b takes an argument) is
- supported by GNU patch 2.1. Apparently POSIX.2
- specifies a -b option without an argument. GNU
- patch 2.1.5 implements this and therefore won't
- work here. GNU patch versions after 2.1.5 are said
- to have a kludge which checks if the last 4 args
- are `-b SUFFIX ORIGFILE PATCHFILE' and if so emit a
- warning (I think -s suppresses it), and then behave
- as CVS expects.
-
- Of course this is yet one more reason why in the long
- run we want Rcs-diff to replace Patched. */
-
- run_setup (PATCH_PROGRAM);
- run_arg ("-f");
- run_arg ("-s");
- run_arg ("-b");
- run_arg ("~");
- run_arg (filename);
- run_arg (temp_filename);
- retcode = run_exec (DEVNULL, RUN_TTY, RUN_TTY, RUN_NORMAL);
- }
- /* FIXME: should we really be silently ignoring errors? */
- (void) unlink_file (temp_filename);
- if (retcode == 0)
- {
- /* FIXME: should we really be silently ignoring errors? */
- (void) unlink_file (backup);
- }
- else
- {
- int old_errno = errno;
- char *path_tmp;
-
- if (isfile (backup))
- rename_file (backup, filename);
-
- /* Get rid of the patch reject file. */
- path_tmp = xmalloc (strlen (filename) + 10);
- strcpy (path_tmp, filename);
- strcat (path_tmp, ".rej");
- /* FIXME: should we really be silently ignoring errors? */
- (void) unlink_file (path_tmp);
- free (path_tmp);
-
- error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0,
- "could not patch %s%s", filename,
- retcode == -1 ? "" : "; will refetch");
-
- patch_failed = 1;
- }
- free (backup);
-#endif /* Use patch. */
}
else
{
@@ -1842,15 +1922,16 @@ update_entries (data_arg, ent_list, short_pathname, filename)
{
if (stored_checksum_valid)
{
- struct MD5Context context;
+ struct cvs_MD5Context context;
unsigned char checksum[16];
/* We have a checksum. Check it before writing
the file out, so that we don't have to read it
back in again. */
- MD5Init (&context);
- MD5Update (&context, (unsigned char *) patchedbuf, patchedlen);
- MD5Final (checksum, &context);
+ cvs_MD5Init (&context);
+ cvs_MD5Update (&context,
+ (unsigned char *) patchedbuf, patchedlen);
+ cvs_MD5Final (checksum, &context);
if (memcmp (checksum, stored_checksum, 16) != 0)
{
error (0, 0,
@@ -1887,7 +1968,7 @@ update_entries (data_arg, ent_list, short_pathname, filename)
if (stored_checksum_valid && ! patch_failed)
{
FILE *e;
- struct MD5Context context;
+ struct cvs_MD5Context context;
unsigned char buf[8192];
unsigned len;
unsigned char checksum[16];
@@ -1906,12 +1987,12 @@ update_entries (data_arg, ent_list, short_pathname, filename)
if (e == NULL)
error (1, errno, "could not open %s", short_pathname);
- MD5Init (&context);
+ cvs_MD5Init (&context);
while ((len = fread (buf, 1, sizeof buf, e)) != 0)
- MD5Update (&context, buf, len);
+ cvs_MD5Update (&context, buf, len);
if (ferror (e))
error (1, errno, "could not read %s", short_pathname);
- MD5Final (checksum, &context);
+ cvs_MD5Final (checksum, &context);
fclose (e);
@@ -1958,10 +2039,13 @@ update_entries (data_arg, ent_list, short_pathname, filename)
free (buf);
}
- if (stored_mode_valid)
+ if (stored_mode != NULL)
+ {
change_mode (filename, stored_mode, 1);
- stored_mode_valid = 0;
-
+ free (stored_mode);
+ stored_mode = NULL;
+ }
+
if (stored_modtime_valid)
{
struct utimbuf t;
@@ -2020,7 +2104,17 @@ update_entries (data_arg, ent_list, short_pathname, filename)
else if (local_timestamp == NULL)
{
local_timestamp = file_timestamp;
- mark_up_to_date (filename);
+
+ /* Checking for command_name of "commit" doesn't seem like
+ the cleanest way to handle this, but it seem to roughly
+ parallel what the :local: code which calls
+ mark_up_to_date ends up amounting to. Some day, should
+ think more about what the Checked-in response means
+ vis-a-vis both Entries and Base and clarify
+ cvsclient.texi accordingly. */
+
+ if (!strcmp (command_name, "commit"))
+ mark_up_to_date (filename);
}
Register (ent_list, filename, vn, local_timestamp,
@@ -2263,7 +2357,20 @@ set_sticky (data, ent_list, short_pathname, filename)
FILE *f;
read_line (&tagspec);
- f = open_file (CVSADM_TAG, "w+");
+
+ /* FIXME-update-dir: error messages should include the directory. */
+ f = CVS_FOPEN (CVSADM_TAG, "w+");
+ if (f == NULL)
+ {
+ /* Making this non-fatal is a bit of a kludge (see dirs2
+ in testsuite). A better solution would be to avoid having
+ the server tell us about a directory we shouldn't be doing
+ anything with anyway (e.g. by handling directory
+ addition/removal better). */
+ error (0, errno, "cannot open %s", CVSADM_TAG);
+ free (tagspec);
+ return;
+ }
if (fprintf (f, "%s\n", tagspec) < 0)
error (1, errno, "writing %s", CVSADM_TAG);
if (fclose (f) == EOF)
@@ -2568,6 +2675,22 @@ send_repository (dir, repos, update_dir)
if (client_prune_dirs)
add_prune_candidate (update_dir);
+ /* Add a directory name to the list of those sent to the
+ server. */
+ if (update_dir && (*update_dir != '\0')
+ && (strcmp (update_dir, ".") != 0)
+ && (findnode (dirs_sent_to_server, update_dir) == NULL))
+ {
+ Node *n;
+ n = getnode ();
+ n->type = UNKNOWN;
+ n->key = xstrdup (update_dir);
+ n->data = NULL;
+
+ if (addnode (dirs_sent_to_server, n))
+ error (1, 0, "cannot add directory %s to list", n->key);
+ }
+
/* 80 is large enough for any of CVSADM_*. */
adm_name = xmalloc (strlen (dir) + 80);
@@ -2762,47 +2885,55 @@ send_a_repository (dir, repository, update_dir)
* directories (and cvs invoked on the containing
* directory). I'm not sure the latter case needs to
* work.
+ *
+ * 21 Aug 1998: Well, Mr. Above-Comment-Writer, it
+ * does need to work after all. When we are using the
+ * client in a multi-cvsroot environment, it will be
+ * fairly common that we have the above case (e.g.,
+ * cwd checked out from one repository but
+ * subdirectory checked out from another). We can't
+ * assume that by walking up a directory in our wd we
+ * necessarily walk up a directory in the repository.
*/
/*
* This gets toplevel_repos wrong for "cvs update ../foo"
* but I'm not sure toplevel_repos matters in that case.
*/
- int slashes_in_update_dir;
- int slashes_skipped;
- char *p;
- /*
- * Strip trailing slashes from the name of the update directory.
- * Otherwise, running `cvs update dir/' provokes the failure
- * `protocol error: illegal directory syntax in dir/' when
- * running in client/server mode.
- */
- strip_trailing_slashes (update_dir);
+ int repository_len, update_dir_len;
- slashes_in_update_dir = 0;
- for (p = update_dir; *p != '\0'; ++p)
- if (*p == '/')
- ++slashes_in_update_dir;
+ strip_trailing_slashes (update_dir);
- slashes_skipped = 0;
- p = repository + strlen (repository);
- while (1)
+ repository_len = strlen (repository);
+ update_dir_len = strlen (update_dir);
+
+ /* Try to remove the path components in UPDATE_DIR
+ from REPOSITORY. If the path elements don't exist
+ in REPOSITORY, or the removal of those path
+ elements mean that we "step above"
+ CVSroot_directory, set toplevel_repos to
+ CVSroot_directory. */
+ if ((repository_len > update_dir_len)
+ && (strcmp (repository + repository_len - update_dir_len,
+ update_dir) == 0)
+ /* TOPLEVEL_REPOS shouldn't be above CVSroot_directory */
+ && ((repository_len - update_dir_len)
+ > strlen (CVSroot_directory)))
{
- if (p == repository)
- error (1, 0,
- "internal error: not enough slashes in %s",
- repository);
- if (*p == '/')
- ++slashes_skipped;
- if (slashes_skipped < slashes_in_update_dir + 1)
- --p;
- else
- break;
+ /* The repository name contains UPDATE_DIR. Set
+ toplevel_repos to the repository name without
+ UPDATE_DIR. */
+
+ toplevel_repos = xmalloc (repository_len - update_dir_len);
+ /* Note that we don't copy the trailing '/'. */
+ strncpy (toplevel_repos, repository,
+ repository_len - update_dir_len - 1);
+ toplevel_repos[repository_len - update_dir_len - 1] = '\0';
+ }
+ else
+ {
+ toplevel_repos = xstrdup (CVSroot_directory);
}
- toplevel_repos = xmalloc (p - repository + 1);
- /* Note that we don't copy the trailing '/'. */
- strncpy (toplevel_repos, repository, p - repository);
- toplevel_repos[p - repository] = '\0';
}
}
}
@@ -3047,10 +3178,61 @@ handle_mt (args, len)
case '+':
if (strcmp (tag, "+updated") == 0)
updated_seen = 1;
+ else if (strcmp (tag, "+importmergecmd") == 0)
+ importmergecmd.seen = 1;
break;
case '-':
if (strcmp (tag, "-updated") == 0)
updated_seen = 0;
+ else if (strcmp (tag, "-importmergecmd") == 0)
+ {
+ char buf[80];
+
+ /* Now that we have gathered the information, we can
+ output the suggested merge command. */
+
+ if (importmergecmd.conflicts == 0
+ || importmergecmd.mergetag1 == NULL
+ || importmergecmd.mergetag2 == NULL
+ || importmergecmd.repository == NULL)
+ {
+ error (0, 0,
+ "invalid server: incomplete importmergecmd tags");
+ break;
+ }
+
+ sprintf (buf, "\n%d conflicts created by this import.\n",
+ importmergecmd.conflicts);
+ cvs_output (buf, 0);
+ cvs_output ("Use the following command to help the merge:\n\n",
+ 0);
+ cvs_output ("\t", 1);
+ cvs_output (program_name, 0);
+ if (CVSroot_cmdline != NULL)
+ {
+ cvs_output (" -d ", 0);
+ cvs_output (CVSroot_cmdline, 0);
+ }
+ cvs_output (" checkout -j", 0);
+ cvs_output (importmergecmd.mergetag1, 0);
+ cvs_output (" -j", 0);
+ cvs_output (importmergecmd.mergetag2, 0);
+ cvs_output (" ", 1);
+ cvs_output (importmergecmd.repository, 0);
+ cvs_output ("\n\n", 0);
+
+ /* Clear the static variables so that everything is
+ ready for any subsequent importmergecmd tag. */
+ importmergecmd.conflicts = 0;
+ free (importmergecmd.mergetag1);
+ importmergecmd.mergetag1 = NULL;
+ free (importmergecmd.mergetag2);
+ importmergecmd.mergetag2 = NULL;
+ free (importmergecmd.repository);
+ importmergecmd.repository = NULL;
+
+ importmergecmd.seen = 0;
+ }
break;
default:
if (updated_seen)
@@ -3073,6 +3255,21 @@ handle_mt (args, len)
or they reflect future extensions that we can
safely ignore. */
}
+ else if (importmergecmd.seen)
+ {
+ if (strcmp (tag, "conflicts") == 0)
+ importmergecmd.conflicts = atoi (text);
+ else if (strcmp (tag, "mergetag1") == 0)
+ importmergecmd.mergetag1 = xstrdup (text);
+ else if (strcmp (tag, "mergetag2") == 0)
+ importmergecmd.mergetag2 = xstrdup (text);
+ else if (strcmp (tag, "repository") == 0)
+ importmergecmd.repository = xstrdup (text);
+ /* Swallow all other tags. Either they are text for
+ which we are going to print our own version when we
+ see -importmergecmd, or they are future extensions
+ we can safely ignore. */
+ }
else if (strcmp (tag, "newline") == 0)
printf ("\n");
else if (text != NULL)
@@ -3404,9 +3601,12 @@ get_responses_and_close ()
{
time_t now;
- (void) time (&now);
- if (now == last_register_time)
+ for (;;)
+ {
+ (void) time (&now);
+ if (now != last_register_time) break;
sleep (1); /* to avoid time-stamp races */
+ }
}
return errs;
@@ -3424,7 +3624,7 @@ supported_request (name)
for (rq = requests; rq->name; rq++)
if (!strcmp (rq->name, name))
- return rq->status == rq_supported;
+ return (rq->flags & RQ_SUPPORTED) != 0;
error (1, 0, "internal error: testing support for unknown option?");
/* NOTREACHED */
return 0;
@@ -3490,7 +3690,6 @@ recv_line (sock, resultp)
int sock;
char **resultp;
{
- int c;
char *result;
size_t input_index = 0;
size_t result_size = 80;
@@ -3500,23 +3699,16 @@ recv_line (sock, resultp)
while (1)
{
char ch;
- if (recv (sock, &ch, 1, 0) < 0)
+ int n;
+ n = recv (sock, &ch, 1, 0);
+ if (n <= 0)
error (1, 0, "recv() from server %s: %s", CVSroot_hostname,
- SOCK_STRERROR (SOCK_ERRNO));
- c = ch;
+ n == 0 ? "EOF" : SOCK_STRERROR (SOCK_ERRNO));
- if (c == EOF)
- {
- free (result);
-
- /* It's end of file. */
- error (1, 0, "end of file from server");
- }
-
- if (c == '\012')
+ if (ch == '\012')
break;
- result[input_index++] = c;
+ result[input_index++] = ch;
while (input_index + 1 >= result_size)
{
result_size *= 2;
@@ -3535,6 +3727,28 @@ recv_line (sock, resultp)
return input_index;
}
+/* Connect to a forked server process. */
+
+void
+connect_to_forked_server (tofdp, fromfdp)
+ int *tofdp, *fromfdp;
+{
+ /* This is pretty simple. All we need to do is choose the correct
+ cvs binary and call piped_child. */
+
+ char *command[3];
+
+ command[0] = getenv ("CVS_SERVER");
+ if (! command[0])
+ command[0] = "cvs";
+
+ command[1] = "server";
+ command[2] = NULL;
+
+ if (! piped_child (command, tofdp, fromfdp))
+ error (1, 0, "could not fork server process");
+}
+
/* Connect to the authenticating server.
If VERIFY_ONLY is non-zero, then just verify that the password is
@@ -3960,6 +4174,13 @@ start_server ()
int tofd, fromfd;
char *log = getenv ("CVS_CLIENT_LOG");
+
+ /* Clear our static variables for this invocation. */
+ if (toplevel_repos != NULL)
+ free (toplevel_repos);
+ toplevel_repos = NULL;
+
+
/* Note that generally speaking we do *not* fall back to a different
way of connecting if the first one does not work. This is slow
(*really* slow on a 14.4kbps link); the clean way to have a CVS
@@ -4020,6 +4241,10 @@ the :server: access method is not supported by this port of CVS");
#endif
break;
+ case fork_method:
+ connect_to_forked_server (&tofd, &fromfd);
+ break;
+
default:
error (1, 0, "\
(start_server internal error): unknown access method");
@@ -4119,7 +4344,11 @@ the :server: access method is not supported by this port of CVS");
free (last_update_dir);
last_update_dir = NULL;
stored_checksum_valid = 0;
- stored_mode_valid = 0;
+ if (stored_mode != NULL)
+ {
+ free (stored_mode);
+ stored_mode = NULL;
+ }
if (strcmp (command_name, "init") != 0)
{
@@ -4648,9 +4877,10 @@ send_modified (file, short_pathname, vers)
{
size_t newsize = 0;
- read_and_gzip (fd, short_pathname, (unsigned char **)&buf,
- &bufsize, &newsize,
- file_gzip_level);
+ if (read_and_gzip (fd, short_pathname, (unsigned char **)&buf,
+ &bufsize, &newsize,
+ file_gzip_level))
+ error (1, 0, "aborting due to compression error");
if (close (fd) < 0)
error (0, errno, "warning: can't close %s", short_pathname);
@@ -5050,7 +5280,7 @@ send_file_names (argc, argv, flags)
int i;
int level;
int max_level;
-
+
/* The fact that we do this here as well as start_recursion is a bit
of a performance hit. Perhaps worth cleaning up someday. */
if (flags & SEND_EXPAND_WILD)
@@ -5091,6 +5321,9 @@ send_file_names (argc, argv, flags)
char *p = argv[i];
char *line = NULL;
+ if (arg_should_not_be_sent_to_server (argv[i]))
+ continue;
+
#ifdef FILENAMES_CASE_INSENSITIVE
/* We want to send the file name as it appears
in CVS/Entries. We put this inside an ifdef
@@ -5224,7 +5457,7 @@ client_import_setup (repository)
*/
int
client_process_import_file (message, vfile, vtag, targc, targv, repository,
- all_files_binary)
+ all_files_binary, modtime)
char *message;
char *vfile;
char *vtag;
@@ -5232,6 +5465,9 @@ client_process_import_file (message, vfile, vtag, targc, targv, repository,
char *targv[];
char *repository;
int all_files_binary;
+
+ /* Nonzero for "import -d". */
+ int modtime;
{
char *update_dir;
char *fullname;
@@ -5281,6 +5517,28 @@ client_process_import_file (message, vfile, vtag, targc, targv, repository,
error (0, 0,
"warning: ignoring -k options due to server limitations");
}
+ if (modtime)
+ {
+ if (supported_request ("Checkin-time"))
+ {
+ struct stat sb;
+ char *rcsdate;
+ char netdate[MAXDATELEN];
+
+ if (CVS_STAT (vfile, &sb) < 0)
+ error (1, errno, "cannot stat %s", fullname);
+ rcsdate = date_from_time_t (sb.st_mtime);
+ date_to_internet (netdate, rcsdate);
+ free (rcsdate);
+
+ send_to_server ("Checkin-time ", 0);
+ send_to_server (netdate, 0);
+ send_to_server ("\012", 1);
+ }
+ else
+ error (0, 0,
+ "warning: ignoring -d option due to server limitations");
+ }
send_modified (vfile, fullname, &vers);
if (vers.options != NULL)
free (vers.options);
@@ -5466,27 +5724,15 @@ option_with_arg (option, arg)
We then convert that to the format required in the protocol
(including the "-D" option) and send it. According to
- cvsclient.texi, RFC 822/1123 format is preferred, but for now we
- use the format that we always have, for
- conservatism/laziness/paranoia. As far as I know all servers
- support the RFC 822/1123 format, so probably there would be no
- particular danger in switching. */
+ cvsclient.texi, RFC 822/1123 format is preferred. */
void
client_senddate (date)
const char *date;
{
- int year, month, day, hour, minute, second;
- char buf[100];
-
- if (sscanf (date, SDATEFORM, &year, &month, &day, &hour, &minute, &second)
- != 6)
- {
- error (1, 0, "client_senddate: sscanf failed on date");
- }
+ char buf[MAXDATELEN];
- sprintf (buf, "%d/%d/%d %d:%d:%d GMT", month, day, year,
- hour, minute, second);
+ date_to_internet (buf, (char *)date);
option_with_arg ("-D", buf);
}
diff --git a/contrib/cvs/src/client.h b/contrib/cvs/src/client.h
index 996dc63..c323cf3 100644
--- a/contrib/cvs/src/client.h
+++ b/contrib/cvs/src/client.h
@@ -6,8 +6,6 @@ extern int change_mode PROTO((char *, char *, int));
extern int gzip_level;
extern int file_gzip_level;
-extern int filter_through_gzip PROTO((int, int, int, pid_t *));
-extern int filter_through_gunzip PROTO((int, int, pid_t *));
#if defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT)
@@ -195,7 +193,8 @@ extern char *toplevel_wd;
extern void client_import_setup PROTO((char *repository));
extern int client_process_import_file
PROTO((char *message, char *vfile, char *vtag,
- int targc, char *targv[], char *repository, int all_files_binary));
+ int targc, char *targv[], char *repository, int all_files_binary,
+ int modtime));
extern void client_import_done PROTO((void));
extern void client_notify PROTO((char *, char *, char *, int, char *));
#endif /* CLIENT_SUPPORT */
diff --git a/contrib/cvs/src/create_adm.c b/contrib/cvs/src/create_adm.c
index c51785c..7f8f581 100644
--- a/contrib/cvs/src/create_adm.c
+++ b/contrib/cvs/src/create_adm.c
@@ -36,15 +36,13 @@ Create_Admin (dir, update_dir, repository, tag, date, nonbranch, warn)
char *reposcopy;
char *tmp;
-#ifdef SERVER_SUPPORT
if (trace)
{
- fprintf (stderr, "%c-> Create_Admin (%s, %s, %s, %s, %s, %d, %d)\n",
- (server_active) ? 'S' : ' ',
+ fprintf (stderr, "%s-> Create_Admin (%s, %s, %s, %s, %s, %d, %d)\n",
+ CLIENT_SERVER_STR,
dir, update_dir, repository, tag ? tag : "",
date ? date : "", nonbranch, warn);
}
-#endif
if (noexec)
return 0;
diff --git a/contrib/cvs/src/cvsrc.c b/contrib/cvs/src/cvsrc.c
index e35ec21..accc53f 100644
--- a/contrib/cvs/src/cvsrc.c
+++ b/contrib/cvs/src/cvsrc.c
@@ -65,6 +65,11 @@ read_cvsrc (argc, argv, cmdname)
/* determine filename for ~/.cvsrc */
homedir = get_homedir ();
+ /* If we can't find a home directory, ignore ~/.cvsrc. This may
+ make tracking down problems a bit of a pain, but on the other
+ hand it might be obnoxious to complain when CVS will function
+ just fine without .cvsrc (and many users won't even know what
+ .cvsrc is). */
if (!homedir)
return;
@@ -96,7 +101,7 @@ read_cvsrc (argc, argv, cmdname)
/* stop if we match the current command */
if (!strncmp (line, cmdname, command_len)
- && isspace (*(line + command_len)))
+ && isspace ((unsigned char) *(line + command_len)))
{
found = 1;
break;
diff --git a/contrib/cvs/src/edit.c b/contrib/cvs/src/edit.c
index aa0f4c4..59d363c 100644
--- a/contrib/cvs/src/edit.c
+++ b/contrib/cvs/src/edit.c
@@ -89,8 +89,8 @@ watch_onoff (argc, argv)
if (local)
send_arg ("-l");
- send_file_names (argc, argv, SEND_EXPAND_WILD);
send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
+ send_file_names (argc, argv, SEND_EXPAND_WILD);
send_to_server (turning_on ? "watch-on\012" : "watch-off\012", 0);
return get_responses_and_close ();
}
@@ -722,6 +722,9 @@ notify_proc (repository, filter)
return (pclose (pipefp));
}
+/* FIXME: this function should have a way to report whether there was
+ an error so that server.c can know whether to report Notified back
+ to the client. */
void
notify_do (type, filename, who, val, watches, repository)
int type;
@@ -743,6 +746,11 @@ notify_do (type, filename, who, val, watches, repository)
switch (type)
{
case 'E':
+ if (strpbrk (val, ",>;=\n") != NULL)
+ {
+ error (0, 0, "invalid character in editor value");
+ return;
+ }
editor_set (filename, who, val);
break;
case 'U':
@@ -864,7 +872,14 @@ notify_do (type, filename, who, val, watches, repository)
{
char *cp;
args.notifyee = xstrdup (line + len + 1);
- cp = strchr (args.notifyee, ':');
+
+ /* There may or may not be more
+ colon-separated fields added to this in the
+ future; in any case, we ignore them right
+ now, and if there are none we make sure to
+ chop off the final newline, if any. */
+ cp = strpbrk (args.notifyee, ":\n");
+
if (cp != NULL)
*cp = '\0';
break;
@@ -876,7 +891,8 @@ notify_do (type, filename, who, val, watches, repository)
error (0, errno, "cannot close %s", usersname);
}
free (usersname);
- free (line);
+ if (line != NULL)
+ free (line);
if (args.notifyee == NULL)
{
@@ -1008,29 +1024,29 @@ editors_fileproc (callerdat, finfo)
if (them == NULL)
return 0;
- fputs (finfo->fullname, stdout);
+ cvs_output (finfo->fullname, 0);
p = them;
while (1)
{
- putc ('\t', stdout);
+ cvs_output ("\t", 1);
while (*p != '>' && *p != '\0')
- putc (*p++, stdout);
+ cvs_output (p++, 1);
if (*p == '\0')
{
/* Only happens if attribute is misformed. */
- putc ('\n', stdout);
+ cvs_output ("\n", 1);
break;
}
++p;
- putc ('\t', stdout);
+ cvs_output ("\t", 1);
while (1)
{
while (*p != '+' && *p != ',' && *p != '\0')
- putc (*p++, stdout);
+ cvs_output (p++, 1);
if (*p == '\0')
{
- putc ('\n', stdout);
+ cvs_output ("\n", 1);
goto out;
}
if (*p == ',')
@@ -1039,9 +1055,9 @@ editors_fileproc (callerdat, finfo)
break;
}
++p;
- putc ('\t', stdout);
+ cvs_output ("\t", 1);
}
- putc ('\n', stdout);
+ cvs_output ("\n", 1);
}
out:;
return 0;
@@ -1086,8 +1102,8 @@ editors (argc, argv)
if (local)
send_arg ("-l");
- send_file_names (argc, argv, SEND_EXPAND_WILD);
send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
+ send_file_names (argc, argv, SEND_EXPAND_WILD);
send_to_server ("editors\012", 0);
return get_responses_and_close ();
}
diff --git a/contrib/cvs/src/entries.c b/contrib/cvs/src/entries.c
index aeab313..7e258a9 100644
--- a/contrib/cvs/src/entries.c
+++ b/contrib/cvs/src/entries.c
@@ -157,7 +157,9 @@ write_entries (list)
rename_file (entfilename, CVSADM_ENT);
/* now, remove the log file */
- unlink_file (CVSADM_ENTLOG);
+ if (unlink_file (CVSADM_ENTLOG) < 0
+ && !existence_error (errno))
+ error (0, errno, "cannot remove %s", CVSADM_ENTLOG);
}
/*
@@ -171,12 +173,8 @@ Scratch_Entry (list, fname)
Node *node;
if (trace)
-#ifdef SERVER_SUPPORT
- (void) fprintf (stderr, "%c-> Scratch_Entry(%s)\n",
- (server_active) ? 'S' : ' ', fname);
-#else
- (void) fprintf (stderr, "-> Scratch_Entry(%s)\n", fname);
-#endif
+ (void) fprintf (stderr, "%s-> Scratch_Entry(%s)\n",
+ CLIENT_SERVER_STR, fname);
/* hashlookup to see if it is there */
if ((node = findnode_fn (list, fname)) != NULL)
@@ -231,18 +229,11 @@ Register (list, fname, vn, ts, options, tag, date, ts_conflict)
if (trace)
{
-#ifdef SERVER_SUPPORT
- (void) fprintf (stderr, "%c-> Register(%s, %s, %s%s%s, %s, %s %s)\n",
- (server_active) ? 'S' : ' ',
+ (void) fprintf (stderr, "%s-> Register(%s, %s, %s%s%s, %s, %s %s)\n",
+ CLIENT_SERVER_STR,
fname, vn, ts ? ts : "",
ts_conflict ? "+" : "", ts_conflict ? ts_conflict : "",
options, tag ? tag : "", date ? date : "");
-#else
- (void) fprintf (stderr, "-> Register(%s, %s, %s%s%s, %s, %s %s)\n",
- fname, vn, ts ? ts : "",
- ts_conflict ? "+" : "", ts_conflict ? ts_conflict : "",
- options, tag ? tag : "", date ? date : "");
-#endif
}
entnode = Entnode_Create (ENT_FILE, fname, vn, ts, options, tag, date,
@@ -252,7 +243,15 @@ Register (list, fname, vn, ts, options, tag, date, ts_conflict)
if (!noexec)
{
entfilename = CVSADM_ENTLOG;
- entfile = open_file (entfilename, "a");
+ entfile = CVS_FOPEN (entfilename, "a");
+
+ if (entfile == NULL)
+ {
+ /* Warning, not error, as in write_entries. */
+ /* FIXME-update-dir: should be including update_dir in message. */
+ error (0, errno, "cannot open %s", entfilename);
+ return;
+ }
if (fprintf (entfile, "A ") < 0)
error (1, errno, "cannot write %s", entfilename);
@@ -507,7 +506,9 @@ Entries_Open (aflag, update_dir)
(void) AddEntryNode (entries, ent);
}
- fclose (fpin);
+ if (fclose (fpin) < 0)
+ /* FIXME-update-dir: should include update_dir in message. */
+ error (0, errno, "cannot close %s", CVSADM_ENT);
}
fpin = CVS_FOPEN (CVSADM_ENTLOG, "r");
@@ -535,7 +536,9 @@ Entries_Open (aflag, update_dir)
}
}
do_rewrite = 1;
- fclose (fpin);
+ if (fclose (fpin) < 0)
+ /* FIXME-update-dir: should include update_dir in message. */
+ error (0, errno, "cannot close %s", CVSADM_ENTLOG);
}
/* Update the list private data to indicate whether subdirectory
diff --git a/contrib/cvs/src/error.c b/contrib/cvs/src/error.c
index 9dcc162..64b686c 100644
--- a/contrib/cvs/src/error.c
+++ b/contrib/cvs/src/error.c
@@ -61,8 +61,6 @@ void exit ();
extern char *strerror ();
#endif
-extern int vasprintf ();
-
void
error_exit PROTO ((void))
{
@@ -80,7 +78,10 @@ error_exit PROTO ((void))
}
/* Print the program name and error message MESSAGE, which is a printf-style
- format string with optional args.
+ format string with optional args. This is a very limited printf subset:
+ %s, %d, %c, %x and %% only (without anything between the % and the s,
+ d, &c). Callers who want something fancier can use sprintf.
+
If ERRNUM is nonzero, print its corresponding system error message.
Exit with status EXIT_FAILURE if STATUS is nonzero. If MESSAGE is "",
no need to print a message.
@@ -100,7 +101,7 @@ error_exit PROTO ((void))
/* VARARGS */
void
-#if defined (HAVE_VPRINTF) && defined (__STDC__)
+#if defined (__STDC__)
error (int status, int errnum, const char *message, ...)
#else
error (status, errnum, message, va_alist)
@@ -110,116 +111,84 @@ error (status, errnum, message, va_alist)
va_dcl
#endif
{
- /* Prevent strtoul (via int_vasprintf) from clobbering it. */
int save_errno = errno;
-#ifdef HAVE_VPRINTF
if (message[0] != '\0')
{
va_list args;
- char *mess = NULL;
- char *entire;
- size_t len;
-
- VA_START (args, message);
- vasprintf (&mess, message, args);
- va_end (args);
-
- if (mess == NULL)
+ const char *p;
+ char *q;
+ char *str;
+ int num;
+ unsigned int unum;
+ int ch;
+ unsigned char buf[100];
+
+ cvs_outerr (program_name, 0);
+ if (command_name && *command_name)
{
- entire = NULL;
- status = 1;
+ cvs_outerr (" ", 1);
+ if (status != 0)
+ cvs_outerr ("[", 1);
+ cvs_outerr (command_name, 0);
+ if (status != 0)
+ cvs_outerr (" aborted]", 0);
}
- else
+ cvs_outerr (": ", 2);
+
+ VA_START (args, message);
+ p = message;
+ while ((q = strchr (p, '%')) != NULL)
{
- len = strlen (mess) + strlen (program_name) + 80;
- if (command_name != NULL)
- len += strlen (command_name);
- if (errnum != 0)
- len += strlen (strerror (errnum));
- entire = malloc (len);
- if (entire == NULL)
- {
- free (mess);
- status = 1;
- }
- else
+ static const char msg[] =
+ "\ninternal error: bad % in error()\n";
+ if (q - p > 0)
+ cvs_outerr (p, q - p);
+
+ switch (q[1])
{
- strcpy (entire, program_name);
- if (command_name != NULL && command_name[0] != '\0')
- {
- strcat (entire, " ");
- if (status != 0)
- strcat (entire, "[");
- strcat (entire, command_name);
- if (status != 0)
- strcat (entire, " aborted]");
- }
- strcat (entire, ": ");
- strcat (entire, mess);
- if (errnum != 0)
- {
- strcat (entire, ": ");
- strcat (entire, strerror (errnum));
- }
- strcat (entire, "\n");
- free (mess);
+ case 's':
+ str = va_arg (args, char *);
+ cvs_outerr (str, strlen (str));
+ break;
+ case 'd':
+ num = va_arg (args, int);
+ sprintf (buf, "%d", num);
+ cvs_outerr (buf, strlen (buf));
+ break;
+ case 'x':
+ unum = va_arg (args, unsigned int);
+ sprintf (buf, "%x", unum);
+ cvs_outerr (buf, strlen (buf));
+ break;
+ case 'c':
+ ch = va_arg (args, int);
+ buf[0] = ch;
+ cvs_outerr (buf, 1);
+ break;
+ case '%':
+ cvs_outerr ("%", 1);
+ break;
+ default:
+ cvs_outerr (msg, sizeof (msg) - 1);
+ /* Don't just keep going, because q + 1 might point to the
+ terminating '\0'. */
+ goto out;
}
+ p = q + 2;
}
- cvs_outerr (entire ? entire : "out of memory\n", 0);
- if (entire != NULL)
- free (entire);
- }
-
-#else /* No HAVE_VPRINTF */
- /* I think that all relevant systems have vprintf these days. But
- just in case, I'm leaving this code here. */
-
- if (message[0] != '\0')
- {
- FILE *out = stderr;
+ cvs_outerr (p, strlen (p));
+ out:
+ va_end (args);
- if (error_use_protocol)
+ if (errnum != 0)
{
- out = stdout;
- printf ("E ");
+ cvs_outerr (": ", 2);
+ cvs_outerr (strerror (errnum), 0);
}
-
- if (command_name && *command_name)
- {
- if (status)
- fprintf (out, "%s [%s aborted]: ", program_name, command_name);
- else
- fprintf (out, "%s %s: ", program_name, command_name);
- }
- else
- fprintf (out, "%s: ", program_name);
-
-#ifdef HAVE_VPRINTF
- VA_START (args, message);
- vfprintf (out, message, args);
- va_end (args);
-#else
-#ifdef HAVE_DOPRNT
- _doprnt (message, &args, out);
-#else
- fprintf (out, message, a1, a2, a3, a4, a5, a6, a7, a8);
-#endif
-#endif
- if (errnum)
- fprintf (out, ": %s", strerror (errnum));
- putc ('\n', out);
-
- /* In the error_use_protocol case, this probably does
- something useful. In most other cases, I suspect it is a
- noop (either stderr is line buffered or we haven't written
- anything to stderr) or unnecessary (if stderr is not line
- buffered, maybe there is a reason....). */
- fflush (out);
+ cvs_outerr ("\n", 1);
}
-#endif /* No HAVE_VPRINTF */
-
if (status)
error_exit ();
errno = save_errno;
diff --git a/contrib/cvs/src/expand_path.c b/contrib/cvs/src/expand_path.c
index 5cf414e..25e561c 100644
--- a/contrib/cvs/src/expand_path.c
+++ b/contrib/cvs/src/expand_path.c
@@ -43,7 +43,7 @@ variable_set (nameval)
Node *node;
p = nameval;
- while (isalnum (*p) || *p == '_')
+ while (isalnum ((unsigned char) *p) || *p == '_')
++p;
if (*p != '=')
error (1, 0, "illegal character in user variable name in %s", nameval);
@@ -133,7 +133,7 @@ expand_path (name, file, line)
{
if (flag
? *s =='}'
- : isalnum (*s) == 0 && *s != '_')
+ : isalnum ((unsigned char) *s) == 0 && *s != '_')
break;
doff = d - mybuf;
expand_string (&mybuf, &mybuf_size, doff + 1);
@@ -214,6 +214,9 @@ expand_path (name, file, line)
t = ps->pw_dir;
#endif
}
+ if (t == NULL)
+ error (1, 0, "cannot find home directory");
+
doff = d - buf;
expand_string (&buf, &buf_size, doff + 1);
d = buf + doff;
@@ -283,7 +286,7 @@ expand_variable (name, file, line)
return Editor;
else if (strcmp (name, "USER") == 0)
return getcaller ();
- else if (isalpha (name[0]))
+ else if (isalpha ((unsigned char) name[0]))
{
/* These names are reserved for future versions of CVS,
so that is why it is an error. */
diff --git a/contrib/cvs/src/fileattr.h b/contrib/cvs/src/fileattr.h
index 7e02b3a..046b975 100644
--- a/contrib/cvs/src/fileattr.h
+++ b/contrib/cvs/src/fileattr.h
@@ -12,28 +12,24 @@
#ifndef FILEATTR_H
-/* File containing per-file attributes. Format is a series of entries:
+/* File containing per-file attributes. The format of this file is in
+ cvs.texinfo but here is a quick summary. The file contains a
+ series of entries:
ENT-TYPE FILENAME <tab> ATTRNAME = ATTRVAL
{; ATTRNAME = ATTRVAL} <linefeed>
- ENT-TYPE is 'F' for a file, in which case the entry specifies the
- attributes for that file.
+ ENT-TYPE is 'F' for a file.
- ENT-TYPE is 'D', and FILENAME empty, to specify default attributes
- to be used for newly added files.
+ ENT-TYPE is 'D', and FILENAME empty, for default attributes.
- Other ENT-TYPE are reserved for future expansion. CVS 1.9 and older
- will delete them any time it writes file attributes. Current versions
- of CVS will preserve them.
+ Other ENT-TYPE are reserved for future expansion.
Note that the order of the line is not significant; CVS is free to
rearrange them at its convenience.
- There is currently no way of quoting tabs or linefeeds in the
- filename, '=' in ATTRNAME, ';' in ATTRVAL, etc. I'm not sure
- whether I think we need one. Note: the current implementation also
- doesn't handle '\0' in any of the fields.
+ FIXME: this implementation doesn't handle '\0' in any of the
+ fields. We are encouraged to fix this (by cvs.texinfo).
By convention, ATTRNAME starting with '_' is for an attribute given
special meaning by CVS; other ATTRNAMEs are for user-defined attributes
diff --git a/contrib/cvs/src/find_names.c b/contrib/cvs/src/find_names.c
index 4fa795a..6fb927b 100644
--- a/contrib/cvs/src/find_names.c
+++ b/contrib/cvs/src/find_names.c
@@ -50,6 +50,11 @@ add_entries_proc (node, closure)
return (0);
}
+/* Find files in the repository and/or working directory. On error,
+ may either print a nonfatal error and return NULL, or just give
+ a fatal error. On success, return non-NULL (even if it is an empty
+ list). */
+
List *
Find_Names (repository, which, aflag, optentries)
char *repository;
@@ -85,7 +90,10 @@ Find_Names (repository, which, aflag, optentries)
{
/* search the repository */
if (find_rcs (repository, files) != 0)
- error (1, errno, "cannot open directory %s", repository);
+ {
+ error (0, errno, "cannot open directory %s", repository);
+ goto error_exit;
+ }
/* search the attic too */
if (which & W_ATTIC)
@@ -93,7 +101,11 @@ Find_Names (repository, which, aflag, optentries)
char *dir;
dir = xmalloc (strlen (repository) + sizeof (CVSATTIC) + 10);
(void) sprintf (dir, "%s/%s", repository, CVSATTIC);
- (void) find_rcs (dir, files);
+ if (find_rcs (dir, files) != 0
+ && !existence_error (errno))
+ /* For now keep this a fatal error, seems less useful
+ for access control than the case above. */
+ error (1, errno, "cannot open directory %s", dir);
free (dir);
}
}
@@ -101,6 +113,9 @@ Find_Names (repository, which, aflag, optentries)
/* sort the list into alphabetical order and return it */
sortlist (files, fsortcmp);
return (files);
+ error_exit:
+ dellist (&files);
+ return NULL;
}
/*
@@ -235,7 +250,9 @@ Find_Directories (repository, which, entries)
/*
* Finds all the ,v files in the argument directory, and adds them to the
* files list. Returns 0 for success and non-zero if the argument directory
- * cannot be opened.
+ * cannot be opened, in which case errno is set to indicate the error.
+ * In the error case LIST is left in some reasonable state (unchanged, or
+ * containing the files which were found before the error occurred).
*/
static int
find_rcs (dir, list)
@@ -251,6 +268,7 @@ find_rcs (dir, list)
return (1);
/* read the dir, grabbing the ,v files */
+ errno = 0;
while ((dp = readdir (dirp)) != NULL)
{
if (CVS_FNMATCH (RCSPAT, dp->d_name, 0) == 0)
@@ -265,6 +283,14 @@ find_rcs (dir, list)
if (addnode (list, p) != 0)
freenode (p);
}
+ errno = 0;
+ }
+ if (errno != 0)
+ {
+ int save_errno = errno;
+ (void) closedir (dirp);
+ errno = save_errno;
+ return 1;
}
(void) closedir (dirp);
return (0);
@@ -275,7 +301,7 @@ find_rcs (dir, list)
* the specified list. Sub-directories without a CVS administration
* directory are optionally ignored. If ENTRIES is not NULL, all
* files on the list are ignored. Returns 0 for success or 1 on
- * error.
+ * error, in which case errno is set to indicate the error.
*/
static int
find_dirs (dir, list, checkadm, entries)
@@ -305,6 +331,7 @@ find_dirs (dir, list, checkadm, entries)
return (1);
/* read the dir, grabbing sub-dirs */
+ errno = 0;
while ((dp = readdir (dirp)) != NULL)
{
if (strcmp (dp->d_name, ".") == 0 ||
@@ -312,34 +339,34 @@ find_dirs (dir, list, checkadm, entries)
strcmp (dp->d_name, CVSATTIC) == 0 ||
strcmp (dp->d_name, CVSLCK) == 0 ||
strcmp (dp->d_name, CVSREP) == 0)
- continue;
+ goto do_it_again;
/* findnode() is going to be significantly faster than stat()
because it involves no system calls. That is why we bother
with the entries argument, and why we check this first. */
if (entries != NULL && findnode (entries, dp->d_name) != NULL)
- continue;
+ goto do_it_again;
if (skip_emptydir
&& strcmp (dp->d_name, CVSNULLREPOS) == 0)
- continue;
+ goto do_it_again;
#ifdef DT_DIR
if (dp->d_type != DT_DIR)
{
if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_LNK)
- continue;
+ goto do_it_again;
#endif
/* don't bother stating ,v files */
if (CVS_FNMATCH (RCSPAT, dp->d_name, 0) == 0)
- continue;
+ goto do_it_again;
expand_string (&tmp,
&tmp_size,
strlen (dir) + strlen (dp->d_name) + 10);
sprintf (tmp, "%s/%s", dir, dp->d_name);
if (!isdir (tmp))
- continue;
+ goto do_it_again;
#ifdef DT_DIR
}
@@ -354,12 +381,12 @@ find_dirs (dir, list, checkadm, entries)
{
/* we're either unknown or a symlink at this point */
if (dp->d_type == DT_LNK)
- continue;
+ goto do_it_again;
#endif
/* Note that we only get here if we already set tmp
above. */
if (islink (tmp))
- continue;
+ goto do_it_again;
#ifdef DT_DIR
}
#endif
@@ -371,7 +398,7 @@ find_dirs (dir, list, checkadm, entries)
+ sizeof (CVSADM) + 10));
(void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, CVSADM);
if (!isdir (tmp))
- continue;
+ goto do_it_again;
}
/* put it in the list */
@@ -380,6 +407,16 @@ find_dirs (dir, list, checkadm, entries)
p->key = xstrdup (dp->d_name);
if (addnode (list, p) != 0)
freenode (p);
+
+ do_it_again:
+ errno = 0;
+ }
+ if (errno != 0)
+ {
+ int save_errno = errno;
+ (void) closedir (dirp);
+ errno = save_errno;
+ return 1;
}
(void) closedir (dirp);
if (tmp != NULL)
diff --git a/contrib/cvs/src/hardlink.c b/contrib/cvs/src/hardlink.c
index b279aa9..046cf3a 100644
--- a/contrib/cvs/src/hardlink.c
+++ b/contrib/cvs/src/hardlink.c
@@ -66,7 +66,7 @@ lookup_file_by_inode (filepath)
inodestr = (char *) xmalloc (2*sizeof(ino_t)*sizeof(char) + 1);
if (stat (file, &sb) < 0)
{
- if (errno == ENOENT)
+ if (existence_error (errno))
{
/* The file doesn't exist; we may be doing an update on a
file that's been removed. A nonexistent file has no
diff --git a/contrib/cvs/src/history.c b/contrib/cvs/src/history.c
index 8f1e254..bc7d1a6 100644
--- a/contrib/cvs/src/history.c
+++ b/contrib/cvs/src/history.c
@@ -719,12 +719,8 @@ history_write (type, update_dir, revs, name, repository)
}
if (trace)
-#ifdef SERVER_SUPPORT
- fprintf (stderr, "%c-> fopen(%s,a)\n",
- (server_active) ? 'S' : ' ', fname);
-#else
- fprintf (stderr, "-> fopen(%s,a)\n", fname);
-#endif
+ fprintf (stderr, "%s-> fopen(%s,a)\n",
+ CLIENT_SERVER_STR, fname);
if (noexec)
goto out;
fd = CVS_OPEN (fname, O_WRONLY | O_APPEND | O_CREAT | OPEN_BINARY, 0666);
@@ -971,7 +967,7 @@ expand_modules ()
* Return a pointer to the character following the newline.
*/
-#define NEXT_BAR(here) do { while (isspace(*line)) line++; hr->here = line; while ((c = *line++) && c != '|') ; if (!c) return(rtn); *(line - 1) = '\0'; } while (0)
+#define NEXT_BAR(here) do { while (isspace((unsigned char) *line)) line++; hr->here = line; while ((c = *line++) && c != '|') ; if (!c) return(rtn); *(line - 1) = '\0'; } while (0)
static char *
fill_hrec (line, hr)
@@ -985,7 +981,7 @@ fill_hrec (line, hr)
unsigned long date;
memset ((char *) hr, 0, sizeof (*hr));
- while (isspace (*line))
+ while (isspace ((unsigned char) *line))
line++;
if (!(rtn = strchr (line, '\n')))
return ("");
@@ -1062,7 +1058,7 @@ read_hrecs (fname)
*(cp + i) = '\0';
for (cp2 = cp; cp2 - cp < i; cp2++)
{
- if (*cp2 != '\n' && !isprint (*cp2))
+ if (*cp2 != '\n' && !isprint ((unsigned char) *cp2))
*cp2 = ' ';
}
diff --git a/contrib/cvs/src/ignore.c b/contrib/cvs/src/ignore.c
index 5d7ca61..df08017 100644
--- a/contrib/cvs/src/ignore.c
+++ b/contrib/cvs/src/ignore.c
@@ -82,6 +82,11 @@ ign_setup ()
/* Then add entries found in home dir, (if user has one) and file exists */
home_dir = get_homedir ();
+ /* If we can't find a home directory, ignore ~/.cvsignore. This may
+ make tracking down problems a bit of a pain, but on the other
+ hand it might be obnoxious to complain when CVS will function
+ just fine without .cvsignore (and many users won't even know what
+ .cvsignore is). */
if (home_dir)
{
char *file = xmalloc (strlen (home_dir) + sizeof (CVSDOTIGNORE) + 10);
@@ -176,7 +181,7 @@ ign_add (ign, hold)
char save;
/* ignore whitespace before the token */
- if (isspace (*ign))
+ if (isspace ((unsigned char) *ign))
continue;
/*
@@ -184,7 +189,8 @@ ign_add (ign, hold)
* (saving it if necessary). We also catch * as a special case in a
* global ignore file as an optimization
*/
- if ((!*(ign+1) || isspace (*(ign+1))) && (*ign == '!' || *ign == '*'))
+ if ((!*(ign+1) || isspace ((unsigned char) *(ign+1)))
+ && (*ign == '!' || *ign == '*'))
{
if (!hold)
{
@@ -233,7 +239,7 @@ ign_add (ign, hold)
}
/* find the end of this token */
- for (mark = ign; *mark && !isspace (*mark); mark++)
+ for (mark = ign; *mark && !isspace ((unsigned char) *mark); mark++)
/* do nothing */ ;
save = *mark;
@@ -395,11 +401,15 @@ ignore_files (ilist, entries, update_dir, proc)
dirp = CVS_OPENDIR (".");
if (dirp == NULL)
+ {
+ error (0, errno, "cannot open current directory");
return;
+ }
ign_add_file (CVSDOTIGNORE, 1);
wrap_add_file (CVSDOTWRAPPER, 1);
+ errno = 0;
while ((dp = readdir (dirp)) != NULL)
{
file = dp->d_name;
@@ -476,6 +486,9 @@ ignore_files (ilist, entries, update_dir, proc)
}
(*proc) (file, xdir);
+ errno = 0;
}
+ if (errno != 0)
+ error (0, errno, "error reading current directory");
(void) closedir (dirp);
}
diff --git a/contrib/cvs/src/log.c b/contrib/cvs/src/log.c
index 4502e26..398d650 100644
--- a/contrib/cvs/src/log.c
+++ b/contrib/cvs/src/log.c
@@ -7,9 +7,6 @@
*
* Print Log Information
*
- * This line exists solely to test some pcl-cvs/ChangeLog stuff. You
- * can delete it, if indeed it's still here when you read it. -Karl
- *
* Prints the RCS "log" (rlog) information for the specified files. With no
* argument, prints the log information for all the files in the directory
* (recursive by default).
@@ -233,8 +230,8 @@ cvslog (argc, argv)
for (i = 1; i < argc && argv[i][0] == '-'; i++)
send_arg (argv[i]);
- send_file_names (argc - i, argv + i, SEND_EXPAND_WILD);
send_files (argc - i, argv + i, local, 0, SEND_NO_CONTENTS);
+ send_file_names (argc - i, argv + i, SEND_EXPAND_WILD);
send_to_server ("log\012", 0);
err = get_responses_and_close ();
@@ -591,11 +588,11 @@ log_fileproc (callerdat, finfo)
cvs_output ("\n\t", 2);
cp2 = cp;
- while (! isspace (*cp2) && *cp2 != '\0')
+ while (! isspace ((unsigned char) *cp2) && *cp2 != '\0')
++cp2;
cvs_output (cp, cp2 - cp);
cp = cp2;
- while (isspace (*cp) && *cp != '\0')
+ while (isspace ((unsigned char) *cp) && *cp != '\0')
++cp;
}
}
@@ -734,7 +731,7 @@ log_expand_revlist (rcs, revlist, default_branch)
char *branch;
/* Print just the head of the branch. */
- if (isdigit (r->first[0]))
+ if (isdigit ((unsigned char) r->first[0]))
nr->first = RCS_getbranch (rcs, r->first, 1);
else
{
@@ -761,7 +758,7 @@ log_expand_revlist (rcs, revlist, default_branch)
}
else
{
- if (r->first == NULL || isdigit (r->first[0]))
+ if (r->first == NULL || isdigit ((unsigned char) r->first[0]))
nr->first = xstrdup (r->first);
else
{
@@ -780,7 +777,7 @@ log_expand_revlist (rcs, revlist, default_branch)
if (r->last == r->first)
nr->last = xstrdup (nr->first);
- else if (r->last == NULL || isdigit (r->last[0]))
+ else if (r->last == NULL || isdigit ((unsigned char) r->last[0]))
nr->last = xstrdup (r->last);
else
{
@@ -1356,12 +1353,12 @@ version_compare (v1, v2, len)
while (*v1 == '0')
++v1;
- for (d1 = 0; isdigit (v1[d1]); ++d1)
+ for (d1 = 0; isdigit ((unsigned char) v1[d1]); ++d1)
;
while (*v2 == '0')
++v2;
- for (d2 = 0; isdigit (v2[d2]); ++d2)
+ for (d2 = 0; isdigit ((unsigned char) v2[d2]); ++d2)
;
if (d1 != d2)
diff --git a/contrib/cvs/src/modules.c b/contrib/cvs/src/modules.c
index de95f7e..9907cc8 100644
--- a/contrib/cvs/src/modules.c
+++ b/contrib/cvs/src/modules.c
@@ -20,6 +20,7 @@
* command line.
*/
+#include <assert.h>
#include "cvs.h"
#include "savecwd.h"
@@ -120,7 +121,8 @@ do_module (db, mname, m_type, msg, callback_proc, where,
int xmodargc;
char **modargv;
char **xmodargv;
- char *value;
+ /* Found entry from modules file, including options and such. */
+ char *value = NULL;
char *zvalue = NULL;
char *mwhere = NULL;
char *mfile = NULL;
@@ -147,8 +149,8 @@ do_module (db, mname, m_type, msg, callback_proc, where,
+ strlen (msg)
+ (where ? strlen (where) : 0)
+ (extra_arg ? strlen (extra_arg) : 0));
- sprintf (buf, "%c-> do_module (%s, %s, %s, %s)\n",
- (server_active) ? 'S' : ' ',
+ sprintf (buf, "%s-> do_module (%s, %s, %s, %s)\n",
+ CLIENT_SERVER_STR,
mname, msg, where ? where : "",
extra_arg ? extra_arg : "");
cvs_outerr (buf, 0);
@@ -192,13 +194,13 @@ do_module (db, mname, m_type, msg, callback_proc, where,
{
do
*cp-- = '\0';
- while (isspace (*cp));
+ while (isspace ((unsigned char) *cp));
}
else
{
/* Always strip trailing spaces */
cp = strchr (val.dptr, '\0');
- while (cp > val.dptr && isspace(*--cp))
+ while (cp > val.dptr && isspace ((unsigned char) *--cp))
*cp = '\0';
}
@@ -231,7 +233,9 @@ do_module (db, mname, m_type, msg, callback_proc, where,
if (isdir (file))
{
- value = mname;
+ modargv = xmalloc (sizeof (*modargv));
+ modargv[0] = xstrdup (mname);
+ modargc = 1;
is_found = 1;
}
else
@@ -242,14 +246,12 @@ do_module (db, mname, m_type, msg, callback_proc, where,
/* if mname was a file, we have to split it into "dir file" */
if ((cp = strrchr (mname, '/')) != NULL && cp != mname)
{
- char *slashp;
-
- /* put the ' ' in a copy so we don't mess up the
- original */
- xvalue = xmalloc (strlen (mname) + 2);
- value = strcpy (xvalue, mname);
- slashp = strrchr (value, '/');
- *slashp = ' ';
+ modargv = xmalloc (2 * sizeof (*modargv));
+ modargv[0] = xmalloc (strlen (mname) + 2);
+ strncpy (modargv[0], mname, cp - mname);
+ modargv[0][cp - mname] = '\0';
+ modargv[1] = xstrdup (cp + 1);
+ modargc = 2;
}
else
{
@@ -261,31 +263,54 @@ do_module (db, mname, m_type, msg, callback_proc, where,
if (cp == mname)
{
/* drop the leading / if specified */
- xvalue = xmalloc (strlen (mname) + 10);
- value = strcpy (xvalue, ". ");
- (void) strcat (xvalue, mname + 1);
+ modargv = xmalloc (2 * sizeof (*modargv));
+ modargv[0] = xstrdup (".");
+ modargv[1] = xstrdup (mname + 1);
+ modargc = 2;
}
else
{
/* otherwise just copy it */
- xvalue = xmalloc (strlen (mname) + 10);
- value = strcpy (xvalue, ". ");
- (void) strcat (xvalue, mname);
+ modargv = xmalloc (2 * sizeof (*modargv));
+ modargv[0] = xstrdup (".");
+ modargv[1] = xstrdup (mname);
+ modargc = 2;
}
}
is_found = 1;
}
- else
- {
- /* This initialization suppresses a warning from gcc -Wall. */
- value = NULL;
- }
}
free (attic_file);
free (file);
if (is_found)
- goto found;
+ {
+ assert (value == NULL);
+
+ /* OK, we have now set up modargv with the actual
+ file/directory we want to work on. We duplicate a
+ small amount of code here because the vast majority of
+ the code after the "found" label does not pertain to
+ the case where we found a file/directory rather than
+ finding an entry in the modules file. */
+ if (save_cwd (&cwd))
+ error_exit ();
+ cwd_saved = 1;
+
+ err += callback_proc (&modargc, modargv, where, mwhere, mfile,
+ shorten,
+ local_specified, mname, msg);
+
+ free_names (&modargc, modargv);
+
+ /* cd back to where we started. */
+ if (restore_cwd (&cwd, NULL))
+ error_exit ();
+ free_cwd (&cwd);
+ cwd_saved = 0;
+
+ goto do_module_return;
+ }
}
/* look up everything to the first / as a module */
@@ -315,7 +340,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
{
do
*cp2-- = '\0';
- while (isspace (*cp2));
+ while (isspace ((unsigned char) *cp2));
}
value = val.dptr;
@@ -352,6 +377,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
/* copy value to our own string since if we go recursive we'll be
really screwed if we do another dbm lookup */
+ assert (value != NULL);
zvalue = xstrdup (value);
value = zvalue;
@@ -362,7 +388,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
spec_opt = cp + 1; /* save the options for later */
if (cp != value) /* strip whitespace if necessary */
- while (isspace (*--cp))
+ while (isspace ((unsigned char) *--cp))
*cp = '\0';
if (cp == value)
@@ -609,13 +635,13 @@ module `%s' is a request for a file in a module which is not a directory",
/* strip whitespace off the end */
do
*cp = '\0';
- while (isspace (*--cp));
+ while (isspace ((unsigned char) *--cp));
}
else
next_opt = NULL;
/* strip whitespace from front */
- while (isspace (*spec_opt))
+ while (isspace ((unsigned char) *spec_opt))
spec_opt++;
if (*spec_opt == '\0')
@@ -836,15 +862,15 @@ save_d (k, ks, d, ds)
cp = d;
*(cp + ds) = '\0'; /* Assumes an extra byte at end of static dbm buffer */
- while (isspace (*cp))
+ while (isspace ((unsigned char) *cp))
cp++;
/* Turn <spaces> into one ' ' -- makes the rest of this routine simpler */
while (*cp)
{
- if (isspace (*cp))
+ if (isspace ((unsigned char) *cp))
{
*cp2++ = ' ';
- while (isspace (*cp))
+ while (isspace ((unsigned char) *cp))
cp++;
}
else
diff --git a/contrib/cvs/src/myndbm.c b/contrib/cvs/src/myndbm.c
index 6b15e77..f674ac1 100644
--- a/contrib/cvs/src/myndbm.c
+++ b/contrib/cvs/src/myndbm.c
@@ -263,7 +263,7 @@ mydbm_load_file (fp, list)
if (value[0] == '#')
continue; /* comment line */
vp = value;
- while (*vp && isspace (*vp))
+ while (*vp && isspace ((unsigned char) *vp))
vp++;
if (*vp == '\0')
continue; /* empty line */
@@ -277,12 +277,12 @@ mydbm_load_file (fp, list)
char *kp;
kp = vp;
- while (*vp && !isspace (*vp))
+ while (*vp && !isspace ((unsigned char) *vp))
vp++;
*vp++ = '\0'; /* NULL terminate the key */
p->type = NDBMNODE;
p->key = xstrdup (kp);
- while (*vp && isspace (*vp))
+ while (*vp && isspace ((unsigned char) *vp))
vp++; /* skip whitespace to value */
if (*vp == '\0')
{
diff --git a/contrib/cvs/src/no_diff.c b/contrib/cvs/src/no_diff.c
index 078343e..dfca372 100644
--- a/contrib/cvs/src/no_diff.c
+++ b/contrib/cvs/src/no_diff.c
@@ -82,13 +82,8 @@ No_Difference (finfo, vers)
/* Need to call unlink myself because the noexec variable
* has been set to 1. */
if (trace)
- (void) fprintf (stderr, "%c-> unlink (%s)\n",
-#ifdef SERVER_SUPPORT
- (server_active) ? 'S' : ' ',
-#else
- ' ',
-#endif
- tocvsPath);
+ (void) fprintf (stderr, "%s-> unlink (%s)\n",
+ CLIENT_SERVER_STR, tocvsPath);
if ( CVS_UNLINK (tocvsPath) < 0)
error (0, errno, "could not remove %s", tocvsPath);
}
diff --git a/contrib/cvs/src/options.h.in b/contrib/cvs/src/options.h.in
index 67e8c40..a3ee047 100644
--- a/contrib/cvs/src/options.h.in
+++ b/contrib/cvs/src/options.h.in
@@ -88,13 +88,12 @@
* repository, change the contents of CVS/Root files in your
* checked-out code, and CVS will work without problems.
*
- * This is likely to be the default in the future, but we want to give
- * people who may be relying on absolute pathnames time to update
- * their scripts/software.
+ * Therefore, RELATIVE_REPOS is now the default. In the future, this
+ * is likely to disappear entirely as a compile-time (or other) option,
+ * so if you have other software which relies on absolute pathnames,
+ * update them.
*/
-#ifndef RELATIVE_REPOS
-/* #define RELATIVE_REPOS */
-#endif
+#define RELATIVE_REPOS 1
/*
* When committing or importing files, you must enter a log message.
diff --git a/contrib/cvs/src/parseinfo.c b/contrib/cvs/src/parseinfo.c
index 9847ab9..1c1ab70 100644
--- a/contrib/cvs/src/parseinfo.c
+++ b/contrib/cvs/src/parseinfo.c
@@ -77,7 +77,7 @@ Parse_Info (infofile, repository, callproc, all)
continue;
/* skip whitespace at beginning of line */
- for (cp = line; *cp && isspace (*cp); cp++)
+ for (cp = line; *cp && isspace ((unsigned char) *cp); cp++)
;
/* if *cp is null, the whole line was blank */
@@ -85,13 +85,13 @@ Parse_Info (infofile, repository, callproc, all)
continue;
/* the regular expression is everything up to the first space */
- for (exp = cp; *cp && !isspace (*cp); cp++)
+ for (exp = cp; *cp && !isspace ((unsigned char) *cp); cp++)
;
if (*cp != '\0')
*cp++ = '\0';
/* skip whitespace up to the start of the matching value */
- while (*cp && isspace (*cp))
+ while (*cp && isspace ((unsigned char) *cp))
cp++;
/* no value to match with the regular expression is an error */
@@ -358,6 +358,15 @@ warning: this CVS does not support PreservePermissions");
goto error_return;
}
}
+ else if (strcmp (line, "LockDir") == 0)
+ {
+ if (lock_dir != NULL)
+ free (lock_dir);
+ lock_dir = xstrdup (p);
+ /* Could try some validity checking, like whether we can
+ opendir it or something, but I don't see any particular
+ reason to do that now rather than waiting until lock.c. */
+ }
else
{
/* We may be dealing with a keyword which was added in a
diff --git a/contrib/cvs/src/patch.c b/contrib/cvs/src/patch.c
index 9f56b62..f16a331 100644
--- a/contrib/cvs/src/patch.c
+++ b/contrib/cvs/src/patch.c
@@ -763,19 +763,29 @@ patch_dirproc (callerdat, dir, repos, update_dir, entries)
static RETSIGTYPE
patch_cleanup ()
{
+ /* Note that the checks for existence_error are because we are
+ called from a signal handler, without SIG_begincrsect, so
+ we don't know whether the files got created. */
+
if (tmpfile1 != NULL)
{
- (void) unlink_file (tmpfile1);
+ if (unlink_file (tmpfile1) < 0
+ && !existence_error (errno))
+ error (0, errno, "cannot remove %s", tmpfile1);
free (tmpfile1);
}
if (tmpfile2 != NULL)
{
- (void) unlink_file (tmpfile2);
+ if (unlink_file (tmpfile2) < 0
+ && !existence_error (errno))
+ error (0, errno, "cannot remove %s", tmpfile2);
free (tmpfile2);
}
if (tmpfile3 != NULL)
{
- (void) unlink_file (tmpfile3);
+ if (unlink_file (tmpfile3) < 0
+ && !existence_error (errno))
+ error (0, errno, "cannot remove %s", tmpfile3);
free (tmpfile3);
}
tmpfile1 = tmpfile2 = tmpfile3 = NULL;
diff --git a/contrib/cvs/src/release.c b/contrib/cvs/src/release.c
index 82429e0..ca7945b 100644
--- a/contrib/cvs/src/release.c
+++ b/contrib/cvs/src/release.c
@@ -6,10 +6,9 @@
*/
#include "cvs.h"
+#include "savecwd.h"
#include "getline.h"
-static void release_delete PROTO((char *dir));
-
static const char *const release_usage[] =
{
"Usage: %s %s [-d] directories...\n",
@@ -76,6 +75,7 @@ release (argc, argv)
int arg_start_idx;
int err = 0;
short delete_flag = 0;
+ struct saved_cwd cwd;
#ifdef SERVER_SUPPORT
if (server_active)
@@ -111,6 +111,10 @@ release (argc, argv)
/* We're going to run "cvs -n -q update" and check its output; if
* the output is sufficiently unalarming, then we release with no
* questions asked. Else we prompt, then maybe release.
+ * (Well, actually we ask no matter what. Our notion of "sufficiently
+ * unalarming" doesn't take into account "? foo.c" files, so it is
+ * up to the user to take note of them, at least currently
+ * (ignore-193 in testsuite)).
*/
/* Construct the update command. */
update_cmd = xmalloc (strlen (program_path)
@@ -128,6 +132,12 @@ release (argc, argv)
}
#endif /* CLIENT_SUPPORT */
+ /* Remember the directory where "cvs release" was invoked because
+ all args are relative to this directory and we chdir around.
+ */
+ if (save_cwd (&cwd))
+ error_exit ();
+
arg_start_idx = 0;
for (i = arg_start_idx; i < argc; i++)
@@ -146,6 +156,8 @@ release (argc, argv)
{
if (!really_quiet)
error (0, 0, "no repository directory: %s", thisarg);
+ if (restore_cwd (&cwd, NULL))
+ error_exit ();
continue;
}
}
@@ -190,6 +202,9 @@ release (argc, argv)
if ((pclose (fp)) != 0)
{
error (0, 0, "unable to release `%s'", thisarg);
+ free (repository);
+ if (restore_cwd (&cwd, NULL))
+ error_exit ();
continue;
}
@@ -203,6 +218,8 @@ release (argc, argv)
(void) fprintf (stderr, "** `%s' aborted by user choice.\n",
command_name);
free (repository);
+ if (restore_cwd (&cwd, NULL))
+ error_exit ();
continue;
}
}
@@ -239,7 +256,19 @@ release (argc, argv)
}
free (repository);
- if (delete_flag) release_delete (thisarg);
+
+ if (restore_cwd (&cwd, NULL))
+ error_exit ();
+
+ if (delete_flag)
+ {
+ /* FIXME? Shouldn't this just delete the CVS-controlled
+ files and, perhaps, the files that would normally be
+ ignored and leave everything else? */
+
+ if (unlink_file_dir (thisarg) < 0)
+ error (0, errno, "deletion of directory %s failed", thisarg);
+ }
#ifdef CLIENT_SUPPORT
if (client_active)
@@ -247,6 +276,10 @@ release (argc, argv)
#endif /* CLIENT_SUPPORT */
}
+ if (restore_cwd (&cwd, NULL))
+ error_exit ();
+ free_cwd (&cwd);
+
#ifdef CLIENT_SUPPORT
if (client_active)
{
@@ -264,37 +297,3 @@ release (argc, argv)
free (line);
return err;
}
-
-
-/* We want to "rm -r" the working directory, but let us be a little
- paranoid. */
-static void
-release_delete (dir)
- char *dir;
-{
- struct stat st;
- ino_t ino;
-
- (void) CVS_STAT (".", &st);
- ino = st.st_ino;
- (void) CVS_CHDIR ("..");
- (void) CVS_STAT (dir, &st);
- if (ino != st.st_ino)
- {
- /* This test does not work on cygwin32, because under cygwin32
- the st_ino field is not the same when you refer to a file
- by a different name. This is a cygwin32 bug, but then I
- don't see what the point of this test is anyhow. */
-#ifndef __CYGWIN32__
- error (0, 0,
- "Parent dir on a different disk, delete of %s aborted", dir);
- return;
-#endif
- }
- /*
- * XXX - shouldn't this just delete the CVS-controlled files and, perhaps,
- * the files that would normally be ignored and leave everything else?
- */
- if (unlink_file_dir (dir) < 0)
- error (0, errno, "deletion of directory %s failed", dir);
-}
diff --git a/contrib/cvs/src/remove.c b/contrib/cvs/src/remove.c
index 9ed32d7..2dacdf1 100644
--- a/contrib/cvs/src/remove.c
+++ b/contrib/cvs/src/remove.c
@@ -100,9 +100,9 @@ cvsremove (argc, argv)
ign_setup ();
if (local)
send_arg("-l");
- send_file_names (argc, argv, 0);
/* FIXME: Can't we set SEND_NO_CONTENTS here? Needs investigation. */
send_files (argc, argv, local, 0, 0);
+ send_file_names (argc, argv, 0);
send_to_server ("remove\012", 0);
return get_responses_and_close ();
}
@@ -200,7 +200,9 @@ remove_fileproc (callerdat, finfo)
+ sizeof (CVSEXT_LOG)
+ 10);
(void) sprintf (fname, "%s/%s%s", CVSADM, finfo->file, CVSEXT_LOG);
- (void) unlink_file (fname);
+ if (unlink_file (fname) < 0
+ && !existence_error (errno))
+ error (0, errno, "cannot remove %s", CVSEXT_LOG);
if (!quiet)
error (0, 0, "removed `%s'", finfo->fullname);
@@ -216,7 +218,7 @@ remove_fileproc (callerdat, finfo)
error (0, 0, "file `%s' already scheduled for removal",
finfo->fullname);
}
- else if (vers->tag != NULL && isdigit (*vers->tag))
+ else if (vers->tag != NULL && isdigit ((unsigned char) *vers->tag))
{
/* Commit will just give an error, and so there seems to be
little reason to allow the remove. I mean, conflicts that
diff --git a/contrib/cvs/src/root.c b/contrib/cvs/src/root.c
index 050e168..d88c6f4 100644
--- a/contrib/cvs/src/root.c
+++ b/contrib/cvs/src/root.c
@@ -7,8 +7,6 @@
* Name of Root
*
* Determine the path to the CVSROOT and set "Root" accordingly.
- * If this looks like of modified clone of Name_Repository() in
- * repos.c, it is...
*/
#include "cvs.h"
@@ -18,7 +16,7 @@
Watch out if the enum is changed in cvs.h! */
char *method_names[] = {
- "local", "server (rsh)", "pserver", "kserver", "gserver", "ext"
+ "local", "server (rsh)", "pserver", "kserver", "gserver", "ext", "fork"
};
#ifndef DEBUG
@@ -268,6 +266,11 @@ error 0 Server configuration missing --allow-root in inetd.conf\n");
return 0;
}
+/* This global variable holds the global -d option. It is NULL if -d
+ was not used, which means that we must get the CVSroot information
+ from the CVSROOT environment variable or from a CVS/Root file. */
+
+char *CVSroot_cmdline;
/* Parse a CVSROOT variable into its constituent parts -- method,
* username, hostname, directory. The prototypical CVSROOT variable
@@ -287,30 +290,6 @@ char *CVSroot_username; /* the username or NULL if method == local */
char *CVSroot_hostname; /* the hostname or NULL if method == local */
char *CVSroot_directory; /* the directory name */
-#ifdef AUTH_SERVER_SUPPORT
-/* Die if CVSroot_directory and Pserver_Repos don't match. */
-static void
-check_root_consistent ()
-{
- /* FIXME: Should be using a deferred error, as the rest of
- serve_root does. As it is now the call to error could conceivably
- cause deadlock, as noted in server_cleanup. Best solution would
- presumably be to write some code so that error() automatically
- defers the error in those cases where that is needed. */
- /* FIXME? Possible that the wording should be more clear (e.g.
- Root says "%s" but pserver protocol says "%s"
- or something which would aid people who are writing implementations
- of the client side of the CVS protocol. I don't see any security
- problem with revealing that information. */
- if ((Pserver_Repos != NULL) && (CVSroot_directory != NULL))
- if (strcmp (Pserver_Repos, CVSroot_directory) != 0)
- error (1, 0, "repository mismatch: \"%s\" vs \"%s\"",
- Pserver_Repos, CVSroot_directory);
-}
-
-#endif /* AUTH_SERVER_SUPPORT */
-
-
int
parse_cvsroot (CVSroot)
char *CVSroot;
@@ -335,8 +314,9 @@ parse_cvsroot (CVSroot)
/* Access method specified, as in
* "cvs -d :pserver:user@host:/path",
- * "cvs -d :local:e:\path", or
- * "cvs -d :kserver:user@host:/path".
+ * "cvs -d :local:e:\path",
+ * "cvs -d :kserver:user@host:/path", or
+ * "cvs -d :fork:/path".
* We need to get past that part of CVSroot before parsing the
* rest of it.
*/
@@ -363,6 +343,8 @@ parse_cvsroot (CVSroot)
CVSroot_method = server_method;
else if (strcmp (method, "ext") == 0)
CVSroot_method = ext_method;
+ else if (strcmp (method, "fork") == 0)
+ CVSroot_method = fork_method;
else
{
error (0, 0, "unknown method in CVSroot: %s", CVSroot);
@@ -391,7 +373,8 @@ parse_cvsroot (CVSroot)
CVSroot_username = NULL;
CVSroot_hostname = NULL;
- if (CVSroot_method != local_method)
+ if ((CVSroot_method != local_method)
+ && (CVSroot_method != fork_method))
{
/* Check to see if there is a username in the string. */
@@ -416,9 +399,6 @@ parse_cvsroot (CVSroot)
}
CVSroot_directory = cvsroot_copy;
-#ifdef AUTH_SERVER_SUPPORT
- check_root_consistent ();
-#endif /* AUTH_SERVER_SUPPORT */
#if ! defined (CLIENT_SUPPORT) && ! defined (DEBUG)
if (CVSroot_method != local_method)
@@ -442,10 +422,12 @@ parse_cvsroot (CVSroot)
switch (CVSroot_method)
{
case local_method:
+ case fork_method:
if (CVSroot_username || CVSroot_hostname)
{
error (0, 0, "can't specify hostname and username in CVSROOT");
- error (0, 0, "when using local access method");
+ error (0, 0, "when using %s access method",
+ CVSroot_method == local_method ? "local" : "fork");
error (0, 0, "(%s)", CVSroot);
return 1;
}
@@ -464,18 +446,20 @@ parse_cvsroot (CVSroot)
error (0, 0, "but your CVS executable doesn't support it");
error (0, 0, "(%s)", CVSroot);
return 1;
-#endif
+#else
check_hostname = 1;
break;
+#endif
case gserver_method:
#ifndef HAVE_GSSAPI
error (0, 0, "Your CVSROOT is set for a GSSAPI access method");
error (0, 0, "but your CVS executable doesn't support it");
error (0, 0, "(%s)", CVSroot);
return 1;
-#endif
+#else
check_hostname = 1;
break;
+#endif
case server_method:
case ext_method:
case pserver_method:
@@ -504,18 +488,17 @@ parse_cvsroot (CVSroot)
/* Set up the global CVSroot* variables as if we're using the local
- repository DIR. */
+ repository DIR. DIR must point to storage which will last for the
+ rest of the CVS invocation (for example, the caller might malloc it
+ and never free it, or free it just before exiting CVS). */
void
set_local_cvsroot (dir)
char *dir;
{
- CVSroot_original = xstrdup (dir);
+ CVSroot_original = dir;
CVSroot_method = local_method;
CVSroot_directory = CVSroot_original;
-#ifdef AUTH_SERVER_SUPPORT
- check_root_consistent ();
-#endif /* AUTH_SERVER_SUPPORT */
CVSroot_username = NULL;
CVSroot_hostname = NULL;
client_active = 0;
@@ -523,7 +506,11 @@ set_local_cvsroot (dir)
#ifdef DEBUG
-/* This is for testing the parsing function. */
+/* This is for testing the parsing function. Use
+
+ gcc -I. -I.. -I../lib -DDEBUG root.c -o root
+
+ to compile. */
#include <stdio.h>
@@ -531,6 +518,30 @@ char *CVSroot;
char *program_name = "testing";
char *command_name = "parse_cvsroot"; /* XXX is this used??? */
+/* Toy versions of various functions when debugging under unix. Yes,
+ these make various bad assumptions, but they're pretty easy to
+ debug when something goes wrong. */
+
+void
+error_exit PROTO ((void))
+{
+ exit (1);
+}
+
+char *
+xstrdup (str)
+ const char *str;
+{
+ return strdup (str);
+}
+
+int
+isabsolute (dir)
+ const char *dir;
+{
+ return (dir && (*dir == '/'));
+}
+
void
main (argc, argv)
int argc;
@@ -546,7 +557,7 @@ main (argc, argv)
if (parse_cvsroot (argv[1]))
{
- fprintf (stderr, "%s: Parsing failed.", program_name);
+ fprintf (stderr, "%s: Parsing failed.\n", program_name);
exit (1);
}
printf ("CVSroot: %s\n", argv[1]);
diff --git a/contrib/cvs/src/rtag.c b/contrib/cvs/src/rtag.c
index 3207c1b..5fd825f 100644
--- a/contrib/cvs/src/rtag.c
+++ b/contrib/cvs/src/rtag.c
@@ -64,7 +64,7 @@ static int force_tag_move; /* don't move existing tags by default *
static const char *const rtag_usage[] =
{
- "Usage: %s %s [-aflRnF] [-b] [-d] [-r tag|-D date] tag modules...\n",
+ "Usage: %s %s [-aflRnF] [-b] [-d] [-r rev|-D date] tag modules...\n",
"\t-a\tClear tag from removed files that would not otherwise be tagged.\n",
"\t-f\tForce a head revision match if tag/date not found.\n",
"\t-l\tLocal directory only, not recursive\n",
@@ -388,9 +388,16 @@ check_fileproc (callerdat, finfo)
{
if (delete_flag)
{
+ /* Deleting a tag which did not exist is a noop and
+ should not be logged. */
addit = 0;
}
}
+ else if (delete_flag)
+ {
+ free (p->data);
+ p->data = xstrdup (oversion);
+ }
else if (strcmp(oversion, p->data) == 0)
{
addit = 0;
@@ -458,7 +465,7 @@ pretag_proc(repository, filter)
s = xstrdup(filter);
for (cp=s; *cp; cp++)
{
- if (isspace(*cp))
+ if (isspace ((unsigned char) *cp))
{
*cp = '\0';
break;
@@ -583,7 +590,9 @@ rtag_fileproc (callerdat, finfo)
}
return (0);
}
- if (numtag && isdigit (*numtag) && strcmp (numtag, version) != 0)
+ if (numtag
+ && isdigit ((unsigned char) *numtag)
+ && strcmp (numtag, version) != 0)
{
/*
diff --git a/contrib/cvs/src/run.c b/contrib/cvs/src/run.c
index dc35a78..41f4457 100644
--- a/contrib/cvs/src/run.c
+++ b/contrib/cvs/src/run.c
@@ -175,10 +175,11 @@ run_exec (stin, stout, sterr, flags)
/* The output files, if any, are now created. Do the fork and dups.
- We use vfork not so much for the sake of unices without
- copy-on-write (such systems are rare these days), but for the
- sake of systems without an MMU, which therefore can't do
- copy-on-write (e.g. Amiga). The other solution is spawn (see
+ We use vfork not so much for a performance boost (the
+ performance boost, if any, is modest on most modern unices),
+ but for the sake of systems without a memory management unit,
+ which find it difficult or impossible to implement fork at all
+ (e.g. Amiga). The other solution is spawn (see
windows-NT/run.c). */
#ifdef HAVE_VFORK
@@ -365,12 +366,8 @@ run_popen (cmd, mode)
const char *mode;
{
if (trace)
-#ifdef SERVER_SUPPORT
- (void) fprintf (stderr, "%c-> run_popen(%s,%s)\n",
- (server_active) ? 'S' : ' ', cmd, mode);
-#else
- (void) fprintf (stderr, "-> run_popen(%s,%s)\n", cmd, mode);
-#endif
+ (void) fprintf (stderr, "%s-> run_popen(%s,%s)\n",
+ CLIENT_SERVER_STR, cmd, mode);
if (noexec)
return (NULL);
@@ -409,21 +406,21 @@ piped_child (command, tofdp, fromfdp)
if (pid == 0)
{
if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0)
- error (1, errno, "cannot dup2");
+ error (1, errno, "cannot dup2 pipe");
if (close (to_child_pipe[1]) < 0)
- error (1, errno, "cannot close");
+ error (1, errno, "cannot close pipe");
if (close (from_child_pipe[0]) < 0)
- error (1, errno, "cannot close");
+ error (1, errno, "cannot close pipe");
if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0)
- error (1, errno, "cannot dup2");
+ error (1, errno, "cannot dup2 pipe");
execvp (command[0], command);
- error (1, errno, "cannot exec");
+ error (1, errno, "cannot exec %s", command[0]);
}
if (close (to_child_pipe[0]) < 0)
- error (1, errno, "cannot close");
+ error (1, errno, "cannot close pipe");
if (close (from_child_pipe[1]) < 0)
- error (1, errno, "cannot close");
+ error (1, errno, "cannot close pipe");
*tofdp = to_child_pipe[1];
*fromfdp = from_child_pipe[0];
@@ -436,81 +433,7 @@ close_on_exec (fd)
int fd;
{
#if defined (FD_CLOEXEC) && defined (F_SETFD)
- if (fcntl (fd, F_SETFD, 1))
- error (1, errno, "can't set close-on-exec flag on %d", fd);
+ if (fcntl (fd, F_SETFD, 1))
+ error (1, errno, "can't set close-on-exec flag on %d", fd);
#endif
}
-
-/*
- * dir = 0 : main proc writes to new proc, which writes to oldfd
- * dir = 1 : main proc reads from new proc, which reads from oldfd
- *
- * Returns: a file descriptor. On failure (i.e., the exec fails),
- * then filter_stream_through_program() complains and dies.
- */
-
-int
-filter_stream_through_program (oldfd, dir, prog, pidp)
- int oldfd, dir;
- char **prog;
- pid_t *pidp;
-{
- int p[2], newfd;
- pid_t newpid;
-
- if (pipe (p))
- error (1, errno, "cannot create pipe");
-#ifdef USE_SETMODE_BINARY
- setmode (p[0], O_BINARY);
- setmode (p[1], O_BINARY);
-#endif
-
-#ifdef HAVE_VFORK
- newpid = vfork ();
-#else
- newpid = fork ();
-#endif
- if (pidp)
- *pidp = newpid;
- switch (newpid)
- {
- case -1:
- error (1, errno, "cannot fork");
- case 0:
- /* child */
- if (dir)
- {
- /* write to new pipe */
- close (p[0]);
- dup2 (oldfd, 0);
- dup2 (p[1], 1);
- }
- else
- {
- /* read from new pipe */
- close (p[1]);
- dup2 (p[0], 0);
- dup2 (oldfd, 1);
- }
- /* Should I be blocking some signals here? */
- execvp (prog[0], prog);
- error (1, errno, "couldn't exec %s", prog[0]);
- default:
- /* parent */
- close (oldfd);
- if (dir)
- {
- /* read from new pipe */
- close (p[1]);
- newfd = p[0];
- }
- else
- {
- /* write to new pipe */
- close (p[0]);
- newfd = p[1];
- }
- close_on_exec (newfd);
- return newfd;
- }
-}
diff --git a/contrib/cvs/src/sanity.sh b/contrib/cvs/src/sanity.sh
index f97e036..6130289 100755
--- a/contrib/cvs/src/sanity.sh
+++ b/contrib/cvs/src/sanity.sh
@@ -43,6 +43,15 @@
# 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).
+LC_ALL=C
+export LC_ALL
+
# 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:
@@ -69,12 +78,6 @@ echo 'This test should produce no other output than this line, and a final "OK".
if test x"$1" = x"-r"; then
shift
remote=yes
- # If we're going to do remote testing, make sure 'rsh' works first.
- host="`hostname`"
- if test "x`${CVS_RSH-rsh} $host -n 'echo hi'`" != "xhi"; then
- echo "ERROR: cannot test remote CVS, because \`rsh $host' fails." >&2
- exit 1
- fi
else
remote=no
fi
@@ -94,12 +97,16 @@ fi
# Use full path for CVS executable, so that CVS_SERVER gets set properly
# for remote.
case $1 in
+"")
+ echo "Usage: `basename $0` [-r] [--keep] CVS-TO-TEST [TESTS-TO-RUN...]" 1>&2
+ exit 1
+ ;;
/*)
- testcvs=$1
- ;;
+ testcvs=$1
+ ;;
*)
- testcvs=`pwd`/$1
- ;;
+ testcvs=`pwd`/$1
+ ;;
esac
shift
@@ -278,13 +285,18 @@ dotest_internal ()
# so special-case it.
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"
+ if test x"$4" != x; then
+ # We want to match either the empty string or $4.
+ dotest_internal "$1" "$2" "$4"
+ else
+ 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"
+ fi
else
pass "$1"
fi
@@ -477,7 +489,8 @@ dotest_fail ()
fail "$1"
else
: so far so good
- fi
+ fi 2>${TESTDIR}/dotest.tmp1
+ cat ${TESTDIR}/dotest.tmp1 >>${TESTDIR}/dotest.tmp
dotest_internal "$@"
}
@@ -553,34 +566,48 @@ RCSINIT=; export RCSINIT
if test x"$*" = x; then
# Basic/miscellaneous functionality
- tests="basica basicb basicc basic1 deep basic2 commit-readonly"
+ tests="basica basicb basicc basic1 deep basic2"
+ tests="${tests} files spacefiles commit-readonly"
# Branching, tagging, removing, adding, multiple directories
- tests="${tests} rdiff death death2 branches branches2"
+ tests="${tests} rdiff diff death death2 rmadd rmadd2 dirs dirs2"
+ tests="${tests} branches branches2 tagc tagf"
tests="${tests} rcslib multibranch import importb importc"
- tests="${tests} join join2 join3"
+ tests="${tests} import-after-initial"
+ tests="${tests} join join2 join3 join-readonly-conflict"
tests="${tests} new newb conflicts conflicts2 conflicts3"
# Checking out various places (modules, checkout -d, &c)
tests="${tests} modules modules2 modules3 modules4"
+ tests="${tests} mkmodules-temp-file-removal"
tests="${tests} cvsadm emptydir abspath toplevel toplevel2"
# Log messages, error messages.
tests="${tests} mflag editor errmsg1 errmsg2"
# Watches, binary files, history browsing, &c.
- tests="${tests} devcom devcom2 devcom3 watch4"
+ tests="${tests} devcom devcom2 devcom3 watch4 watch5"
tests="${tests} unedit-without-baserev"
- tests="${tests} ignore binfiles binfiles2 mcopy binwrap binwrap2"
+ tests="${tests} ignore binfiles binfiles2 binfiles3"
+ tests="${tests} mcopy binwrap binwrap2"
tests="${tests} binwrap3 mwrap info taginfo config"
- tests="${tests} serverpatch log log2 ann ann-id crerepos rcs rcs2"
+ tests="${tests} serverpatch log log2 ann ann-id"
+ # Repository Storage (RCS file format, CVS lock files, creating
+ # a repository without "cvs init", &c).
+ tests="${tests} crerepos rcs rcs2 rcs3 lockfiles backuprecover"
+ # More history browsing, &c.
tests="${tests} history"
- tests="${tests} big modes modes2 stamps"
+ tests="${tests} big modes modes2 modes3 stamps"
# PreservePermissions stuff: permissions, symlinks et al.
- tests="${tests} perms symlinks hardlinks"
+ tests="${tests} perms symlinks symlinks2 hardlinks"
# More tag and branch tests, keywords.
- tests="${tests} sticky keyword keywordlog"
+ tests="${tests} sticky keyword keyword2 keywordlog"
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"
+ # Multiple root directories and low-level protocol tests.
+ tests="${tests} multiroot multiroot2 multiroot3 multiroot4"
+ tests="${tests} rmroot reposmv pserver server server2 client"
else
tests="$*"
fi
@@ -629,10 +656,13 @@ directory_cmp ()
CVSROOT_DIRNAME=${TESTDIR}/cvsroot
CVSROOT=${CVSROOT_DIRNAME} ; export CVSROOT
if test "x$remote" = xyes; then
- # Use rsh so we can test it without having to muck with inetd
- # or anything like that. Also needed to get CVS_SERVER to
- # work.
- CVSROOT=:ext:`hostname`:${CVSROOT_DIRNAME} ; export CVSROOT
+ # Currently we test :fork: and :ext: (see crerepos test).
+ # Testing :pserver: would be hard (inetd issues).
+ # Also :ext: and :fork support CVS_SERVER in a convenient way.
+ # If you want to edit this script to change the next line to
+ # :ext:, you can run the tests that way. There is a known
+ # difference in modes-15 (see comments there).
+ CVSROOT=:fork:${CVSROOT_DIRNAME} ; export CVSROOT
CVS_SERVER=${testcvs}; export CVS_SERVER
fi
@@ -725,8 +755,8 @@ ${PROG} \[[a-z]* aborted\]: failed to set tag BASE to revision 1\.1 in ${TESTDIR
RCS file: ${TESTDIR}/cvsroot/first-dir/sdir/ssdir/ssfile,v
retrieving revision 1\.1
diff -c -r1\.1 ssfile
-\*\*\* ssfile [0-9/]* [0-9:]* 1\.1
---- ssfile [0-9/]* [0-9:]*
+\*\*\* sdir/ssdir/ssfile [0-9/]* [0-9:]* 1\.1
+--- sdir/ssdir/ssfile [0-9/]* [0-9:]*
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\*\*\* 1 \*\*\*\*
--- 1,2 ----
@@ -738,8 +768,8 @@ ${PLUS} ssfile line 2"
RCS file: ${TESTDIR}/cvsroot/first-dir/sdir/ssdir/ssfile,v
retrieving revision 1\.1
diff -c -r1\.1 ssfile
-\*\*\* ssfile [0-9/]* [0-9:]* 1\.1
---- ssfile [0-9/]* [0-9:]*
+\*\*\* sdir/ssdir/ssfile [0-9/]* [0-9:]* 1\.1
+--- sdir/ssdir/ssfile [0-9/]* [0-9:]*
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\*\*\* 1 \*\*\*\*
--- 1,2 ----
@@ -1140,6 +1170,8 @@ Directory ${TESTDIR}/cvsroot/second-dir added to the repository"
# and then blow it away (don't complain if it does not
# exist). But that is perfectly legal; 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" \
@@ -1149,8 +1181,39 @@ ${PROG} [a-z]*: Updating second-dir" \
${PROG} [a-z]*: Updating first-dir
${PROG} [a-z]*: 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 ." \
+"" "${PROG} 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
+ cd ..
+ mkdir ./first-dir
+ cd ./first-dir
+ fi
+ dotest basicc-11 "${testcvs} -Q release -d ./." \
+"" "${PROG} release: deletion of directory \./\. failed: .*"
+ dotest basicc-11a "test -d ../second-dir" ""
+
cd ..
- rm -r 1
+ cd ..
+
+ mkdir 2; cd 2
+ dotest basicc-12 "${testcvs} -Q co ." ""
+ dotest basicc-13 "echo *" "CVS CVSROOT first-dir second-dir"
+ dotest basicc-14 "${testcvs} -Q release first-dir second-dir" ""
+ dotest basicc-15 "${testcvs} -Q release -d first-dir second-dir" ""
+ dotest basicc-16 "echo *" "CVS CVSROOT"
+
+ cd ..
+ rm -r 1 2
rm -rf ${CVSROOT_DIRNAME}/first-dir
;;
@@ -2047,6 +2110,242 @@ O [0-9/]* [0-9:]* ${PLUS}0000 ${username} \[1\.1\] first-dir =first-di
rm -rf ${CVSROOT_DIRNAME}/second-dir
;;
+ 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 ${TESTDIR}/cvsroot/first-dir added to the repository"
+ cd first-dir
+ touch tfile
+ dotest files-3 "${testcvs} add tfile" \
+"${PROG} [a-z]*: scheduling file .tfile. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest files-4 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/tfile,v
+done
+Checking in tfile;
+${TESTDIR}/cvsroot/first-dir/tfile,v <-- tfile
+initial revision: 1\.1
+done"
+ 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 ${TESTDIR}/cvsroot/first-dir/dir added to the repository
+--> Using per-directory sticky tag .C'"
+ cd dir
+ touch .file
+ dotest files-6 "${testcvs} add .file" \
+"${PROG} [a-z]*: scheduling file .\.file' for addition on branch .C.
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ mkdir sdir
+ dotest files-7 "${testcvs} add sdir" \
+"Directory ${TESTDIR}/cvsroot/first-dir/dir/sdir added to the repository
+--> Using per-directory sticky tag .C'"
+ cd sdir
+ mkdir ssdir
+ dotest files-8 "${testcvs} add ssdir" \
+"Directory ${TESTDIR}/cvsroot/first-dir/dir/sdir/ssdir added to the repository
+--> Using per-directory sticky tag .C'"
+ cd ssdir
+ touch .file
+ dotest files-9 "${testcvs} add .file" \
+"${PROG} [a-z]*: scheduling file .\.file' for addition on branch .C.
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ cd ../..
+ dotest files-10 "${testcvs} -q ci -m test" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/dir/Attic/\.file,v
+done
+Checking in \.file;
+${TESTDIR}/cvsroot/first-dir/dir/Attic/\.file,v <-- \.file
+new revision: 1\.1\.2\.1; previous revision: 1\.1
+done
+RCS file: ${TESTDIR}/cvsroot/first-dir/dir/sdir/ssdir/Attic/\.file,v
+done
+Checking in sdir/ssdir/\.file;
+${TESTDIR}/cvsroot/first-dir/dir/sdir/ssdir/Attic/\.file,v <-- \.file
+new revision: 1\.1\.2\.1; previous revision: 1\.1
+done"
+ dotest files-11 \
+"${testcvs} commit -m test -f ./.file ./sdir/ssdir/.file" \
+"Checking in \.file;
+${TESTDIR}/cvsroot/first-dir/dir/Attic/\.file,v <-- \.file
+new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
+done
+Checking in \./sdir/ssdir/\.file;
+${TESTDIR}/cvsroot/first-dir/dir/sdir/ssdir/Attic/\.file,v <-- \.file
+new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
+done"
+ if test "$remote" = yes; then
+ # 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_fail files-12 \
+"${testcvs} commit -f -m test ./sdir/ssdir/.file ./.file" \
+"${PROG} server: Up-to-date check failed for .\.file'
+${PROG} \[server aborted\]: correct above errors first!"
+
+ # 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-12-workaround \
+"${testcvs} commit -f -m test sdir/ssdir/.file .file" \
+"Checking in sdir/ssdir/\.file;
+${TESTDIR}/cvsroot/first-dir/dir/sdir/ssdir/Attic/\.file,v <-- \.file
+new revision: 1\.1\.2\.3; previous revision: 1\.1\.2\.2
+done
+Checking in \.file;
+${TESTDIR}/cvsroot/first-dir/dir/Attic/\.file,v <-- \.file
+new revision: 1\.1\.2\.3; previous revision: 1\.1\.2\.2
+done"
+ else
+ dotest files-12 \
+"${testcvs} commit -f -m test ./sdir/ssdir/.file ./.file" \
+"Checking in \./sdir/ssdir/\.file;
+${TESTDIR}/cvsroot/first-dir/dir/sdir/ssdir/Attic/\.file,v <-- \.file
+new revision: 1\.1\.2\.3; previous revision: 1\.1\.2\.2
+done
+Checking in \.file;
+${TESTDIR}/cvsroot/first-dir/dir/Attic/\.file,v <-- \.file
+new revision: 1\.1\.2\.3; previous revision: 1\.1\.2\.2
+done"
+ fi
+ dotest files-13 \
+"${testcvs} commit -fmtest ./sdir/../sdir/ssdir/..///ssdir/.file" \
+"Checking in \./sdir/\.\./sdir/ssdir/\.\.///ssdir/\.file;
+${TESTDIR}/cvsroot/first-dir/dir/sdir/ssdir/Attic/\.file,v <-- \.file
+new revision: 1\.1\.2\.4; previous revision: 1\.1\.2\.3
+done"
+ if test "$remote" = yes; then
+ dotest_fail files-14 \
+"${testcvs} commit -fmtest ../../first-dir/dir/.file" \
+"protocol error: .\.\./\.\./first-dir/dir' has too many \.\."
+ else
+ dotest files-14 \
+"${testcvs} commit -fmtest ../../first-dir/dir/.file" \
+"Checking in \.\./\.\./first-dir/dir/\.file;
+${TESTDIR}/cvsroot/first-dir/dir/Attic/\.file,v <-- \.file
+new revision: 1\.1\.2\.4; previous revision: 1\.1\.2\.3
+done"
+ fi
+ cd ../../..
+
+ rm -r 1
+ rm -rf ${CVSROOT_DIRNAME}/first-dir
+ ;;
+
+ spacefiles)
+ # More filename tests, in particular spaces in file names.
+ # If we start using eval in dotest, this test should become
+ # easier to write (in fact, it may be possible to just
+ # change a few of the names in basica or some other test,
+ # always good to keep the testsuite concise).
+
+ # I wrote this test to worry about problems in do_module;
+ # but then I found that the CVS server has its own problems
+ # with filenames starting with "-". Work around it for now.
+ if test "$remote" = yes; then
+ dashb=dashb
+ dashc=dashc
+ else
+ dashb=-b
+ dashc=-c
+ fi
+
+ mkdir 1; cd 1
+ dotest spacefiles-1 "${testcvs} -q co -l ." ""
+ touch ./${dashc} top
+ dotest spacefiles-2 "${testcvs} add -- ${dashc} top" \
+"${PROG} [a-z]*: scheduling file .${dashc}. for addition
+${PROG} [a-z]*: scheduling file .top. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add these files permanently"
+ dotest spacefiles-3 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/${dashc},v
+done
+Checking in ${dashc};
+${TESTDIR}/cvsroot/${dashc},v <-- ${dashc}
+initial revision: 1\.1
+done
+RCS file: ${TESTDIR}/cvsroot/top,v
+done
+Checking in top;
+${TESTDIR}/cvsroot/top,v <-- top
+initial revision: 1\.1
+done"
+ mkdir 'first dir'
+ if ${testcvs} add 'first dir' >${TESTDIR}/output.tmp 2>&1; then
+ dotest spacefiles-4 "cat ${TESTDIR}/output.tmp" \
+"Directory ${TESTDIR}/cvsroot/first dir added to the repository"
+ else
+ fail spacefiles-4
+ fi
+ mkdir ./${dashb}
+ dotest spacefiles-5 "${testcvs} add -- ${dashb}" \
+"Directory ${TESTDIR}/cvsroot/${dashb} added to the repository"
+ cd 'first dir'
+ touch 'a file'
+ if ${testcvs} add 'a file' >${TESTDIR}/output.tmp 2>&1; then
+ dotest spacefiles-6 "cat ${TESTDIR}/output.tmp" \
+"${PROG} [a-z]*: scheduling file .a file. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ else
+ fail spacefiles-6
+ fi
+ dotest spacefiles-7 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/first dir/a file,v
+done
+Checking in a file;
+${TESTDIR}/cvsroot/first dir/a file,v <-- a file
+initial revision: 1\.1
+done"
+ dotest spacefiles-8 "${testcvs} -q tag new-tag" "T a file"
+ cd ../..
+
+ mkdir 2; cd 2
+ # Leading slash strikes me as kind of oddball, but there is
+ # a special case for it in do_module. And (in the case of
+ # "top", rather than "-c") it has worked in CVS 1.10.6 and
+ # presumably back to CVS 1.3 or so.
+ dotest spacefiles-9 "${testcvs} -q co -- /top" "U \./top"
+ dotest spacefiles-10 "${testcvs} co -- ${dashb}" \
+"${PROG} [a-z]*: Updating ${dashb}"
+ dotest spacefiles-11 "${testcvs} -q co -- ${dashc}" "U \./${dashc}"
+ rm ./${dashc}
+ dotest spacefiles-12 "${testcvs} -q co -- /${dashc}" "U \./${dashc}"
+ if ${testcvs} -q co 'first dir' >${TESTDIR}/output.tmp 2>&1; then
+ dotest spacefiles-13 "cat ${TESTDIR}/output.tmp" \
+"U first dir/a file"
+ else
+ fail spacefiles-13
+ fi
+ cd ..
+
+ mkdir 3; cd 3
+ if ${testcvs} -q co 'first dir/a file' >${TESTDIR}/output.tmp 2>&1
+ then
+ dotest spacefiles-14 "cat ${TESTDIR}/output.tmp" \
+"U first dir/a file"
+ else
+ fail spacefiles-14
+ fi
+ cd ..
+
+ rm -r 1 2 3
+ rm -rf "${CVSROOT_DIRNAME}/first dir"
+ rm -r ${CVSROOT_DIRNAME}/${dashb}
+ rm -f ${CVSROOT_DIRNAME}/${dashc},v ${CVSROOT_DIRNAME}/top,v
+ ;;
+
commit-readonly)
mkdir 1; cd 1
module=x
@@ -2194,6 +2493,66 @@ diff -c /dev/null trdiff/new:1\.1
rm -rf ${CVSROOT_DIRNAME}/trdiff
;;
+ 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 ${TESTDIR}/cvsroot/first-dir added to the repository"
+ 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" \
+"${PROG} [a-z]*: I know nothing about xyzpdq"
+ touch abc
+ dotest diff-4 "${testcvs} add abc" \
+"${PROG} [a-z]*: scheduling file .abc. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest diff-5 "${testcvs} -q ci -mtest" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/abc,v
+done
+Checking in abc;
+${TESTDIR}/cvsroot/first-dir/abc,v <-- abc
+initial revision: 1\.1
+done"
+ echo "extern int gethostname ();" >abc
+ dotest diff-6 "${testcvs} -q ci -mtest" \
+"Checking in abc;
+${TESTDIR}/cvsroot/first-dir/abc,v <-- abc
+new revision: 1\.2; previous revision: 1\.1
+done"
+ 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: ${TESTDIR}/cvsroot/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 \*/"
+
+ if test "$keep" = yes; then
+ echo Keeping ${TESTDIR} and exiting due to --keep
+ exit 0
+ fi
+
+ cd ../..
+ rm -rf ${CVSROOT_DIRNAME}/first-dir
+ rm -r 1
+ ;;
+
death)
# next dive. test death support.
@@ -2894,6 +3253,496 @@ ${PLUS} first revision"
cd .. ; rm -rf first-dir ${CVSROOT_DIRNAME}/first-dir
;;
+ 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 ${TESTDIR}/cvsroot/first-dir added to the repository"
+ cd first-dir
+ echo first file1 >file1
+ dotest rmadd-3 "${testcvs} add file1" \
+"${PROG} [a-z]*: scheduling file .file1. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+
+ dotest_fail rmadd-4 "${testcvs} -q ci -r 1.2.2.4 -m add" \
+"${PROG} [a-z]*: cannot add file .file1' with revision .1\.2\.2\.4'; must be on trunk
+${PROG} \[[a-z]* aborted\]: correct above errors first!"
+ dotest_fail rmadd-5 "${testcvs} -q ci -r 1.2.2 -m add" \
+"${PROG} [a-z]*: cannot add file .file1' with revision .1\.2\.2'; must be on trunk
+${PROG} \[[a-z]* aborted\]: correct above errors first!"
+ dotest_fail rmadd-6 "${testcvs} -q ci -r mybranch -m add" \
+"${PROG} \[[a-z]* 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" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+done
+Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+initial revision: 7\.1
+done"
+ if test "$remote" = yes; 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" \
+"${PROG} [a-z]*: scheduling file .file2. for addition on branch .7'
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ # As in the previous example, CVS is confused....
+ dotest rmadd-11 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file2,v
+done
+Checking in file2;
+${TESTDIR}/cvsroot/first-dir/file2,v <-- file2
+initial revision: 7\.1
+done"
+
+ dotest rmadd-12 "${testcvs} -q update -A" ""
+ touch file3
+ dotest rmadd-13 "${testcvs} add file3" \
+"${PROG} [a-z]*: scheduling file .file3. for addition
+${PROG} [a-z]*: use .${PROG} 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" \
+"${PROG} [a-z]*: Up-to-date check failed for .file2'
+${PROG} \[[a-z]* aborted\]: correct above errors first!"
+ # Whatever, let's not let file2 distract us....
+ dotest rmadd-15 "${testcvs} -q ci -r mybranch -m add file3" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/Attic/file3,v
+done
+Checking in file3;
+${TESTDIR}/cvsroot/first-dir/Attic/file3,v <-- file3
+new revision: 1\.1\.2\.1; previous revision: 1\.1
+done"
+
+ touch file4
+ dotest rmadd-16 "${testcvs} add file4" \
+"${PROG} [a-z]*: scheduling file .file4. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ # Same "Up-to-date check" issues as in rmadd-14.
+ # The "no such tag" thing is due to the fact that we only
+ # update val-tags when the tag is used (might be more of a
+ # bug than a feature, I dunno).
+ dotest_fail rmadd-17 \
+"${testcvs} -q ci -r mynonbranch -m add file4" \
+"${PROG} \[[a-z]* aborted\]: no such tag mynonbranch"
+ # Try to make CVS write val-tags.
+ 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" \
+"${PROG} \[[a-z]* aborted\]: no such tag mynonbranch"
+ # Now make CVS write val-tags for real.
+ dotest rmadd-20 "${testcvs} -q update -r mynonbranch file1" ""
+ # 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" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/Attic/file4,v
+done
+Checking in file4;
+${TESTDIR}/cvsroot/first-dir/Attic/file4,v <-- file4
+new revision: 1\.1\.2\.1; previous revision: 1\.1
+done"
+
+ # 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" \
+"${PROG} [a-z]*: scheduling file .file5. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ if test "$remote" = yes; 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-23 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file5,v
+done
+Checking in file5;
+${TESTDIR}/cvsroot/first-dir/file5,v <-- file5
+initial revision: 1\.1
+done"
+ dotest rmadd-23-workaround \
+"${testcvs} -q ci -r 7 -m bump-it file5" \
+"Checking in file5;
+${TESTDIR}/cvsroot/first-dir/file5,v <-- file5
+new revision: 7\.1; previous revision: 1\.1
+done"
+ else
+ dotest rmadd-23 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file5,v
+done
+Checking in file5;
+${TESTDIR}/cvsroot/first-dir/file5,v <-- file5
+initial revision: 7\.1
+done"
+ fi
+ echo change it >file5
+ dotest_fail rmadd-24 "${testcvs} -q ci -r 4.8 -m change file5" \
+"Checking in file5;
+${TESTDIR}/cvsroot/first-dir/file5,v <-- file5
+${PROG} [a-z]*: ${TESTDIR}/cvsroot/first-dir/file5,v: revision 4\.8 too low; must be higher than 7\.1
+${PROG} [a-z]*: could not check in file5
+7\.1 unlocked"
+ dotest rmadd-24a "${testcvs} -q ci -r 8.4 -m change file5" \
+"Checking in file5;
+${TESTDIR}/cvsroot/first-dir/file5,v <-- file5
+new revision: 8\.4; previous revision: 7\.1
+done"
+ # 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 ${TESTDIR}/cvsroot/first-dir/file5,v
+ Sticky Tag: 8\.4
+ Sticky Date: (none)
+ Sticky Options: (none)"
+
+ cd ../..
+ rm -r 1
+ 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 ${TESTDIR}/cvsroot/first-dir added to the repository"
+ cd first-dir
+ echo 'initial contents' >file1
+ dotest rmadd2-3 "${testcvs} add file1" \
+"${PROG} [a-z]*: scheduling file .file1. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest rmadd2-4 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+done
+Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+initial revision: 1\.1
+done"
+ dotest rmadd2-4a "${testcvs} -Q tag tagone" ""
+ dotest rmadd2-5 "${testcvs} rm -f file1" \
+"${PROG} [a-z]*: scheduling .file1. for removal
+${PROG} [a-z]*: use .${PROG} commit. to remove this file permanently"
+ dotest rmadd2-6 "${testcvs} -q ci -m remove" \
+"Removing file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: delete; previous revision: 1\.1
+done"
+ dotest rmadd2-7 "${testcvs} -q update -j 1.2 -j 1.1 file1" "U file1"
+ dotest rmadd2-8 "${testcvs} -q ci -m readd" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.3; previous revision: 1\.2
+done"
+ echo 'new contents' >file1
+ dotest rmadd2-9 "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.4; previous revision: 1\.3
+done"
+ dotest rmadd2-10 "${testcvs} -q update -j 1.4 -j 1.3 file1" \
+"RCS file: ${TESTDIR}/cvsroot/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" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.5; previous revision: 1\.4
+done"
+ 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" \
+"${PROG} [a-z]*: scheduling file1 for removal"
+ dotest rmadd2-15 "${testcvs} -q ci -m re-remove" \
+"Removing file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: delete; previous revision: 1\.5
+done"
+ dotest rmadd2-16 "${testcvs} log -h file1" "
+RCS file: ${TESTDIR}/cvsroot/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 ${TESTDIR}/cvsroot/first-dir/Attic/file1,v
+
+ Existing Tags:
+ tagone (revision: 1.1)"
+
+ cd ../..
+
+ rm -r 1
+ rm -rf ${TESTDIR}/cvsroot/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
+${PROG} [a-z]*: Importing ${TESTDIR}/cvsroot/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.
+ rm -rf ${CVSROOT_DIRNAME}/dir1/sdir
+
+ dotest dirs-3 "${testcvs} update" \
+"${PROG} [a-z]*: Updating dir1
+${PROG} [a-z]*: Updating dir1/sdir
+${PROG} [a-z]*: cannot open directory ${TESTDIR}/cvsroot/dir1/sdir: No such file or directory
+${PROG} [a-z]*: skipping directory dir1/sdir"
+ dotest dirs-3a "${testcvs} update -d" \
+"${PROG} [a-z]*: Updating dir1
+${PROG} [a-z]*: Updating dir1/sdir
+${PROG} [a-z]*: cannot open directory ${TESTDIR}/cvsroot/dir1/sdir: No such file or directory
+${PROG} [a-z]*: skipping directory dir1/sdir"
+
+ # If we say "yes", then CVS gives errors about not being able to
+ # create lock files.
+ if echo no | ${testcvs} release -d dir1/sdir \
+ >${TESTDIR}/output.tmp 2>&1; then
+ pass dirs-4
+ else
+ fail dirs-4
+ fi
+ # The fact that it says "skipping directory " rather than
+ # "skipping directory dir1/sdir" is some kind of bug.
+ dotest dirs-4a "cat ${TESTDIR}/output.tmp" \
+"${PROG} [a-z]*: cannot open directory ${TESTDIR}/cvsroot/dir1/sdir: No such file or directory
+${PROG} [a-z]*: 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" "${PROG} [a-z]*: 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" \
+"${PROG} [a-z]*: Updating dir1"
+
+ cd ..
+
+ rm -r imp-dir 1
+ rm ${TESTDIR}/output.tmp
+
+ # clean up our repositories
+ 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 ${TESTDIR}/cvsroot/first-dir added to the repository"
+ cd first-dir
+ mkdir sdir
+ dotest dirs2-3 "${testcvs} add sdir" \
+"Directory ${TESTDIR}/cvsroot/first-dir/sdir added to the repository"
+ touch sdir/file1
+ dotest dirs2-4 "${testcvs} add sdir/file1" \
+"${PROG} [a-z]*: scheduling file .sdir/file1. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest dirs2-5 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/sdir/file1,v
+done
+Checking in sdir/file1;
+${TESTDIR}/cvsroot/first-dir/sdir/file1,v <-- file1
+initial revision: 1\.1
+done"
+ rm -r sdir/CVS
+ if test "$remote" = yes; then
+ # This is just like conflicts3-23
+ dotest_fail dirs2-6 "${testcvs} update -d" \
+"${QUESTION} sdir
+${PROG} server: Updating \.
+${PROG} update: in directory sdir:
+${PROG} update: cannot open CVS/Entries for reading: No such file or directory
+${PROG} server: Updating sdir
+${PROG} update: move away sdir/file1; it is in the way
+C sdir/file1"
+ rm sdir/file1
+
+ # This is where things are not just like conflicts3-23
+ # As with conflicts3-23, all these CVS/Entries* warnings
+ # are somewhat doubtful, and we probably should think some
+ # about whether they should be changed/fixed.
+ dotest dirs2-7 "${testcvs} update -d" \
+"${QUESTION} sdir
+${PROG} server: Updating \.
+${PROG} update: in directory sdir:
+${PROG} update: cannot open CVS/Entries for reading: No such file or directory
+${PROG} server: Updating sdir
+U sdir/file1
+${PROG} update: cannot open CVS/Entries.Log: No such file or directory"
+ else
+ dotest dirs2-6 "${testcvs} update -d" \
+"${PROG} update: Updating \.
+${QUESTION} sdir"
+ rm sdir/file1
+ dotest dirs2-7 "${testcvs} update -d" \
+"${PROG} 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 test "$remote" = yes; then
+ # Cute little quirk of val-tags; if we don't recurse into
+ # the directories where the tag is defined, val-tags won't
+ # get updated.
+ dotest_fail dirs2-10 "${testcvs} update -d -r br" \
+"${QUESTION} sdir
+${PROG} \[server aborted\]: no such tag br"
+ dotest dirs2-10-rem \
+"${testcvs} -q rdiff -u -r 1.1 -r br first-dir/sdir/file1" \
+""
+ dotest_fail dirs2-10-again "${testcvs} update -d -r br" \
+"${QUESTION} sdir
+${PROG} server: Updating \.
+${PROG} update: in directory sdir:
+${PROG} update: cannot open CVS/Entries for reading: No such file or directory
+${PROG} update: cannot open CVS/Tag: No such file or directory
+${PROG} update: cannot open CVS/Tag: No such file or directory
+${PROG} server: Updating sdir
+${PROG} update: move away sdir/file1; it is in the way
+C sdir/file1
+${PROG} update: cannot open CVS/Tag: No such file or directory"
+ else
+ dotest_fail dirs2-10 "${testcvs} update -d -r br" \
+"${PROG} update: in directory sdir:
+${PROG} \[update aborted\]: there is no version here; do '${PROG} 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" \
+"${PROG} [a-z]*: scheduling .sdir/file1. for removal
+${PROG} [a-z]*: use .${PROG} commit. to remove this file permanently"
+ dotest dirs2-13 "${testcvs} -q ci -m remove" \
+"Removing sdir/file1;
+${TESTDIR}/cvsroot/first-dir/sdir/file1,v <-- file1
+new revision: delete; previous revision: 1\.1\.2
+done"
+ cd ../../2/first-dir
+ if test "$remote" = yes; then
+ dotest dirs2-14 "${testcvs} update -d -r br" \
+"${QUESTION} sdir
+${PROG} server: Updating \.
+${PROG} update: in directory sdir:
+${PROG} update: cannot open CVS/Entries for reading: No such file or directory
+${PROG} update: cannot open CVS/Tag: No such file or directory
+${PROG} update: cannot open CVS/Tag: No such file or directory
+${PROG} server: Updating sdir
+${PROG} update: cannot open CVS/Tag: No such file or directory"
+ else
+ dotest dirs2-14 "${testcvs} update -d -r br" \
+"${PROG} update: Updating \.
+${QUESTION} sdir"
+ fi
+ cd ../..
+
+ rm -r 1 2 3
+ rm -rf ${TESTDIR}/cvsroot/first-dir
+ ;;
+
branches)
# More branch tests, including branches off of branches
mkdir ${CVSROOT_DIRNAME}/first-dir
@@ -2949,14 +3798,18 @@ done"
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" "${PROG}"' [a-z]*: Tagging \.
T file1
T file2
T file3
T file4'
dotest branches-5 "${testcvs} update -r br1" \
-"${PROG}"' [a-z]*: Updating \.'
- echo 1:br1 >file1
+"${PROG} [a-z]*: Updating \.
+M file1"
echo 2:br1 >file2
echo 4:br1 >file4
dotest branches-6 "${testcvs} -q ci -m modify" \
@@ -3389,6 +4242,172 @@ File: file5 Status: Up-to-date
rm -r trunk b1a b1b
;;
+ 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 ${TESTDIR}/cvsroot/first-dir added to the repository"
+ cd first-dir
+ touch file1
+ dotest tagc-3 "${testcvs} add file1" \
+"${PROG} [a-z]*: scheduling file .file1. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest tagc-4 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+done
+Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+initial revision: 1\.1
+done"
+ dotest tagc-5 "${testcvs} -q tag -c tag1" "T file1"
+ touch file1
+ dotest tagc-6 "${testcvs} -q tag -c tag2" "T file1"
+ # Avoid timestamp granularity bugs (FIXME: CVS should be
+ # doing the sleep, right?).
+ sleep 1
+ echo myedit >>file1
+ dotest_fail tagc-7 "${testcvs} -q tag -c tag3" \
+"${PROG} [a-z]*: file1 is locally modified
+${PROG} \[[a-z]* aborted\]: correct the above errors first!"
+ cd ../..
+ mkdir 2
+ cd 2
+ dotest tagc-8 "${testcvs} -q co first-dir" "U first-dir/file1"
+ cd ../1/first-dir
+ dotest tagc-9 "${testcvs} -q ci -m modify" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.2; previous revision: 1\.1
+done"
+ cd ../../2/first-dir
+ # That this is an error is a bug. Although the bug has existed
+ # since tag -c was created, I don't think there would be a
+ # compatibility problem with just fixing it.
+ dotest_fail tagc-10 "${testcvs} -q tag -c tag4" \
+"${PROG} [a-z]*: file1 is locally modified
+${PROG} \[[a-z]* aborted\]: correct the above errors first!"
+ cd ../..
+
+ rm -r 1 2
+ rm -rf ${CVSROOT_DIRNAME}/first-dir
+ ;;
+
+ tagf)
+ # More tagging tests, including using tag -F 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 ${TESTDIR}/cvsroot/first-dir added to the repository"
+ cd first-dir
+ touch file1 file2
+ dotest tagf-3 "${testcvs} add file1 file2" \
+"${PROG} [a-z]*: scheduling file .file1. for addition
+${PROG} [a-z]*: scheduling file .file2. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add these files permanently"
+ dotest tagf-4 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+done
+Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+initial revision: 1\.1
+done
+RCS file: ${TESTDIR}/cvsroot/first-dir/file2,v
+done
+Checking in file2;
+${TESTDIR}/cvsroot/first-dir/file2,v <-- file2
+initial revision: 1\.1
+done"
+
+ # 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" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.1\.2\.1; previous revision: 1\.1
+done
+Checking in file2;
+${TESTDIR}/cvsroot/first-dir/file2,v <-- file2
+new revision: 1\.1\.2\.1; previous revision: 1\.1
+done"
+ # Here we make it a non-branch tag. Some think this should
+ # be an error. But if -F means "I want to put this tag here,
+ # never mind whether there was a tag of that name before", then
+ # an error wouldn't fit.
+ dotest tagf-8 "${testcvs} -q tag -F 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 ${TESTDIR}/cvsroot/first-dir/file1,v
+ 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: ${TESTDIR}/cvsroot/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: ${TESTDIR}/cvsroot/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
+${PROG} [a-z]*: 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" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.1\.4\.1; previous revision: 1\.1
+done
+Checking in file2;
+${TESTDIR}/cvsroot/first-dir/file2,v <-- file2
+new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
+done"
+ cd ../..
+
+ rm -r 1
+ rm -rf ${CVSROOT_DIRNAME}/first-dir
+ ;;
+
rcslib)
# Test librarification of RCS.
# First: test whether `cvs diff' handles $Name expansion
@@ -3603,7 +4622,46 @@ two
${TESTDIR}/cvsroot/first-dir/file1,v <-- file2
new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
done"
- dotest rcslib-symlink-4 "test -L ${CVSROOT_DIRNAME}/first-dir/file2,v"
+ dotest rcslib-symlink-4 "ls -l $CVSROOT_DIRNAME/first-dir/file2,v" \
+".*$CVSROOT_DIRNAME/first-dir/file2,v -> file1,v"
+ # 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" \
+"${PROG} [a-z]*: Tagging .
+T file1
+W file2 : the_tag already exists on version 1.1.2.1 : NOT MOVING tag to version 1.1.2.2"
+ dotest rcslib-symlink-6 "ls -l $CVSROOT_DIRNAME/first-dir/file2,v" \
+".*$CVSROOT_DIRNAME/first-dir/file2,v -> file1,v"
+
+ # 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" \
+"${PROG} [a-z]*: scheduling .file2. for removal
+${PROG} [a-z]*: use .${PROG} commit. to remove this file permanently"
+ dotest rcslib-symlink-9 "${testcvs} -q ci -m rm-it" \
+"Removing file2;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file2
+new revision: delete; previous revision: 1\.2
+done"
+ # 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.
+ dotest rcslib-symlink-10 \
+"${testcvs} -q rtag -b -r the_tag brtag first-dir" \
+"${PROG} [a-z]*: could not read RCS file for file2
+${PROG} [a-z]*: could not read RCS file for first-dir/file2
+${PROG} [a-z]*: could not read RCS file for first-dir/file2"
+ cd ..
cd ..
@@ -3613,7 +4671,7 @@ done"
fi
rm -rf ${CVSROOT_DIRNAME}/first-dir
- rm -r first-dir
+ rm -r first-dir 2
;;
multibranch)
@@ -3718,7 +4776,7 @@ modify-on-br1
mkdir import-dir ; cd import-dir
for i in 1 2 3 4 ; do
- echo imported file"$i" > imported-f"$i"
+ echo imported file"$i" > imported-f"$i"
done
# This directory should be on the default ignore list,
@@ -3729,157 +4787,164 @@ modify-on-br1
echo 'import should not expand $''Id$' >>imported-f2
cp imported-f2 ../imported-f2-orig.tmp
- if ${CVS} import -m first-import first-dir vendor-branch junk-1_0 ; then
- pass 96
- else
- fail 96
- fi
+ 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" ''
- if cmp ../imported-f2-orig.tmp imported-f2; then
- pass 96.5
- else
- fail 96.5
- fi
cd ..
# co
- if ${CVS} co first-dir ; then
- pass 97
- else
- fail 97
- fi
+ 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
- if test -f imported-f"$i" ; then
- pass 98-$i
- else
- fail 98-$i
- fi
+ dotest import-98-$i "test -f imported-f$i" ''
done
- if test -d RCS; then
- fail 98.5
- else
- pass 98.5
- fi
+ dotest_fail import-98.5 "test -d RCS" ''
# remove
rm imported-f1
- if ${CVS} rm imported-f1 2>> ${LOGFILE}; then
- pass 99
- else
- fail 99
- fi
+ dotest import-99 "${testcvs} rm imported-f1" \
+"${PROG}"' [a-z]*: scheduling `imported-f1'\'' for removal
+'"${PROG}"' [a-z]*: use .'"${PROG}"' commit. to remove this file permanently'
# change
echo local-change >> imported-f2
# commit
- if ${CVS} ci -m local-changes >> ${LOGFILE} 2>&1; then
- pass 100
- else
- fail 100
- fi
+ dotest import-100 "${testcvs} ci -m local-changes" \
+"${PROG} [a-z]*: Examining .
+Removing imported-f1;
+${TESTDIR}/cvsroot/first-dir/imported-f1,v <-- imported-f1
+new revision: delete; previous revision: 1\.1\.1\.1
+done
+Checking in imported-f2;
+${TESTDIR}/cvsroot/first-dir/imported-f2,v <-- imported-f2
+new revision: 1\.2; previous revision: 1\.1
+done"
# log
- if ${CVS} log imported-f1 | grep '1.1.1.2 (dead)' ; then
- fail 101
- else
- pass 101
- fi
+ dotest import-101 "${testcvs} log imported-f1" \
+"
+RCS file: ${TESTDIR}/cvsroot/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: [0-9/]* [0-9:]*; author: ${username}; state: dead; lines: ${PLUS}0 -0
+local-changes
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+branches: 1\.1\.1;
+Initial revision
+----------------------------
+revision 1\.1\.1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}0 -0
+first-import
+============================================================================="
# update into the vendor branch.
- if ${CVS} update -rvendor-branch ; then
- pass 102
- else
- fail 102
- fi
+ dotest import-102 "${testcvs} update -rvendor-branch" \
+"${PROG} [a-z]*: Updating .
+[UP] imported-f1
+[UP] imported-f2"
# remove file4 on the vendor branch
rm imported-f4
-
- if ${CVS} rm imported-f4 2>> ${LOGFILE}; then
- pass 103
- else
- fail 103
- fi
+ dotest import-103 "${testcvs} rm imported-f4" \
+"${PROG}"' [a-z]*: scheduling `imported-f4'\'' for removal
+'"${PROG}"' [a-z]*: use .'"${PROG}"' commit. to remove this file permanently'
# commit
- if ${CVS} ci -m vendor-removed imported-f4 >>${LOGFILE}; then
- pass 104
- else
- fail 104
- fi
+ dotest import-104 \
+"${testcvs} ci -m vendor-removed imported-f4" \
+"Removing imported-f4;
+${TESTDIR}/cvsroot/first-dir/imported-f4,v <-- imported-f4
+new revision: delete; previous revision: 1\.1\.1\.1
+done"
# update to main line
- if ${CVS} update -A 2>> ${LOGFILE}; then
- pass 105
- else
- fail 105
- fi
+ dotest import-105 "${testcvs} -q update -A" \
+"${PROG} [a-z]*: warning: imported-f1 is not (any longer) pertinent
+[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"
+ echo rev 2 of file $i >> imported-f"$i"
done
cp imported-f2 ../imported-f2-orig.tmp
- if ${CVS} import -m second-import first-dir vendor-branch junk-2_0 ; then
- pass 106
- else
- fail 106
- fi
- if cmp ../imported-f2-orig.tmp imported-f2; then
- pass 106.5
- else
- fail 106.5
- fi
+ dotest_sort import-106 \
+"${testcvs} import -m second-import first-dir vendor-branch junk-2_0" \
+"
+
+
+ ${PROG} checkout -jvendor-branch:yesterday -jvendor-branch 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
- if ${CVS} co first-dir ; then
- pass 107
- else
- fail 107
- fi
+ dotest import-107 "${testcvs} co first-dir" \
+"${PROG} [a-z]*: Updating first-dir
+[UP] first-dir/imported-f3
+[UP] first-dir/imported-f4"
cd first-dir
- if test -f imported-f1 ; then
- fail 108
- else
- pass 108
- fi
+ dotest_fail import-108 "test -f imported-f1" ''
for i in 2 3 ; do
- if test -f imported-f"$i" ; then
- pass 109-$i
- else
- fail 109-$i
- fi
+ dotest import-109-$i "test -f imported-f$i" ''
done
# check vendor branch for file4
- if ${CVS} update -rvendor-branch ; then
- pass 110
- else
- fail 110
- fi
+ dotest import-110 "${testcvs} -q update -rvendor-branch" \
+"[UP] imported-f1
+[UP] imported-f2"
- if test -f imported-f4 ; then
- pass 111
- else
- fail 111
- fi
+ dotest import-111 "test -f imported-f4" ''
# update to main line
- if ${CVS} update -A 2>> ${LOGFILE}; then
- pass 112
- else
- fail 112
- fi
+ dotest import-112 "${testcvs} -q update -A" \
+"${PROG} [a-z]*: warning: imported-f1 is not (any longer) pertinent
+[UP] imported-f2"
cd ..
@@ -3894,18 +4959,10 @@ rcsmerge: warning: conflicts during merge"
cd first-dir
- if test -f imported-f1 ; then
- fail 114
- else
- pass 114
- fi
+ dotest_fail import-114 "test -f imported-f1" ''
for i in 2 3 ; do
- if test -f imported-f"$i" ; then
- pass 115-$i
- else
- fail 115-$i
- fi
+ dotest import-115-$i "test -f imported-f$i" ''
done
dotest import-116 'cat imported-f2' \
@@ -3950,12 +5007,14 @@ No conflicts created by this import"
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} import -m add -b 1.1.3 first-dir freemunger freemunger-1_0" \
+"${testcvs} -d ${CVSROOT} import -m add -b 1.1.3 first-dir freemunger freemunger-1_0" \
"
- ${PROG} checkout -jfreemunger:yesterday -jfreemunger first-dir
+ ${PROG} -d ${CVSROOT} checkout -jfreemunger:yesterday -jfreemunger first-dir
2 conflicts created by this import.
C first-dir/file1
C first-dir/file2
@@ -4024,16 +5083,25 @@ add
importc)
# Test importing a bunch o' files in a bunch o' directories.
+ # Also the -d option.
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 bdir/subdir/file1
- touch cdir/cfile
+ # If I'm correctly reading the Single Unix Specification,
+ # version 2, then "touch -t 197107040343" or "touch -t 203412251801"
+ # should work. But GNU touch seems to have other ideas.
+ # I sort of wonder if this is lossage by the standards bodies,
+ # I'm not sure.
+ # Note that some versions of touch when used without -t don't handle
+ # y2k and/or set the seconds reliably.
+ # We should probably find a different way of doing this.
+ touch 0704034371 bdir/subdir/file1
+ touch 1225180134 cdir/cfile
dotest_sort importc-1 \
-"${testcvs} import -m import-it first-dir vendor release" \
+"${testcvs} import -d -m import-it first-dir vendor release" \
"
N first-dir/adir/sub1/file1
@@ -4077,7 +5145,7 @@ ${PROG} [a-z]*: Updating bdir/subdir"
# 1.9 did not).
dotest_fail importc-7 "${testcvs} -q ci -m modify -r wip_test" \
"${PROG} [a-z]*: in directory adir/sub1/ssdir:
-${PROG} \[[a-z]* aborted\]: there is no version here; do .cvs checkout. first"
+${PROG} \[[a-z]* aborted\]: there is no version here; do .${PROG} checkout. first"
# The workaround is to leave off the "-r wip_test".
dotest importc-8 "${testcvs} -q ci -m modify" \
"Checking in cdir/cfile;
@@ -4092,13 +5160,136 @@ ${TESTDIR}/cvsroot/first-dir/cdir/cfile,v <-- cfile
new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1
done"
fi
+
+ # TODO: should also be testing "import -d" when we update
+ # an existing file.
+ dotest importc-8 "${testcvs} -q log cdir/cfile" "
+RCS file: ${TESTDIR}/cvsroot/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: 2034/12/2[4-6] [0-9][0-9]:01:[0-9][0-9]; author: ${username}; state: Exp;
+branches: 1\.1\.1;
+Initial revision
+----------------------------
+revision 1\.1\.1\.1
+date: 2034/12/2[4-6] [0-9][0-9]:01:[0-9][0-9]; author: ${username}; state: Exp; lines: ${PLUS}0 -0
+branches: 1\.1\.1\.1\.2;
+import-it
+----------------------------
+revision 1\.1\.1\.1\.2\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+modify
+============================================================================="
+
+ dotest importc-9 "${testcvs} -q log bdir/subdir/file1" "
+RCS file: ${TESTDIR}/cvsroot/first-dir/bdir/subdir/file1,v
+Working file: bdir/subdir/file1
+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: 2; selected revisions: 2
+description:
+----------------------------
+revision 1\.1
+date: 1971/07/0[3-5] [0-9][0-9]:43:[0-9][0-9]; author: ${username}; state: Exp;
+branches: 1\.1\.1;
+Initial revision
+----------------------------
+revision 1\.1\.1\.1
+date: 1971/07/0[3-5] [0-9][0-9]:43:[0-9][0-9]; author: ${username}; state: Exp; lines: ${PLUS}0 -0
+import-it
+============================================================================="
cd ..
+ # Now tests of absolute pathnames and .. as repository directory.
+ cd ../1
+ dotest_fail importc-10 \
+"${testcvs} import -m imp ../other vendor release2" \
+"${PROG} \[[a-z]* aborted\]: directory \.\./other not relative within the repository"
+ dotest_fail importc-11 \
+"${testcvs} import -m imp ${TESTDIR}/other vendor release3" \
+"${PROG} \[[a-z]* aborted\]: directory ${TESTDIR}/other not relative within the repository"
+ dotest_fail importc-12 "test -d ${TESTDIR}/other" ""
cd ..
+
rm -r 1 2
rm -rf ${CVSROOT_DIRNAME}/first-dir
;;
+ import-after-initial)
+ # Properly handle the case in which the first version of a
+ # file is created by a regular cvs add and commit, and there
+ # is a subsequent cvs import of the same file. cvs update with
+ # a date tag must resort to searching the vendor branch only if
+ # the initial version of the file was created at the same time
+ # as the initial version on the vendor branch.
+
+ mkdir 1; cd 1
+ module=x
+
+ echo > unused-file
+
+ # Create the module.
+ dotest import-after-initial-1 \
+ "$testcvs -Q import -m. $module X Y" ''
+
+ file=m
+ # Check it out and add a file.
+ dotest import-after-initial-2 "$testcvs -Q co $module" ''
+ cd $module
+ echo original > $file
+ dotest import-after-initial-3 "${testcvs} -Q add $file" \
+"${PROG}"' [a-z]*: use .'"${PROG}"' commit. to add this file permanently'
+ dotest import-after-initial-4 "${testcvs} -Q ci -m. $file" \
+"RCS file: ${TESTDIR}/cvsroot/$module/$file,v
+done
+Checking in $file;
+${TESTDIR}/cvsroot/$module/$file,v <-- $file
+initial revision: 1\.1
+done"
+
+ # Delay a little so the following import isn't done in the same
+ # second as the preceding commit.
+ sleep 2
+
+ # Do the first import of $file *after* $file already has an
+ # initial version.
+ mkdir sub
+ cd sub
+ echo newer-via-import > $file
+ dotest import-after-initial-5 \
+ "$testcvs -Q import -m. $module X Y2" ''
+ cd ..
+
+ # Sleep a second so we're sure to be after the second of the import.
+ sleep 1
+
+ dotest import-after-initial-6 \
+ "$testcvs -Q update -p -D now $file" 'original'
+
+ cd ../..
+ rm -rf 1
+ rm -rf ${CVSROOT_DIRNAME}/$module
+ ;;
+
join)
# Test doing joins which involve adding and removing files.
# Variety of scenarios (see list below), in the context of:
@@ -4108,6 +5299,8 @@ done"
# See also binfile2, which does similar things with binary files.
# See also join2, which tests joining (and update -A) on only
# a single file, rather than a directory.
+ # See also rmadd2, which tests -j cases not involving branches
+ # (e.g. undoing a commit)
# See also join3, which tests some cases involving the greatest
# common ancestor. Here is a list of tests according to branch
# topology:
@@ -4728,6 +5921,60 @@ br2:line1
rm -rf ${CVSROOT_DIRNAME}/first-dir
;;
+ join-readonly-conflict)
+ # Demonstrate that cvs-1.9.29 can fail on 2nd and subsequent
+ # conflict-evoking join attempts.
+ # Even with that version of CVS, This test failed only in
+ # client-server mode, and would have been noticed in normal
+ # operation only for files that were read-only (either due to
+ # use of cvs' global -r option, setting the CVSREAD envvar,
+ # or use of watch lists).
+ mkdir 1; cd 1
+ dotest join-readonly-conflict-1 "$testcvs -q co -l ." ''
+ module=x
+ mkdir $module
+ $testcvs -q add $module >>$LOGFILE 2>&1
+ cd $module
+
+ file=m
+ echo trunk > $file
+ $testcvs -q add $file >>$LOGFILE 2>&1
+ $testcvs -q ci -m . $file >>$LOGFILE 2>&1
+
+ $testcvs tag -b B $file >>$LOGFILE 2>&1
+ $testcvs -q update -rB $file >>$LOGFILE 2>&1
+ echo branch B > $file
+ $testcvs ci -m . $file >>$LOGFILE 2>&1
+
+ rm $file
+ $testcvs update -A $file >>$LOGFILE 2>&1
+ # Make sure $file is read-only. This can happen more realistically
+ # via patch -- which could be used to apply a delta, yet would
+ # preserve a file's read-only permissions.
+ echo conflict > $file; chmod u-w $file
+ $testcvs update -r B $file >>$LOGFILE 2>&1
+
+ rm -f $file
+ $testcvs update -A $file >>$LOGFILE 2>&1
+ # This one would fail because cvs couldn't open the existing
+ # (and read-only) .# file for writing.
+ echo conflict > $file
+
+ test -w ".#$file.1.1" && fail "$file is writable"
+ dotest join-readonly-conflict-2 "$testcvs update -r B $file" \
+"RCS file: ${TESTDIR}/cvsroot/$module/$file,v
+retrieving revision 1\.1
+retrieving revision 1\.1\.2\.1
+Merging differences between 1\.1 and 1\.1\.2\.1 into $file
+rcsmerge: warning: conflicts during merge
+${PROG} [a-z]*: conflicts found in $file
+C m"
+
+ cd ../..
+ rm -rf 1
+ rm -rf ${CVSROOT_DIRNAME}/$module
+ ;;
+
new) # look for stray "no longer pertinent" messages.
mkdir ${CVSROOT_DIRNAME}/first-dir
@@ -4973,6 +6220,14 @@ File: a Status: Needs Merge
Sticky Tag: (none)
Sticky Date: (none)
Sticky Options: (none)"
+ dotest conflicts-129a "${testcvs} -nq update a" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/a,v
+retrieving revision 1\.1
+retrieving revision 1\.2
+Merging differences between 1\.1 and 1\.2 into a
+rcsmerge: warning: conflicts during merge
+${PROG} [a-z]*: conflicts found in a
+C a"
dotest conflicts-130 "${testcvs} -q update" \
"RCS file: ${TESTDIR}/cvsroot/first-dir/a,v
retrieving revision 1\.1
@@ -5163,6 +6418,9 @@ done"
U first-dir/abc'
cd ..
+ # BEGIN TESTS USING THE FILE A
+ # FIXME: would be cleaner to separate them out into their own
+ # tests; conflicts2 is getting long.
# Now test that if one person modifies and commits a
# file and a second person removes it, it is a
# conflict
@@ -5186,7 +6444,46 @@ C a"
dotest conflicts2-142b5 "${testcvs} add a" "U a
${PROG} [a-z]*: a, version 1\.1, resurrected"
dotest conflicts2-142b6 "${testcvs} -q update" ''
+
+ # Now one level up.
+ cd ..
+ dotest conflicts2-142b7 "${testcvs} rm -f first-dir/a" \
+"${PROG} [a-z]*: scheduling .first-dir/a. for removal
+${PROG} [a-z]*: use .${PROG} commit. to remove this file permanently"
+
+ if test "$remote" = no; then
+ # The "nothing known" is a bug. Correct behavior is for a to get
+ # created, as above. Cause is pretty obvious - add.c
+ # calls update() without dealing with the fact we are chdir'd.
+ # Also note that resurrecting 1.2 instead of 1.1 is also a
+ # bug, I think (the same part of add.c has a comment which says
+ # "XXX - bugs here; this really resurrect the head" which
+ # presumably refers to this).
+ # The fix for both is presumably to call RCS_checkout() or
+ # something other than update().
+ dotest conflicts2-142b8 "${testcvs} add first-dir/a" \
+"${PROG} [a-z]*: nothing known about first-dir
+${PROG} [a-z]*: first-dir/a, version 1\.2, resurrected"
+ cd first-dir
+ # Now recover from the damage that the 142b8 test did.
+ dotest conflicts2-142b9 "${testcvs} rm -f a" \
+"${PROG} [a-z]*: scheduling .a. for removal
+${PROG} [a-z]*: use .${PROG} commit. to remove this file permanently"
+ else
+ # Haven't investigated this one.
+ dotest_fail conflicts2-142b8 "${testcvs} add first-dir/a" \
+"${PROG} add: in directory \.:
+${PROG} \[add aborted\]: there is no version here; do '${PROG} checkout' first"
+ cd first-dir
+ fi
+
+ # As before, 1.2 instead of 1.1 is a bug.
+ dotest conflicts2-142b10 "${testcvs} add a" "U a
+${PROG} [a-z]*: a, version 1\.2, resurrected"
+ # As with conflicts2-142b6, check that things are normal again.
+ dotest conflicts2-142b11 "${testcvs} -q update" ''
cd ../..
+ # END TESTS USING THE FILE A
# Now test that if one person removes a file and
# commits it, and a second person removes it, is it
@@ -5438,7 +6735,7 @@ ${PROG} [a-z]*: ignoring first-dir/sdir (CVS/Entries missing)"
dotest conflicts3-21 "${testcvs} -q update -d sdir" "U sdir/sfile"
rm -r sdir/CVS
- dotest conflicts3-22 "${testcvs} -q update" "? sdir"
+ dotest conflicts3-22 "${testcvs} -q update" "${QUESTION} sdir"
if test "x$remote" = xyes; then
# It isn't particularly swift that CVS prints this
# "cannot open CVS/Entries" where it has already printed
@@ -5456,6 +6753,37 @@ C sdir/sfile"
"${QUESTION} sdir"
fi
+ # Not that it should really affect much, but let's do the case
+ # where sfile has been removed. For example, suppose that sdir
+ # had been a CVS-controlled directory which was then removed
+ # by removing each file (and using update -P or some such). Then
+ # suppose that the build process creates an sdir directory which
+ # is not supposed to be under CVS.
+ rm -r sdir
+ dotest conflicts3-24 "${testcvs} -q update -d sdir" "U sdir/sfile"
+ rm sdir/sfile
+ dotest conflicts3-25 "${testcvs} rm sdir/sfile" \
+"${PROG} [a-z]*: scheduling .sdir/sfile. for removal
+${PROG} [a-z]*: use .${PROG} commit. to remove this file permanently"
+ dotest conflicts3-26 "${testcvs} ci -m remove sdir/sfile" \
+"Removing sdir/sfile;
+${TESTDIR}/cvsroot/first-dir/sdir/sfile,v <-- sfile
+new revision: delete; previous revision: 1\.1
+done"
+ rm -r sdir/CVS
+ dotest conflicts3-27 "${testcvs} -q update" "${QUESTION} sdir"
+ if test "x$remote" = xyes; then
+ # Regarding "cannot open CVS/Entries", see comments at
+ # conflicts3-23.
+ dotest conflicts3-28 "${testcvs} -q update -PdA" \
+"${QUESTION} sdir
+${PROG} update: in directory sdir:
+${PROG} update: cannot open CVS/Entries for reading: No such file or directory"
+ else
+ dotest conflicts3-28 "${testcvs} -q update -PdA" \
+"${QUESTION} sdir"
+ fi
+
cd ../..
rm -r 1 2
@@ -5906,10 +7234,7 @@ ${PROG} [a-z]*: Rebuilding administrative file database"
dotest modules2-5 "test -d ampermodule/second-dir" ''
# Test ability of cvs release to handle multiple arguments
- # Other CVS release tests:
- # info-cleanup-0 for "cvs -n release".
- # ignore-193 for the text of the question that cvs release asks.
- # Also for interactions with cvsignore.
+ # See comment at "release" for list of other cvs release tests.
cd ampermodule
if ${testcvs} release -d first-dir second-dir <<EOF >>${LOGFILE}
yes
@@ -5983,26 +7308,15 @@ U first-dir/amper1"
dotest modules2-16 "test -f combmodule/first-dir/amper1" ""
cd combmodule
rm -r first-dir
- # Might be possible to have a more graceful error message,
- # but at least for now there is no way to tell CVS that
+ # At least for now there is no way to tell CVS that
# some files/subdirectories come from one repository directory,
# and others from another.
- if test "$remote" = no; then
- dotest_fail modules2-17 "${testcvs} update -d" \
-"${PROG} [a-z]*: Updating \.
-${PROG} [a-z]*: Updating first-dir
-${PROG} \[[a-z]* aborted\]: cannot open directory ${TESTDIR}/cvsroot/third-dir/first-dir: No such file or directory"
- # Clean up the droppings left by the previous command.
- # This should definitely not be necessary (I think).
- rm -r first-dir
- else
- # This seems like a pretty sensible behavior to me, in the
- # sense that first-dir doesn't "really" exist within
- # third-dir, so CVS just acts as if there is nothing there
- # to do.
- dotest modules2-17 "${testcvs} update -d" \
-"${PROG} server: Updating \."
- fi
+ # This seems like a pretty sensible behavior to me, in the
+ # sense that first-dir doesn't "really" exist within
+ # third-dir, so CVS just acts as if there is nothing there
+ # to do.
+ dotest modules2-17 "${testcvs} update -d" \
+"${PROG} [a-z]*: Updating \."
cd ..
dotest modules2-18 "${testcvs} -q co combmodule" \
@@ -6164,7 +7478,7 @@ done"
if test "x$remote" = xyes; then
dotest_fail modules3-11b \
"${testcvs} -q update ${TESTDIR}/1/src/sub1/sub2/sub3/dir/file1" \
-"${PROG} .server aborted.: absolute pathname .${TESTDIR}/1/src/sub1/sub2/sub3/dir/file1. illegal for server"
+"absolute pathname .${TESTDIR}/1/src/sub1/sub2/sub3/dir. illegal for server"
fi # end of remote-only tests
cd ..
@@ -6332,6 +7646,30 @@ add-it
rm -rf ${CVSROOT_DIRNAME}/first-dir
;;
+ mkmodules-temp-file-removal)
+ # When a file listed in checkoutlist doesn't exist, cvs-1.10.4
+ # would fail to remove the CVSROOT/.#[0-9]* temporary file it
+ # creates while mkmodules is in the process of trying to check
+ # out the missing file.
+
+ mkdir 1; cd 1
+ dotest mtfr-1 "${testcvs} -Q co CVSROOT" ''
+ cd CVSROOT
+ echo no-such-file >> checkoutlist
+ dotest mtfr-2 "${testcvs} -Q ci -m. checkoutlist" \
+"Checking in checkoutlist;
+$CVSROOT_DIRNAME/CVSROOT/checkoutlist,v <-- checkoutlist
+new revision: 1\.2; previous revision: 1\.1
+done
+$PROG [a-z]*: Rebuilding administrative file database"
+
+ dotest mtfr-3 "echo $CVSROOT_DIRNAME/CVSROOT/.#[0-9]*" \
+ "$CVSROOT_DIRNAME/CVSROOT/\.#\[0-9\]\*"
+
+ cd ../..
+ rm -rf 1
+ ;;
+
cvsadm)
# These test check the content of CVS' administrative
# files as they are checked out in various configurations.
@@ -7812,22 +9150,15 @@ done"
U dir2d1/sub2d1/file1"
cd dir2d1
touch emptyfile
- # The fact that CVS lets us add a file here is a CVS bug, right?
- # I can just make this an error message (on the add and/or the
- # commit) without getting flamed, right?
- # Right?
- # Right?
+ # It doesn't make any sense to add a file (or do much of anything
+ # else) in Emptydir; Emptydir is a placeholder indicating that
+ # the working directory doesn't correspond to anything in
+ # the repository.
dotest emptydir-7 "${testcvs} add emptyfile" \
"${PROG} [a-z]*: scheduling file .emptyfile. for addition
${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
- dotest emptydir-8 "${testcvs} -q ci -m add" \
-"RCS file: ${TESTDIR}/cvsroot/CVSROOT/Emptydir/emptyfile,v
-done
-Checking in emptyfile;
-${TESTDIR}/cvsroot/CVSROOT/Emptydir/emptyfile,v <-- emptyfile
-initial revision: 1\.1
-done
-${PROG} [a-z]*: Rebuilding administrative file database"
+ dotest_fail emptydir-8 "${testcvs} -q ci -m add" \
+"${PROG} \[[a-z]* aborted\]: cannot check in to ${TESTDIR}/cvsroot/CVSROOT/Emptydir"
cd ..
rm -rf CVS dir2d1
@@ -8739,6 +10070,10 @@ Checking in first-dir/sdir10/ssdir/ssfile;
${TESTDIR}/cvsroot/first-dir/sdir10/ssdir/ssfile,v <-- ssfile
initial revision: 1\.1
done"
+ dotest errmsg2-18 "${testcvs} -Q tag test" ''
+
+ dotest_fail errmsg2-19 "${testcvs} annotate -rtest -Dyesterday" \
+"${PROG} \[[a-z]* aborted\]: rcsbuf_open: internal error"
cd ..
rm -r 1
@@ -8806,17 +10141,7 @@ done"
pass 177
fi
- if ${testcvs} editors >../ans178.tmp; then
- pass 178
- else
- fail 178
- fi
- cat ../ans178.tmp >>${LOGFILE}
- if test -s ../ans178.tmp; then
- fail 178a
- else
- pass 178a
- fi
+ dotest devcom-178 "${testcvs} editors" ""
if ${testcvs} edit abb; then
pass 179
@@ -8824,17 +10149,13 @@ done"
fail 179
fi
- if ${testcvs} editors >../ans180.tmp; then
- pass 180
- else
- fail 180
- fi
- cat ../ans180.tmp >>${LOGFILE}
- if test -s ../ans180.tmp; then
- pass 181
- else
- fail 181
- fi
+ # Here we test for the traditional ISO C ctime() date format.
+ # We assume the C locale; I guess that works provided we set
+ # LC_ALL at the start of this script but whether these
+ # strings should vary based on locale does not strike me as
+ # self-evident.
+ dotest devcom-180 "${testcvs} editors" \
+"abb ${username} [SMTWF][uoehra][neduit] [JFAMSOND][aepuco][nbrylgptvc] [0-9 ][0-9] [0-9:]* [0-9][0-9][0-9][0-9] GMT [-a-zA-Z_.0-9]* ${TESTDIR}/2/first-dir"
echo aaaa >>abb
if ${testcvs} ci -m modify abb >>${LOGFILE} 2>&1; then
@@ -8845,17 +10166,7 @@ done"
# Unedit of a file not being edited should be a noop.
dotest 182.5 "${testcvs} unedit abb" ''
- if ${testcvs} editors >../ans183.tmp; then
- pass 183
- else
- fail 183
- fi
- cat ../ans183.tmp >>${LOGFILE}
- if test -s ../ans183.tmp; then
- fail 184
- else
- pass 184
- fi
+ dotest devcom-183 "${testcvs} editors" ""
if test -w abb; then
fail 185
@@ -9083,7 +10394,7 @@ D _watched="
Fw2 _watched="
# Now write a few more lines, just as if we were a newer version
# of CVS implementing some new feature.
- cat <<EOF >>${CVSROOT_DIRNAME}/first-dir/CVS/fileattr
+ cat <<'EOF' >>${CVSROOT_DIRNAME}/first-dir/CVS/fileattr
Enew line here
G@#$^!@#=&
EOF
@@ -9112,6 +10423,31 @@ Fw1 _watched=
Enew line here
G@#..!@#=&"
+ # Now test disconnected "cvs edit" and the format of the
+ # CVS/Notify file.
+ if test "$remote" = yes; then
+ CVS_SERVER_SAVED=${CVS_SERVER}
+ CVS_SERVER=${TESTDIR}/cvs-none; export CVS_SERVER
+
+ # The ${DOTSTAR} matches the exact exec error message
+ # (which varies) and either "end of file from server"
+ # (if the process doing the exec exits before the parent
+ # gets around to sending data to it) or "broken pipe" (if it
+ # is the other way around).
+ dotest_fail devcom3-9a "${testcvs} edit w1" \
+"${PROG} \[edit aborted\]: cannot exec ${TESTDIR}/cvs-none: ${DOTSTAR}"
+ dotest devcom3-9b "test -w w1" ""
+ dotest devcom3-9c "cat CVS/Notify" \
+"Ew1 [SMTWF][uoehra][neduit] [JFAMSOND][aepuco][nbrylgptvc] [0-9 ][0-9] [0-9:]* [0-9][0-9][0-9][0-9] GMT [-a-zA-Z_.0-9]* ${TESTDIR}/1/first-dir EUC"
+ CVS_SERVER=${CVS_SERVER_SAVED}; export CVS_SERVER
+ dotest devcom3-9d "${testcvs} -q update" ""
+ dotest_fail devcom3-9e "test -f CVS/Notify" ""
+ dotest devcom3-9f "${testcvs} watchers w1" \
+"w1 ${username} tedit tunedit tcommit"
+ dotest devcom3-9g "${testcvs} unedit w1" ""
+ dotest devcom3-9h "${testcvs} watchers w1" ""
+ fi
+
cd ../..
# OK, now change the tab to a space, and see that CVS gives
# a reasonable error (this is database corruption but CVS should
@@ -9221,6 +10557,71 @@ C file1"
rm -rf ${CVSROOT_DIRNAME}/first-dir
;;
+ watch5)
+ # This test was designed to catch a problem in server
+ # mode where an 'cvs edit'd file disappeared from the
+ # CVS/Base directory when 'cvs status' or 'cvs update'
+ # was called on the file after the file was touched.
+ #
+ # This test is still here to prevent the bug from
+ # being reintroduced.
+ #
+ # The rationale for having CVS/Base stay around is that
+ # CVS/Base should be there if "cvs edit" has been run (this
+ # may be helpful as a "cvs editors" analogue, it is
+ # client-side and based on working directory not username;
+ # but more importantly, it isn't clear why a "cvs status"
+ # would act like an unedit, and even if it does, it would
+ # need to make the file read-only again).
+
+ mkdir watch5; cd watch5
+ dotest watch5-0a "${testcvs} -q co -l ." ''
+ mkdir first-dir
+ dotest watch5-0b "${testcvs} add first-dir" \
+"Directory ${TESTDIR}/cvsroot/first-dir added to the repository"
+
+ cd first-dir
+ dotest watch5-1 "${testcvs} watch on" ''
+ # This is just like the 173 test
+ touch file1
+ dotest watch5-2 "${testcvs} add file1" \
+"${PROG} [a-z]*: scheduling file .file1. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest watch5-3 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+done
+Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+initial revision: 1\.1
+done"
+ dotest watch5-4 "${testcvs} edit file1" ''
+ dotest watch5-5 "test -f CVS/Base/file1" ''
+ if ${testcvs} status file1 >>${LOGFILE} 2>&1; then
+ pass watch5-6
+ else
+ fail watch5-6
+ fi
+ dotest watch5-7 "test -f CVS/Base/file1" ''
+
+ # Here's where the file used to dissappear
+ touch file1
+ if ${testcvs} status file1 >>${LOGFILE} 2>&1; then
+ pass watch5-8
+ else
+ fail watch5-8
+ fi
+ dotest watch5-10 "test -f CVS/Base/file1" ''
+
+ # Make sure update won't remove the file either
+ touch file1
+ dotest watch5-11 "${testcvs} -q up" ''
+ dotest watch5-12 "test -f CVS/Base/file1" ''
+
+ cd ../..
+ rm -r watch5
+ rm -rf ${CVSROOT_DIRNAME}/first-dir
+ ;;
+
unedit-without-baserev)
mkdir 1; cd 1
module=x
@@ -9250,7 +10651,7 @@ ${PROG} unedit: run update to complete the unedit"
# SunOS4.1.4 systems make it this far, but with a corrupted
# CVS/Entries file. Demonstrate the corruption!
dotest unedit-without-baserev-5 "cat CVS/Entries" \
- "/$file/1\.1\.1\.1/.*"
+ "/$file/1\.1\.1\.1/${DOTSTAR}"
if test "$remote" = yes; then
dotest unedit-without-baserev-6 "${testcvs} -q update" "U m"
@@ -9476,11 +10877,18 @@ Are you sure you want to release (and delete) directory .second-dir': "
binfiles)
# Test cvs's ability to handle binary files.
+ # List of binary file tests:
+ # * conflicts, "cvs admin": binfiles
+ # * branching and joining: binfiles2
+ # * adding and removing files: binfiles3
+ # * -k wrappers: binwrap, binwrap2, binwrap3
+ # * "cvs import" and wrappers: binwrap, binwrap2, binwrap3
+ # * -k option to "cvs import": none yet, as far as I know.
mkdir ${CVSROOT_DIRNAME}/first-dir
mkdir 1; cd 1
dotest binfiles-1 "${testcvs} -q co first-dir" ''
- awk 'BEGIN { printf "%c%c%c%c%c%c", 2, 10, 137, 0, 13, 10 }' \
- </dev/null >binfile.dat
+ awk 'BEGIN { printf "%c%c%c@%c%c", 2, 10, 137, 13, 10 }' \
+ </dev/null | tr '@' '\000' >binfile.dat
cat binfile.dat binfile.dat >binfile2.dat
cd first-dir
cp ../binfile.dat binfile
@@ -9577,7 +10985,6 @@ done"
dotest binfiles-13 "${testcvs} -q update -A" ''
cd ../..
- rm -r 1
mkdir 3
cd 3
@@ -9713,8 +11120,14 @@ keyword substitution: v
total revisions: 1
============================================================================="
+ # Check that the contents were right. This isn't the hard case
+ # (in which RCS_delete_revs does a diff), but might as well.
+ dotest binfiles-o4 "${testcvs} -q update binfile" "U binfile"
+ dotest binfiles-o5 "cmp binfile ../../1/binfile.dat" ""
+
cd ../..
rm -rf ${CVSROOT_DIRNAME}/first-dir
+ rm -r 1
rm -r 2
;;
@@ -9746,8 +11159,8 @@ total revisions: 1
# each be distinct from each other. We also make sure to include
# a few likely end-of-line patterns to make sure nothing is
# being munged as if in text mode.
- awk 'BEGIN { printf "%c%c%c%c%c%c", 2, 10, 137, 0, 13, 10 }' \
- </dev/null >../binfile
+ awk 'BEGIN { printf "%c%c%c@%c%c", 2, 10, 137, 13, 10 }' \
+ </dev/null | tr '@' '\000' >../binfile
cat ../binfile ../binfile >../binfile2
cat ../binfile2 ../binfile >../binfile3
@@ -9902,6 +11315,96 @@ checkin
rm -r 1
;;
+ binfiles3)
+ # More binary file tests, especially removing, adding, &c.
+ # See "binfiles" for a list of binary file tests.
+ mkdir ${CVSROOT_DIRNAME}/first-dir
+ mkdir 1; cd 1
+ dotest binfiles3-1 "${testcvs} -q co first-dir" ''
+ awk 'BEGIN { printf "%c%c%c@%c%c", 2, 10, 137, 13, 10 }' \
+ </dev/null | tr '@' '\000' >binfile.dat
+ cd first-dir
+ echo hello >file1
+ dotest binfiles3-2 "${testcvs} add file1" \
+"${PROG} [a-z]*: scheduling file .file1. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest binfiles3-3 "${testcvs} -q ci -m add-it" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+done
+Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+initial revision: 1\.1
+done"
+ rm file1
+ dotest binfiles3-4 "${testcvs} rm file1" \
+"${PROG} [a-z]*: scheduling .file1. for removal
+${PROG} [a-z]*: use .${PROG} commit. to remove this file permanently"
+ dotest binfiles3-5 "${testcvs} -q ci -m remove-it" \
+"Removing file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: delete; previous revision: 1\.1
+done"
+ cp ../binfile.dat file1
+ dotest binfiles3-6 "${testcvs} add -kb file1" \
+"${PROG} [a-z]*: re-adding file file1 (in place of dead revision 1\.2)
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ # The idea behind this test is to make sure that the file
+ # gets opened in binary mode to send to "cvs ci".
+ dotest binfiles3-6a "cat CVS/Entries" \
+"/file1/0/[A-Za-z0-9 :]*/-kb/
+D"
+ # TODO: This just tests the case where the old keyword
+ # expansion mode is the default (RCS_getexpand == NULL
+ # in checkaddfile()); should also test the case in which
+ # we are changing it from one non-default value to another.
+ dotest binfiles3-7 "${testcvs} -q ci -m readd-it" \
+"${PROG} [a-z]*: changing keyword expansion mode to -kb
+Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.3; previous revision: 1\.2
+done"
+ dotest binfiles3-8 "${testcvs} -q log -h -N file1" "
+RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+Working file: file1
+head: 1\.3
+branch:
+locks: strict
+access list:
+keyword substitution: b
+total revisions: 3
+============================================================================="
+
+ # OK, now test admin -o on a binary file. See "admin"
+ # test for a more complete list of admin -o tests.
+ cp ${TESTDIR}/1/binfile.dat ${TESTDIR}/1/binfile4.dat
+ echo '%%$$##@@!!jjiiuull' | tr j '\000' >>${TESTDIR}/1/binfile4.dat
+ cp ${TESTDIR}/1/binfile4.dat ${TESTDIR}/1/binfile5.dat
+ echo 'aawwee%$$##@@!!jjil' | tr w '\000' >>${TESTDIR}/1/binfile5.dat
+
+ cp ../binfile4.dat file1
+ dotest binfiles3-9 "${testcvs} -q ci -m change" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.4; previous revision: 1\.3
+done"
+ cp ../binfile5.dat file1
+ dotest binfiles3-10 "${testcvs} -q ci -m change" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.5; previous revision: 1\.4
+done"
+ dotest binfiles3-11 "${testcvs} admin -o 1.3::1.5 file1" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+deleting revision 1\.4
+done"
+ dotest binfiles3-12 "${testcvs} -q update -r 1.3 file1" "U file1"
+ dotest binfiles3-13 "cmp file1 ${TESTDIR}/1/binfile.dat" ""
+
+ cd ../..
+ rm -r 1
+ rm -rf ${CVSROOT_DIRNAME}/first-dir
+ ;;
+
mcopy)
# See comment at "mwrap" test for list of other wrappers tests.
# Test cvs's ability to handle nonmergeable files specified with
@@ -10447,7 +11950,24 @@ done"
cd ../..
cd m1/first-dir
echo "changed in m1" >aa
- dotest_fail mwrap-7 "${testcvs} -nq update" "C aa"
+ if test "$remote" = no; then
+ dotest mwrap-7 "${testcvs} -nq update" \
+"U aa
+${PROG} [a-z]*: nonmergeable file needs merge
+${PROG} [a-z]*: revision 1\.2 from repository is now in aa
+${PROG} [a-z]*: file from working directory is now in \.#aa\.1\.1
+C aa"
+ else
+ # The tagged text code swallows up "U aa" but isn't yet up to
+ # trying to figure out how it interacts with the "C aa" and
+ # other stuff. The whole deal of having both is pretty iffy.
+ dotest mwrap-7 "${testcvs} -nq update" \
+"${PROG} [a-z]*: nonmergeable file needs merge
+${PROG} [a-z]*: revision 1\.2 from repository is now in aa
+${PROG} [a-z]*: file from working directory is now in \.#aa\.1\.1
+C aa
+U aa"
+ fi
dotest mwrap-8 "${testcvs} -q update" \
"U aa
${PROG} [a-z]*: nonmergeable file needs merge
@@ -10630,6 +12150,7 @@ ${PROG} [a-z]*: Rebuilding administrative file database"
fi
cd ..
rm -r wnt
+ rm $HOME/.cvsrc
rm -rf ${CVSROOT_DIRNAME}/first-dir
;;
@@ -10639,8 +12160,6 @@ ${PROG} [a-z]*: Rebuilding administrative file database"
# Tests to add:
# -F to move
- # -d
- # rtag
mkdir 1; cd 1
dotest taginfo-1 "${testcvs} -q co CVSROOT" "U CVSROOT/${DOTSTAR}"
@@ -10708,6 +12227,16 @@ ${PROG} \[[a-z]* aborted\]: correct the above errors first!"
# specified or not.
dotest taginfo-13 "${testcvs} -nq tag would-be-tag" "T file1"
+ # Deleting: the cases are basically either the tag existed,
+ # or it didn't exist.
+ dotest taginfo-14 "${testcvs} -q tag -d tag1" "D file1"
+ dotest taginfo-15 "${testcvs} -q tag -d tag1" ""
+
+ # Likewise with rtag.
+ dotest taginfo-16 "${testcvs} -q rtag tag1 first-dir" ""
+ dotest taginfo-17 "${testcvs} -q rtag -d tag1 first-dir" ""
+ dotest taginfo-18 "${testcvs} -q rtag -d tag1 first-dir" ""
+
# The "br" example should be passing 1.1.2 or 1.1.0.2.
# But it turns out that is very hard to implement, since
# check_fileproc doesn't know what branch number it will
@@ -10722,7 +12251,12 @@ ${PROG} \[[a-z]* aborted\]: correct the above errors first!"
dotest taginfo-examine "cat ${TESTDIR}/1/taglog" \
"tag1 add ${TESTDIR}/cvsroot/first-dir file1 1.1
br add ${TESTDIR}/cvsroot/first-dir file1 1.1
-brtag mov ${TESTDIR}/cvsroot/first-dir file1 1.1.2.1"
+brtag mov ${TESTDIR}/cvsroot/first-dir file1 1.1.2.1
+tag1 del ${TESTDIR}/cvsroot/first-dir file1 1.1
+tag1 del ${TESTDIR}/cvsroot/first-dir
+tag1 add ${TESTDIR}/cvsroot/first-dir file1 1.1
+tag1 del ${TESTDIR}/cvsroot/first-dir file1 1.1
+tag1 del ${TESTDIR}/cvsroot/first-dir"
cd ..
cd CVSROOT
@@ -10859,6 +12393,7 @@ U file1'
# -N: log, log2, admin-19a-log
# -b, -r: log
# -d: rcs
+ # -s, -R: rcs3
# Check in a file with a few revisions and branches.
mkdir ${CVSROOT_DIRNAME}/first-dir
@@ -11003,6 +12538,28 @@ description:
${log_rev3}
${log_trailer}"
+ dotest log-14a "${testcvs} log -rHEAD file1" \
+"${log_header}
+${log_tags}
+${log_header2}
+total revisions: 5; selected revisions: 1
+description:
+${log_rev3}
+${log_trailer}"
+
+ # The user might not realize that "-r" must not take a space.
+ # In the error message, HEAD is a file name, not a tag name (which
+ # might be confusing itself).
+ dotest_fail log-14b "${testcvs} log -r HEAD file1" \
+"${PROG} [a-z]*: nothing known about HEAD
+${log_header}
+${log_tags}
+${log_header2}
+total revisions: 5; selected revisions: 1
+description:
+${log_rev3}
+${log_trailer}"
+
dotest log-15 "${testcvs} log -r1.2 file1" \
"${log_header}
${log_tags}
@@ -11182,6 +12739,9 @@ date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
dotest log2-7 "${testcvs} admin -t${TESTDIR}/descrip file1" \
"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
done"
+ dotest_fail log2-7a "${testcvs} admin -t${TESTDIR}/nonexist file1" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+${PROG} \[[a-z]* aborted\]: can't stat ${TESTDIR}/nonexist: No such file or directory"
dotest log2-8 "${testcvs} log -N file1" "
RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
Working file: file1
@@ -11204,6 +12764,11 @@ date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
# See comments in cvs.texinfo for a few more notes on this.
if test "x$remote" = xno; then
+ # TODO: `cvs admin -t "my message" file1' is a request to
+ # read the message from stdin and to operate on two files.
+ # Should test that there is an error because "my message"
+ # doesn't exist.
+
if echo change from stdin | ${testcvs} admin -t -q file1
then
pass log2-9
@@ -11240,6 +12805,7 @@ date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
# Tests of "cvs annotate". See also:
# basica-10 A simple annotate test
# rcs Annotate and the year 2000
+ # keywordlog Annotate and $Log.
mkdir 1; cd 1
dotest ann-1 "${testcvs} -q co -l ." ''
mkdir first-dir
@@ -11471,8 +13037,26 @@ ${testcvs} -d ${TESTDIR}/crerepos release -d CVSROOT >>${LOGFILE}; then
mkdir crerepos
mkdir crerepos/CVSROOT
+ # Use :ext: rather than :fork:. Most of the tests use :fork:,
+ # so we want to make sure that we test :ext: _somewhere_.
+
+ # Maybe a bit dubious in the sense that people need to
+ # have rsh working to run the tests, but at least it
+ # isn't inetd :-). Might want to think harder about this -
+ # maybe try :ext:, and if it fails, print a (single, nice)
+ # message and fall back to :fork:. Maybe testing :ext:
+ # with our own CVS_RSH rather than worrying about a system one
+ # would do the trick.
+
+ # Note that we set CVS_SERVER at the beginning.
CREREPOS_ROOT=:ext:`hostname`:${TESTDIR}/crerepos
+ # If we're going to do remote testing, make sure 'rsh' works first.
+ host="`hostname`"
+ if test "x`${CVS_RSH-rsh} $host -n 'echo hi'`" != "xhi"; then
+ echo "ERROR: cannot test remote CVS, because \`rsh $host' fails." >&2
+ exit 1
+ fi
fi
if test "x$remote" = "xno"; then
@@ -11491,6 +13075,10 @@ ${testcvs} -d ${TESTDIR}/crerepos release -d CVSROOT >>${LOGFILE}; then
else # remote
# Test that CVS rejects a relative path in CVSROOT.
mkdir 1; cd 1
+ # Note that having the client reject the pathname (as :fork:
+ # does), does _not_ test for the bugs we are trying to catch
+ # here. The point is that malicious clients might send all
+ # manner of things and the server better protect itself.
dotest_fail crerepos-6a \
"${testcvs} -q -d :ext:`hostname`:../crerepos get ." \
"Root ../crerepos must be an absolute pathname"
@@ -11560,31 +13148,17 @@ U first-dir/file1"
dotest crerepos-17 "${testcvs} -d ${CREREPOS_ROOT} co crerepos-dir" \
"${PROG} [a-z]*: Updating crerepos-dir
U crerepos-dir/cfile"
-
- if test x`cat crerepos-dir/CVS/Repository` = xcrerepos-dir; then
- # RELATIVE_REPOS
- # Fatal error so that we don't go traipsing through the
- # directories which happen to have the same names from the
- # wrong repository.
- dotest_fail crerepos-18 "${testcvs} -q update" \
-"${PROG} \[[a-z]* aborted\]: cannot open directory ${TESTDIR}/cvsroot/crerepos-dir: .*" ''
- else
- if test "$remote" = no; then
- # The lack of an error doesn't mean CVS is really
- # working (things are getting logged to the wrong
- # history file and such).
- dotest crerepos-18 "${testcvs} -q update" ''
- else
- # Fatal error so that we don't go traipsing through the
- # directories which happen to have the same names from the
- # wrong repository.
- dotest_fail crerepos-18 "${testcvs} -q update" \
-"protocol error: directory .${TESTDIR}/crerepos/crerepos-dir. not within root .${TESTDIR}/cvsroot."
- fi
- fi
+ dotest crerepos-18 "${testcvs} update" \
+"${PROG} [a-z]*: Updating first-dir
+${PROG} [a-z]*: Updating crerepos-dir"
cd ..
+ if test "$keep" = yes; then
+ echo Keeping ${TESTDIR} and exiting due to --keep
+ exit 0
+ fi
+
rm -r 1
rm -rf ${CVSROOT_DIRNAME}/first-dir ${TESTDIR}/crerepos
;;
@@ -12145,6 +13719,38 @@ EOF
dotest rcs2-5 "cat ${TESTDIR}/rcs4.tmp" \
"${PROG} \[[a-z]* aborted\]: Can't parse date/time: 2003-02-29 11:30 UT"
fi
+
+ dotest rcs2-6 "${testcvs} -q update -p -D 2007-01-07 file1" \
+"head revision"
+ # This assumes that the clock of the machine running the tests
+ # is set to at least the year 1998 or so. There don't seem
+ # to be a lot of ways to test the relative date code (short
+ # of something like LD_LIBRARY_PRELOAD'ing in our own
+ # getttimeofday, or hacking the CVS source with testing
+ # features, which always seems to be problematic since then
+ # someone feels like documenting them and things go downhill
+ # from there).
+ #
+ # Hmm, if this test is run on the 31st of the month, and 100
+ # months from now is a month with only 30 days (e.g. run on
+ # 31 May 1999), it seems to fail.
+ #
+ # Sigh.
+ if ${testcvs} -q update -p -D '100 months' file1 \
+ >${TESTDIR}/rcs4.tmp 2>&1
+ then
+ dotest rcs2-7 "cat ${TESTDIR}/rcs4.tmp" "head revision"
+ else
+ fail rcs2-7
+ fi
+ if ${testcvs} -q update -p -D '8 years' file1 \
+ >${TESTDIR}/rcs4.tmp 2>&1
+ then
+ dotest rcs2-8 "cat ${TESTDIR}/rcs4.tmp" "head revision"
+ else
+ fail rcs2-8
+ fi
+
rm ${TESTDIR}/rcs4.tmp
cd ..
@@ -12152,6 +13758,440 @@ EOF
rm -rf ${CVSROOT_DIRNAME}/first-dir
;;
+ rcs3)
+ # More RCS file tests, in particular at least some of the
+ # error handling issues.
+ mkdir ${CVSROOT_DIRNAME}/first-dir
+ cat <<EOF >${CVSROOT_DIRNAME}/first-dir/file1,v
+head 1.1; access; symbols; locks; expand o; 1.1 date 2007.03.20.04.03.02
+; author jeremiah ;state ; branches; next;desc@@1.1log@@text@head@
+EOF
+ mkdir 1; cd 1
+ # CVS requires whitespace between "desc" and its value.
+ # The rcsfile(5) manpage doesn't really seem to answer the
+ # question one way or the other (it has a grammar but almost
+ # nothing about lexical analysis).
+ dotest_fail rcs3-1 "${testcvs} -q co first-dir" \
+"${PROG} \[[a-z]* aborted\]: unexpected end of file reading ${TESTDIR}/cvsroot/first-dir/file1,v"
+ cat <<EOF >${CVSROOT_DIRNAME}/first-dir/file1,v
+head 1.1; access; symbols; locks; expand o; 1.1 date 2007.03.20.04.03.02
+; author jeremiah ;state ; branches; next;desc @@1.1log@@text@head@
+EOF
+ # Whitespace issues, likewise.
+ dotest_fail rcs3-2 "${testcvs} -q co first-dir" \
+"${PROG} \[[a-z]* aborted\]: unexpected '.x6c' reading revision number in RCS file ${TESTDIR}/cvsroot/first-dir/file1,v"
+ cat <<EOF >${CVSROOT_DIRNAME}/first-dir/file1,v
+head 1.1; access; symbols; locks; expand o; 1.1 date 2007.03.20.04.03.02
+; author jeremiah ;state ; branches; next;desc @@1.1 log@@text@head@
+EOF
+ # Charming array of different messages for similar
+ # whitespace issues (depending on where the whitespace is).
+ dotest_fail rcs3-3 "${testcvs} -q co first-dir" \
+"${PROG} \[[a-z]* aborted\]: EOF while looking for value in RCS file ${TESTDIR}/cvsroot/first-dir/file1,v"
+ cat <<EOF >${CVSROOT_DIRNAME}/first-dir/file1,v
+head 1.1; access; symbols; locks; expand o; 1.1 date 2007.03.20.04.03.02
+; author jeremiah ;state ; branches; next;desc @@1.1 log @@text @head@
+EOF
+ dotest rcs3-4 "${testcvs} -q co first-dir" 'U first-dir/file1'
+ if test "$remote" = no; then
+ # Ouch, didn't expect this one. FIXCVS. Or maybe just remove
+ # the feature, if this is a -s problem?
+ dotest_fail rcs3-5 "${testcvs} log -s nostate first-dir/file1" \
+".*[Aa]ssertion.*failed${DOTSTAR}" ".*failed assertion${DOTSTAR}"
+ else # remote
+ # Is this a reaction to the lack of TopLevelAdmin or something?
+ # Seems pretty strange to me. Seems vaguely similar to the
+ # "no repository" message in errmsg2-16 although I'm leaving
+ # it here in case there is a difference between "cvs add" and a
+ # normal start_recursion command like "cvs log".
+ dotest_fail rcs3-5 "${testcvs} log -s nostate first-dir/file1" \
+"${PROG} log: cannot open CVS/Entries for reading: No such file or directory
+${PROG} \[log aborted\]: no repository"
+ cd first-dir
+ dotest_fail rcs3-5a "${testcvs} log -s nostate file1" \
+"${DOTSTAR}ssertion.*failed${DOTSTAR}" "${DOTSTAR}failed assertion${DOTSTAR}"
+ cd ..
+ fi # remote
+
+ # See remote code above for rationale for cd.
+ cd first-dir
+ dotest rcs3-6 "${testcvs} log -R file1" \
+"${TESTDIR}/cvsroot/first-dir/file1,v"
+
+ # OK, now put an extraneous '\0' at the end.
+ awk </dev/null 'BEGIN { printf "@%c", 10 }' | tr '@' '\000' \
+ >>${CVSROOT_DIRNAME}/first-dir/file1,v
+ dotest_fail rcs3-7 "${testcvs} log -s nostate file1" \
+"${PROG} \[[a-z]* aborted\]: unexpected '.x0' reading revision number in RCS file ${TESTDIR}/cvsroot/first-dir/file1,v"
+
+ cd ../..
+ rm -r 1
+ rm -rf ${CVSROOT_DIRNAME}/first-dir
+ ;;
+
+ lockfiles)
+ # Tests of CVS lock files.
+ # TODO-maybe: Add a test where we arrange for a loginfo
+ # script (or some such) to ensure that locks are in place
+ # so then we can see how they are behaving.
+
+ mkdir 1; cd 1
+ mkdir sdir
+ mkdir sdir/ssdir
+ echo file >sdir/ssdir/file1
+ dotest lockfiles-1 \
+"${testcvs} -Q import -m import-it first-dir bar baz" ""
+ cd ..
+
+ mkdir 2; cd 2
+ dotest lockfiles-2 "${testcvs} -q co first-dir" \
+"U first-dir/sdir/ssdir/file1"
+ dotest lockfiles-3 "${testcvs} -Q co CVSROOT" ""
+ cd CVSROOT
+ echo "LockDir=${TESTDIR}/locks" >config
+ dotest lockfiles-4 "${testcvs} -q ci -m config-it" \
+"Checking in config;
+${TESTDIR}/cvsroot/CVSROOT/config,v <-- config
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
+done
+${PROG} [a-z]*: Rebuilding administrative file database"
+ cd ../first-dir/sdir/ssdir
+ # The error message appears twice because Lock_Cleanup only
+ # stops recursing after the first attempt.
+ dotest_fail lockfiles-5 "${testcvs} -q update" \
+"${PROG} \[[a-z]* aborted\]: cannot stat ${TESTDIR}/locks: No such file or directory
+${PROG} \[[a-z]* aborted\]: cannot stat ${TESTDIR}/locks: No such file or directory"
+ mkdir ${TESTDIR}/locks
+ chmod u=rwx,g=r,o= ${TESTDIR}/locks
+ umask 0077
+ CVSUMASK=0077; export CVSUMASK
+ dotest lockfiles-6 "${testcvs} -q update" ""
+ # TODO: should also be testing that CVS continues to honor the
+ # umask and CVSUMASK normally. In the case of the umask, CVS
+ # doesn't seem to use it for much (although it perhaps should).
+ dotest lockfiles-7 "ls ${TESTDIR}/locks/first-dir/sdir/ssdir" ""
+
+ # The policy is that when CVS creates new lock directories, they
+ # inherit the permissions from the parent directory. CVSUMASK
+ # isn't right, because typically the reason for LockDir is to
+ # use a different set of permissions.
+ dotest lockfiles-7a "ls -ld ${TESTDIR}/locks/first-dir" \
+"drwxr----- .*first-dir"
+ dotest lockfiles-7b "ls -ld ${TESTDIR}/locks/first-dir/sdir/ssdir" \
+"drwxr----- .*first-dir/sdir/ssdir"
+
+ cd ../../..
+ dotest lockfiles-8 "${testcvs} -q update" ""
+
+ cd CVSROOT
+ echo "# nobody here but us comments" >config
+ dotest lockfiles-cleanup-1 "${testcvs} -q ci -m config-it" \
+"Checking in config;
+${TESTDIR}/cvsroot/CVSROOT/config,v <-- config
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
+done
+${PROG} [a-z]*: Rebuilding administrative file database"
+ cd ../..
+ # Perhaps should restore the umask and CVSUMASK to what they
+ # were before. But the other tests "should" not care about them...
+ umask 0077
+ unset CVSUMASK
+ rm -r ${TESTDIR}/locks
+ rm -r 1 2
+ rm -rf ${CVSROOT_DIRNAME}/first-dir
+ ;;
+
+ backuprecover)
+ # Tests to make sure we get the expected behavior
+ # when we recover a repository from an old backup
+ #
+ # Details:
+ # Backup will be older than some developer's workspaces
+ # This means the first attempt at an update will fail
+ # The workaround for this is to replace the CVS
+ # directories with those from a "new" checkout from
+ # the recovered repository. Due to this, multiple
+ # merges should cause conflicts (the same data
+ # will be merged more than once).
+ # A workspace updated before the date of the recovered
+ # copy will not need any extra attention
+ #
+ # Note that backuprecover-15 is probably a failure case
+ # If nobody else had a more recent update, the data would be lost
+ # permanently
+ # Granted, the developer should have been notified not to do this
+ # by now, but still...
+ #
+ mkdir backuprecover; cd backuprecover
+ mkdir 1; cd 1
+ dotest backuprecover-1 "${testcvs} -q co -l ." ''
+ mkdir first-dir
+ dotest backuprecover-2 "${testcvs} add first-dir" \
+"Directory ${TESTDIR}/cvsroot/first-dir added to the repository"
+ cd first-dir
+ mkdir dir
+ dotest backuprecover-3 "${testcvs} add dir" \
+"Directory ${TESTDIR}/cvsroot/first-dir/dir added to the repository"
+ touch file1 dir/file2
+ dotest backuprecover-4 "${testcvs} -q add file1 dir/file2" \
+"${PROG} [a-z]*: use '${PROG} commit' to add these files permanently"
+ dotest backuprecover-5 "${testcvs} -q ci -mtest" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+done
+Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+initial revision: 1\.1
+done
+RCS file: ${TESTDIR}/cvsroot/first-dir/dir/file2,v
+done
+Checking in dir/file2;
+${TESTDIR}/cvsroot/first-dir/dir/file2,v <-- file2
+initial revision: 1\.1
+done"
+ echo "Line one" >>file1
+ echo " is the place" >>file1
+ echo " we like to begin" >>file1
+ echo "Anything else" >>file1
+ echo " looks like" >>file1
+ echo " a sin" >>file1
+ echo "File 2" >>dir/file2
+ echo " is the place" >>dir/file2
+ echo " the rest of it goes" >>dir/file2
+ echo "Why I don't use" >>dir/file2
+ echo " something like 'foo'" >>dir/file2
+ echo " God only knows" >>dir/file2
+ dotest backuprecover-6 "${testcvs} -q ci -mtest" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.2; previous revision: 1\.1
+done
+Checking in dir/file2;
+${TESTDIR}/cvsroot/first-dir/dir/file2,v <-- file2
+new revision: 1\.2; previous revision: 1\.1
+done"
+
+ # Simulate the lazy developer
+ # (he did some work but didn't check it in...)
+ cd ../..
+ mkdir 2; cd 2
+ dotest backuprecover-7 "${testcvs} -Q co first-dir" ''
+ cd first-dir
+ sed -e"s/looks like/just looks like/" file1 >tmp; mv tmp file1
+ sed -e"s/don't use/don't just use/" dir/file2 >tmp; mv tmp dir/file2
+
+ # developer 1 is on a roll
+ cd ../../1/first-dir
+ echo "I need some more words" >>file1
+ echo " to fill up this space" >>file1
+ echo " anything else would be a disgrace" >>file1
+ echo "My rhymes cross many boundries" >>dir/file2
+ echo " this time it's files" >>dir/file2
+ echo " a word that fits here would be something like dials" >>dir/file2
+ dotest backuprecover-8 "${testcvs} -q ci -mtest" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.3; previous revision: 1\.2
+done
+Checking in dir/file2;
+${TESTDIR}/cvsroot/first-dir/dir/file2,v <-- file2
+new revision: 1\.3; previous revision: 1\.2
+done"
+
+ # Save a backup copy
+ cp -r ${TESTDIR}/cvsroot/first-dir ${TESTDIR}/cvsroot/backup
+
+ # Simulate developer 3
+ cd ../..
+ mkdir 3; cd 3
+ dotest backuprecover-9a "${testcvs} -Q co first-dir" ''
+ cd first-dir
+ echo >>file1
+ echo >>dir/file2
+ echo "Developer 1 makes very lame rhymes" >>file1
+ echo " I think he should quit and become a mime" >>file1
+ echo "What the %*^# kind of rhyme crosses a boundry?" >>dir/file2
+ echo " I think you should quit and get a job in the foundry" >>dir/file2
+ dotest backuprecover-9b "${testcvs} -q ci -mtest" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.4; previous revision: 1\.3
+done
+Checking in dir/file2;
+${TESTDIR}/cvsroot/first-dir/dir/file2,v <-- file2
+new revision: 1\.4; previous revision: 1\.3
+done"
+
+ # Developer 4 so we can simulate a conflict later...
+ cd ../..
+ mkdir 4; cd 4
+ dotest backuprecover-10 "${testcvs} -Q co first-dir" ''
+ cd first-dir
+ sed -e"s/quit and/be fired so he can/" dir/file2 >tmp; mv tmp dir/file2
+
+ # And back to developer 1
+ cd ../../1/first-dir
+ dotest backuprecover-11 "${testcvs} -Q update" ''
+ echo >>file1
+ echo >>dir/file2
+ echo "Oh yeah, well rhyme this" >>file1
+ echo " developer three" >>file1
+ echo " you want opposition" >>file1
+ echo " you found some in me!" >>file1
+ echo "I'll give you mimes" >>dir/file2
+ echo " and foundries galore!" >>dir/file2
+ echo " your head will spin" >>dir/file2
+ echo " once you find what's in store!" >>dir/file2
+ dotest backuprecover-12 "${testcvs} -q ci -mtest" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.5; previous revision: 1\.4
+done
+Checking in dir/file2;
+${TESTDIR}/cvsroot/first-dir/dir/file2,v <-- file2
+new revision: 1\.5; previous revision: 1\.4
+done"
+
+ # developer 3'll do a bit of work that never gets checked in
+ cd ../../3/first-dir
+ dotest backuprecover-13 "${testcvs} -Q update" ''
+ sed -e"s/very/some extremely/" file1 >tmp; mv tmp file1
+ dotest backuprecover-14 "${testcvs} -q ci -mtest" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.6; previous revision: 1\.5
+done"
+ echo >>file1
+ echo "Tee hee hee hee" >>file1
+ echo >>dir/file2
+ echo "Find what's in store?" >>dir/file2
+ echo " Oh, I'm so sure!" >>dir/file2
+ echo " You've got an ill, and I have the cure!" >>dir/file2
+
+ # Slag the original and restore it a few revisions back
+ rm -rf ${TESTDIR}/cvsroot/first-dir
+ mv ${TESTDIR}/cvsroot/backup ${TESTDIR}/cvsroot/first-dir
+
+ # Have developer 1 try an update and lose some data
+ #
+ # Feel free to imagine the horrific scream of despair
+ cd ../../1/first-dir
+ dotest backuprecover-15 "${testcvs} update" \
+"${PROG} [a-z]*: Updating .
+U file1
+${PROG} [a-z]*: Updating dir
+U dir/file2"
+
+ # Developer 3 tries the same thing (he has an office)
+ # but fails without losing data since all of his files have
+ # uncommitted changes
+ cd ../../3/first-dir
+ dotest_fail backuprecover-16 "${testcvs} update" \
+"${PROG} [a-z]*: Updating \.
+${PROG} \[[a-z]* aborted\]: could not find desired version 1\.6 in ${TESTDIR}/cvsroot/first-dir/file1,v"
+
+ # create our workspace fixin' script
+ cd ../..
+ echo \
+"#!/bin/sh
+
+# This script will copy the CVS database dirs from the checked out
+# version of a newly recovered repository and replace the CVS
+# database dirs in a workspace with later revisions than those in the
+# recovered repository
+cd repos-first-dir
+DATADIRS=\`find . -name CVS\`
+cd ../first-dir
+find . -name CVS |xargs rm -rf
+for file in \${DATADIRS}; do
+ cp -r ../repos-first-dir/\${file} \${file}
+done" >fixit
+
+ # We only need to fix the workspaces of developers 3 and 4
+ # (1 lost all her data and 2 has an update date from
+ # before the date the backup was made)
+ cd 3
+ dotest backuprecover-17 \
+ "${testcvs} -Q co -d repos-first-dir first-dir" ''
+ cd ../4
+ dotest backuprecover-18 \
+ "${testcvs} -Q co -d repos-first-dir first-dir" ''
+ sh ../fixit
+ cd ../3; sh ../fixit
+
+ # (re)commit developer 3's stuff
+ cd first-dir
+ dotest backuprecover-19 "${testcvs} -q ci -mrecover/merge" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.4; previous revision: 1\.3
+done
+Checking in dir/file2;
+${TESTDIR}/cvsroot/first-dir/dir/file2,v <-- file2
+new revision: 1\.4; previous revision: 1\.3
+done"
+
+ # and we should get a conflict on developer 4's stuff
+ cd ../../4/first-dir
+ dotest backuprecover-20 "${testcvs} update" \
+"${PROG} [a-z]*: Updating \.
+RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+retrieving revision 1\.3
+retrieving revision 1\.4
+Merging differences between 1\.3 and 1\.4 into file1
+rcsmerge: warning: conflicts during merge
+${PROG} [a-z]*: conflicts found in file1
+C file1
+${PROG} [a-z]*: Updating dir
+RCS file: ${TESTDIR}/cvsroot/first-dir/dir/file2,v
+retrieving revision 1\.3
+retrieving revision 1\.4
+Merging differences between 1\.3 and 1\.4 into file2
+rcsmerge: warning: conflicts during merge
+${PROG} [a-z]*: conflicts found in dir/file2
+C dir/file2"
+ sed -e \
+"/^<<<<<<</,/^=======/d
+/^>>>>>>>/d" file1 >tmp; mv tmp file1
+ sed -e \
+"/^<<<<<<</,/^=======/d
+/^>>>>>>>/d
+s/quit and/be fired so he can/" dir/file2 >tmp; mv tmp dir/file2
+ dotest backuprecover-21 "${testcvs} -q ci -mrecover/merge" \
+"Checking in dir/file2;
+${TESTDIR}/cvsroot/first-dir/dir/file2,v <-- file2
+new revision: 1\.5; previous revision: 1\.4
+done"
+
+ # go back and commit developer 2's stuff to prove it can still be done
+ cd ../../2/first-dir
+ dotest backuprecover-22 "${testcvs} -Q update" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+retrieving revision 1\.2
+retrieving revision 1\.4
+Merging differences between 1\.2 and 1\.4 into file1
+RCS file: ${TESTDIR}/cvsroot/first-dir/dir/file2,v
+retrieving revision 1\.2
+retrieving revision 1\.5
+Merging differences between 1\.2 and 1\.5 into file2"
+ dotest backuprecover-23 "${testcvs} -q ci -mtest" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.5; previous revision: 1\.4
+done
+Checking in dir/file2;
+${TESTDIR}/cvsroot/first-dir/dir/file2,v <-- file2
+new revision: 1\.6; previous revision: 1\.5
+done"
+
+ # and restore the data to developer 1
+ cd ../../1/first-dir
+ dotest backuprecover-24 "${testcvs} -Q update" ''
+
+ cd ../../..
+ rm -r backuprecover
+ rm -rf ${CVSROOT_DIRNAME}/first-dir
+ ;;
+
history)
# CVSROOT/history tests:
# history: various "cvs history" invocations
@@ -12368,10 +14408,13 @@ done"
if test "x$remote" = xyes; then
# The problem here is that the CVSUMASK environment variable
# needs to be set on the server (e.g. .bashrc). This is, of
- # course, bogus, but that is the way it is currently.
+ # course, bogus, but that is the way it is currently. The
+ # first match is for the :ext: method (where the CVSUMASK
+ # won't be set), while the second is for the :fork: method
+ # (where it will be).
dotest modes-15 \
"ls -l ${TESTDIR}/cvsroot/first-dir/Attic/ac,v" \
-"-r--r--r--.*"
+"-r--r--r--.*" "-r--r-----.*"
else
dotest modes-15 \
"ls -l ${TESTDIR}/cvsroot/first-dir/Attic/ac,v" \
@@ -12431,6 +14474,64 @@ done"
rm -rf ${CVSROOT_DIRNAME}/first-dir
;;
+ modes3)
+ # Repository permissions. Particularly, what happens if we
+ # can't read/write in the repository.
+ # TODO: the case where we can access the repository, just not
+ # the attic (may that one can remain a fatal error, seems less
+ # useful for access control).
+ mkdir 1; cd 1
+ dotest modes-1 "${testcvs} -q co -l ." ''
+ mkdir first-dir second-dir
+ dotest modes-2 "${testcvs} add first-dir second-dir" \
+"Directory ${TESTDIR}/cvsroot/first-dir added to the repository
+Directory ${TESTDIR}/cvsroot/second-dir added to the repository"
+ touch first-dir/aa second-dir/ab
+ dotest modes-3 "${testcvs} add first-dir/aa second-dir/ab" \
+"${PROG} [a-z]*: scheduling file .first-dir/aa. for addition
+${PROG} [a-z]*: scheduling file .second-dir/ab. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add these files permanently"
+ dotest modes-4 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/aa,v
+done
+Checking in first-dir/aa;
+${TESTDIR}/cvsroot/first-dir/aa,v <-- aa
+initial revision: 1\.1
+done
+RCS file: ${TESTDIR}/cvsroot/second-dir/ab,v
+done
+Checking in second-dir/ab;
+${TESTDIR}/cvsroot/second-dir/ab,v <-- ab
+initial revision: 1\.1
+done"
+ chmod a= ${TESTDIR}/cvsroot/first-dir
+ dotest modes-5 "${testcvs} update" \
+"${PROG} [a-z]*: Updating \.
+${PROG} [a-z]*: Updating first-dir
+${PROG} [a-z]*: cannot open directory ${TESTDIR}/cvsroot/first-dir: Permission denied
+${PROG} [a-z]*: skipping directory first-dir
+${PROG} [a-z]*: Updating second-dir"
+
+ # OK, I can see why one might say the above case could be a
+ # fatal error, because normally users without access to first-dir
+ # won't have it in their working directory. But the next
+ # one is more of a problem if it is fatal.
+ rm -r first-dir
+ dotest modes-6 "${testcvs} update -dP" \
+"${PROG} [a-z]*: Updating .
+${PROG} [a-z]*: Updating CVSROOT
+U ${DOTSTAR}
+${PROG} [a-z]*: Updating first-dir
+${PROG} [a-z]*: cannot open directory ${TESTDIR}/cvsroot/first-dir: Permission denied
+${PROG} [a-z]*: skipping directory first-dir
+${PROG} [a-z]*: Updating second-dir"
+
+ cd ..
+ rm -r 1
+ chmod u+rwx ${TESTDIR}/cvsroot/first-dir
+ rm -rf ${TESTDIR}/cvsroot/first-dir ${TESTDIR}/cvsroot/second-dir
+ ;;
+
stamps)
# Test timestamps.
mkdir 1; cd 1
@@ -12665,6 +14766,45 @@ done"
chmod 444 ${CVSROOT_DIRNAME}/CVSROOT/config
;;
+ symlinks2)
+ # Symlinks in working directory without PreservePermissions.
+ # Also see: symlinks: with PreservePermissions
+ # rcslib-symlink-*: symlinks in repository.
+ mkdir 1; cd 1
+ dotest symlinks2-1 "${testcvs} -q co -l ." ''
+ mkdir first-dir
+ dotest symlinks2-2 "${testcvs} add first-dir" \
+"Directory ${TESTDIR}/cvsroot/first-dir added to the repository"
+ cd first-dir
+ echo nonsymlink > slink
+ dotest symlinks2-3 "${testcvs} add slink" \
+"${PROG} [a-z]*: scheduling file .slink. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest symlinks2-4 "${testcvs} -q ci -m ''" \
+"RCS file: ${CVSROOT_DIRNAME}/first-dir/slink,v
+done
+Checking in slink;
+${TESTDIR}/cvsroot/first-dir/slink,v <-- slink
+initial revision: 1\.1
+done"
+ rm slink
+ # Choose name cvslog.* so it is in default ignore list.
+ echo second file >cvslog.file2
+ dotest symlinks2-5 "ln -s cvslog.file2 slink" ""
+ dotest symlinks2-6 "${testcvs} -q ci -m linkify" \
+"Checking in slink;
+${TESTDIR}/cvsroot/first-dir/slink,v <-- slink
+new revision: 1\.2; previous revision: 1\.1
+done"
+ dotest symlinks2-7 "${testcvs} -q update -r 1.1 slink" "[UP] slink"
+ dotest symlinks2-8 "cat slink" "nonsymlink"
+ dotest symlinks2-9 "ls -l slink" "-[-rwx]* .* slink"
+ cd ../..
+
+ rm -rf 1
+ rm -rf ${CVSROOT_DIRNAME}/first-dir
+ ;;
+
hardlinks)
# short cut around checking out and committing CVSROOT
rm -f ${CVSROOT_DIRNAME}/CVSROOT/config
@@ -12872,7 +15012,10 @@ U file1" "U file1"
# "rdiff" tests "cvs co -k".
# "binfiles" (and this test) test "cvs update -k".
# "binwrap" tests setting the mode from wrappers.
+ # "keyword2" tests "cvs update -kk -j" with text and binary files
# I don't think any test is testing "cvs import -k".
+ # Other keyword expansion tests:
+ # keywordlog - $Log.
mkdir 1; cd 1
dotest keyword-1 "${testcvs} -q co -l ." ''
mkdir first-dir
@@ -13051,12 +15194,20 @@ new revision: 1\.3; previous revision: 1\.2
done"
dotest keyword-21 "${testcvs} -q update -r tag1" "[UP] file1"
- # FIXME: This test fails when remote. The second expect
- # string below should be removed when this is fixed.
- dotest keyword-22 "cat file1" '\$'"Name: tag1 "'\$' \
-'\$'"Name: "'\$'
+ dotest keyword-22 "cat file1" '\$'"Name: tag1 "'\$'
- dotest keyword-23 "${testcvs} update -A file1" "[UP] file1"
+ if test "$remote" = yes; then
+ # Like serverpatch-8. Not sure there is anything much we
+ # can or should do about this.
+ dotest keyword-23 "${testcvs} update -A file1" "P file1
+${PROG} update: checksum failure after patch to \./file1; will refetch
+${PROG} client: refetching unpatchable files
+U file1"
+ else
+ dotest keyword-23 "${testcvs} update -A file1" "[UP] file1"
+ fi
+ dotest keyword-24 "cat file1" '\$'"Name: "'\$'"
+change"
cd ../..
rm -r 1
@@ -13071,22 +15222,18 @@ done"
dotest keywordlog-2 "${testcvs} add first-dir" \
"Directory ${TESTDIR}/cvsroot/first-dir added to the repository"
cd first-dir
- echo change >file1
+ echo initial >file1
dotest keywordlog-3 "${testcvs} add file1" \
"${PROG} [a-z]*: scheduling file .file1. for addition
${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
- # Note that we wanted to try "ci -r 1.3 -m add file1" and CVS
- # seemed to get all confused, thinking it was adding on a branch
- # or something. FIXME? Do something about this? Document it
- # in BUGS or someplace?
-
- dotest keywordlog-4 "${testcvs} -q ci -m add file1" \
+ # See "rmadd" for a list of other tests of cvs ci -r.
+ dotest keywordlog-4 "${testcvs} -q ci -r 1.3 -m add file1" \
"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
done
Checking in file1;
${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
-initial revision: 1\.1
+initial revision: 1\.3
done"
cd ../..
@@ -13094,21 +15241,29 @@ done"
dotest keywordlog-4a "${testcvs} -q co first-dir" "U first-dir/file1"
cd ../1/first-dir
- echo 'xx $''Log$' > file1
+ echo 'xx $''Log$' >> file1
cat >${TESTDIR}/comment.tmp <<EOF
First log line
Second log line
EOF
+ # As with rmadd-25, "cvs ci -r" sets a sticky tag.
+ dotest_fail keywordlog-4b \
+"${testcvs} ci -F ${TESTDIR}/comment.tmp file1" \
+"${PROG} [a-z]*: sticky tag .1\.3. for file .file1. is not a branch
+${PROG} \[[a-z]* aborted\]: correct above errors first!"
+ dotest keywordlog-4c "${testcvs} -q update -A" "M file1"
+
dotest keywordlog-5 "${testcvs} ci -F ${TESTDIR}/comment.tmp file1" \
"Checking in file1;
${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
+new revision: 1\.4; previous revision: 1\.3
done"
rm -f ${TESTDIR}/comment.tmp
dotest keywordlog-6 "${testcvs} -q tag -b br" "T file1"
dotest keywordlog-7 "cat file1" \
-"xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.2 [0-9/]* [0-9:]* ${username}
+"initial
+xx "'\$'"Log: file1,v "'\$'"
+xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
xx First log line
xx Second log line
xx"
@@ -13116,8 +15271,9 @@ xx"
cd ../../2/first-dir
dotest keywordlog-8 "${testcvs} -q update" "[UP] file1"
dotest keywordlog-9 "cat file1" \
-"xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.2 [0-9/]* [0-9:]* ${username}
+"initial
+xx "'\$'"Log: file1,v "'\$'"
+xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
xx First log line
xx Second log line
xx"
@@ -13127,14 +15283,15 @@ xx"
dotest keywordlog-10 "${testcvs} ci -m modify file1" \
"Checking in file1;
${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
-new revision: 1\.3; previous revision: 1\.2
+new revision: 1\.5; previous revision: 1\.4
done"
dotest keywordlog-11 "cat file1" \
-"xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.3 [0-9/]* [0-9:]* ${username}
+"initial
+xx "'\$'"Log: file1,v "'\$'"
+xx Revision 1\.5 [0-9/]* [0-9:]* ${username}
xx modify
xx
-xx Revision 1\.2 [0-9/]* [0-9:]* ${username}
+xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
xx First log line
xx Second log line
xx
@@ -13143,11 +15300,12 @@ change"
cd ../../2/first-dir
dotest keywordlog-12 "${testcvs} -q update" "[UP] file1"
dotest keywordlog-13 "cat file1" \
-"xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.3 [0-9/]* [0-9:]* ${username}
+"initial
+xx "'\$'"Log: file1,v "'\$'"
+xx Revision 1\.5 [0-9/]* [0-9:]* ${username}
xx modify
xx
-xx Revision 1\.2 [0-9/]* [0-9:]* ${username}
+xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
xx First log line
xx Second log line
xx
@@ -13159,14 +15317,15 @@ change"
dotest keywordlog-15 "${testcvs} -q ci -m br-modify" \
"Checking in file1;
${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
-new revision: 1\.2\.2\.1; previous revision: 1\.2
+new revision: 1\.4\.2\.1; previous revision: 1\.4
done"
dotest keywordlog-16 "cat file1" \
-"xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.2\.2\.1 [0-9/]* [0-9:]* ${username}
+"initial
+xx "'\$'"Log: file1,v "'\$'"
+xx Revision 1\.4\.2\.1 [0-9/]* [0-9:]* ${username}
xx br-modify
xx
-xx Revision 1\.2 [0-9/]* [0-9:]* ${username}
+xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
xx First log line
xx Second log line
xx
@@ -13174,47 +15333,272 @@ br-change"
cd ../../2/first-dir
dotest keywordlog-17 "${testcvs} -q update -r br" "[UP] file1"
dotest keywordlog-18 "cat file1" \
-"xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.2\.2\.1 [0-9/]* [0-9:]* ${username}
+"initial
+xx "'\$'"Log: file1,v "'\$'"
+xx Revision 1\.4\.2\.1 [0-9/]* [0-9:]* ${username}
xx br-modify
xx
-xx Revision 1\.2 [0-9/]* [0-9:]* ${username}
+xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
xx First log line
xx Second log line
xx
br-change"
cd ../..
dotest keywordlog-19 "${testcvs} -q co -p -r br first-dir/file1" \
-"xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.2\.2\.1 [0-9/]* [0-9:]* ${username}
+"initial
+xx "'\$'"Log: file1,v "'\$'"
+xx Revision 1\.4\.2\.1 [0-9/]* [0-9:]* ${username}
xx br-modify
xx
-xx Revision 1\.2 [0-9/]* [0-9:]* ${username}
+xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
xx First log line
xx Second log line
xx
br-change"
dotest keywordlog-20 "${testcvs} -q co -p first-dir/file1" \
-"xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.3 [0-9/]* [0-9:]* ${username}
+"initial
+xx "'\$'"Log: file1,v "'\$'"
+xx Revision 1\.5 [0-9/]* [0-9:]* ${username}
xx modify
xx
-xx Revision 1\.2 [0-9/]* [0-9:]* ${username}
+xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
xx First log line
xx Second log line
xx
change"
- dotest keywordlog-21 "${testcvs} -q co -p -r 1.2 first-dir/file1" \
-"xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.2 [0-9/]* [0-9:]* ${username}
+ dotest keywordlog-21 "${testcvs} -q co -p -r 1.4 first-dir/file1" \
+"initial
+xx "'\$'"Log: file1,v "'\$'"
+xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
xx First log line
xx Second log line
xx"
+ cd 2/first-dir
+ # OK, the basic rule for keyword expansion is that it
+ # happens on checkout. And the rule for annotate is that
+ # it annotates a checked-in revision, rather than a checked-out
+ # file. So, although it is kind of confusing that the latest
+ # revision does not appear in the annotated output, and the
+ # annotated output does not quite match what you'd get with
+ # update or checkout, the behavior is more or less logical.
+ # The same issue occurs with annotate and other keywords,
+ # I think, although it is particularly noticeable for $Log.
+ dotest keywordlog-22 "${testcvs} ann -r br file1" \
+"Annotations for file1
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+1\.3 (${username} *[0-9a-zA-Z-]*): initial
+1\.4\.2\.1 (${username} *[0-9a-zA-Z-]*): xx "'\$'"Log: file1,v "'\$'"
+1\.4\.2\.1 (${username} *[0-9a-zA-Z-]*): xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
+1\.4\.2\.1 (${username} *[0-9a-zA-Z-]*): xx First log line
+1\.4\.2\.1 (${username} *[0-9a-zA-Z-]*): xx Second log line
+1\.4\.2\.1 (${username} *[0-9a-zA-Z-]*): xx
+1\.4\.2\.1 (${username} *[0-9a-zA-Z-]*): br-change"
+ dotest keywordlog-23 "${testcvs} ann -r HEAD file1" \
+"Annotations for file1
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+1\.3 (${username} *[0-9a-zA-Z-]*): initial
+1\.5 (${username} *[0-9a-zA-Z-]*): xx "'\$'"Log: file1,v "'\$'"
+1\.5 (${username} *[0-9a-zA-Z-]*): xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
+1\.5 (${username} *[0-9a-zA-Z-]*): xx First log line
+1\.5 (${username} *[0-9a-zA-Z-]*): xx Second log line
+1\.5 (${username} *[0-9a-zA-Z-]*): xx
+1\.5 (${username} *[0-9a-zA-Z-]*): change"
+ cd ../..
+
+ #
+ # test the operation of 'admin -o' in conjunction with keywords
+ # (especially Log - this used to munge the RCS file for all time)
+ #
+
+ dotest keywordlog-24 \
+"${testcvs} admin -oHEAD 1/first-dir/file1" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+deleting revision 1\.5
+done"
+
+ dotest keywordlog-25 \
+"${testcvs} -q co -p first-dir/file1" \
+"initial
+xx "'\$'"Log: file1,v "'\$'"
+xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
+xx First log line
+xx Second log line
+xx"
+
+ if test $keep = yes; then
+ echo Keeping ${TESTDIR} and exiting due to --keep
+ exit 0
+ fi
+
rm -r 1 2
rm -rf ${CVSROOT_DIRNAME}/first-dir
;;
+ keyword2)
+ # Test merging on files with keywords:
+ # without -kk
+ # with -kk
+ # on text files
+ # on binary files
+ # Note: This test assumes that CVS has already passed the binfiles
+ # test sequence
+ # Note2: We are testing positive on binary corruption here
+ # we probably really DON'T want to 'cvs update -kk' a binary file...
+ mkdir 1; cd 1
+ dotest keyword2-1 "${testcvs} -q co -l ." ''
+ mkdir first-dir
+ dotest keyword2-2 "${testcvs} add first-dir" \
+"Directory ${TESTDIR}/cvsroot/first-dir added to the repository"
+ cd first-dir
+
+ echo '$''Revision$' >> file1
+ echo "I" >>file1
+ echo "like" >>file1
+ echo "long" >>file1
+ echo "files!" >>file1
+ echo "" >>file1
+ echo "a test line for our times" >>file1
+ echo "" >>file1
+ echo "They" >>file1
+ echo "make" >>file1
+ echo "diff" >>file1
+ echo "look like it" >>file1
+ echo "did a much better" >>file1
+ echo "job." >>file1
+ dotest keyword2-3 "${testcvs} add file1" \
+"${PROG} [a-z]*: scheduling file .file1. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+
+ awk 'BEGIN { printf "%c%c%c%sRevision: 1.1 $@%c%c", \
+ 2, 10, 137, "$", 13, 10 }' \
+ </dev/null | tr '@' '\000' >../binfile.dat
+ cp ../binfile.dat .
+ dotest keyword2-5 "${testcvs} add -kb binfile.dat" \
+"${PROG} [a-z]*: scheduling file .binfile\.dat. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+
+ dotest keyword2-6 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/binfile\.dat,v
+done
+Checking in binfile\.dat;
+${TESTDIR}/cvsroot/first-dir/binfile\.dat,v <-- binfile\.dat
+initial revision: 1\.1
+done
+RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+done
+Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+initial revision: 1\.1
+done"
+
+ dotest keyword2-7 "${testcvs} -q tag -b branch" \
+"T binfile\.dat
+T file1"
+
+ sed -e 's/our/the best of and the worst of/' file1 >f; mv f file1
+ dotest keyword2-8 "${testcvs} -q ci -m change" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.2; previous revision: 1\.1
+done"
+
+ dotest keyword2-9 "${testcvs} -q update -r branch" '[UP] file1'
+
+ echo "what else do we have?" >>file1
+ dotest keyword2-10 "${testcvs} -q ci -m change" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.1\.2\.1; previous revision: 1\.1
+done"
+
+ # Okay, first a conflict in file1 - should be okay with binfile.dat
+ dotest keyword2-11 "${testcvs} -q update -A -j branch" \
+"U file1
+RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+retrieving revision 1\.1
+retrieving revision 1\.1\.2\.1
+Merging differences between 1\.1 and 1\.1\.2\.1 into file1
+rcsmerge: warning: conflicts during merge"
+
+ dotest_fail keyword2-12 "${testcvs} diff file1" \
+"Index: file1
+===================================================================
+RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+retrieving revision 1\.2
+diff -r1\.2 file1
+0a1
+> <<<<<<< file1
+1a3,5
+> =======
+> \\\$""Revision: 1\.1\.2\.1 \\\$
+> >>>>>>> 1\.1\.2\.1
+14a19
+> what else do we have${QUESTION}"
+
+ # Here's the problem... shouldn't -kk a binary file...
+ rm file1
+ if test "$remote" = yes; then
+ dotest keyword2-13 "${testcvs} -q update -A -kk -j branch" \
+"U binfile.dat
+U file1
+RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+retrieving revision 1\.1
+retrieving revision 1\.1\.2\.1
+Merging differences between 1\.1 and 1\.1\.2\.1 into file1"
+ else
+ dotest keyword2-13 "${testcvs} -q update -A -kk -j branch" \
+"U binfile.dat
+${PROG} [a-z]*: warning: file1 was lost
+U file1
+RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+retrieving revision 1\.1
+retrieving revision 1\.1\.2\.1
+Merging differences between 1\.1 and 1\.1\.2\.1 into file1"
+ fi
+
+ # binfile won't get checked in, but it is now corrupt and could
+ # have been checked in if it had changed on the branch...
+ dotest keyword2-14 "${testcvs} -q ci -m change" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.3; previous revision: 1\.2
+done"
+
+ dotest_fail keyword2-15 "cmp binfile.dat ../binfile.dat" \
+"binfile\.dat \.\./binfile\.dat differ: char 13, line 2"
+
+ # Okay, restore everything and make CVS try and merge a binary file...
+ dotest keyword2-16 "${testcvs} -q update -A" \
+"[UP] binfile.dat
+[UP] file1"
+ dotest keyword2-17 "${testcvs} -q tag -b branch2" \
+"T binfile\.dat
+T file1"
+ dotest keyword2-18 "${testcvs} -q update -r branch2" ''
+
+ awk 'BEGIN { printf "%c%c%c@%c%c", 2, 10, 137, 13, 10 }' \
+ </dev/null | tr '@' '\000' >>binfile.dat
+ dotest keyword2-19 "${testcvs} -q ci -m badbadbad" \
+"Checking in binfile\.dat;
+${TESTDIR}/cvsroot/first-dir/binfile\.dat,v <-- binfile\.dat
+new revision: 1\.1\.4\.1; previous revision: 1\.1
+done"
+ dotest keyword2-20 "${testcvs} -q update -A -kk -j branch2" \
+"U binfile\.dat
+RCS file: ${TESTDIR}/cvsroot/first-dir/binfile\.dat,v
+retrieving revision 1\.1
+retrieving revision 1\.1\.4\.1
+Merging differences between 1\.1 and 1\.1\.4\.1 into binfile\.dat
+U file1"
+
+ # Yep, it's broke, 'cept for that gal in Hodunk who uses -kk
+ # so that some files only merge when she says so. Time to clean up...
+ cd ../..
+ rm -r 1
+ rm -rf ${CVSROOT_DIRNAME}/first-dir
+ ;;
+
head)
# Testing handling of the HEAD special tag.
# There are many cases involving added and removed files
@@ -13385,6 +15769,21 @@ done"
tagdate)
# Test combining -r and -D.
+ #
+ # Note that this is not a complete test. It relies on the fact
+ # that update, checkout and export have a LOT of shared code.
+ # Notice:
+ # 1) checkout is never tested at all with -r -D
+ # 2) update never uses an argument to '-D' besides 'now'
+ # (this test does not provide enough data to prove
+ # that 'cvs update' with both a '-r' and a '-D'
+ # specified does not ignore '-D': a 'cvs up
+ # -r<branch> -Dnow' and a 'cvs up -r<branch>'
+ # should specify the same file revision).
+ # 3) export uses '-r<branch> -D<when there was a different
+ # revision>', hopefully completing this behavior test
+ # for checkout and update as well.
+ #
mkdir 1; cd 1
dotest tagdate-1 "${testcvs} -q co -l ." ''
mkdir first-dir
@@ -13422,11 +15821,95 @@ done"
${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
new revision: 1\.1\.4\.1; previous revision: 1\.1
done"
+
# Then the case where br2 does have revisions:
dotest tagdate-11 "${testcvs} -q update -p -r br1 -D now" "trunk-1"
+ # For some reason, doing this on a branch seems to be relevant.
+ dotest_fail tagdate-12 "${testcvs} -q update -j:yesterday" \
+"${PROG} \[[a-z]* aborted\]: argument to join may not contain a date specifier without a tag"
+ # And check export
+
+ # Wish some shorter sleep interval would suffice, but I need to
+ # guarantee that the point in time specified by the argument to -D
+ # in tagdate-14 and tagdate-16
+ # falls in the space of time between commits to br2 and I
+ # figure 60 seconds is probably a large enough range to
+ # account for most network file system delays and such...
+ # as it stands, it takes between 1 and 2 seconds between
+ # calling CVS on my machine and the -D argument being used to
+ # recall the file revision and this timing will certainly vary
+ # by several seconds between machines - dependant on CPUspeeds,
+ # I/O speeds, load, etc.
+ sleep 60
+
+ echo br2-2 >file1
+ dotest tagdate-13 "${testcvs} -q ci -m modify-2-on-br2" \
+"Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+new revision: 1\.1\.4\.2; previous revision: 1\.1\.4\.1
+done"
cd ../..
- rm -r 1
+ mkdir 2; cd
+ if ${testcvs} -q export -r br2 -D'1 minute ago' first-dir \
+ >${TESTDIR}/tagdate.tmp 2>&1; then
+ if ${EXPR} "`cat ${TESTDIR}/tagdate.tmp`" : \
+"[UP] first-dir/file1" >/dev/null; then
+ pass tagdate-14
+ else
+ echo "** expected: " >>${LOGFILE}
+ echo "[UP] first-dir/file1" >>${LOGFILE}
+ echo "** got: " >>${LOGFILE}
+ cat ${TESTDIR}/tagdate.tmp >>${LOGFILE}
+ fail tagdate-14
+ fi
+ else
+ echo "Bad exit status" >>${LOGFILE}
+ fail tagdate-14
+ fi
+
+ if ${EXPR} "`cat first-dir/file1`" : "br2-1" >/dev/null; then
+ pass tagdate-15
+ else
+ fail tagdate-15
+ fi
+
+ # Now for annotate
+ cd ../1/first-dir
+ if ${testcvs} annotate -rbr2 -D'1 minute ago' \
+ >${TESTDIR}/tagdate.tmp 2>&1; then
+ if ${EXPR} "`cat ${TESTDIR}/tagdate.tmp`" : \
+"Annotations for file1
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+1\.1\.4\.1 (${username} *[0-9a-zA-Z-]*): br2-1" >/dev/null; then
+ pass tagdate-16
+ else
+ echo "** expected: " >>${LOGFILE}
+ echo "Annotations for file1
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+1\.1\.4\.1 (${username} *[0-9a-zA-Z-]*): br2-1" >>${LOGFILE}
+ echo "** got: " >>${LOGFILE}
+ cat ${TESTDIR}/tagdate.tmp >>${LOGFILE}
+ fail tagdate-16
+ fi
+ else
+ echo "Bad exit status" >>${LOGFILE}
+ fail tagdate-16
+ fi
+
+ dotest tagdate-17 "${testcvs} annotate -rbr2 -Dnow" \
+"Annotations for file1
+\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
+1\.1\.4\.2 (${username} *[0-9a-zA-Z-]*): br2-2"
+
+ if test $keep = yes; then
+ echo Keeping ${TESTDIR} and exiting due to --keep
+ exit 0
+ fi
+
+ cd ../..
+ rm ${TESTDIR}/tagdate.tmp
+ rm -r 1 2
rm -rf ${CVSROOT_DIRNAME}/first-dir
;;
@@ -13621,14 +16104,13 @@ done"
dotest tag8k-15 "$testcvs -Q tag $t-9 $file" ''
dotest tag8k-16 "$testcvs -Q tag $t-a $file" ''
- # Determine the length of the author value.
+ # Extract the author value.
name=`sed -n 's/.*; author \([^;]*\);.*/\1/p' ${TESTDIR}/cvsroot/$module/$file,v|head -1`
- name_len=`expr length $name`
+ # Form a suffix string of length (16 - length($name)).
# CAREFUL: this will lose if $name is longer than 16.
- # Then, form a string of length 16 - $name_len.
- add_len=`expr 16 - $name_len`
- suffix=`expr substr 1234567890123456 1 $add_len`
+ sed_pattern=`echo $name|sed s/././g`
+ suffix=`echo 1234567890123456|sed s/$sed_pattern//`
# Add a final tag with length chosen so that it will push the
# offset of the `;' in the 2nd occurrence of `;\tauthor' in the
@@ -13663,12 +16145,14 @@ done"
# head-o1 (::branch, where this deletes a revision or is noop)
# branches-o1 (::branch, similar, with different branch topology)
# log-o1 (1.3.2.1::)
- # binfiles-o1 (1.3:: and ::1.3)
+ # binfiles-o1 (1.3:: and ::1.3; binary files)
+ # binfiles3-9 (binary files)
# Also could be testing:
# 1.3.2.6::1.3.2.8
# 1.3.2.6::1.3.2
# 1.3.2.1::1.3.2.6
# 1.3::1.3.2.6 (error? or synonym for ::1.3.2.6?)
+ # -n: admin, tagf tests.
mkdir 1; cd 1
dotest admin-1 "${testcvs} -q co -l ." ''
@@ -13803,6 +16287,7 @@ modify-on-branch
# test for what CVS actually exports, and figure we can revise
# the check as needed (within the confines of the RCS5 format as
# documented in RCSFILES).
+ # Note that we must accept either 2 or 4 digit year.
dotest admin-13 "cat ${CVSROOT_DIRNAME}/first-dir/file1,v" \
"head 1\.1;
branch 1\.1\.2;
@@ -13817,13 +16302,13 @@ comment @xx@;
1\.1
-date [0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]; author ${username}; state Exp;
+date [0-9][0-9]*\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]; author ${username}; state Exp;
branches
1\.1\.2\.1;
next ;
1\.1\.2\.1
-date [0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]; author ${username}; state foo;
+date [0-9][0-9]*\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]; author ${username}; state foo;
branches;
next ;
@@ -13973,6 +16458,11 @@ total revisions: 2
done"
fi # end of tests skipped for remote
+ # Now test that plain -e is at least parsed right. CVS 1.10
+ # would wrongly treat "-e file1" as "-efile1".
+ dotest_fail admin-19a-2 "${testcvs} -q admin -e file1" \
+"${PROG} \[[a-z]* aborted\]: removing entire access list not yet implemented"
+
# Add another revision to file2, so we can delete one.
echo 'add a line' >> file2
dotest admin-21 "${testcvs} -q ci -m modify file2" \
@@ -14222,13 +16712,13 @@ comment @xx@;
1\.1
-date [0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]; author ${username}; state Exp;
+date [0-9][0-9]*\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]; author ${username}; state Exp;
branches
1\.1\.2\.1;
next ;
1\.1\.2\.1
-date [0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]; author ${username}; state foo;
+date [0-9][0-9]*\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]; author ${username}; state foo;
branches;
next ;
@@ -14393,17 +16883,17 @@ comment @# @;
1\.4
-date [0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]; author ${username}; state Exp;
+date [0-9][0-9]*\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]; author ${username}; state Exp;
branches;
next 1\.3;
1\.3
-date [0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]; author ${username}; state Exp;
+date [0-9][0-9]*\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]; author ${username}; state Exp;
branches;
next 1\.2;
1\.2
-date [0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]; author ${username}; state Exp;
+date [0-9][0-9]*\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]; author ${username}; state Exp;
branches;
next ;
@@ -15496,6 +17986,2277 @@ d472 12
rm -rf ${CVSROOT_DIRNAME}/diffmerge2
;;
+ release)
+ # Tests of "cvs release", particularly multiple arguments.
+ # Other CVS release tests:
+ # info-cleanup-0 for "cvs -n release".
+ # ignore-193 for the text of the question that cvs release asks.
+ # Also for interactions with cvsignore.
+ # basicc: "-d .", global -Q, no arguments (is a noop),
+ # "cvs release" without -d, multiple arguments.
+ # dirs-4: repository directory has been deleted.
+ # modules2-6: multiple arguments.
+
+ # First the usual setup; create a directory first-dir.
+ mkdir 1; cd 1
+ dotest release-1 "${testcvs} -q co -l ." ''
+ mkdir first-dir
+ dotest release-2 "${testcvs} add first-dir" \
+"Directory ${TESTDIR}/cvsroot/first-dir added to the repository"
+ cd first-dir
+ mkdir dir1
+ dotest release-3 "${testcvs} add dir1" \
+"Directory ${TESTDIR}/cvsroot/first-dir/dir1 added to the repository"
+ mkdir dir2
+ dotest release-4 "${testcvs} add dir2" \
+"Directory ${TESTDIR}/cvsroot/first-dir/dir2 added to the repository"
+ cd dir2
+ mkdir dir3
+ dotest release-5 "${testcvs} add dir3" \
+"Directory ${TESTDIR}/cvsroot/first-dir/dir2/dir3 added to the repository"
+
+ cd ../..
+ dotest release-6 "${testcvs} release -d first-dir/dir2/dir3 first-dir/dir1" \
+"You have .0. altered files in this repository.
+Are you sure you want to release (and delete) directory .first-dir/dir2/dir3.: \
+You have .0. altered files in this repository.
+Are you sure you want to release (and delete) directory .first-dir/dir1.: " <<EOF
+yes
+yes
+EOF
+ dotest_fail release-7 "test -d first-dir/dir1" ''
+ dotest_fail release-8 "test -d first-dir/dir2/dir3" ''
+ dotest release-9 "${testcvs} update" \
+"${PROG} [a-z]*: Updating \.
+${PROG} [a-z]*: Updating first-dir
+${PROG} [a-z]*: Updating first-dir/dir2"
+
+ cd first-dir
+ mkdir dir1
+ dotest release-10 "${testcvs} add dir1" \
+"Directory ${TESTDIR}/cvsroot/first-dir/dir1 added to the repository"
+ cd dir2
+ mkdir dir3
+ dotest release-11 "${testcvs} add dir3" \
+"Directory ${TESTDIR}/cvsroot/first-dir/dir2/dir3 added to the repository"
+
+ cd ../..
+ dotest release-12 "${testcvs} release first-dir/dir2/dir3 first-dir/dir1" \
+"You have .0. altered files in this repository.
+Are you sure you want to release directory .first-dir/dir2/dir3.: .. .release. aborted by user choice.
+You have .0. altered files in this repository.
+Are you sure you want to release directory .first-dir/dir1.: " <<EOF
+no
+yes
+EOF
+ dotest release-13 "${testcvs} release first-dir/dir2/dir3 first-dir/dir2" \
+"You have .0. altered files in this repository.
+Are you sure you want to release directory .first-dir/dir2/dir3.: \
+You have .0. altered files in this repository.
+Are you sure you want to release directory .first-dir/dir2.: " <<EOF
+yes
+yes
+EOF
+ dotest release-14 "test -d first-dir/dir1" ''
+ dotest release-15 "test -d first-dir/dir2/dir3" ''
+ rm -rf first-dir/dir1 first-dir/dir2
+
+ dotest release-16 "${testcvs} update" \
+"${PROG} [a-z]*: Updating \.
+${PROG} [a-z]*: Updating first-dir"
+ cd ..
+ rm -rf 1
+ ;;
+
+ multiroot)
+
+ #
+ # set up two repositories
+ #
+
+ CVSROOT1_DIRNAME=${TESTDIR}/root1
+ CVSROOT2_DIRNAME=${TESTDIR}/root2
+ CVSROOT1=${CVSROOT1_DIRNAME} ; export CVSROOT1
+ CVSROOT2=${CVSROOT2_DIRNAME} ; export CVSROOT2
+ if test "x$remote" = xyes; then
+ CVSROOT1=:fork:${CVSROOT1_DIRNAME} ; export CVSROOT1
+ CVSROOT2=:fork:${CVSROOT2_DIRNAME} ; export CVSROOT2
+ fi
+ testcvs1="${testcvs} -d ${CVSROOT1}"
+ testcvs2="${testcvs} -d ${CVSROOT2}"
+
+ dotest multiroot-setup-1 "mkdir ${CVSROOT1_DIRNAME} ${CVSROOT2_DIRNAME}" ""
+ dotest multiroot-setup-2 "${testcvs1} init" ""
+ dotest multiroot-setup-3 "${testcvs2} init" ""
+
+ #
+ # create some directories in root1
+ #
+ mkdir 1; cd 1
+ dotest multiroot-setup-4 "${testcvs1} co -l ." "${PROG} [a-z]*: Updating ."
+ mkdir mod1-1 mod1-2
+ dotest multiroot-setup-5 "${testcvs1} add mod1-1 mod1-2" \
+"Directory ${CVSROOT1_DIRNAME}/mod1-1 added to the repository
+Directory ${CVSROOT1_DIRNAME}/mod1-2 added to the repository"
+ echo file1-1 > mod1-1/file1-1
+ echo file1-2 > mod1-2/file1-2
+ dotest multiroot-setup-6 "${testcvs1} add mod1-1/file1-1 mod1-2/file1-2" \
+"${PROG} [a-z]*: scheduling file .mod1-1/file1-1. for addition
+${PROG} [a-z]*: scheduling file .mod1-2/file1-2. for addition
+${PROG} [a-z]*: use '${PROG} commit' to add these files permanently"
+ dotest multiroot-setup-7 "${testcvs1} commit -m is" \
+"${PROG} [a-z]*: Examining \.
+${PROG} [a-z]*: Examining mod1-1
+${PROG} [a-z]*: Examining mod1-2
+RCS file: ${CVSROOT1_DIRNAME}/mod1-1/file1-1,v
+done
+Checking in mod1-1/file1-1;
+${CVSROOT1_DIRNAME}/mod1-1/file1-1,v <-- file1-1
+initial revision: 1.1
+done
+RCS file: ${CVSROOT1_DIRNAME}/mod1-2/file1-2,v
+done
+Checking in mod1-2/file1-2;
+${CVSROOT1_DIRNAME}/mod1-2/file1-2,v <-- file1-2
+initial revision: 1.1
+done"
+ cd ..
+ rm -rf 1
+
+ #
+ # create some directories in root2
+ #
+ mkdir 1; cd 1
+ dotest multiroot-setup-8 "${testcvs2} co -l ." "${PROG} [a-z]*: Updating ."
+ mkdir mod2-1 mod2-2
+ dotest multiroot-setup-9 "${testcvs2} add mod2-1 mod2-2" \
+"Directory ${CVSROOT2_DIRNAME}/mod2-1 added to the repository
+Directory ${CVSROOT2_DIRNAME}/mod2-2 added to the repository"
+ echo file2-1 > mod2-1/file2-1
+ echo file2-2 > mod2-2/file2-2
+ dotest multiroot-setup-6 "${testcvs2} add mod2-1/file2-1 mod2-2/file2-2" \
+"${PROG} [a-z]*: scheduling file .mod2-1/file2-1. for addition
+${PROG} [a-z]*: scheduling file .mod2-2/file2-2. for addition
+${PROG} [a-z]*: use '${PROG} commit' to add these files permanently"
+ dotest multiroot-setup-10 "${testcvs2} commit -m anyone" \
+"${PROG} [a-z]*: Examining \.
+${PROG} [a-z]*: Examining mod2-1
+${PROG} [a-z]*: Examining mod2-2
+RCS file: ${CVSROOT2_DIRNAME}/mod2-1/file2-1,v
+done
+Checking in mod2-1/file2-1;
+${CVSROOT2_DIRNAME}/mod2-1/file2-1,v <-- file2-1
+initial revision: 1.1
+done
+RCS file: ${CVSROOT2_DIRNAME}/mod2-2/file2-2,v
+done
+Checking in mod2-2/file2-2;
+${CVSROOT2_DIRNAME}/mod2-2/file2-2,v <-- file2-2
+initial revision: 1.1
+done"
+ cd ..
+ rm -rf 1
+
+ # check out a few directories, from simple/shallow to
+ # complex/deep
+ mkdir 1; cd 1
+
+ # OK, this case is kind of weird. If we just run things from
+ # here, without CVS/Root, then CVS will contact the server
+ # mentioned in CVSROOT (which is irrelevant) which will print
+ # some messages. Our workaround is to make sure we have a
+ # CVS/Root file at top level. In the future, it is possible
+ # the best behavior will be to extend the existing behavior
+ # ("being called from a directory without CVS administration
+ # has always meant to process each of the sub-dirs") to also
+ # do that if there is no CVSROOT, CVS/Root, or -d at top level.
+ #
+ # The local case could stumble through the tests without creating
+ # the top-level CVS/Root, but we create it for local and for
+ # remote to reduce special cases later in the test.
+ dotest multiroot-workaround "${testcvs1} -q co -l ." ""
+
+ dotest multiroot-setup-11 "${testcvs1} co mod1-1 mod1-2" \
+"${PROG} [a-z]*: Updating mod1-1
+U mod1-1/file1-1
+${PROG} [a-z]*: Updating mod1-2
+U mod1-2/file1-2"
+ dotest multiroot-setup-12 "${testcvs2} co mod2-1 mod2-2" \
+"${PROG} [a-z]*: Updating mod2-1
+U mod2-1/file2-1
+${PROG} [a-z]*: Updating mod2-2
+U mod2-2/file2-2"
+ cd mod1-2
+ dotest multiroot-setup-13 "${testcvs2} co mod2-2" \
+"${PROG} [a-z]*: Updating mod2-2
+U mod2-2/file2-2"
+ cd ..
+ cd mod2-2
+ dotest multiroot-setup-14 "${testcvs1} co mod1-2" \
+"${PROG} [a-z]*: Updating mod1-2
+U mod1-2/file1-2"
+ cd ..
+
+ # Try to determine whether RELATIVE_REPOS is defined
+ # so that we can make the following a lot less
+ # verbose.
+
+ echo "${CVSROOT1_DIRNAME}/mod1-1" > dotest.abs
+ echo "mod1-1" > dotest.rel
+ if cmp dotest.abs mod1-1/CVS/Repository >/dev/null 2>&1; then
+ AREP1="${CVSROOT1_DIRNAME}/"
+ AREP2="${CVSROOT2_DIRNAME}/"
+ elif cmp dotest.rel mod1-1/CVS/Repository >/dev/null 2>&1; then
+ AREP1=""
+ AREP2=""
+ else
+ fail "Cannot figure out if RELATIVE_REPOS is defined."
+ fi
+ rm -f dotest.abs dotest.rel
+
+ #
+ # Make sure that the Root and Repository files contain the
+ # correct information.
+ #
+ dotest multiroot-cvsadm-1a "cat mod1-1/CVS/Root" "${CVSROOT1}"
+ dotest multiroot-cvsadm-1b "cat mod1-1/CVS/Repository" "${AREP1}mod1-1"
+ dotest multiroot-cvsadm-2a "cat mod2-1/CVS/Root" "${CVSROOT2}"
+ dotest multiroot-cvsadm-2b "cat mod2-1/CVS/Repository" "${AREP2}mod2-1"
+ dotest multiroot-cvsadm-3a "cat mod1-2/CVS/Root" "${CVSROOT1}"
+ dotest multiroot-cvsadm-3b "cat mod1-2/CVS/Repository" "${AREP1}mod1-2"
+ dotest multiroot-cvsadm-3c "cat mod1-2/mod2-2/CVS/Root" "${CVSROOT2}"
+ dotest multiroot-cvsadm-3d "cat mod1-2/mod2-2/CVS/Repository" "${AREP2}mod2-2"
+ dotest multiroot-cvsadm-4a "cat mod2-2/CVS/Root" "${CVSROOT2}"
+ dotest multiroot-cvsadm-4b "cat mod2-2/CVS/Repository" "${AREP2}mod2-2"
+ dotest multiroot-cvsadm-4c "cat mod2-2/mod1-2/CVS/Root" "${CVSROOT1}"
+ dotest multiroot-cvsadm-4d "cat mod2-2/mod1-2/CVS/Repository" "${AREP1}mod1-2"
+
+ #
+ # Start testing various cvs commands. Begin with commands
+ # without extra arguments (e.g. "cvs update", "cvs diff",
+ # etc.
+ #
+
+ # Do at least one command with both CVSROOTs to make sure
+ # that there's not some kind of unexpected dependency on the
+ # choice of which CVSROOT is specified on the command line.
+
+ if test "${AREP1}" = ""; then
+ # RELATIVE_REPOS.
+ dotest multiroot-update-1a "${testcvs1} update" \
+"${PROG} [a-z]*: Updating \.
+${PROG} [a-z]*: Updating mod1-1
+${PROG} [a-z]*: Updating mod1-2
+${PROG} [a-z]*: Updating mod1-2/mod2-2
+${PROG} [a-z]*: cannot open directory ${TESTDIR}/root1/mod2-2: No such file or directory
+${PROG} [a-z]*: skipping directory mod1-2/mod2-2
+${PROG} [a-z]*: Updating mod2-1
+${PROG} [a-z]*: cannot open directory ${TESTDIR}/root1/mod2-1: No such file or directory
+${PROG} [a-z]*: skipping directory mod2-1
+${PROG} [a-z]*: Updating mod2-2
+${PROG} [a-z]*: cannot open directory ${TESTDIR}/root1/mod2-2: No such file or directory
+${PROG} [a-z]*: skipping directory mod2-2"
+
+ # Same deal but with -d ${CVSROOT2}.
+ dotest multiroot-update-1b "${testcvs2} update" \
+"${PROG} [a-z]*: Updating \.
+${PROG} [a-z]*: Updating mod1-1
+${PROG} [a-z]*: cannot open directory ${TESTDIR}/root2/mod1-1: No such file or directory
+${PROG} [a-z]*: skipping directory mod1-1
+${PROG} [a-z]*: Updating mod1-2
+${PROG} [a-z]*: cannot open directory ${TESTDIR}/root2/mod1-2: No such file or directory
+${PROG} [a-z]*: skipping directory mod1-2
+${PROG} [a-z]*: Updating mod2-1
+${PROG} [a-z]*: Updating mod2-2
+${PROG} [a-z]*: Updating mod2-2/mod1-2
+${PROG} [a-z]*: cannot open directory ${TESTDIR}/root2/mod1-2: No such file or directory
+${PROG} [a-z]*: skipping directory mod2-2/mod1-2"
+ else
+ # non-RELATIVE_REPOS.
+ if test "$remote" = no; then
+ # The basic idea is that -d overrides CVS/Root.
+ # With RELATIVE_REPOS, CVS could print an error when it
+ # tries to recurse to mod2-2, which doesn't exist in
+ # this repository (?) With absolute, CVS will just look at the
+ # CVS/Repository for the other root (and log to the wrong
+ # history file and that sort of thing).
+ dotest multiroot-update-1a "${testcvs1} update" \
+"${PROG} update: Updating \.
+${PROG} [a-z]*: Updating mod1-1
+${PROG} [a-z]*: Updating mod1-2
+${PROG} [a-z]*: Updating mod1-2/mod2-2
+${PROG} [a-z]*: Updating mod2-1
+${PROG} [a-z]*: Updating mod2-2
+${PROG} [a-z]*: Updating mod2-2/mod1-2"
+ else
+ # Hmm, this one is specific to non-RELATIVE_REPOS too I think.
+ dotest_fail multiroot-update-1a "${testcvs1} update" \
+"protocol error: directory '${TESTDIR}/root2/mod2-2' not within root '${TESTDIR}/root1'"
+ fi # non-remote
+
+ # Same deal but with -d ${CVSROOT2}.
+ if test "$remote" = no; then
+ dotest multiroot-update-1b "${testcvs2} update" \
+"${PROG} update: Updating \.
+${PROG} [a-z]*: Updating mod1-1
+${PROG} [a-z]*: Updating mod1-2
+${PROG} [a-z]*: Updating mod1-2/mod2-2
+${PROG} [a-z]*: Updating mod2-1
+${PROG} [a-z]*: Updating mod2-2
+${PROG} [a-z]*: Updating mod2-2/mod1-2"
+ else
+ dotest_fail multiroot-update-1b "${testcvs2} update" \
+"protocol error: directory '${TESTDIR}/root1' not within root '${TESTDIR}/root2'"
+ fi # non-remote
+ fi # non-RELATIVE_REPOS
+
+ # modify all files and do a diff
+
+ echo bobby >> mod1-1/file1-1
+ echo brown >> mod1-2/file1-2
+ echo goes >> mod2-1/file2-1
+ echo down >> mod2-2/file2-2
+
+ dotest_status multiroot-diff-1 1 "${testcvs} diff" \
+"${PROG} diff: Diffing \.
+${PROG} [a-z]*: Diffing mod1-1
+Index: mod1-1/file1-1
+===================================================================
+RCS file: ${TESTDIR}/root1/mod1-1/file1-1,v
+retrieving revision 1\.1
+diff -r1\.1 file1-1
+1a2
+> bobby
+${PROG} [a-z]*: Diffing mod1-2
+Index: mod1-2/file1-2
+===================================================================
+RCS file: ${TESTDIR}/root1/mod1-2/file1-2,v
+retrieving revision 1\.1
+diff -r1\.1 file1-2
+1a2
+> brown
+${PROG} [a-z]*: Diffing mod2-2/mod1-2
+${PROG} [a-z]*: Diffing mod1-2/mod2-2
+${PROG} [a-z]*: Diffing mod2-1
+Index: mod2-1/file2-1
+===================================================================
+RCS file: ${TESTDIR}/root2/mod2-1/file2-1,v
+retrieving revision 1\.1
+diff -r1\.1 file2-1
+1a2
+> goes
+${PROG} [a-z]*: Diffing mod2-2
+Index: mod2-2/file2-2
+===================================================================
+RCS file: ${TESTDIR}/root2/mod2-2/file2-2,v
+retrieving revision 1\.1
+diff -r1\.1 file2-2
+1a2
+> down" \
+"${PROG} server: Diffing \.
+${PROG} [a-z]*: Diffing mod1-1
+Index: mod1-1/file1-1
+===================================================================
+RCS file: ${TESTDIR}/root1/mod1-1/file1-1,v
+retrieving revision 1\.1
+diff -r1\.1 file1-1
+1a2
+> bobby
+${PROG} [a-z]*: Diffing mod1-2
+Index: mod1-2/file1-2
+===================================================================
+RCS file: ${TESTDIR}/root1/mod1-2/file1-2,v
+retrieving revision 1\.1
+diff -r1\.1 file1-2
+1a2
+> brown
+${PROG} [a-z]*: Diffing mod2-2
+${PROG} [a-z]*: Diffing mod2-2/mod1-2
+${PROG} [a-z]*: Diffing mod1-2
+${PROG} [a-z]*: Diffing mod1-2/mod2-2
+${PROG} [a-z]*: Diffing mod2-1
+Index: mod2-1/file2-1
+===================================================================
+RCS file: ${TESTDIR}/root2/mod2-1/file2-1,v
+retrieving revision 1\.1
+diff -r1\.1 file2-1
+1a2
+> goes
+${PROG} [a-z]*: Diffing mod2-2
+Index: mod2-2/file2-2
+===================================================================
+RCS file: ${TESTDIR}/root2/mod2-2/file2-2,v
+retrieving revision 1\.1
+diff -r1\.1 file2-2
+1a2
+> down"
+
+
+ dotest multiroot-commit-1 "${testcvs} commit -m actually" \
+"${PROG} [a-z]*: Examining \.
+${PROG} [a-z]*: Examining mod1-1
+${PROG} [a-z]*: Examining mod1-2
+${PROG} [a-z]*: Examining mod2-2/mod1-2
+Checking in mod1-1/file1-1;
+${TESTDIR}/root1/mod1-1/file1-1,v <-- file1-1
+new revision: 1.2; previous revision: 1.1
+done
+Checking in mod1-2/file1-2;
+${TESTDIR}/root1/mod1-2/file1-2,v <-- file1-2
+new revision: 1.2; previous revision: 1.1
+done
+${PROG} [a-z]*: Examining mod1-2/mod2-2
+${PROG} [a-z]*: Examining mod2-1
+${PROG} [a-z]*: Examining mod2-2
+Checking in mod2-1/file2-1;
+${TESTDIR}/root2/mod2-1/file2-1,v <-- file2-1
+new revision: 1.2; previous revision: 1.1
+done
+Checking in mod2-2/file2-2;
+${TESTDIR}/root2/mod2-2/file2-2,v <-- file2-2
+new revision: 1.2; previous revision: 1.1
+done"
+
+ dotest multiroot-update-2 "${testcvs} update" \
+"${PROG} update: Updating \.
+${PROG} [a-z]*: Updating mod1-1
+${PROG} [a-z]*: Updating mod1-2
+${PROG} [a-z]*: Updating mod2-2/mod1-2
+U mod2-2/mod1-2/file1-2
+${PROG} [a-z]*: Updating mod1-2/mod2-2
+U mod1-2/mod2-2/file2-2
+${PROG} [a-z]*: Updating mod2-1
+${PROG} [a-z]*: Updating mod2-2" \
+"${PROG} server: Updating \.
+${PROG} [a-z]*: Updating mod1-1
+${PROG} [a-z]*: Updating mod1-2
+${PROG} [a-z]*: Updating mod2-2
+${PROG} [a-z]*: Updating mod2-2/mod1-2
+P mod2-2/mod1-2/file1-2
+${PROG} [a-z]*: Updating mod1-2
+${PROG} [a-z]*: Updating mod1-2/mod2-2
+P mod1-2/mod2-2/file2-2
+${PROG} [a-z]*: Updating mod2-1
+${PROG} [a-z]*: Updating mod2-2"
+
+ dotest multiroot-tag-1 "${testcvs} tag cattle" \
+"${PROG} tag: Tagging \.
+${PROG} [a-z]*: Tagging mod1-1
+T mod1-1/file1-1
+${PROG} [a-z]*: Tagging mod1-2
+T mod1-2/file1-2
+${PROG} [a-z]*: Tagging mod2-2/mod1-2
+${PROG} [a-z]*: Tagging mod1-2/mod2-2
+T mod1-2/mod2-2/file2-2
+${PROG} [a-z]*: Tagging mod2-1
+T mod2-1/file2-1
+${PROG} [a-z]*: Tagging mod2-2" \
+"${PROG} server: Tagging \.
+${PROG} [a-z]*: Tagging mod1-1
+T mod1-1/file1-1
+${PROG} [a-z]*: Tagging mod1-2
+T mod1-2/file1-2
+${PROG} [a-z]*: Tagging mod2-2
+${PROG} [a-z]*: Tagging mod2-2/mod1-2
+${PROG} [a-z]*: Tagging mod1-2
+${PROG} [a-z]*: Tagging mod1-2/mod2-2
+T mod1-2/mod2-2/file2-2
+${PROG} [a-z]*: Tagging mod2-1
+T mod2-1/file2-1
+${PROG} [a-z]*: Tagging mod2-2"
+
+ echo anotherfile1-1 > mod1-1/anotherfile1-1
+ echo anotherfile2-1 > mod2-1/anotherfile2-1
+ echo anotherfile1-2 > mod2-2/mod1-2/anotherfile1-2
+ echo anotherfile2-2 > mod1-2/mod2-2/anotherfile2-2
+
+ if test "x$remote" = xno; then
+ dotest multiroot-add-1 "${testcvs} add mod1-1/anotherfile1-1 mod2-1/anotherfile2-1 mod2-2/mod1-2/anotherfile1-2 mod1-2/mod2-2/anotherfile2-2" \
+"${PROG} [a-z]*: scheduling file .mod1-1/anotherfile1-1. for addition
+${PROG} [a-z]*: scheduling file .mod2-1/anotherfile2-1. for addition
+${PROG} [a-z]*: scheduling file .mod2-2/mod1-2/anotherfile1-2. for addition
+${PROG} [a-z]*: scheduling file .mod1-2/mod2-2/anotherfile2-2. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add these files permanently"
+ else
+ cd mod1-1
+ dotest multiroot-add-1a "${testcvs} add anotherfile1-1" \
+"${PROG} [a-z]*: scheduling file .anotherfile1-1. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ cd ../mod2-1
+ dotest multiroot-add-1b "${testcvs} add anotherfile2-1" \
+"${PROG} [a-z]*: scheduling file .anotherfile2-1. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ cd ../mod2-2/mod1-2
+ dotest multiroot-add-1c "${testcvs} add anotherfile1-2" \
+"${PROG} [a-z]*: scheduling file .anotherfile1-2. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ cd ../../mod1-2/mod2-2
+ dotest multiroot-add-1d "${testcvs} add anotherfile2-2" \
+"${PROG} [a-z]*: scheduling file .anotherfile2-2. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ cd ../..
+ fi
+
+ dotest multiroot-status-1 "${testcvs} status -v" \
+"${PROG} status: Examining \.
+${PROG} [a-z]*: Examining mod1-1
+===================================================================
+File: anotherfile1-1 Status: Locally Added
+
+ Working revision: New file!
+ Repository revision: No revision control file
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+===================================================================
+File: file1-1 Status: Up-to-date
+
+ Working revision: 1\.2.*
+ Repository revision: 1\.2 ${CVSROOT1_DIRNAME}/mod1-1/file1-1,v
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+ Existing Tags:
+ cattle (revision: 1\.2)
+
+${PROG} [a-z]*: Examining mod1-2
+===================================================================
+File: file1-2 Status: Up-to-date
+
+ Working revision: 1\.2.*
+ Repository revision: 1\.2 ${CVSROOT1_DIRNAME}/mod1-2/file1-2,v
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+ Existing Tags:
+ cattle (revision: 1\.2)
+
+${PROG} [a-z]*: Examining mod2-2/mod1-2
+===================================================================
+File: anotherfile1-2 Status: Locally Added
+
+ Working revision: New file!
+ Repository revision: No revision control file
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+===================================================================
+File: file1-2 Status: Up-to-date
+
+ Working revision: 1\.2.*
+ Repository revision: 1\.2 ${CVSROOT1_DIRNAME}/mod1-2/file1-2,v
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+ Existing Tags:
+ cattle (revision: 1\.2)
+
+${PROG} [a-z]*: Examining mod1-2/mod2-2
+===================================================================
+File: anotherfile2-2 Status: Locally Added
+
+ Working revision: New file!
+ Repository revision: No revision control file
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+===================================================================
+File: file2-2 Status: Up-to-date
+
+ Working revision: 1\.2.*
+ Repository revision: 1\.2 ${CVSROOT2_DIRNAME}/mod2-2/file2-2,v
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+ Existing Tags:
+ cattle (revision: 1\.2)
+
+${PROG} [a-z]*: Examining mod2-1
+===================================================================
+File: anotherfile2-1 Status: Locally Added
+
+ Working revision: New file!
+ Repository revision: No revision control file
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+===================================================================
+File: file2-1 Status: Up-to-date
+
+ Working revision: 1\.2.*
+ Repository revision: 1\.2 ${CVSROOT2_DIRNAME}/mod2-1/file2-1,v
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+ Existing Tags:
+ cattle (revision: 1\.2)
+
+${PROG} [a-z]*: Examining mod2-2
+===================================================================
+File: file2-2 Status: Up-to-date
+
+ Working revision: 1\.2.*
+ Repository revision: 1\.2 ${CVSROOT2_DIRNAME}/mod2-2/file2-2,v
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+ Existing Tags:
+ cattle (revision: 1\.2)" \
+"${PROG} server: Examining \.
+${PROG} [a-z]*: Examining mod1-1
+===================================================================
+File: anotherfile1-1 Status: Locally Added
+
+ Working revision: New file!
+ Repository revision: No revision control file
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+===================================================================
+File: file1-1 Status: Up-to-date
+
+ Working revision: 1\.2.*
+ Repository revision: 1\.2 ${CVSROOT1_DIRNAME}/mod1-1/file1-1,v
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+ Existing Tags:
+ cattle (revision: 1\.2)
+
+${PROG} [a-z]*: Examining mod1-2
+===================================================================
+File: file1-2 Status: Up-to-date
+
+ Working revision: 1\.2.*
+ Repository revision: 1\.2 ${CVSROOT1_DIRNAME}/mod1-2/file1-2,v
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+ Existing Tags:
+ cattle (revision: 1\.2)
+
+${PROG} [a-z]*: Examining mod2-2
+${PROG} [a-z]*: Examining mod2-2/mod1-2
+===================================================================
+File: anotherfile1-2 Status: Locally Added
+
+ Working revision: New file!
+ Repository revision: No revision control file
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+===================================================================
+File: file1-2 Status: Up-to-date
+
+ Working revision: 1\.2.*
+ Repository revision: 1\.2 ${CVSROOT1_DIRNAME}/mod1-2/file1-2,v
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+ Existing Tags:
+ cattle (revision: 1\.2)
+
+${PROG} [a-z]*: Examining mod1-2
+${PROG} [a-z]*: Examining mod1-2/mod2-2
+===================================================================
+File: anotherfile2-2 Status: Locally Added
+
+ Working revision: New file!
+ Repository revision: No revision control file
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+===================================================================
+File: file2-2 Status: Up-to-date
+
+ Working revision: 1\.2.*
+ Repository revision: 1\.2 ${CVSROOT2_DIRNAME}/mod2-2/file2-2,v
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+ Existing Tags:
+ cattle (revision: 1\.2)
+
+${PROG} [a-z]*: Examining mod2-1
+===================================================================
+File: anotherfile2-1 Status: Locally Added
+
+ Working revision: New file!
+ Repository revision: No revision control file
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+===================================================================
+File: file2-1 Status: Up-to-date
+
+ Working revision: 1\.2.*
+ Repository revision: 1\.2 ${CVSROOT2_DIRNAME}/mod2-1/file2-1,v
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+ Existing Tags:
+ cattle (revision: 1\.2)
+
+${PROG} [a-z]*: Examining mod2-2
+===================================================================
+File: file2-2 Status: Up-to-date
+
+ Working revision: 1\.2.*
+ Repository revision: 1\.2 ${CVSROOT2_DIRNAME}/mod2-2/file2-2,v
+ Sticky Tag: (none)
+ Sticky Date: (none)
+ Sticky Options: (none)
+
+ Existing Tags:
+ cattle (revision: 1\.2)"
+
+ dotest multiroot-commit-2 "${testcvs} commit -m reading" \
+"${PROG} [a-z]*: Examining \.
+${PROG} [a-z]*: Examining mod1-1
+${PROG} [a-z]*: Examining mod1-2
+${PROG} [a-z]*: Examining mod2-2/mod1-2
+RCS file: ${CVSROOT1_DIRNAME}/mod1-1/anotherfile1-1,v
+done
+Checking in mod1-1/anotherfile1-1;
+${CVSROOT1_DIRNAME}/mod1-1/anotherfile1-1,v <-- anotherfile1-1
+initial revision: 1\.1
+done
+RCS file: ${CVSROOT1_DIRNAME}/mod1-2/anotherfile1-2,v
+done
+Checking in mod2-2/mod1-2/anotherfile1-2;
+${CVSROOT1_DIRNAME}/mod1-2/anotherfile1-2,v <-- anotherfile1-2
+initial revision: 1\.1
+done
+${PROG} [a-z]*: Examining mod1-2/mod2-2
+${PROG} [a-z]*: Examining mod2-1
+${PROG} [a-z]*: Examining mod2-2
+RCS file: ${CVSROOT2_DIRNAME}/mod2-2/anotherfile2-2,v
+done
+Checking in mod1-2/mod2-2/anotherfile2-2;
+${CVSROOT2_DIRNAME}/mod2-2/anotherfile2-2,v <-- anotherfile2-2
+initial revision: 1\.1
+done
+RCS file: ${CVSROOT2_DIRNAME}/mod2-1/anotherfile2-1,v
+done
+Checking in mod2-1/anotherfile2-1;
+${CVSROOT2_DIRNAME}/mod2-1/anotherfile2-1,v <-- anotherfile2-1
+initial revision: 1\.1
+done"
+
+ dotest multiroot-update-3 "${testcvs} update" \
+"${PROG} update: Updating \.
+${PROG} [a-z]*: Updating mod1-1
+${PROG} [a-z]*: Updating mod1-2
+U mod1-2/anotherfile1-2
+${PROG} [a-z]*: Updating mod2-2/mod1-2
+${PROG} [a-z]*: Updating mod1-2/mod2-2
+${PROG} [a-z]*: Updating mod2-1
+${PROG} [a-z]*: Updating mod2-2
+U mod2-2/anotherfile2-2" \
+"${PROG} server: Updating \.
+${PROG} [a-z]*: Updating mod1-1
+${PROG} [a-z]*: Updating mod1-2
+U mod1-2/anotherfile1-2
+${PROG} [a-z]*: Updating mod2-2
+${PROG} [a-z]*: Updating mod2-2/mod1-2
+${PROG} [a-z]*: Updating mod1-2
+${PROG} [a-z]*: Updating mod1-2/mod2-2
+${PROG} [a-z]*: Updating mod2-1
+${PROG} [a-z]*: Updating mod2-2
+U mod2-2/anotherfile2-2"
+
+ dotest multiroot-log-1 "${testcvs} log" \
+"${PROG} log: Logging \.
+${PROG} [a-z]*: Logging mod1-1
+
+RCS file: ${CVSROOT1_DIRNAME}/mod1-1/anotherfile1-1,v
+Working file: mod1-1/anotherfile1-1
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+keyword substitution: kv
+total revisions: 1; selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+reading
+=============================================================================
+
+RCS file: ${CVSROOT1_DIRNAME}/mod1-1/file1-1,v
+Working file: mod1-1/file1-1
+head: 1\.2
+branch:
+locks: strict
+access list:
+symbolic names:
+ cattle: 1\.2
+keyword substitution: kv
+total revisions: 2; selected revisions: 2
+description:
+----------------------------
+revision 1\.2
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+actually
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+is
+=============================================================================
+${PROG} [a-z]*: Logging mod1-2
+
+RCS file: ${CVSROOT1_DIRNAME}/mod1-2/anotherfile1-2,v
+Working file: mod1-2/anotherfile1-2
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+keyword substitution: kv
+total revisions: 1; selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+reading
+=============================================================================
+
+RCS file: ${CVSROOT1_DIRNAME}/mod1-2/file1-2,v
+Working file: mod1-2/file1-2
+head: 1\.2
+branch:
+locks: strict
+access list:
+symbolic names:
+ cattle: 1\.2
+keyword substitution: kv
+total revisions: 2; selected revisions: 2
+description:
+----------------------------
+revision 1\.2
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+actually
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+is
+=============================================================================
+${PROG} [a-z]*: Logging mod2-2/mod1-2
+
+RCS file: ${CVSROOT1_DIRNAME}/mod1-2/anotherfile1-2,v
+Working file: mod2-2/mod1-2/anotherfile1-2
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+keyword substitution: kv
+total revisions: 1; selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+reading
+=============================================================================
+
+RCS file: ${CVSROOT1_DIRNAME}/mod1-2/file1-2,v
+Working file: mod2-2/mod1-2/file1-2
+head: 1\.2
+branch:
+locks: strict
+access list:
+symbolic names:
+ cattle: 1\.2
+keyword substitution: kv
+total revisions: 2; selected revisions: 2
+description:
+----------------------------
+revision 1\.2
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+actually
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+is
+=============================================================================
+${PROG} [a-z]*: Logging mod1-2/mod2-2
+
+RCS file: ${CVSROOT2_DIRNAME}/mod2-2/anotherfile2-2,v
+Working file: mod1-2/mod2-2/anotherfile2-2
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+keyword substitution: kv
+total revisions: 1; selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+reading
+=============================================================================
+
+RCS file: ${CVSROOT2_DIRNAME}/mod2-2/file2-2,v
+Working file: mod1-2/mod2-2/file2-2
+head: 1\.2
+branch:
+locks: strict
+access list:
+symbolic names:
+ cattle: 1\.2
+keyword substitution: kv
+total revisions: 2; selected revisions: 2
+description:
+----------------------------
+revision 1\.2
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+actually
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+anyone
+=============================================================================
+${PROG} [a-z]*: Logging mod2-1
+
+RCS file: ${CVSROOT2_DIRNAME}/mod2-1/anotherfile2-1,v
+Working file: mod2-1/anotherfile2-1
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+keyword substitution: kv
+total revisions: 1; selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+reading
+=============================================================================
+
+RCS file: ${CVSROOT2_DIRNAME}/mod2-1/file2-1,v
+Working file: mod2-1/file2-1
+head: 1\.2
+branch:
+locks: strict
+access list:
+symbolic names:
+ cattle: 1\.2
+keyword substitution: kv
+total revisions: 2; selected revisions: 2
+description:
+----------------------------
+revision 1\.2
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+actually
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+anyone
+=============================================================================
+${PROG} [a-z]*: Logging mod2-2
+
+RCS file: ${CVSROOT2_DIRNAME}/mod2-2/anotherfile2-2,v
+Working file: mod2-2/anotherfile2-2
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+keyword substitution: kv
+total revisions: 1; selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+reading
+=============================================================================
+
+RCS file: ${CVSROOT2_DIRNAME}/mod2-2/file2-2,v
+Working file: mod2-2/file2-2
+head: 1\.2
+branch:
+locks: strict
+access list:
+symbolic names:
+ cattle: 1\.2
+keyword substitution: kv
+total revisions: 2; selected revisions: 2
+description:
+----------------------------
+revision 1\.2
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+actually
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+anyone
+=============================================================================" \
+"${PROG} server: Logging \.
+${PROG} [a-z]*: Logging mod1-1
+
+RCS file: ${CVSROOT1_DIRNAME}/mod1-1/anotherfile1-1,v
+Working file: mod1-1/anotherfile1-1
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+keyword substitution: kv
+total revisions: 1; selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+reading
+=============================================================================
+
+RCS file: ${CVSROOT1_DIRNAME}/mod1-1/file1-1,v
+Working file: mod1-1/file1-1
+head: 1\.2
+branch:
+locks: strict
+access list:
+symbolic names:
+ cattle: 1\.2
+keyword substitution: kv
+total revisions: 2; selected revisions: 2
+description:
+----------------------------
+revision 1\.2
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+actually
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+is
+=============================================================================
+${PROG} [a-z]*: Logging mod1-2
+
+RCS file: ${CVSROOT1_DIRNAME}/mod1-2/anotherfile1-2,v
+Working file: mod1-2/anotherfile1-2
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+keyword substitution: kv
+total revisions: 1; selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+reading
+=============================================================================
+
+RCS file: ${CVSROOT1_DIRNAME}/mod1-2/file1-2,v
+Working file: mod1-2/file1-2
+head: 1\.2
+branch:
+locks: strict
+access list:
+symbolic names:
+ cattle: 1\.2
+keyword substitution: kv
+total revisions: 2; selected revisions: 2
+description:
+----------------------------
+revision 1\.2
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+actually
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+is
+=============================================================================
+${PROG} [a-z]*: Logging mod2-2
+${PROG} [a-z]*: Logging mod2-2/mod1-2
+
+RCS file: ${CVSROOT1_DIRNAME}/mod1-2/anotherfile1-2,v
+Working file: mod2-2/mod1-2/anotherfile1-2
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+keyword substitution: kv
+total revisions: 1; selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+reading
+=============================================================================
+
+RCS file: ${CVSROOT1_DIRNAME}/mod1-2/file1-2,v
+Working file: mod2-2/mod1-2/file1-2
+head: 1\.2
+branch:
+locks: strict
+access list:
+symbolic names:
+ cattle: 1\.2
+keyword substitution: kv
+total revisions: 2; selected revisions: 2
+description:
+----------------------------
+revision 1\.2
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+actually
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+is
+=============================================================================
+${PROG} [a-z]*: Logging mod1-2
+${PROG} [a-z]*: Logging mod1-2/mod2-2
+
+RCS file: ${CVSROOT2_DIRNAME}/mod2-2/anotherfile2-2,v
+Working file: mod1-2/mod2-2/anotherfile2-2
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+keyword substitution: kv
+total revisions: 1; selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+reading
+=============================================================================
+
+RCS file: ${CVSROOT2_DIRNAME}/mod2-2/file2-2,v
+Working file: mod1-2/mod2-2/file2-2
+head: 1\.2
+branch:
+locks: strict
+access list:
+symbolic names:
+ cattle: 1\.2
+keyword substitution: kv
+total revisions: 2; selected revisions: 2
+description:
+----------------------------
+revision 1\.2
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+actually
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+anyone
+=============================================================================
+${PROG} [a-z]*: Logging mod2-1
+
+RCS file: ${CVSROOT2_DIRNAME}/mod2-1/anotherfile2-1,v
+Working file: mod2-1/anotherfile2-1
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+keyword substitution: kv
+total revisions: 1; selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+reading
+=============================================================================
+
+RCS file: ${CVSROOT2_DIRNAME}/mod2-1/file2-1,v
+Working file: mod2-1/file2-1
+head: 1\.2
+branch:
+locks: strict
+access list:
+symbolic names:
+ cattle: 1\.2
+keyword substitution: kv
+total revisions: 2; selected revisions: 2
+description:
+----------------------------
+revision 1\.2
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+actually
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+anyone
+=============================================================================
+${PROG} [a-z]*: Logging mod2-2
+
+RCS file: ${CVSROOT2_DIRNAME}/mod2-2/anotherfile2-2,v
+Working file: mod2-2/anotherfile2-2
+head: 1\.1
+branch:
+locks: strict
+access list:
+symbolic names:
+keyword substitution: kv
+total revisions: 1; selected revisions: 1
+description:
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+reading
+=============================================================================
+
+RCS file: ${CVSROOT2_DIRNAME}/mod2-2/file2-2,v
+Working file: mod2-2/file2-2
+head: 1\.2
+branch:
+locks: strict
+access list:
+symbolic names:
+ cattle: 1\.2
+keyword substitution: kv
+total revisions: 2; selected revisions: 2
+description:
+----------------------------
+revision 1\.2
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
+actually
+----------------------------
+revision 1\.1
+date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
+anyone
+============================================================================="
+
+
+ # After the simple cases, let's execute some commands which
+ # refer to parts of our checked-out tree (e.g. "cvs update
+ # mod1-1 mod2-2")
+
+ if test "$keep" = yes; then
+ echo Keeping ${TESTDIR} and exiting due to --keep
+ exit 0
+ fi
+
+ # clean up after ourselves
+ cd ..
+ rm -r 1
+
+ # clean up our repositories
+ rm -rf root1 root2
+ ;;
+
+ multiroot2)
+ # More multiroot tests. In particular, nested directories.
+
+ CVSROOT1_DIRNAME=${TESTDIR}/root1
+ CVSROOT2_DIRNAME=${TESTDIR}/root2
+ CVSROOT1=${CVSROOT1_DIRNAME} ; export CVSROOT1
+ CVSROOT2=${CVSROOT2_DIRNAME} ; export CVSROOT2
+ if test "x$remote" = xyes; then
+ CVSROOT1=:fork:${CVSROOT1_DIRNAME} ; export CVSROOT1
+ CVSROOT2=:fork:${CVSROOT2_DIRNAME} ; export CVSROOT2
+ fi
+
+ dotest multiroot2-1 "${testcvs} -d ${CVSROOT1} init" ""
+ dotest multiroot2-2 "${testcvs} -d ${CVSROOT2} init" ""
+
+ mkdir imp-dir; cd imp-dir
+ echo file1 >file1
+ mkdir sdir
+ echo sfile >sdir/sfile
+ mkdir sdir/ssdir
+ echo ssfile >sdir/ssdir/ssfile
+ dotest_sort multiroot2-3 \
+"${testcvs} -d ${CVSROOT1} import -m import-to-root1 dir1 vend rel" "
+
+N dir1/file1
+N dir1/sdir/sfile
+N dir1/sdir/ssdir/ssfile
+No conflicts created by this import
+${PROG} [a-z]*: Importing ${TESTDIR}/root1/dir1/sdir
+${PROG} [a-z]*: Importing ${TESTDIR}/root1/dir1/sdir/ssdir"
+ cd sdir
+ dotest_sort multiroot2-4 \
+"${testcvs} -d ${CVSROOT2} import -m import-to-root2 sdir vend2 rel2" "
+
+N sdir/sfile
+N sdir/ssdir/ssfile
+No conflicts created by this import
+${PROG} [a-z]*: Importing ${TESTDIR}/root2/sdir/ssdir"
+ cd ../..
+
+ mkdir 1; cd 1
+ # Get TopLevelAdmin-like behavior.
+ dotest multiroot2-5 "${testcvs} -d ${CVSROOT1} -q co -l ."
+ dotest multiroot2-5 "${testcvs} -d ${CVSROOT1} -q co dir1" \
+"U dir1/file1
+U dir1/sdir/sfile
+U dir1/sdir/ssdir/ssfile"
+ cd dir1
+ dotest multiroot2-6 "${testcvs} -Q release -d sdir" ""
+ dotest multiroot2-7 "${testcvs} -d ${CVSROOT2} -q co sdir" \
+"U sdir/sfile
+U sdir/ssdir/ssfile"
+ cd ..
+ # This has one subtle effect - it deals with Entries.Log
+ # so that the next test doesn't get trace messages for
+ # Entries.Log
+ dotest multiroot2-8 "${testcvs} update" \
+"${PROG} update: Updating \.
+${PROG} update: Updating dir1
+${PROG} update: Updating dir1/sdir
+${PROG} update: Updating dir1/sdir/ssdir" \
+"${PROG} server: Updating \.
+${PROG} server: Updating dir1
+${PROG} server: Updating dir1
+${PROG} server: Updating dir1/sdir
+${PROG} server: Updating dir1/sdir/ssdir"
+ # Two reasons we don't run this on the server: (1) the server
+ # also prints some trace messages, and (2) the server trace
+ # messages are subject to out-of-order bugs (this one is hard
+ # to work around).
+ if test "$remote" = no; then
+ dotest multiroot2-9 "${testcvs} -t update" \
+"${PROG} update: notice: main loop with CVSROOT=${TESTDIR}/root1
+${PROG} update: Updating \.
+${PROG} update: Updating dir1
+${PROG} update: notice: main loop with CVSROOT=${TESTDIR}/root2
+${PROG} update: Updating dir1/sdir
+${PROG} update: Updating dir1/sdir/ssdir"
+ fi
+
+ dotest multiroot2-9 "${testcvs} -q tag tag1" \
+"T dir1/file1
+T dir1/sdir/sfile
+T dir1/sdir/ssdir/ssfile"
+ echo "change it" >>dir1/file1
+ echo "change him too" >>dir1/sdir/sfile
+ dotest multiroot2-10 "${testcvs} -q ci -m modify" \
+"Checking in dir1/file1;
+${TESTDIR}/root1/dir1/file1,v <-- file1
+new revision: 1\.2; previous revision: 1\.1
+done
+Checking in dir1/sdir/sfile;
+${TESTDIR}/root2/sdir/sfile,v <-- sfile
+new revision: 1\.2; previous revision: 1\.1
+done"
+ dotest multiroot2-11 "${testcvs} -q tag tag2" \
+"T dir1/file1
+T dir1/sdir/sfile
+T dir1/sdir/ssdir/ssfile"
+ dotest_status multiroot2-12 1 \
+"${testcvs} -q diff -u -r tag1 -r tag2" \
+"Index: dir1/file1
+===================================================================
+RCS file: ${TESTDIR}/root1/dir1/file1,v
+retrieving revision 1\.1\.1\.1
+retrieving revision 1\.2
+diff -u -r1\.1\.1\.1 -r1\.2
+--- dir1/file1 [0-9/]* [0-9:]* 1\.1\.1\.1
+${PLUS}${PLUS}${PLUS} dir1/file1 [0-9/]* [0-9:]* 1\.2
+@@ -1 ${PLUS}1,2 @@
+ file1
+${PLUS}change it
+Index: dir1/sdir/sfile
+===================================================================
+RCS file: ${TESTDIR}/root2/sdir/sfile,v
+retrieving revision 1\.1\.1\.1
+retrieving revision 1\.2
+diff -u -r1\.1\.1\.1 -r1\.2
+--- dir1/sdir/sfile [0-9/]* [0-9:]* 1\.1\.1\.1
+${PLUS}${PLUS}${PLUS} dir1/sdir/sfile [0-9/]* [0-9:]* 1\.2
+@@ -1 ${PLUS}1,2 @@
+ sfile
+${PLUS}change him too"
+
+ if test "$keep" = yes; then
+ echo Keeping ${TESTDIR} and exiting due to --keep
+ exit 0
+ fi
+
+ # clean up after ourselves
+ cd ..
+ rm -r imp-dir 1
+
+ # clean up our repositories
+ rm -rf root1 root2
+ ;;
+
+ multiroot3)
+ # More multiroot tests. Directories are side-by-side, not nested.
+ # Not drastically different from multiroot but it covers somewhat
+ # different stuff.
+
+ if test "x$remote" = xyes; then
+ CVSROOT1=:fork:${TESTDIR}/root1 ; export CVSROOT1
+ CVSROOT2=:fork:${TESTDIR}/root2 ; export CVSROOT2
+ else
+ CVSROOT1=${TESTDIR}/root1 ; export CVSROOT1
+ CVSROOT2=${TESTDIR}/root2 ; export CVSROOT2
+ fi
+
+ mkdir 1; cd 1
+ dotest multiroot3-1 "${testcvs} -d ${CVSROOT1} init" ""
+ dotest multiroot3-2 "${testcvs} -d ${CVSROOT1} -q co -l ." ""
+ mkdir dir1
+ dotest multiroot3-3 "${testcvs} add dir1" \
+"Directory ${TESTDIR}/root1/dir1 added to the repository"
+ dotest multiroot3-4 "${testcvs} -d ${CVSROOT2} init" ""
+ rm -r CVS
+ dotest multiroot3-5 "${testcvs} -d ${CVSROOT2} -q co -l ." ""
+ mkdir dir2
+
+ # OK, the problem is that CVS/Entries doesn't look quite right,
+ # I suppose because of the "rm -r".
+ # For local this fixes it up.
+ dotest multiroot3-6 "${testcvs} -d ${CVSROOT1} -q co dir1" ""
+ if test "$remote" = yes; then
+ # For remote that doesn't do it. Use the quick and dirty fix.
+ echo "D/dir1////" >CVS/Entries
+ echo "D/dir2////" >>CVS/Entries
+ fi
+
+ dotest multiroot3-7 "${testcvs} add dir2" \
+"Directory ${TESTDIR}/root2/dir2 added to the repository"
+
+ touch dir1/file1 dir2/file2
+ if test "$remote" = yes; then
+ # Trying to add them both in one command doesn't work,
+ # because add.c doesn't do multiroot (it doesn't use recurse.c).
+ # Furthermore, it can't deal with the parent directory
+ # having a different root from the child, hence the cd.
+ cd dir1
+ dotest multiroot3-8 "${testcvs} add file1" \
+"${PROG} [a-z]*: scheduling file .file1. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ cd ..
+ dotest multiroot3-8a "${testcvs} add dir2/file2" \
+"${PROG} [a-z]*: scheduling file .dir2/file2. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ else
+ dotest multiroot3-8 "${testcvs} add dir1/file1 dir2/file2" \
+"${PROG} [a-z]*: scheduling file .dir1/file1. for addition
+${PROG} [a-z]*: scheduling file .dir2/file2. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add these files permanently"
+ fi
+
+ dotest multiroot3-9 "${testcvs} -q ci -m add-them" \
+"RCS file: ${TESTDIR}/root2/dir2/file2,v
+done
+Checking in dir2/file2;
+${TESTDIR}/root2/dir2/file2,v <-- file2
+initial revision: 1\.1
+done
+RCS file: ${TESTDIR}/root1/dir1/file1,v
+done
+Checking in dir1/file1;
+${TESTDIR}/root1/dir1/file1,v <-- file1
+initial revision: 1\.1
+done"
+
+ if test "`cat dir1/CVS/Repository`" = "dir1"; then
+ # RELATIVE_REPOS
+ # That this is an error is good - we are asking CVS to do
+ # something which doesn't make sense.
+ dotest_fail multiroot3-10 \
+"${testcvs} -q -d ${CVSROOT1} diff dir1/file1 dir2/file2" \
+"${PROG} [a-z]*: failed to create lock directory in repository .${TESTDIR}/root1/dir2': No such file or directory
+${PROG} [a-z]*: failed to obtain dir lock in repository .${TESTDIR}/root1/dir2'
+${PROG} \[[a-z]* aborted\]: read lock failed - giving up"
+ else
+ # Not RELATIVE_REPOS.
+ if test "$remote" = yes; then
+ # This is good behavior - we are asking CVS to do something
+ # which doesn't make sense.
+ dotest_fail multiroot3-10 \
+"${testcvs} -q -d ${CVSROOT1} diff dir1/file1 dir2/file2" \
+"protocol error: directory '${TESTDIR}/root2/dir2' not within root '${TESTDIR}/root1'"
+ else
+ # Local isn't as picky as we'd want in terms of getting
+ # the wrong root.
+ dotest multiroot3-10 \
+"${testcvs} -q -d ${CVSROOT1} diff dir1/file1 dir2/file2" ""
+ fi
+ fi
+ # This one is supposed to work.
+ dotest multiroot3-11 "${testcvs} -q diff dir1/file1 dir2/file2" ""
+
+ cd ..
+
+ if test "$keep" = yes; then
+ echo Keeping ${TESTDIR} and exiting due to --keep
+ exit 0
+ fi
+
+ rm -r 1
+ rm -rf ${TESTDIR}/root1 ${TESTDIR}/root2
+ unset CVSROOT1
+ unset CVSROOT2
+ ;;
+
+ multiroot4)
+ # More multiroot tests, in particular we have two roots with
+ # similarly-named directories and we try to see that CVS can
+ # keep them separate.
+ if test "x$remote" = xyes; then
+ CVSROOT1=:fork:${TESTDIR}/root1 ; export CVSROOT1
+ CVSROOT2=:fork:${TESTDIR}/root2 ; export CVSROOT2
+ else
+ CVSROOT1=${TESTDIR}/root1 ; export CVSROOT1
+ CVSROOT2=${TESTDIR}/root2 ; export CVSROOT2
+ fi
+
+ mkdir 1; cd 1
+ dotest multiroot4-1 "${testcvs} -d ${CVSROOT1} init" ""
+ dotest multiroot4-2 "${testcvs} -d ${CVSROOT1} -q co -l ." ""
+ mkdir dircom
+ dotest multiroot4-3 "${testcvs} add dircom" \
+"Directory ${TESTDIR}/root1/dircom added to the repository"
+ cd dircom
+ touch file1
+ dotest multiroot4-4 "${testcvs} add file1" \
+"${PROG} [a-z]*: scheduling file .file1. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest multiroot4-5 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/root1/dircom/file1,v
+done
+Checking in file1;
+${TESTDIR}/root1/dircom/file1,v <-- file1
+initial revision: 1\.1
+done"
+ cd ../..
+ mkdir 2; cd 2
+ dotest multiroot4-6 "${testcvs} -d ${CVSROOT2} init" ""
+ dotest multiroot4-7 "${testcvs} -d ${CVSROOT2} -q co -l ." ""
+ mkdir dircom
+ dotest multiroot4-8 "${testcvs} add dircom" \
+"Directory ${TESTDIR}/root2/dircom added to the repository"
+ cd dircom
+ touch file2
+ dotest multiroot4-9 "${testcvs} add file2" \
+"${PROG} [a-z]*: scheduling file .file2. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest multiroot4-10 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/root2/dircom/file2,v
+done
+Checking in file2;
+${TESTDIR}/root2/dircom/file2,v <-- file2
+initial revision: 1\.1
+done"
+
+ cd ../..
+ cd 1/dircom
+ # This may look contrived; the real world example which inspired
+ # it was that a user was changing from local to remote. Cases
+ # like switching servers (among those mounting the same
+ # repository) and so on would also look the same.
+ mkdir sdir2
+ dotest multiroot4-11 "${testcvs} -d ${CVSROOT2} add sdir2" \
+"Directory ${TESTDIR}/root2/dircom/sdir2 added to the repository"
+
+ dotest multiroot4-12 "${testcvs} -q update" ""
+ cd ..
+ dotest multiroot4-13 "${testcvs} -q update dircom" ""
+ cd ..
+
+ rm -r 1 2
+ rm -rf ${TESTDIR}/root1 ${TESTDIR}/root2
+ unset CVSROOT1
+ unset CVSROOT2
+ ;;
+
+ rmroot)
+ # When the Entries/Root file is removed from an existing
+ # workspace, CVS should assume $CVSROOT instead
+ #
+ # Right now only checking that CVS exits normally on an
+ # update once CVS/Root is deleted
+ #
+ # There was a time when this would core dump when run in
+ # client/server mode
+
+ mkdir 1; cd 1
+ dotest rmroot-setup-1 "${testcvs} -q co -l ." ''
+ mkdir first-dir
+ dotest rmroot-setup-2 "${testcvs} add first-dir" \
+"Directory ${TESTDIR}/cvsroot/first-dir added to the repository"
+ cd first-dir
+ touch file1 file2
+ dotest rmroot-setup-3 "${testcvs} add file1 file2" \
+"${PROG} [a-z]*: scheduling file .file1. for addition
+${PROG} [a-z]*: scheduling file .file2. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add these files permanently"
+ dotest rmroot-setup-4 "${testcvs} -q commit -minit" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+done
+Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+initial revision: 1\.1
+done
+RCS file: ${TESTDIR}/cvsroot/first-dir/file2,v
+done
+Checking in file2;
+${TESTDIR}/cvsroot/first-dir/file2,v <-- file2
+initial revision: 1\.1
+done"
+ rm CVS/Root
+ dotest rmroot-1 "${testcvs} -q update" ''
+
+ cd ../..
+ rm -rf 1
+ ;;
+
+ reposmv)
+ # More tests of repositories and specifying them.
+ # Similar to crerepos but that test is probably getting big
+ # enough.
+
+ if test "x$remote" = xyes; then
+ CVSROOT1=:fork:${TESTDIR}/root1 ; export CVSROOT1
+ CVSROOT_MOVED=:fork:${TESTDIR}/root-moved ; export CVSROOT1
+ else
+ CVSROOT1=${TESTDIR}/root1 ; export CVSROOT1
+ CVSROOT_MOVED=${TESTDIR}/root-moved ; export CVSROOT1
+ fi
+
+ dotest reposmv-setup-1 "${testcvs} -d ${CVSROOT1} init" ""
+ mkdir imp-dir; cd imp-dir
+ echo file1 >file1
+ dotest reposmv-setup-2 \
+"${testcvs} -d ${CVSROOT1} import -m add dir1 vendor release" \
+"N dir1/file1
+
+No conflicts created by this import"
+ cd ..
+
+ mkdir 1; cd 1
+ dotest reposmv-1 "${testcvs} -d ${CVSROOT1} -Q co dir1" ""
+ mv ${TESTDIR}/root1 ${TESTDIR}/root-moved
+ cd dir1
+
+ # If we didn't have a relative repository, get one now.
+ dotest reposmv-1a "cat CVS/Repository" \
+"${TESTDIR}/root1/dir1" "dir1"
+ echo dir1 >CVS/Repository
+
+ # There were some duplicated warnings and such; only test
+ # for the part of the error message which makes sense.
+ # Bug: "skipping directory " without filename.
+ if test "$remote" = no; then
+ dotest reposmv-2 "${testcvs} update" "${DOTSTAR}
+${PROG} update: ignoring CVS/Root because it specifies a non-existent repository ${TESTDIR}/root1
+${PROG} update: cannot open directory ${TESTDIR}/cvsroot/dir1: No such file or directory
+${PROG} update: skipping directory "
+ else
+ dotest_fail reposmv-2 "${testcvs} update" \
+"Cannot access ${TESTDIR}/root1/CVSROOT
+No such file or directory"
+ fi
+
+ # CVS/Root overrides $CVSROOT
+ if test "$remote" = no; then
+ CVSROOT_SAVED=${CVSROOT}
+ CVSROOT=${TESTDIR}/root-moved; export CVSROOT
+ dotest reposmv-3 "${testcvs} update" \
+"${DOTSTAR}
+${PROG} update: ignoring CVS/Root because it specifies a non-existent repository ${TESTDIR}/root1
+${PROG} update: Updating \.
+${DOTSTAR}"
+ CVSROOT=${CVSROOT_SAVED}; export CVSROOT
+ else
+ CVSROOT_SAVED=${CVSROOT}
+ CVSROOT=:fork:${TESTDIR}/root-moved; export CVSROOT
+ dotest_fail reposmv-3 "${testcvs} update" \
+"Cannot access ${TESTDIR}/root1/CVSROOT
+No such file or directory"
+ CVSROOT=${CVSROOT_SAVED}; export CVSROOT
+ fi
+
+ if test "$remote" = no; then
+ # CVS/Root doesn't seem to quite completely override $CVSROOT
+ # Bug? Not necessarily a big deal if it only affects error
+ # messages.
+ CVSROOT_SAVED=${CVSROOT}
+ CVSROOT=${TESTDIR}/root-none; export CVSROOT
+ dotest_fail reposmv-4 "${testcvs} update" \
+"${PROG} update: in directory \.:
+${PROG} update: ignoring CVS/Root because it specifies a non-existent repository ${TESTDIR}/root1
+${PROG} \[update aborted\]: ${TESTDIR}/root-none/CVSROOT: No such file or directory"
+ CVSROOT=${CVSROOT_SAVED}; export CVSROOT
+ else
+ CVSROOT_SAVED=${CVSROOT}
+ CVSROOT=:fork:${TESTDIR}/root-none; export CVSROOT
+ dotest_fail reposmv-4 "${testcvs} update" \
+"Cannot access ${TESTDIR}/root1/CVSROOT
+No such file or directory"
+ CVSROOT=${CVSROOT_SAVED}; export CVSROOT
+ fi
+
+ # -d overrides CVS/Root
+ #
+ # Oddly enough, with CVS 1.10 I think this didn't work for
+ # local (that is, it would appear that CVS/Root would not
+ # get used, but would produce an error if it didn't exist).
+ dotest reposmv-5 "${testcvs} -d ${CVSROOT_MOVED} update" \
+"${PROG} [a-z]*: Updating \."
+
+ # TODO: could also test various other things, like what if the
+ # user removes CVS/Root (which is legit). Or another set of
+ # tests would be if both repositories exist but we want to make
+ # sure that CVS is using the correct one.
+
+ cd ../..
+ rm -r imp-dir 1
+ rm -rf root1 root2
+ unset CVSROOT1
+ ;;
+
+ pserver)
+ # Test basic pserver functionality.
+ if test "$remote" = yes; then
+ # First set SystemAuth=no. Not really necessary, I don't
+ # think, but somehow it seems like the clean thing for
+ # the testsuite.
+ mkdir 1; cd 1
+ dotest pserver-1 "${testcvs} -Q co CVSROOT" ""
+ cd CVSROOT
+ echo "SystemAuth=no" >config
+ dotest pserver-2 "${testcvs} -q ci -m config-it" \
+"Checking in config;
+${TESTDIR}/cvsroot/CVSROOT/config,v <-- config
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
+done
+${PROG} [a-z]*: Rebuilding administrative file database"
+ echo "testme:q6WV9d2t848B2:`id -un`" \
+ >${CVSROOT_DIRNAME}/CVSROOT/passwd
+ ${testcvs} pserver >${TESTDIR}/pserver.tmp 2>&1 <<EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+EOF
+ dotest pserver-3 "cat ${TESTDIR}/pserver.tmp" \
+"error 0 Server configuration missing --allow-root in inetd.conf"
+
+ # Sending the Root and noop before waiting for the
+ # "I LOVE YOU" is bogus, but hopefully we can get
+ # away with it.
+ ${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver >${TESTDIR}/pserver.tmp 2>&1 <<EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+Root ${CVSROOT_DIRNAME}
+noop
+EOF
+ dotest pserver-4 "cat ${TESTDIR}/pserver.tmp" \
+"${DOTSTAR} LOVE YOU
+ok"
+
+ ${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver >${TESTDIR}/pserver.tmp 2>&1 <<EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END AUTH REQUEST
+Root ${TESTDIR}/1
+noop
+EOF
+ dotest pserver-5 "cat ${TESTDIR}/pserver.tmp" \
+"${DOTSTAR} LOVE YOU
+E Protocol error: Root says \"${TESTDIR}/1\" but pserver says \"${CVSROOT_DIRNAME}\"
+error "
+
+ ${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver >${TESTDIR}/pserver.tmp 2>&1 <<EOF
+BEGIN AUTH REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d^b?hd
+END AUTH REQUEST
+EOF
+ dotest pserver-6 "cat ${TESTDIR}/pserver.tmp" \
+"I HATE YOU"
+
+ ${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver >${TESTDIR}/pserver.tmp 2>&1 <<EOF
+BEGIN VERIFICATION REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d^b?hd
+END VERIFICATION REQUEST
+EOF
+ dotest pserver-7 "cat ${TESTDIR}/pserver.tmp" \
+"I HATE YOU"
+
+ ${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver >${TESTDIR}/pserver.tmp 2>&1 <<EOF
+BEGIN VERIFICATION REQUEST
+${CVSROOT_DIRNAME}
+testme
+Ay::'d
+END VERIFICATION REQUEST
+EOF
+ dotest pserver-8 "cat ${TESTDIR}/pserver.tmp" \
+"${DOTSTAR} LOVE YOU"
+
+ # Clean up.
+ echo "# comments only" >config
+ dotest pserver-cleanup-1 "${testcvs} -q ci -m config-it" \
+"Checking in config;
+${TESTDIR}/cvsroot/CVSROOT/config,v <-- config
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
+done
+${PROG} [a-z]*: Rebuilding administrative file database"
+ cd ../..
+ rm -r 1
+ rm ${CVSROOT_DIRNAME}/CVSROOT/passwd
+ fi # skip the whole thing for local
+ ;;
+
+ server)
+ # Some tests of the server (independent of the client).
+ if test "$remote" = yes; then
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Directory bogus
+mumble/bar
+update
+EOF
+ dotest server-1 "cat ${TESTDIR}/server.tmp" \
+"E Protocol error: Root request missing
+error "
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server-1
+ fi
+
+ # Could also test for relative pathnames here (so that crerepos-6a
+ # and crerepos-6b can use :fork:).
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Set OTHER=variable
+Set MYENV=env-value
+init ${TESTDIR}/crerepos
+EOF
+ dotest server-2 "cat ${TESTDIR}/server.tmp" "ok"
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server-2
+ fi
+ dotest server-3 "test -d ${TESTDIR}/crerepos/CVSROOT" ""
+
+ # Now some tests of gzip-file-contents (used by jCVS).
+ awk 'BEGIN { \
+printf "%c%c%c%c%c%c.6%c%c+I-.%c%c%c%c5%c;%c%c%c%c", \
+31, 139, 8, 64, 5, 7, 64, 3, 225, 2, 64, 198, 185, 5, 64, 64, 64}' \
+ </dev/null | tr '\100' '\000' >gzipped.dat
+ # Note that the CVS client sends "-b 1.1.1", and this
+ # test doesn't. But the server also defaults to that.
+ cat <<EOF >session.dat
+Root ${TESTDIR}/crerepos
+UseUnchanged
+gzip-file-contents 3
+Argument -m
+Argument msg
+Argumentx
+Argument dir1
+Argument tag1
+Argument tag2
+Directory .
+${TESTDIR}/crerepos
+Modified file1
+u=rw,g=r,o=r
+z25
+EOF
+ cat gzipped.dat >>session.dat
+ echo import >>session.dat
+ if ${testcvs} server >${TESTDIR}/server.tmp <session.dat; then
+ dotest server-4 "cat ${TESTDIR}/server.tmp" "M N dir1/file1
+M
+M No conflicts created by this import
+M
+ok"
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server-4
+ fi
+ dotest server-5 \
+"${testcvs} -q -d ${TESTDIR}/crerepos co -p dir1/file1" "test"
+
+ # OK, here are some notify tests.
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Root ${TESTDIR}/crerepos
+Directory .
+${TESTDIR}/crerepos/dir1
+Notify file1
+E Fri May 7 13:21:09 1999 GMT myhost some-work-dir EUC
+noop
+EOF
+ dotest server-6 "cat ${TESTDIR}/server.tmp" \
+"Notified \./
+${TESTDIR}/crerepos/dir1/file1
+ok"
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server-6
+ fi
+ # Sending the second "noop" before waiting for the output
+ # from the first is bogus but hopefully we can get away
+ # with it.
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Root ${TESTDIR}/crerepos
+Directory .
+${TESTDIR}/crerepos/dir1
+Notify file1
+E Fri May 7 13:21:09 1999 GMT myhost some-work-dir EUC
+noop
+Notify file1
+E The 57th day of Discord in the YOLD 3165 myhost some-work-dir EUC
+noop
+EOF
+ dotest server-7 "cat ${TESTDIR}/server.tmp" \
+"Notified \./
+${TESTDIR}/crerepos/dir1/file1
+ok
+Notified \./
+${TESTDIR}/crerepos/dir1/file1
+ok"
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server-7
+ fi
+
+ # OK, now test a few error conditions.
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Root ${TESTDIR}/crerepos
+Directory .
+${TESTDIR}/crerepos/dir1
+Notify file1
+E Setting Orange, the 52th day of Discord in the YOLD 3165 myhost some-work-dir EUC
+noop
+EOF
+ # FIXCVS: should give "error" and no "Notified", like server-9
+ dotest server-8 "cat ${TESTDIR}/server.tmp" \
+"E ${PROG} server: invalid character in editor value
+Notified \./
+${TESTDIR}/crerepos/dir1/file1
+ok"
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server-8
+ fi
+
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Root ${TESTDIR}/crerepos
+Directory .
+${TESTDIR}/crerepos/dir1
+Notify file1
+E Setting Orange+57th day of Discord myhost some-work-dir EUC
+noop
+EOF
+ dotest server-9 "cat ${TESTDIR}/server.tmp" \
+"E Protocol error; misformed Notify request
+error "
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server-9
+ fi
+
+ # First demonstrate an interesting quirk in the protocol.
+ # The "watchers" request selects the files to operate based
+ # on files which exist in the working directory. So if we
+ # don't send "Entry" or the like, it won't do anything.
+ # Wants to be documented in cvsclient.texi...
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Root ${TESTDIR}/crerepos
+Directory .
+${TESTDIR}/crerepos/dir1
+watchers
+EOF
+ dotest server-10 "cat ${TESTDIR}/server.tmp" \
+"ok"
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server-10
+ fi
+
+ # See if "watchers" and "editors" display the right thing.
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Root ${TESTDIR}/crerepos
+Directory .
+${TESTDIR}/crerepos/dir1
+Entry /file1/1.1////
+watchers
+EOF
+ dotest server-11 "cat ${TESTDIR}/server.tmp" \
+"M file1 ${username} tedit tunedit tcommit
+ok"
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server-11
+ fi
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Root ${TESTDIR}/crerepos
+Directory .
+${TESTDIR}/crerepos/dir1
+Entry /file1/1.1////
+editors
+EOF
+ dotest server-12 "cat ${TESTDIR}/server.tmp" \
+"M file1 ${username} The 57th day of Discord in the YOLD 3165 myhost some-work-dir
+ok"
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server-12
+ fi
+
+ # Now do an unedit.
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Root ${TESTDIR}/crerepos
+Directory .
+${TESTDIR}/crerepos/dir1
+Notify file1
+U 7 May 1999 15:00 GMT myhost some-work-dir EUC
+noop
+EOF
+ dotest server-13 "cat ${TESTDIR}/server.tmp" \
+"Notified \./
+${TESTDIR}/crerepos/dir1/file1
+ok"
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server-13
+ fi
+
+ # Now try "watchers" and "editors" again.
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Root ${TESTDIR}/crerepos
+Directory .
+${TESTDIR}/crerepos/dir1
+watchers
+EOF
+ dotest server-14 "cat ${TESTDIR}/server.tmp" \
+"ok"
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server-14
+ fi
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Root ${TESTDIR}/crerepos
+Directory .
+${TESTDIR}/crerepos/dir1
+editors
+EOF
+ dotest server-15 "cat ${TESTDIR}/server.tmp" \
+"ok"
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server-15
+ fi
+
+ if test "$keep" = yes; then
+ echo Keeping ${TESTDIR} and exiting due to --keep
+ exit 0
+ fi
+
+ rm -rf ${TESTDIR}/crerepos
+ rm gzipped.dat session.dat
+ rm ${TESTDIR}/server.tmp
+ fi # skip the whole thing for local
+ ;;
+
+ server2)
+ # More server tests, in particular testing that various
+ # possible security holes are plugged.
+ if test "$remote" = yes; then
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Root ${TESTDIR}/cvsroot
+Directory .
+${TESTDIR}/cvsroot/../dir1
+noop
+EOF
+ dotest server2-1 "cat ${TESTDIR}/server.tmp" \
+"E protocol error: directory '${TESTDIR}/cvsroot/\.\./dir1' not within root '${TESTDIR}/cvsroot'
+error "
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server2-1
+ fi
+
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Root ${TESTDIR}/cvsroot
+Directory .
+${TESTDIR}/cvsrootdir1
+noop
+EOF
+ dotest server2-2 "cat ${TESTDIR}/server.tmp" \
+"E protocol error: directory '${TESTDIR}/cvsrootdir1' not within root '${TESTDIR}/cvsroot'
+error "
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server2-2
+ fi
+
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Root ${TESTDIR}/cvsroot
+Directory .
+${TESTDIR}
+noop
+EOF
+ dotest server2-3 "cat ${TESTDIR}/server.tmp" \
+"E protocol error: directory '${TESTDIR}' not within root '${TESTDIR}/cvsroot'
+error "
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server2-3
+ fi
+
+ # OK, now a few tests for the rule that one cannot pass a
+ # filename containing a slash to Modified, Is-modified,
+ # Notify, Questionable, or Unchanged. For completeness
+ # we'd try them all. For lazyness/conciseness we don't.
+ if ${testcvs} server >${TESTDIR}/server.tmp <<EOF; then
+Root ${TESTDIR}/cvsroot
+Directory .
+${TESTDIR}/cvsroot
+Unchanged foo/bar
+noop
+EOF
+ dotest server2-4 "cat ${TESTDIR}/server.tmp" \
+"E protocol error: directory 'foo/bar' not within current directory
+error "
+ else
+ echo "exit status was $?" >>${LOGFILE}
+ fail server2-4
+ fi
+ fi
+ ;;
+
+ client)
+ # Some tests of the client (independent of the server).
+ if test "$remote" = yes; then
+ cat >${TESTDIR}/serveme <<EOF
+#!${TESTSHELL}
+# This is admittedly a bit cheezy, in the sense that we make lots
+# of assumptions about what the client is going to send us.
+# We don't mention Repository, because current clients don't require it.
+# Sending these at our own pace, rather than waiting for the client to
+# make the requests, is bogus, but hopefully we can get away with it.
+echo "Valid-requests Root Valid-responses valid-requests Directory Entry Modified Unchanged Argument Argumentx ci co update"
+echo "ok"
+echo "M special message"
+echo "Created first-dir/"
+echo "${TESTDIR}/cvsroot/first-dir/file1"
+echo "/file1/1.1///"
+echo "u=rw,g=rw,o=rw"
+echo "4"
+echo "xyz"
+echo "ok"
+cat >/dev/null
+EOF
+ chmod +x ${TESTDIR}/serveme
+ CVS_SERVER=${TESTDIR}/serveme; export CVS_SERVER
+ mkdir 1; cd 1
+ dotest_fail client-1 "${testcvs} -q co first-dir" \
+"${PROG} \[checkout aborted\]: This server does not support the global -q option\."
+ dotest client-2 "${testcvs} co first-dir" "special message"
+
+ cat >${TESTDIR}/serveme <<EOF
+#!${TESTSHELL}
+echo "Valid-requests Root Valid-responses valid-requests Directory Entry Modified Unchanged Argument Argumentx ci co update"
+echo "ok"
+echo "M merge-it"
+echo "Copy-file ./"
+echo "${TESTDIR}/cvsroot/first-dir/file1"
+echo "${TESTDIR}/bogus/.#file1.1.1"
+echo "Merged ./"
+echo "${TESTDIR}/cvsroot/first-dir/file1"
+echo "/file1/1.2///"
+echo "u=rw,g=rw,o=rw"
+echo "4"
+echo "abd"
+echo "ok"
+cat >/dev/null
+EOF
+ cd first-dir
+ mkdir ${TESTDIR}/bogus
+ dotest_fail client-3 "${testcvs} update" "merge-it
+${PROG} \[update aborted\]: protocol error: Copy-file tried to specify directory"
+ cat >${TESTDIR}/serveme <<EOF
+#!${TESTSHELL}
+echo "Valid-requests Root Valid-responses valid-requests Directory Entry Modified Unchanged Argument Argumentx ci co update"
+echo "ok"
+echo "M merge-it"
+echo "Copy-file ./"
+echo "${TESTDIR}/cvsroot/first-dir/file1"
+echo ".#file1.1.1"
+echo "Merged ./"
+echo "${TESTDIR}/cvsroot/first-dir/file1"
+echo "/file1/1.2///"
+echo "u=rw,g=rw,o=rw"
+echo "4"
+echo "abc"
+echo "ok"
+cat >/dev/null
+EOF
+ dotest client-4 "${testcvs} update" "merge-it"
+ dotest client-5 "cat .#file1.1.1" "xyz"
+ dotest client-6 "cat CVS/Entries" "/file1/1.2/[A-Za-z0-9 :]*//
+D"
+ dotest client-7 "cat file1" "abc"
+
+ cat >${TESTDIR}/serveme <<EOF
+#!${TESTSHELL}
+echo "Valid-requests Root Valid-responses valid-requests Directory Entry Modified Unchanged Argument Argumentx ci co update"
+echo "ok"
+echo "M OK, whatever"
+echo "ok"
+cat >${TESTDIR}/client.tmp
+EOF
+ chmod u=rw,go= file1
+ # By specifying the time zone in local time, we don't
+ # know exactly how that will translate to GMT.
+ dotest client-8 "${testcvs} update -D 99-10-04" "OK, whatever"
+ dotest client-9 "cat ${TESTDIR}/client.tmp" \
+"Root ${TESTDIR}/cvsroot
+Valid-responses [-a-zA-Z ]*
+valid-requests
+Argument -D
+Argument [34] Oct 1999 [0-9][0-9]:00:00 -0000
+Directory \.
+${TESTDIR}/cvsroot/first-dir
+Entry /file1/1\.2///
+Modified file1
+u=rw,g=,o=
+4
+abc
+update"
+
+ cd ../..
+ rm -r 1
+ rmdir ${TESTDIR}/bogus
+ rm ${TESTDIR}/serveme
+ CVS_SERVER=${testcvs}; export CVS_SERVER
+ fi # skip the whole thing for local
+ ;;
+
*)
echo $what is not the name of a test -- ignored
;;
@@ -15531,10 +20292,15 @@ echo "OK, all tests completed."
# * Test ability to send notifications in response to watches. (currently
# hard to test because CVS doesn't send notifications if username is the
# same).
-# * Test that remote edit and/or unedit works when disconnected from
-# server (e.g. set CVS_SERVER to "foobar").
# * Test the contents of adm files other than Root and Repository.
# Entries seems the next most important thing.
+# * Test the following compatibility issues:
+# - The filler fields in "D" entries in CVS/Entries get preserved
+# (per cvs.texinfo).
+# - Unrecognized entry types in CVS/Entries get ignored (looks like
+# this needs to be documented in cvs.texinfo, but is not)
+# - Test that unrecognized files in CVS directories (e.g. CVS/Foobar)
+# are ignored (per cvs.texinfo).
# End of TODO list.
# Remove the test directory, but first change out of it.
diff --git a/contrib/cvs/src/server.h b/contrib/cvs/src/server.h
index f94b7aa..caeff8a 100644
--- a/contrib/cvs/src/server.h
+++ b/contrib/cvs/src/server.h
@@ -7,6 +7,16 @@
#define STDERR_FILENO 2
#endif
+
+/*
+ * Expand to `S', ` ', or the empty string. Used in `%s-> ...' trace printfs.
+ */
+#ifdef SERVER_SUPPORT
+# define CLIENT_SERVER_STR ((server_active) ? "S" : " ")
+#else
+# define CLIENT_SERVER_STR ""
+#endif
+
#ifdef SERVER_SUPPORT
/*
@@ -139,38 +149,30 @@ struct request
void (*func) PROTO((char *args));
#endif
- /* Stuff for use by the client. */
- enum {
- /*
- * Failure to implement this request can imply a fatal
- * error. This should be set only for commands which were in the
- * original version of the protocol; it should not be set for new
- * commands.
- */
- rq_essential,
-
- /* Some servers might lack this request. */
- rq_optional,
-
- /*
- * Set by the client to one of the following based on what this
- * server actually supports.
- */
- rq_supported,
- rq_not_supported,
-
- /*
- * If the server supports this request, and we do too, tell the
- * server by making the request.
- */
- rq_enableme
- } status;
+ /* One or more of the RQ_* flags described below. */
+ int flags;
+
+ /* If set, failure to implement this request can imply a fatal
+ error. This should be set only for commands which were in the
+ original version of the protocol; it should not be set for new
+ commands. */
+#define RQ_ESSENTIAL 1
+
+ /* Set by the client if the server we are talking to supports it. */
+#define RQ_SUPPORTED 2
+
+ /* If set, and client and server both support the request, the
+ client should tell the server by making the request. */
+#define RQ_ENABLEME 4
+
+ /* The server may accept this request before "Root". */
+#define RQ_ROOTLESS 8
};
/* Table of requests ending with an entry with a NULL name. */
extern struct request requests[];
/* Gzip library, see zlib.c. */
-extern void gunzip_and_write PROTO ((int, char *, unsigned char *, size_t));
-extern void read_and_gzip PROTO ((int, char *, unsigned char **, size_t *,
- size_t *, int));
+extern int gunzip_and_write PROTO ((int, char *, unsigned char *, size_t));
+extern int read_and_gzip PROTO ((int, char *, unsigned char **, size_t *,
+ size_t *, int));
diff --git a/contrib/cvs/src/status.c b/contrib/cvs/src/status.c
index 541a969..4e5ddcb 100644
--- a/contrib/cvs/src/status.c
+++ b/contrib/cvs/src/status.c
@@ -67,37 +67,38 @@ cvsstatus (argc, argv)
wrap_setup ();
#ifdef CLIENT_SUPPORT
- if (client_active) {
- start_server ();
+ if (client_active)
+ {
+ start_server ();
- ign_setup ();
+ ign_setup ();
- if (long_format)
- send_arg("-v");
- if (local)
- send_arg("-l");
+ if (long_format)
+ send_arg("-v");
+ if (local)
+ send_arg("-l");
- send_file_names (argc, argv, SEND_EXPAND_WILD);
+ /* For a while, we tried setting SEND_NO_CONTENTS here so this
+ could be a fast operation. That prevents the
+ server from updating our timestamp if the timestamp is
+ changed but the file is unmodified. Worse, it is user-visible
+ (shows "locally modified" instead of "up to date" if
+ timestamp is changed but file is not). And there is no good
+ workaround (you might not want to run "cvs update"; "cvs -n
+ update" doesn't update CVS/Entries; "cvs diff --brief" or
+ something perhaps could be made to work but somehow that
+ seems nonintuitive to me even if so). Given that timestamps
+ seem to have the potential to get munged for any number of
+ reasons, it seems better to not rely too much on them. */
- /* For a while, we tried setting SEND_NO_CONTENTS here so this
- could be a fast operation. That prevents the
- server from updating our timestamp if the timestamp is
- changed but the file is unmodified. Worse, it is user-visible
- (shows "locally modified" instead of "up to date" if
- timestamp is changed but file is not). And there is no good
- workaround (you might not want to run "cvs update"; "cvs -n
- update" doesn't update CVS/Entries; "cvs diff --brief" or
- something perhaps could be made to work but somehow that
- seems nonintuitive to me even if so). Given that timestamps
- seem to have the potential to get munged for any number of
- reasons, it seems better to not rely too much on them. */
+ send_files (argc, argv, local, 0, 0);
- send_files (argc, argv, local, 0, 0);
+ send_file_names (argc, argv, SEND_EXPAND_WILD);
- send_to_server ("status\012", 0);
- err = get_responses_and_close ();
+ send_to_server ("status\012", 0);
+ err = get_responses_and_close ();
- return err;
+ return err;
}
#endif
@@ -242,7 +243,7 @@ status_fileproc (callerdat, finfo)
}
else
{
- if (isdigit (edata->tag[0]))
+ if (isdigit ((unsigned char) edata->tag[0]))
{
cvs_output (" Sticky Tag:\t\t", 0);
cvs_output (edata->tag, 0);
@@ -288,20 +289,20 @@ status_fileproc (callerdat, finfo)
}
else if (!really_quiet)
cvs_output (" Sticky Options:\t(none)\n", 0);
+ }
- if (long_format && vers->srcfile)
- {
- List *symbols = RCS_symbols(vers->srcfile);
+ if (long_format && vers->srcfile)
+ {
+ List *symbols = RCS_symbols(vers->srcfile);
- cvs_output ("\n Existing Tags:\n", 0);
- if (symbols)
- {
- xrcsnode = finfo->rcs;
- (void) walklist (symbols, tag_list_proc, NULL);
- }
- else
- cvs_output ("\tNo Tags Exist\n", 0);
+ cvs_output ("\n Existing Tags:\n", 0);
+ if (symbols)
+ {
+ xrcsnode = finfo->rcs;
+ (void) walklist (symbols, tag_list_proc, NULL);
}
+ else
+ cvs_output ("\tNo Tags Exist\n", 0);
}
cvs_output ("\n", 0);
diff --git a/contrib/cvs/src/subr.c b/contrib/cvs/src/subr.c
index 07d516f..6a97f28 100644
--- a/contrib/cvs/src/subr.c
+++ b/contrib/cvs/src/subr.c
@@ -16,7 +16,7 @@ extern char *getlogin ();
/*
* malloc some data and die if it fails
*/
-char *
+void *
xmalloc (bytes)
size_t bytes;
{
@@ -30,8 +30,12 @@ xmalloc (bytes)
cp = malloc (bytes);
if (cp == NULL)
- error (1, 0, "out of memory; can not allocate %lu bytes",
- (unsigned long) bytes);
+ {
+ char buf[80];
+ sprintf (buf, "out of memory; can not allocate %lu bytes",
+ (unsigned long) bytes);
+ error (1, 0, buf);
+ }
return (cp);
}
@@ -53,7 +57,12 @@ xrealloc (ptr, bytes)
cp = realloc (ptr, bytes);
if (cp == NULL)
- error (1, 0, "can not reallocate %lu bytes", (unsigned long) bytes);
+ {
+ char buf[80];
+ sprintf (buf, "out of memory; can not reallocate %lu bytes",
+ (unsigned long) bytes);
+ error (1, 0, buf);
+ }
return (cp);
}
@@ -64,7 +73,11 @@ xrealloc (ptr, bytes)
memory which is likely to get as big as MAX_INCR shouldn't be doing
it in one block which must be contiguous, but since getrcskey does
so, we might as well limit the wasted memory to MAX_INCR or so
- bytes. */
+ bytes.
+
+ MIN_INCR and MAX_INCR should both be powers of two and we generally
+ try to keep our allocations to powers of two for the most part.
+ Most malloc implementations these days tend to like that. */
#define MIN_INCR 1024
#define MAX_INCR (2*1024*1024)
@@ -84,11 +97,15 @@ expand_string (strptr, n, newsize)
while (*n < newsize)
{
if (*n < MIN_INCR)
- *n += MIN_INCR;
- else if (*n > MAX_INCR)
+ *n = MIN_INCR;
+ else if (*n >= MAX_INCR)
*n += MAX_INCR;
else
+ {
*n *= 2;
+ if (*n > MAX_INCR)
+ *n = MAX_INCR;
+ }
}
*strptr = xrealloc (*strptr, *n);
}
@@ -487,7 +504,7 @@ check_numeric (rev, argc, argv)
int argc;
char **argv;
{
- if (rev == NULL || !isdigit (*rev))
+ if (rev == NULL || !isdigit ((unsigned char) *rev))
return;
/* Note that the check for whether we are processing more than one
@@ -534,7 +551,7 @@ make_message_rcslegal (message)
}
/* Backtrack to last non-space at end of string, and truncate. */
- while (dp > dst && isspace (dp[-1]))
+ while (dp > dst && isspace ((unsigned char) dp[-1]))
--dp;
*dp = '\0';
@@ -615,15 +632,14 @@ get_file (name, fullname, mode, buf, bufsize, len)
}
else
{
- if (CVS_LSTAT (name, &s) < 0)
- error (1, errno, "can't stat %s", fullname);
+ /* Although it would be cleaner in some ways to just read
+ until end of file, reallocating the buffer, this function
+ does get called on files in the working directory which can
+ be of arbitrary size, so I think we better do all that
+ extra allocation. */
- /* Don't attempt to read special files or symlinks. */
- if (!S_ISREG (s.st_mode))
- {
- *len = 0;
- return;
- }
+ if (CVS_STAT (name, &s) < 0)
+ error (1, errno, "can't stat %s", fullname);
/* Convert from signed to unsigned. */
filesize = s.st_size;
@@ -652,9 +668,7 @@ get_file (name, fullname, mode, buf, bufsize, len)
if (feof (e))
break;
- /* It's probably paranoid to think S.ST_SIZE might be
- too small to hold the entire file contents, but we
- handle it just in case. */
+ /* Allocate more space if needed. */
if (tobuf == *buf + *bufsize)
{
int c;
@@ -684,3 +698,49 @@ get_file (name, fullname, mode, buf, bufsize, len)
(*buf)[nread] = '\0';
}
}
+
+
+/* Follow a chain of symbolic links to its destination. FILENAME
+ should be a handle to a malloc'd block of memory which contains the
+ beginning of the chain. This routine will replace the contents of
+ FILENAME with the destination (a real file). */
+
+void
+resolve_symlink (filename)
+ char **filename;
+{
+ if ((! filename) || (! *filename))
+ return;
+
+ while (islink (*filename))
+ {
+ char *newname;
+#ifdef HAVE_READLINK
+ /* The clean thing to do is probably to have each filesubr.c
+ implement this (with an error if not supported by the
+ platform, in which case islink would presumably return 0).
+ But that would require editing each filesubr.c and so the
+ expedient hack seems to be looking at HAVE_READLINK. */
+ newname = xreadlink (*filename);
+#else
+ error (1, 0, "internal error: islink doesn't like readlink");
+#endif
+
+ if (isabsolute (newname))
+ {
+ free (*filename);
+ *filename = newname;
+ }
+ else
+ {
+ char *oldname = last_component (*filename);
+ int dirlen = oldname - *filename;
+ char *fullnewname = xmalloc (dirlen + strlen (newname) + 1);
+ strncpy (fullnewname, *filename, dirlen);
+ strcpy (fullnewname + dirlen, newname);
+ free (newname);
+ free (*filename);
+ *filename = fullnewname;
+ }
+ }
+}
diff --git a/contrib/cvs/src/tag.c b/contrib/cvs/src/tag.c
index a5b8794..fb19cba 100644
--- a/contrib/cvs/src/tag.c
+++ b/contrib/cvs/src/tag.c
@@ -59,7 +59,7 @@ static List *tlist;
static const char *const tag_usage[] =
{
- "Usage: %s %s [-lRF] [-b] [-d] [-c] [-r tag|-D date] tag [files...]\n",
+ "Usage: %s %s [-lRF] [-b] [-d] [-c] [-r rev|-D date] tag [files...]\n",
"\t-l\tLocal directory only, not recursive.\n",
"\t-R\tProcess directories recursively.\n",
"\t-d\tDelete the given tag.\n",
@@ -178,15 +178,13 @@ cvstag (argc, argv)
send_arg (symtag);
- send_file_names (argc, argv, SEND_EXPAND_WILD);
-
- /* SEND_NO_CONTENTS has a mildly bizarre interaction with
- check_uptodate; if the timestamp is modified but the file
- is unmodified, the check will fail, only to have "cvs diff"
- show no differences (and one must do "update" or something to
- reset the client's notion of the timestamp). */
+ send_files (argc, argv, local, 0,
- send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
+ /* I think the -c case is like "cvs status", in
+ which we really better be correct rather than
+ being fast; it is just too confusing otherwise. */
+ check_uptodate ? 0 : SEND_NO_CONTENTS);
+ send_file_names (argc, argv, SEND_EXPAND_WILD);
send_to_server ("tag\012", 0);
return get_responses_and_close ();
}
@@ -297,9 +295,16 @@ check_fileproc (callerdat, finfo)
{
if (delete_flag)
{
+ /* Deleting a tag which did not exist is a noop and
+ should not be logged. */
addit = 0;
}
}
+ else if (delete_flag)
+ {
+ free (p->data);
+ p->data = xstrdup (oversion);
+ }
else if (strcmp(oversion, p->data) == 0)
{
addit = 0;
@@ -367,7 +372,7 @@ pretag_proc(repository, filter)
s = xstrdup(filter);
for (cp=s; *cp; cp++)
{
- if (isspace(*cp))
+ if (isspace ((unsigned char) *cp))
{
*cp = '\0';
break;
@@ -747,12 +752,12 @@ tag_check_valid (name, argc, argv, local, aflag, repository)
int which;
/* Numeric tags require only a syntactic check. */
- if (isdigit (name[0]))
+ if (isdigit ((unsigned char) name[0]))
{
char *p;
for (p = name; *p != '\0'; ++p)
{
- if (!(isdigit (*p) || *p == '.'))
+ if (!(isdigit ((unsigned char) *p) || *p == '.'))
error (1, 0, "\
Numeric tag %s contains characters other than digits and '.'", name);
}
@@ -903,12 +908,19 @@ tag_check_valid_join (join_tag, argc, argv, local, aflag, repository)
s = strchr (c, ':');
if (s != NULL)
{
- if (isdigit (join_tag[0]))
+ if (isdigit ((unsigned char) join_tag[0]))
error (1, 0,
"Numeric join tag %s may not contain a date specifier",
join_tag);
*s = '\0';
+ /* hmmm... I think it makes sense to allow -j:<date>, but
+ * for now this fixes a bug where CVS just spins and spins (I
+ * think in the RCS code) looking for a zero length tag.
+ */
+ if (!*c)
+ error (1, 0,
+ "argument to join may not contain a date specifier without a tag");
}
tag_check_valid (c, argc, argv, local, aflag, repository);
diff --git a/contrib/cvs/src/vers_ts.c b/contrib/cvs/src/vers_ts.c
index be0f588..e1ba32d 100644
--- a/contrib/cvs/src/vers_ts.c
+++ b/contrib/cvs/src/vers_ts.c
@@ -34,6 +34,10 @@ Version_TS (finfo, options, tag, date, force_tag_match, set_time)
struct stickydirtag *sdtp;
Entnode *entdata;
+#ifdef UTIME_EXPECTS_WRITABLE
+ int change_it_back = 0;
+#endif
+
/* get a new Vers_TS struct */
vers_ts = (Vers_TS *) xmalloc (sizeof (Vers_TS));
memset ((char *) vers_ts, 0, sizeof (*vers_ts));
@@ -209,12 +213,28 @@ Version_TS (finfo, options, tag, date, force_tag_match, set_time)
{
t.actime = t.modtime;
+#ifdef UTIME_EXPECTS_WRITABLE
+ if (!iswritable (finfo->file))
+ {
+ xchmod (finfo->file, 1);
+ change_it_back = 1;
+ }
+#endif /* UTIME_EXPECTS_WRITABLE */
+
/* This used to need to ignore existence_errors
(for cases like where update.c now clears
set_time if noexec, but didn't used to). I
think maybe now it doesn't (server_modtime does
not like those kinds of cases). */
(void) utime (finfo->file, &t);
+
+#ifdef UTIME_EXPECTS_WRITABLE
+ if (change_it_back == 1)
+ {
+ xchmod (finfo->file, 0);
+ change_it_back = 0;
+ }
+#endif /* UTIME_EXPECTS_WRITABLE */
}
}
}
diff --git a/contrib/cvs/src/version.c b/contrib/cvs/src/version.c
index 479e5e6..97622ff 100644
--- a/contrib/cvs/src/version.c
+++ b/contrib/cvs/src/version.c
@@ -12,8 +12,7 @@
#include "cvs.h"
-/* NOTE: remember to remove `Halibut' when patching this code. */
-char *version_string = "\nConcurrent Versions System (CVS) 1.10 `Halibut'";
+char *version_string = "\nConcurrent Versions System (CVS) 1.10.7";
#ifdef CLIENT_SUPPORT
#ifdef SERVER_SUPPORT
diff --git a/contrib/cvs/src/watch.c b/contrib/cvs/src/watch.c
index d9ba1d7..b2935ac 100644
--- a/contrib/cvs/src/watch.c
+++ b/contrib/cvs/src/watch.c
@@ -337,8 +337,8 @@ watch_addremove (argc, argv)
send_arg ("-a");
send_arg ("none");
}
- send_file_names (argc, argv, SEND_EXPAND_WILD);
send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
+ send_file_names (argc, argv, SEND_EXPAND_WILD);
send_to_server (the_args.adding ?
"watch-add\012" : "watch-remove\012",
0);
@@ -437,29 +437,29 @@ watchers_fileproc (callerdat, finfo)
if (them == NULL)
return 0;
- fputs (finfo->fullname, stdout);
+ cvs_output (finfo->fullname, 0);
p = them;
while (1)
{
- putc ('\t', stdout);
+ cvs_output ("\t", 1);
while (*p != '>' && *p != '\0')
- putc (*p++, stdout);
+ cvs_output (p++, 1);
if (*p == '\0')
{
/* Only happens if attribute is misformed. */
- putc ('\n', stdout);
+ cvs_output ("\n", 1);
break;
}
++p;
- putc ('\t', stdout);
+ cvs_output ("\t", 1);
while (1)
{
while (*p != '+' && *p != ',' && *p != '\0')
- putc (*p++, stdout);
+ cvs_output (p++, 1);
if (*p == '\0')
{
- putc ('\n', stdout);
+ cvs_output ("\n", 1);
goto out;
}
if (*p == ',')
@@ -468,9 +468,9 @@ watchers_fileproc (callerdat, finfo)
break;
}
++p;
- putc ('\t', stdout);
+ cvs_output ("\t", 1);
}
- putc ('\n', stdout);
+ cvs_output ("\n", 1);
}
out:;
return 0;
@@ -515,8 +515,8 @@ watchers (argc, argv)
if (local)
send_arg ("-l");
- send_file_names (argc, argv, SEND_EXPAND_WILD);
send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
+ send_file_names (argc, argv, SEND_EXPAND_WILD);
send_to_server ("watchers\012", 0);
return get_responses_and_close ();
}
diff --git a/contrib/cvs/src/wrapper.c b/contrib/cvs/src/wrapper.c
index e7c540d..2d53c7a 100644
--- a/contrib/cvs/src/wrapper.c
+++ b/contrib/cvs/src/wrapper.c
@@ -118,6 +118,11 @@ void wrap_setup()
/* Then add entries found in home dir, (if user has one) and file
exists. */
homedir = get_homedir ();
+ /* If we can't find a home directory, ignore ~/.cvswrappers. This may
+ make tracking down problems a bit of a pain, but on the other
+ hand it might be obnoxious to complain when CVS will function
+ just fine without .cvswrappers (and many users won't even know what
+ .cvswrappers is). */
if (homedir != NULL)
{
char *file;
@@ -348,9 +353,11 @@ wrap_add (line, isTemp)
memset (&e, 0, sizeof(e));
/* Search for the wild card */
- while(*line && isspace(*line))
+ while (*line && isspace ((unsigned char) *line))
++line;
- for(temp=line;*line && !isspace(*line);++line)
+ for (temp = line;
+ *line && !isspace ((unsigned char) *line);
+ ++line)
;
if(temp==line)
return;
@@ -423,8 +430,6 @@ wrap_add (line, isTemp)
error (1, 0, "Correct above errors first");
break;
case 'm':
- /* FIXME: look into whether this option is still relevant given
- the 24 Jun 96 change to merge_file. */
if(*temp=='C' || *temp=='c')
e.mergeMethod=WRAP_COPY;
else
diff --git a/contrib/cvs/src/zlib.c b/contrib/cvs/src/zlib.c
index ca50130..fa0c2ad 100644
--- a/contrib/cvs/src/zlib.c
+++ b/contrib/cvs/src/zlib.c
@@ -430,18 +430,14 @@ compress_buffer_shutdown_output (closure)
/* Here is our librarified gzip implementation. It is very minimal
but attempts to be RFC1952 compliant. */
-/* Note that currently only the client uses the gzip library. If we
- make the server use it too (which should be straightforward), then
- filter_stream_through_program, filter_through_gzip, and
- filter_through_gunzip can go away. */
/* BUF should contain SIZE bytes of gzipped data (RFC1952/RFC1951).
We are to uncompress the data and write the result to the file
- descriptor FD. If something goes wrong, give an error message
- mentioning FULLNAME as the name of the file for FD (and make it a
- fatal error if we can't recover from it). */
+ descriptor FD. If something goes wrong, give a nonfatal error message
+ mentioning FULLNAME as the name of the file for FD. Return 1 if
+ it is an error we can't recover from. */
-void
+int
gunzip_and_write (fd, fullname, buf, size)
int fd;
char *fullname;
@@ -455,9 +451,15 @@ gunzip_and_write (fd, fullname, buf, size)
unsigned long crc;
if (buf[0] != 31 || buf[1] != 139)
- error (1, 0, "gzipped data does not start with gzip identification");
+ {
+ error (0, 0, "gzipped data does not start with gzip identification");
+ return 1;
+ }
if (buf[2] != 8)
- error (1, 0, "only the deflate compression method is supported");
+ {
+ error (0, 0, "only the deflate compression method is supported");
+ return 1;
+ }
/* Skip over the fixed header, and then skip any of the variable-length
fields. */
@@ -496,9 +498,15 @@ gunzip_and_write (fd, fullname, buf, size)
zstr.next_out = outbuf;
zstatus = inflate (&zstr, Z_NO_FLUSH);
if (zstatus != Z_STREAM_END && zstatus != Z_OK)
- compress_error (1, zstatus, &zstr, fullname);
+ {
+ compress_error (0, zstatus, &zstr, fullname);
+ return 1;
+ }
if (write (fd, outbuf, sizeof (outbuf) - zstr.avail_out) < 0)
- error (1, errno, "writing decompressed file %s", fullname);
+ {
+ error (0, errno, "writing decompressed file %s", fullname);
+ return 1;
+ }
crc = crc32 (crc, outbuf, sizeof (outbuf) - zstr.avail_out);
} while (zstatus != Z_STREAM_END);
zstatus = inflateEnd (&zstr);
@@ -509,23 +517,31 @@ gunzip_and_write (fd, fullname, buf, size)
+ (buf[zstr.total_in + 11] << 8)
+ (buf[zstr.total_in + 12] << 16)
+ (buf[zstr.total_in + 13] << 24)))
- error (1, 0, "CRC error uncompressing %s", fullname);
+ {
+ error (0, 0, "CRC error uncompressing %s", fullname);
+ return 1;
+ }
if (zstr.total_out != (buf[zstr.total_in + 14]
+ (buf[zstr.total_in + 15] << 8)
+ (buf[zstr.total_in + 16] << 16)
+ (buf[zstr.total_in + 17] << 24)))
- error (1, 0, "invalid length uncompressing %s", fullname);
+ {
+ error (0, 0, "invalid length uncompressing %s", fullname);
+ return 1;
+ }
+
+ return 0;
}
/* Read all of FD and put the gzipped data (RFC1952/RFC1951) into *BUF,
replacing previous contents of *BUF. *BUF is malloc'd and *SIZE is
its allocated size. Put the actual number of bytes of data in
- *LEN. If something goes wrong, give an error message mentioning
- FULLNAME as the name of the file for FD (and make it a fatal error
- if we can't recover from it). LEVEL is the compression level (1-9). */
+ *LEN. If something goes wrong, give a nonfatal error mentioning
+ FULLNAME as the name of the file for FD, and return 1 if we can't
+ recover from it). LEVEL is the compression level (1-9). */
-void
+int
read_and_gzip (fd, fullname, buf, size, len, level)
int fd;
char *fullname;
@@ -542,8 +558,16 @@ read_and_gzip (fd, fullname, buf, size, len, level)
if (*size < 1024)
{
+ unsigned char *newbuf;
+
*size = 1024;
- *buf = (unsigned char *) xrealloc (*buf, *size);
+ newbuf = realloc (*buf, *size);
+ if (newbuf == NULL)
+ {
+ error (0, 0, "out of memory");
+ return 1;
+ }
+ *buf = newbuf;
}
(*buf)[0] = 31;
(*buf)[1] = 139;
@@ -559,7 +583,10 @@ read_and_gzip (fd, fullname, buf, size, len, level)
Z_DEFAULT_STRATEGY);
crc = crc32 (0, NULL, 0);
if (zstatus != Z_OK)
- compress_error (1, zstatus, &zstr, fullname);
+ {
+ compress_error (0, zstatus, &zstr, fullname);
+ return 1;
+ }
zstr.avail_out = *size;
zstr.next_out = *buf + 10;
@@ -569,7 +596,10 @@ read_and_gzip (fd, fullname, buf, size, len, level)
nread = read (fd, inbuf, sizeof inbuf);
if (nread < 0)
- error (1, errno, "cannot read %s", fullname);
+ {
+ error (0, errno, "cannot read %s", fullname);
+ return 1;
+ }
else if (nread == 0)
/* End of file. */
finish = 1;
@@ -588,9 +618,17 @@ read_and_gzip (fd, fullname, buf, size, len, level)
if (zstr.avail_out < 4096)
{
+ unsigned char *newbuf;
+
offset = zstr.next_out - *buf;
*size *= 2;
- *buf = xrealloc (*buf, *size);
+ newbuf = realloc (*buf, *size);
+ if (newbuf == NULL)
+ {
+ error (0, 0, "out of memory");
+ return 1;
+ }
+ *buf = newbuf;
zstr.next_out = *buf + offset;
zstr.avail_out = *size - offset;
}
@@ -618,5 +656,7 @@ read_and_gzip (fd, fullname, buf, size, len, level)
zstatus = deflateEnd (&zstr);
if (zstatus != Z_OK)
compress_error (0, zstatus, &zstr, fullname);
+
+ return 0;
}
#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
OpenPOWER on IntegriCloud