aboutsummaryrefslogtreecommitdiff
path: root/contrib/cvs/src
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cvs/src')
-rw-r--r--contrib/cvs/src/ChangeLog9664
-rw-r--r--contrib/cvs/src/ChangeLog-9194524
-rw-r--r--contrib/cvs/src/ChangeLog-93953731
-rw-r--r--contrib/cvs/src/ChangeLog-964434
-rw-r--r--contrib/cvs/src/ChangeLog-973249
-rw-r--r--contrib/cvs/src/Makefile.am138
-rw-r--r--contrib/cvs/src/Makefile.in658
-rw-r--r--contrib/cvs/src/add.c951
-rw-r--r--contrib/cvs/src/admin.c950
-rw-r--r--contrib/cvs/src/annotate.c302
-rw-r--r--contrib/cvs/src/buffer.c1980
-rw-r--r--contrib/cvs/src/buffer.h168
-rw-r--r--contrib/cvs/src/checkin.c192
-rw-r--r--contrib/cvs/src/checkout.c1284
-rw-r--r--contrib/cvs/src/classify.c474
-rw-r--r--contrib/cvs/src/client.c5948
-rw-r--r--contrib/cvs/src/client.h222
-rw-r--r--contrib/cvs/src/commit.c2433
-rw-r--r--contrib/cvs/src/create_adm.c187
-rw-r--r--contrib/cvs/src/cvs.h945
-rwxr-xr-xcontrib/cvs/src/cvsbug.in525
-rw-r--r--contrib/cvs/src/cvsrc.c169
-rw-r--r--contrib/cvs/src/diff.c1178
-rw-r--r--contrib/cvs/src/edit.c1164
-rw-r--r--contrib/cvs/src/edit.h41
-rw-r--r--contrib/cvs/src/entries.c1263
-rw-r--r--contrib/cvs/src/error.c255
-rw-r--r--contrib/cvs/src/error.h62
-rw-r--r--contrib/cvs/src/expand_path.c318
-rw-r--r--contrib/cvs/src/fileattr.c656
-rw-r--r--contrib/cvs/src/fileattr.h136
-rw-r--r--contrib/cvs/src/filesubr.c1100
-rw-r--r--contrib/cvs/src/find_names.c427
-rw-r--r--contrib/cvs/src/hardlink.c307
-rw-r--r--contrib/cvs/src/hardlink.h35
-rw-r--r--contrib/cvs/src/hash.c528
-rw-r--r--contrib/cvs/src/hash.h64
-rw-r--r--contrib/cvs/src/history.c1666
-rw-r--r--contrib/cvs/src/history.h15
-rw-r--r--contrib/cvs/src/ignore.c503
-rw-r--r--contrib/cvs/src/import.c1653
-rw-r--r--contrib/cvs/src/lock.c1166
-rw-r--r--contrib/cvs/src/log.c1818
-rw-r--r--contrib/cvs/src/login.c686
-rw-r--r--contrib/cvs/src/logmsg.c988
-rw-r--r--contrib/cvs/src/main.c1240
-rw-r--r--contrib/cvs/src/mkmodules.c1054
-rw-r--r--contrib/cvs/src/modules.c1101
-rw-r--r--contrib/cvs/src/myndbm.c331
-rw-r--r--contrib/cvs/src/myndbm.h59
-rw-r--r--contrib/cvs/src/no_diff.c101
-rw-r--r--contrib/cvs/src/parseinfo.c511
-rw-r--r--contrib/cvs/src/patch.c849
-rw-r--r--contrib/cvs/src/rcs.c9074
-rw-r--r--contrib/cvs/src/rcs.h266
-rw-r--r--contrib/cvs/src/rcscmds.c628
-rw-r--r--contrib/cvs/src/recurse.c1299
-rw-r--r--contrib/cvs/src/release.c334
-rw-r--r--contrib/cvs/src/remove.c294
-rw-r--r--contrib/cvs/src/repos.c211
-rw-r--r--contrib/cvs/src/root.c864
-rw-r--r--contrib/cvs/src/root.h57
-rw-r--r--contrib/cvs/src/run.c578
-rwxr-xr-xcontrib/cvs/src/sanity.sh30254
-rw-r--r--contrib/cvs/src/scramble.c245
-rw-r--r--contrib/cvs/src/server.c6760
-rw-r--r--contrib/cvs/src/server.h202
-rw-r--r--contrib/cvs/src/stack.c188
-rw-r--r--contrib/cvs/src/stack.h17
-rw-r--r--contrib/cvs/src/status.c357
-rw-r--r--contrib/cvs/src/subr.c968
-rw-r--r--contrib/cvs/src/tag.c1465
-rw-r--r--contrib/cvs/src/update.c3049
-rw-r--r--contrib/cvs/src/update.h23
-rw-r--r--contrib/cvs/src/vers_ts.c429
-rw-r--r--contrib/cvs/src/version.c86
-rw-r--r--contrib/cvs/src/watch.c522
-rw-r--r--contrib/cvs/src/watch.h52
-rw-r--r--contrib/cvs/src/wrapper.c623
-rw-r--r--contrib/cvs/src/zlib.c760
80 files changed, 0 insertions, 120008 deletions
diff --git a/contrib/cvs/src/ChangeLog b/contrib/cvs/src/ChangeLog
deleted file mode 100644
index 4e7a42284795..000000000000
--- a/contrib/cvs/src/ChangeLog
+++ /dev/null
@@ -1,9664 +0,0 @@
-2008-03-10 Mark D. Baushke <mdb@gnu.org>
-
- * mkmodules.c, parseinfo.c: Update copyright.
-
- * parseinfo.c (parse_config): Add support for new
- "IgnoreUnknownConfigKeys" configuration key.
- * mkmodules.c (config_contents): Add text about the
- "IgnoreUnknownConfigKeys" option.
- * sanity.sh (config): Test that IgnoreUnknownConfigKeys=yes works.
-
-2008-01-30 Derek R. Price <derek@ximbiot.com>
-
- * update.c (join_file): Use local copy to detect deletion conflicts,
- as opposed to the base revision. Restore freeing of rev2 to its
- original location. Use simpler conflict message.
- * sanity.sh: Update to compensate.
-
-2008-01-29 Derek R. Price <derek@ximbiot.com>
-
- * update.c (join_file): Remove trace that is no longer needed.
-
-2008-01-29 Derek R. Price <derek@ximbiot.com>
- Paul Edwards <fight.subjugation@gmail.com>
-
- * update.c (join_file): Detect deletion conflicts.
- * sanity.sh (join, join4): Adjusted for this fix.
- (join8, join9): Add new tests for conflicts.
-
-2008-01-27 Mark D. Baushke <mdb@gnu.org>
-
- * filesubr.c (xreadlink): s/128/BUFSIZ/ avoid magic numbers.
-
- * client.c (start_rsh_server): Use CVS_SSH for the :extssh:
- method or fall back to "ssh" as set using the --with-ssh flag to
- configure.
-
- * client.h, log.c, main.c, recurse.c, root.c: Update copyright for
- 2008.
-
-2008-01-24 Mark D. Baushke <mdb@gnu.org>
-
- * log.c (cvslog): New -n option to revert the -N switch.
- (log_usage): Add -n to the help string.
- * main.c (cmds[]): Add "blame" as a synonym for the
- "annotate" command.
- * sanity.sh (cvs-log): New tests for 'cvs log -N -n' validation.
- (ann-10w1blame): Test the 'cvs blame' synonym for annotate.
- (Patch suggested by "David O'Brien" <obrien@FreeBSD.org>)
-
- * edit.c (notify_check): Rename to...
- (cvs_notify_check): ...this to avoid Mac OSX symbol conflicts.
- * client.h, edit.h, recurse.c: Change all references.
-
- * client.c (start_rsh_server): Use RSH_DFLT not a hardcoded "rsh"
- * root.c (parse_cvsroot): Fix parsing for the :extssh: method.
-
- * sanity.sh (expr_set_DASHDASH): Fix for non-POSIX expr
- implementations.
- (CVSROOTDIR): Use 'cvsrootdir' instead of 'cvsroot' to
- avoid problems on case preserving and/or case insensitive
- filesystems (e.g., HFS+).
- (CVSROOT_DIRNAME): Use ${TESTDIR}/${CVSROOTDIR} instead of
- ${TESTDIR}/cvsroot to avoid filesystem case sensitivity problems.
- (crerepos-extssh): Clone of crerepos tests, but use the :extssh:
- method.
-
-2007-12-19 Larry Jones <lawrence.jones@siemens.com>
-
- * client.c, import.c, lock.c, login.c, mkmodules.c, modules.c,
- rcs.c, server.c: Fix gcc -Wall warnings.
-
-2007-12-16 Larry Jones <lawrence.jones@siemens.com>
-
- * rcs.c (HAVE_MMAP): Fall back to stdio if mmap fails.
-
-2007-12-13 Larry Jones <lawrence.jones@siemens.com>
-
- * rcs.c (rcsbuf_ftell): Avoid potential overflow.
-
-2007-12-12 Larry Jones <lawrence.jones@siemens.com>
-
- * vers_ts.c (time_stamp): Add warnings for [l]stat failures
- other than no such file.
-
-2007-08-26 Derek Price <derek@ximbiot.com>
-
- * mkmodules.c (in_root): Rename to...
- (in_repository): ...this.
-
-2007-08-26 Larry Jones <lawrence.jones@ugs.com>
-
- * mkmodules.c (in_root, init): Unmix declarations and code.
-
-2007-08-22 Derek Price <derek@ximbiot.com>
-
- * add.c (add): Check last component of argument paths instead of the
- entire argument.
- * sanity.sh (add-restricted): Test indirect paths to `CVS' dir with
- add.
-
- * server.c (serve_init): Remove unnecessary argument to printf style
- function.
-
- * mkmodules.c (in_root): New function.
- (init): Verify that new roots are not created inside others.
- * sanity.sh (init-3): New test for same.
-
-2007-08-16 Derek Price <derek@ximbiot.com>
-
- * root.c (root_allow_used): New function and...
- * root.h (root_allow_used): ...its prototype.
- * server.c (serve_root): Backport --allow-root test for `cvs server'.
- * sanity.sh (server2-5, server2-6): New tests for the above.
-
-2007-06-18 Derek Price <derek@ximbiot.com>
-
- * client.c (send_repository): Don't attempt to send metadata from CVS
- subdirectories when importing.
-
-2007-06-15 Derek Price <derek@ximbiot.com>
-
- * import.c (import): Check more carefully for files and directories
- named "CVS".
- * sanity.sh (import-1b): New test for same.
- (import-2): Test files named "CVS", in addition to directories.
-
-2007-05-22 Larry Jones <lawrence.jones@ugs.com>
-
- * rcs.c (RCS_fully_parse): Include revision in error message.
-
-2007-05-07 Derek Price <derek@ximbiot.com>
-
- * mkmodules.c (init): Assert that the server is not active.
- * server.c (serve_init): Send error message when the init command is
- received from a client.
-
- * sanity.sh (*): Avoid using remote init.
- (skip_always, localonly, restore_adm): New convenience functions.
-
-2007-03-08 Larry Jones <lawrence.jones@ugs.com>
-
- * rcs.c (findmagictag): Cast node->data before doing arithmetic
- since it's now (void *).
-
-2007-03-05 Larry Jones <lawrence.jones@ugs.com>
-
- * rcs.c (RCS_delete_revs): When checking for tagged revisions,
- include magic branch tags.
-
-2007-03-01 Larry Jones <lawrence.jones@ugs.com>
-
- * import.c (import_descend_dir): Correct error message.
- * sanity.sh (pserver-3a): New test.
-
-2006-09-14 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (server3, client2): New tests.
-
-2006-09-07 Derek Price <derek@ximbiot.com>
-
- [bug #17560]
- * rcs.c (apply_rcs_changes): Improve comments. Restore repaired error
- handling.
-
-2006-09-06 Larry Jones <lawrence.jones@ugs.com>
-
- * rcs.c (apply_rcs_changes): Improve linked list handling. Remove
- unused variables and unreachable error handling code. Avoid unneeded
- dynamic allocation of temp linevector. Minor stylistic code clean up.
-
-2006-09-06 Derek Price <derek@ximbiot.com>
-
- [bug #17560]
- * rcs.c (apply_rcs_changes): Improve header block comment. Clean up
- unused linevector on non-fatal error.
-
-2006-09-06 Derek Price <derek@ximbiot.com>
-
- [bug #17560]
- * rcs.c (apply_rcs_changes): Remove an unecessary memcpy. Avoid some
- other processing on error.
- (linevector_delete): Remove - it's no longer used.
-
-2006-09-06 Mark D. Baushke <mdb@gnu.org>
-
- [bug #17560]
- * rcs.c (apply_rcs_changes): Fix the merge algorithm from O(n^2)
- to O(n).
- (Based on a patch submitted by "Michael J. Smith"
- <msmith@ideorlando.org>)
-
-2006-08-28 Derek Price <derek@ximbiot.com>
-
- * recurse.c (do_recursion): Remove misguided assertion.
- * sanity.sh (dottedroot-3): Add test for the above.
- (Thanks to report from Paul Eggert <eggert@CS.UCLA.EDU>.)
-
- [bug #17168]
- * classify.c (Classify_File): Use T_PATCH for changed keywords instead
- of T_CHECKOUT to conserver bandwidth. Don't sticky check when marking
- files for update anyhow.
- * sanity.sh: Update to compensate (s/^U /[UP] /).
-
-2006-08-25 Derek Price <derek@ximbiot.com>
-
- [bug #17168]
- * classify.c (Classify_file): Mark files with potential keyword
- substitution changes as needing update.
- * sanity.sh: Update to compensate.
- (keyword, keywordname, serverpatch): Update to compensate, removing
- the last few "checksum failed" tests.
-
- * classify.c (Classify_File): Remove hacks which worked around checksum
- failures from bug #17032.
-
-2006-08-24 Derek Price <derek@ximbiot.com>
-
- [bug #17032]
- * update.c (patch_file): Correctly recreate client working files
- containing the RCS `Name' keyword before generating patches.
- * sanity.sh (keyword-23r): Merge with local case to compensate.
-
-2006-08-17 Larry Jones <lawrence.jones@ugs.com>
-
- * hash.h: Rename structs node and list to hashnode and hashlist
- to avoid name clashes.
-
-2006-07-25 Mark D. Baushke <mdb@gnu.org>
-
- * login.c (free_cvs_password): New function to control freeing of
- the static get_cvs_passwd() returned storage.
- (login): Call it.
- * cvs.h (free_cvs_password): Add prototype for it.
- * client.c (auth_server): Call it.
- [Alter the previous NetBSD coverity cid-3404 patch.]
-
-2006-07-11 Larry Jones <lawrence.jones@ugs.com>
-
- * log.c (log_usage): Fix misleading description of -b (it selects
- revisions on the default branch *in addition to* revisions selected
- with -r).
-
-2006-06-29 Derek Price <derek@ximbiot.com>
-
- * client.c (is_arg_a_parent_or_listed_dir): Strip trailing slashes from
- dir name defore searching for it. Partially addresses TODO #205.
- * sanity.sh (trailingslashes): Update to compensate.
-
-2006-06-28 Derek Price <derek@ximbiot.com>
-
- [bug #16961]
- * login.c (get_cvs_password): Return copy of global variable.
- (Patch from <mbarabas@redhat.com>.)
-
-2006-06-23 Larry Jones <lawrence.jones@ugs.com>
-
- * server.c (do_cvs_command): Remove unused variable.
-
-2006-06-22 Larry Jones <lawrence.jones@ugs.com>
-
- * mkmodules.c (modules_contents): Remove defunct -i option.
-
-2006-06-10 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (conflicts4): Don't expect specific file permissions. Use
- $PLUS.
-
-2006-06-08 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (conflicts4): Test that the client honors Empty-conflicts.
-
- * server.c (requests): Add "Empty-conflicts" marker.
- * client.c (send_fileproc): Send contents of all files with conflicts
- unless the server can handle the conflict marker in the Entry.
-
- * sanity.sh (conflicts4): New tests.
- (Original patch from Mark D. Baushke <mdb@gnu.org>.)
-
-2006-06-07 Mark D. Baushke <mdb@gnu.org>
-
- * modules.c (my_module): Remove unused variable xvalue.
- [Fixes NetBSD coverity cid-705.]
-
-2006-05-31 Mark D. Baushke <mdb@gnu.org>
-
- * add.c (add): Fix memory leak.
- [Fixes NetBSD coverity cid-3751.]
- (add_directory): Fix memory leak.
- [Fixes NetBSD coverity cid-3640.]
-
- * checkin.c (Checkin): Avoid possible NULL dereference.
- [Fixes NetBSD coverity cid-2425.]
-
- * client.c (auth_server): Fix memory leak.
- [Fixes NetBSD coverity cid-3404.]
-
- * commit.c (remove_file): Fix memory leak.
- [Fixes NetBSD coverity cid-3752.]
-
- * rcs.c (RCS_checkin): Add assert (tip).
- [Fixes NetBSD coverity cid-2424.]
-
-2006-05-26 Mark D. Baushke <mdb@gnu.org>
-
- * add.c (add): Do not leak memory.
- [Fixes NetBSD coverity cid-2199.]
-
- * edit.c (onoff_fileproc): Do not leak memory.
- [Fixes NetBSD coverity cid-2201.]
-
- * edit.c (onoff_filesdoneproc): Do not leak memory.
- [Fixes NetBSD coverity cid-2202.]
-
- * lock.c (readers_exist): Add assert (lockdir).
- [Fixes NetBSD coverity cid-2411.]
-
- * rcs.c (RCS_findlock_or_tip): Do not leak memory.
- [Fixes NetBSD coverity cid-2198.]
-
- * rcs.c (RCS_getdate): Avoid possible NULL dereference.
- [Fixes NetBSD coverity cid-2412.]
-
- * server.c (serve_sticky): Do not leak file descriptors.
- [Fixes NetBSD coverity cid-2197.]
-
- * server.c (do_cvs_command): Do not leak memory.
- [Fixes NetBSD coverity cid-2204.]
-
- * tag.c (add_to_val_tags): Do not leak memory.
- [Fixes NetBSD coverity cid-2071.]
-
-2006-05-25 Derek Price <derek@ximbiot.com>
-
- * client.c (start_rsh_server): Default rsh client to RSH_DFLT. Remove
- verbose comment attempting to justify the previous default.
-
-2006-05-24 Larry Jones <lawrence.jones@ugs.com>
-
- * sanity.sh: Add -v|--verbose option to echo test names. Clean
- up help message.
- Remove val-tags files for cleanup instead of truncating since the
- truncation code doesn't work right on Solaris. Always use -f when
- removing val-tags.
-
-2006-05-22 Derek Price <derek@ximbiot.com>
-
- * rcs.c (RCS_reparsercsfile, RCS_fully_parse, RCS_checkout, RCS_deltas,
- RCS_getdeltatext, RCS_copydeltas): Verify input revision numbers.
- (rcs6): Update to compensate.
-
- * sanity.sh (rcs6): New test.
-
-2006-05-16 Derek Price <derek@ximbiot.com>
-
- * main.c: Update copyright for 2006.
-
-2006-05-12 Mark D. Baushke <mdb@gnu.org>
-
- * log.c (log_expand_revlist): Add assert (r->first). It should
- only be possible for both r->first == NULL && r->last == NULL
- which would have been handled.
- [Fixes NetBSD coverity cid-1063.]
-
- * server.c (do_cvs_command): Protect close (dev_null_fd) against
- invalid fd value in error_exit.
- [Fixes NetBSD coverity cid-1307.]
-
- * rcs.c (RCS_isdead): Assert that the first argument is not NULL.
- [Fixes NetBSD coverity cid-1058.]
-
- * commit.c (checkaddfile): Do not dereference NULL on call to
- error().
- [Fixes NetBSD coverity cid-1061.]
-
- * log.c (cvslog): Assert p->start && p->end instead of masking the
- problem.
- * server.c (server_updated): Assert findnode_fn results instead of
- masking the problem.
-
- * add.c (add_directory): Revert previous change. The xstrdup()
- function already deals a NULL argument.
- * client.c (handle_mt): Ditto.
- * entries.c (Entnode_Create): Ditto.
- (Entries_Open): Ditto.
- * logmsg.c (fmt_proc): Ditto.
- * vers_ts.c (Version_TS): Ditto.
-
-2006-05-11 Mark D. Baushke <mdb@gnu.org>
-
- * add.c (add_directory): Protect tag from NULL dereference.
- [Fixes NetBSD cid-1054.]
-
- * client.c (handle_mt): Deal with missing text argument.
- [Fixes NetBSD cid-924.]
-
- * entries.c (Entnode_Create): Protect date, tag and ts_conflict
- from possible NULL dereference.
- [Fixes NetBSD coverity cid-994, cid-995, cid-1055, cid-1057.]
-
- * entries.c (Entries_Open): Protect dirtag and dirdate from
- possible NULL dereference.
- [Fixes NetBSD coverity cid-996.]
-
- * log.c (cvslog): Validate start and end args to
- date_to_internet().
- [Fixes NetBSD coverity cid-2427 and cid-2428.]
-
- * logmsg.c (fmt_proc): Protect li->tag from NULL dereference.
- [Fixes NetBSD coverity cid-997.]
-
- * vers_ts.c (Version_TS): Protect tag and vers_ts->tag from NULL
- dereference.
- [Fixes NetBSD coverity cid-1053.]
-
-2006-05-04 Mark D. Baushke <mdb@gnu.org>
-
- * filesubr.c (cvs_temp_file): Avoid keeping pointers to free()'d
- storage laying around.
- * commit.c (commit): Handle possible NULL filename values
- returned from cvs_temp_file().
- * filesubr.c (cvs_temp_name): Ditto.
- * import.c (import): Ditto.
- * login.c (password_entry_operation): Ditto.
- * logmsg.c (do_verify): Ditto.
- * patch.c (patch_fileproc): Ditto.
- [Fixes NetBSD coverity cid-2545.]
-
- * buffer.c (packetizing_buffer_output): Initialize outdata.
- [Fixes NetBSD coverity cid-2474.]
-
- * server.c (server_updated): Check for NULL return from
- findnode_fn(). [Fixes NetBSD coverity cid-1352.]
-
-2006-04-19 Larry Jones <lawrence.jones@ugs.com>
-
- * history.c (sort_order): Back out previous change - not needed.
-
-2006-04-15 Larry Jones <lawrence.jones@ugs.com>
-
- * history.c (sort_order): Add prototype.
- * server.c (template_proc): Add prototype and make args const.
- * update.c (RegisterMerge): Make static to match prototype.
-
-2006-04-07 Derek Price <derek@ximbiot.com>
-
- * client.c (strto_file_size): New function which checks for errors when
- parsing protocol input.
- (read_counted_file, update_entries, handle_mbinary): Use new function.
- Remove FIXME.
- (Thanks to a report from Brendan Harrison
- <brendan.harrison@klocwork.com>.)
-
- * client.c (send_a_repository): Add assertion.
- (Thanks to an incorrect report from Brendan Harrison
- <brendan.harrison@klocwork.com>.)
-
-2006-04-06 Derek Price <derek@ximbiot.com>
-
- * filesubr.c (last_component, expand_wild), rcs.c (RCS_deltas,
- RCS_rewrite), server.c (server_checked_in): Add assertions.
- (Thanks to an incorrect report from Brendan Harrison
- <brendan.harrison@klocwork.com>.)
-
-2006-03-31 Mark D. Baushke <mdb@gnu.org>
-
- * cvsrc.c (read_cvsrc): Deal with \r\n (DOS) line endings in
- .cvsrc files.
-
-2006-03-07 Derek Price <derek@ximbiot.com>
-
- * tag.c (rtag_proc): Search the Attic when -F is used.
- * sanity.sh (tests): Run death-rtag.
- (death-rtag): Expect success.
-
- * sanity.sh (death-rtag): Add failing force tag move test.
-
-2006-03-06 Derek Price <derek@ximbiot.com>
-
- * tag.c (rtag_proc): Always search in the attic when -r is used.
-
- * sanity.sh (death-rtag): New test.
- (Original report from C. Michael Pilato <cmpilato@collab.net>.)
-
-2006-03-01 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: Set MALLOC_CHECK_ in hopes of exposing common memory
- errors when CVS is linked with glibc 2.x.
-
-2006-02-27 Derek Price <derek@ximbiot.com>
-
- * lock.c (internal_lock): Back out previous change, we don't change
- user visible output on stable unless absolutely necessary.
-
- * lock.c (internal_lock): Improve error message.
-
-2006-02-26 Derek Price <derek@ximbiot.com>
-
- * client.c (call_in_directory): Remove unneeded code.
- * sanity.sh (toplevel-12): Compensate by failing to expect a redundant
- error message.
-
-2006-02-24 Mark D. Baushke <mdb@gnu.org>
-
- * client.c (gzip_level): Move to...
- * main.c (gzip_level): ...here.
- (main): Revert previous change in '-z' argument processing and
- remove CLIENT_SUPPORT ifdef/endif.
- * sanity.h (crerepos-6a): Deal with --disable-client output.
-
- * main.c (main): Validate the gzip compression level for
- --disable-client configurations.
-
-2006-02-13 Derek Price <derek@ximbiot.com>
-
- * server.c (do_cvs_command): Skip server_cleanup in the child process.
-
- * sanity.sh (sshstdio-6): Rewrite using more portable sed script.
-
-2006-02-02 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (sshstdio): Attempt to ignore spurious SSH output.
-
- * main.c (main), release.c (release), server.c (do_cvs_command): Always
- call the cleanup hooks before exit.
-
-2006-02-01 Derek Price <derek@ximbiot.com>
-
- * tag.c (add_to_val_tags): When a tag turns out to exist in the db when
- it isn't expected, release the lock.
-
- * history.c (save_user, save_file, save_mod, read_hrecs): Avoid
- overflow.
-
-2006-01-30 Derek Price <derek@ximbiot.com>
-
- * server.c (do_cvs_command): Set flow control pipe to blocking mode
- before waiting for it to close.
- (set_block_fd): New function.
- (Original patch from Garrett Rooney <grooney@collab.net>.)
-
-2006-01-13 Larry Jones <lawrence.jones@ugs.com>
-
- * mkmodules.c (config_contents): Change SystemAuth to yes to match
- the default value. Add missing newline in RereadLogAfterVerify.
-
-2006-01-09 Larry Jones <lawrence.jones@ugs.com>
-
- * commit.c (remove_file): Record correct revision in history file.
- (Reported by Chris Reed <cr@progress.com>.)
-
-2005-12-07 Derek Price <derek@ximbiot.com>
-
- * client.c (start_server), root.c (method_names), root.h (CVSmethod):
- Handle :extssh: as a kindness to Eclipse users.
- (Suggestion from Joseph P. Skudlarek <Jskud@Jskud.com>.)
-
-2005-12-06 Mark D. Baushke <mdb@gnu.org>
-
- * buffer.c (stdio_buffer_shutdown): No longer assert() the
- fstat(). Use error (0, ...) instead of error (1, ...) to avoid
- infinite loops. (patch #4678)
- Patch adapted from "Allan L. Bazinet" <allan.bazinet@gmail.com>
-
-2005-11-10 Larry Jones <lawrence.jones@ugs.com>
-
- * commit.c (commit): Complain about obsolete -n option if not in
- server mode.
-
-2005-11-09 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (pserver-4.2): Accept a "no such sytem user" message when
- a root attempt is made.
-
-2005-09-30 Larry Jones <lawrence.jones@ugs.com>
-
- * expand_path.c (expand_path): Fix memory leaks.
-
-2005-09-29 Paul Eggert <eggert@CS.UCLA.EDU>
- Derek Price <derek@ximbiot.com>
-
- * client.c (handle_m, handle_e): Remove incomplete workaround for
- O_NONBLOCK problem; no longer needed because of the fix below.
- (start_rsh_server): We need the O_NONBLOCK fix, so pass 'true' to
- piped_child to enable the workaround.
- * cvs.h (piped_child): New bool argument saying whether O_NONBLOCK
- fix is needed. All uses changed.
- * run.c (work_around_openssh_glitch): New function.
- (piped_child): Use it if the fix is requested. Avoid call call to
- vfork with undefined behavior.
-
-2005-09-26 Conrad T. Pino <Conrad@Pino.com>
-
- * rcs.c: Use "#ifdef HAVE_FSYNC" just like every where else.
-
-2005-09-25 Derek Price <derek@ximbiot.com>
-
- * rcs.c (rcs_internal_unlockfile): Fsync files before renaming them.
- Patch from Rahul Bhargava <rahul@wandisco.com>.
-
-2005-09-24 Derek Price <derek@ximbiot.com>
-
- * update.c (merge_file): Check for RCS_checkout errors.
-
-2005-09-23 Larry Jones <lawrence.jones@ugs.com>
-
- * checkout.c (export_usage): Note that -r requires a tag.
-
-2005-09-22 Larry Jones <lawrence.jones@ugs.com>
-
- * patch.c (patch_usage): Document -k option.
-
-2005-09-22 Derek Price <derek@ximbiot.com>
-
- * classify.c (Classify_File): If a file had a conflict and the
- timestamp hasn't changed, it still has a conflict. Add comment about
- how T_MODIFIED could later turn out to have conflict markers and why
- it should not be checked in this function.
- * client.c (send_fileproc): Don't send contents for files known to have
- conflicts unless this is for `cvs diff'.
- * commit.c (check_fileproc): T_CONFLICT should be handled like
- T_MODIFIED, since force could be requested. Simplify logic since
- T_CONFLICT can now be trusted.
- * cvs.h (file_has_conflict): Remove proto.
- * rcs.c (RCS_Checkout): Comment noexec behavior in header block.
- * server.c (serve_unchanged, serve_is_modified): Handle conflicts.
- * status.c (status_fileproc): Trust T_CONFLICT to simplify.
- * subr.c (file_has_conflict): Removed.
- * update.c (update_fileproc): Trust T_CONFLICT.
- (RegisterMerge): New function factored from...
- (merge_file, join_file): ...these two functions.
- * vers_ts.c (time_stamp_server): Handle = conflict timestamps in server
- entdata.
- * sanity.sh (files-12): Account for slight behavior improvement.
- (status, conflicts, mwrap): Account for corrected behavior.
- (join-readonly-conflict-10): Correct comment.
- (binfiles-con1b): New test for correct behavior.
-
-2005-09-19 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (modules5-8): Rename...
- (modules5-8r): ...to this and comment Mac OS X failure.
- Comment Solaris 9 failure below with a `FIXME?' tag.
-
- * sanity.sh: Remove previous hack in favor of setting TESTDIR on
- Solaris (and Mac OS X) until problem is solved correctly.
-
-2005-09-15 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: Use /bin/pwd to verify current dir since Solaris 9 is
- sometimes resolving symlinked paths.
-
-2005-09-14 Derek Price <derek@ximbiot.com>
-
- * edit.c (edit_usage, unedit_usage, editors_usage), watch.c
- (watch_usage, watchers_usage): Add quotes and reword for clarity and
- consistency.
-
- * edit.c (edit_usage): Add missing syntax. Reword description for
- clarity. Mention default behavior.
-
-2005-09-13 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: Split $username into $username & $username8. Rename
- $author as $anyusername.
-
-2005-09-12 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (binfiles-con1b): Back out accidental addition.
-
- * sanity.sh (username): Cut $username down to 8 characters when longer,
- since that is all that appears in output.
-
-2005-09-07 Derek Price <derek@ximbiot.com>
-
- Close <http://savannah.nongnu.org/bugs/?func=detailitem&item_id=14462>.
- * rcs.c (RCS_parse): Free variable *after* using it for the last time.
-
-2005-09-06 Derek Price <derek@ximbiot.com>
-
- * rcs.c (RCS_putdtree): Remove unused variable.
-
-2005-09-06 Mark D. Baushke <mdb@gnu.org>
-
- Close <https://savannah.nongnu.org/bugs/?func=detailitem&item_id=14435>.
- * rcs.c (RCS_putdtree): Avoid stack overflow which may be
- possible with excessive recursive calls to RCS_putdtree().
- (Patch from Serg Masyutin.)
-
-2005-09-03 Derek Price <derek@ximbiot.com>
-
- * add.c (add_usage): Standardize usage message somewhat.
-
-2005-09-02 Larry Jones <lawrence.jones@ugs.com>
-
- * commit.c (checkaddfile): Improve error messages for lock_RCS failure.
- * release.c (release): Improve error message for pclose failure.
-
- * root.h (struct cvsroot_s): Always declare isremote to simplify
- other code. Simplify referencing code.
- * root.c (new_cvsroot_t): Always initialize isremote.
- * server.h: Always declare server_active to simplify other code.
- Simplify referencing code.
- * server.c: Always define server_active.
-
-2005-09-01 Derek Price <derek@ximbiot.com>
-
- * main.c, wrapper.c: Update links.
-
-2005-09-01 Derek Price <derek@ximbiot.com>
-
- * recurse.c: Update bug report email address.
-
-2005-08-30 Larry Jones <lawrence.jones@ugs.com>
-
- * import.c (import_descend): Lock repository directory during import.
-
-2005-07-12 Derek Price <derek@ximbiot.com>
-
- * buffer.c, buffer.h, client.h, expand_path.c, history.c, myndbm.h,
- release.c: Add copyright notices.
-
-2005-07-11 Derek Price <derek@ximbiot.com>
-
- * buffer.c, buffer.h, client.h, expand_path.c, history.c, myndbm.h,
- release.c: Update license notices.
-
-2005-06-22 Larry Jones <lawrence.jones@ugs.com>
-
- * vers_ts (Version_TS): Don't allow command line keyword expansion
- modes to override binary mode.
- * sanity.sh (): Tests for the above.
- (Merged from trunk.)
-
-2005-06-06 Conrad T. Pino <Conrad@Pino.com>
-
- * cvs.h: Reverse patch committed 2005-05-27 by Conrad T. Pino.
- * run.c: Reverse patch committed 2005-05-27 by Conrad T. Pino.
-
-2005-06-02 Derek Price <derek@ximbiot.com>
-
- * zlib.c (compress_buffer_shutdown_input): Don't attempt to read EOF
- from the client during shutdown. It might never be sent.
- * sanity.sh (abspath2): Test for this.
-
-2005-05-31 Derek Price <derek@ximbiot.com>
- for Alexander Taler <alex@0--0.org>
-
- * rcscmds.c: Change type of call_diff_argc_allocated from int to
- size_t, to match the prototype of run_add_arg_p(). This fixes a
- bus error in OpenBSD 3.6 sparc64.
-
-2005-05-27 Conrad T. Pino <Conrad@Pino.com>
-
- * cvs.h: Replace "run_arg" function with "#define run_arg run_add_arg",
- add "run_add_arg" prototype, change "piped_child" prototype to be same
- as feature branch to reflect "(os2,src,windows-NT)/run.c" changes.
- * run.c: Remove "run_arg" to synchronize with "../windows-NT/run.c".
- Function "run_add_arg" scope was "static" and is now "extern" scope.
- Synchronize "piped_child" function arguments with feature branch.
-
-2005-05-27 Derek Price <derek@ximbiot.com>
-
- * client.c (send_arg): Make arg const.
- (send_option_string): Rename to...
- (send_options): ...this and accept argc/argv in place of string.
- * client.h: Update protos to match the changes to client.c.
- * cvs.h (RCS_exec_rcsdiff, diff_exec): Update protos.
- (run_add_arg_p, run_arg_free_p): New protos.
- * diff.c (opts, opts_allocated): Replace with...
- (diff_argv, diff_argc, diff_arg_allocated): ...these.
- (add_diff_args): New convenience function.
- (diff): Use new constructs and APIs.
- * patch.c (patch_fileproc, RCS_checkin, RCS_delete_revs), rcscmds.c
- (call_diff_add_arg, call_diff_setup, RCS_merge, RCS_exec_rcsdiff,
- diff_exec, RCS_output_diff_options), update.c (patch_file): Use new
- APIs.
- * run.c (run_add_arg_p, run_arg_free_p): New functions.
- (run_argc_allocated): Make size_t.
- (run_setup, run_add_arg): Use new functions.
- * sanity.sh: Accomodate above changes.
- (rcslib-diffrgx-3): Slip in test for space splitting.
-
-2005-05-02 Derek Price <derek@ximbiot.com>
-
- Remove unnecessary level of indirection.
- * lock.c (L_HISTORY_LOCK, L_VAL_TAGS_LOCK): Remove macros.
- (internal_lock, internal_clear_lock): Accept lock as argument.
- (history_lock, clear_history_lock, val_tags_lock, clear_val_tags_lock):
- Replace old macro arg with an actual lock pointer.
-
-2005-05-02 Derek Price <derek@ximbiot.com>
-
- * lock.c (internal_lock, internal_clear_lock): Add protos.
- (history_lock, val_tags_lock): Return the chartered true/false status.
-
-2005-05-02 Derek Price <derek@ximbiot.com>
-
- * cvs.h (CVSHISTLCK): Rename macro to...
- (CVSHISTORYLCK): ...this.
- (CVSVALTAGSLCK): New macro.
- (val_tags_lock, clear_val_tags_lock): New functions.
- * lock.c (global_val_tags_lock): New global.
- (Lock_Cleanup): Clean up after val-tags lock if necessary.
- (L_HISTORY_LOCK, L_VAL_TAGS_LOCK): New local macros.
- (internal_lock, internal_clear_lock, val_tags_lock,
- clear_val_tags_lock): New functions.
- (history_lock, clear_history_lock): Use new internal functions.
- * tag.c (is_in_val_tags, add_to_val_tags): New functions using the
- write-lock for val-tags and factored from...
- (tag_check_valid): ...this function.
- * sanity.sh (lockfiles-22): Add val-tags lock test.
-
-2005-04-28 Derek Price <derek@ximbiot.com>
-
- * cvs.h (history_lock, clear_history_lock): New protos.
- * lock.c (struct lock): Add lockdirname.
- (global_history_lock): New global.
- (global_read_lock): Initialize.
- (lock_name): Handle const args.
- (lock_simple_remove): Factor out code in favor of clear_lock call.
- (set_lock): Handle variable lockdirname.
- (lock_filesdoneproc): Set new lockdirname.
- (history_lock, clear_history_lock): New functions.
- (clear_lock): Avoid segfault on missing lock.
- (Lock_Cleanup): Clean up history locks when necessary.
- * history.c (history_write): Use new lock.
- * sanity.sh (lockfiles-20): Test new lock.
-
-2005-04-28 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (lockfiles): Port some locking tests over from 1.12.x.
-
-2005-04-28 Derek Price <derek@ximbiot.com>
-
- * lock.c (clear_lock): Improve comment.
-
-2005-04-28 Derek Price <derek@ximbiot.com>
-
- * lock.c (struct lock): Store lockdir name.
- (masterlock): Remove global.
- (remove_lock_files, clear_lock, set_lock): Update to compensate.
-
-2005-04-20 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (rcs5): Minor cosmetic change.
-
-2005-04-20 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (tests): Add rcs4.
- (rcs5): Add comments.
-
-2005-04-20 Derek Price <derek@ximbiot.com>
-
- * rcs.c (expand_keywords): Avoid buffer overflow.
- (Original patch from Stewart Brodie <stewart@eh.org>.)
-
- * sanity.sh (rcs5): New tests for the above.
-
-2005-03-17 Derek Price <derek@ximbiot.com>
-
- * login.c (password_entry_parseline): Avoid using uninitialized
- variable.
- * rcs.c (RCS_deltas): Avoid buffer overflow.
- (RCS_checkout): Avoid using uninitialized loglen.
- * patch.c (patch_fileproc): Free original pointer, not one that may
- have been incremented.
- (Thanks to report from Alen Zukich <alen.zukich@klocwork.com>.)
-
-2005-03-17 Derek Price <derek@ximbiot.com>
-
- * commit.c (checkaddfile): Avoid dereferencing a NULL pointer in
- response to a rare error.
- * admin.c (admin_fileproc), log.c (log_expand_revlist), mkmodules.c
- (checkout_file), rcs.c (RCS_getdate, RCS_deltas, RCS_findlock_or_tip,
- RCS_tag2rev): Avoid dereferencing NULL pointer.
- (Thanks to report from Alen Zukich <alen.zukich@klocwork.com>.)
-
-2005-03-17 Derek Price <derek@ximbiot.com>
-
- * rcs.c (RCS_reparsercsfile): Avoid memory leak.
- (Thanks to report from Alen Zukich <alen.zukich@klocwork.com>.)
-
-2005-03-17 Derek Price <derek@ximbiot.com>
-
- * log.c (log_expand_revlist): Suppress message and not error handling
- when really_quiet.
-
-2005-03-17 Derek Price <derek@ximbiot.com>
-
- * client.c (call_in_directory): Put function call after var decls.
-
-2005-03-16 Derek Price <derek@ximbiot.com>
-
- * client.c (call_in_directory), commit.c (commit_filesdoneproc), log.c
- (log_expand_revlist, log_version), logmsg.c (logfile_write), modules
- (my_module), no_diff.c (No_Difference), parseinfo.c (Parse_Info), rcs.c
- (RCS_deltas, RCS_checkin, RCS_addbranch, do_locks, do_symbols),
- rcscmds.c (RCS_merge), root.c (parse_cvsroot, normalize_cvsroot),
- update.c (merge_file): Verify assumptions via assertions.
- (Thanks to (probably) incorrect reports from Alen Zukich
- <alen.zukich@klocwork.com>.)
-
-2005-03-16 Derek Price <derek@ximbiot.com>
-
- * server.c (create_adm_p, serve_entry), tag.c (rtag_proc): Avoid memory
- leaks.
- (Thanks to report from Alen Zukich <alen.zukich@klocwork.com>.)
-
-2005-03-15 Mark D. Baushke <mdb@cvshome.org>
-
- * history.c (select_hrec): Avoid possible memory leak.
-
-2005-03-15 Derek Price <derek@ximbiot.com>
-
- * patch.c (patch_proc): Avoid memory leak.
- (Thanks to report from Alen Zukich <alen.zukich@klocwork.com>.)
-
-2005-03-11 Mark D. Baushke <mdb@cvshome.org>
-
- * modules.c (my_module): Protect against free (NULL) code path.
-
-2005-03-11 Derek Price <derek@ximbiot.com>
-
- * annotate.c (rannotate_proc), fileattr.c (fileattr_write), rcs.c
- (RCS_deltas), server.c (check_repository_password), update.c (update):
- Avoid memory leaks.
- (Thanks to report from Alen Zukich <alen.zukich@klocwork.com>.)
-
-2005-03-09 Derek Price <derek@ximbiot.com>
-
- * add.c (add, add_directory), buffer.c (allocate_buffer_datas),
- client.c (update_entries), commit.c (checkaddfile), entries.c
- (Entries_Open), fileattr.c (fileattr_read), ignore.c (ign_add),
- import.c (import), main.c (main), parseinfo.c (parse_config), rcs.c
- (RCS_reparsercsfile, RCS_getbranchpoint, RCS_checkout,
- RCS_delete_revs, apply_rcs_changes): Avoid memory leaks.
- (Thanks to report from Alen Zukich <alen.zukich@klocwork.com>.)
-
- * hardlink.c, hardlink.h: Avoid compiling entire contents of these
- files w/o preserve permissions support.
-
-2005-03-09 Mark D. Baushke <mdb@cvshome.org>
-
- * history.c (history, save_file): Cleanup the API to match the
- comments.
-
-2005-02-27 Jim Meyering <jim@meyering.net>
-
- * login.c (password_entry_operation): Exit nonzero when
- failing to close a just-appended-to .cvspass file.
-
-2005-02-26 Larry Jones <lawrence.jones@ugs.com>
-
- * release.c (release): Remove unneeded code.
-
-2005-02-22 Derek Price <derek@ximbiot.com>
-
- * edit.c: Load watch settings before setting new ones with
- `cvs watch on/off'.
- (Original patch from Jim Hyslop <jhyslop@ieee.org>.)
-
- * sanity.sh (watch6): New tests for same.
- (Outline from Jim Hyslop <jhyslop@ieee.org>.)
-
-2005-02-21 Mark D. Baushke <mdb@cvshome.org>
-
- * import.c (import): Avoid using assert with side effects it may
- be configured away using NDEBUG.
- (Patch from Frank Hemer <frank@hemer.org>.)
-
-2005-02-08 Derek Price <derek@ximbiot.com>
-
- * build_src.com: Build stack.c on VMS.
- (Suggestion from Piet Schuermans <pschuermans@mac.com>.)
-
-2005-02-01 Larry Jones <lawrence.jones@ugs.com>
-
- * log.c (log_fileproc, log_expand_revlist): Add support for BASE tag.
- * sanity.sh (log): New tests for above.
-
-2005-01-31 Derek Price <derek@ximbiot.com>
-
- * main.c: Update year in copyright notice to match GNU standards.
- * sanity.sh (version-1): Update to match.
-
-2005-01-31 Derek Price <derek@ximbiot.com>
-
- * main.c: Rephrase --version message.
- * sanity.sh (version-1): Update to match.
-
-2005-01-31 Derek Price <derek@ximbiot.com>
-
- * Makefile.am, add.c, admin.c, annotate.c, checkin.c, checkout.c,
- classify.c, commit.c, create_adm.c, cvs.h, cvsrc.c, diff.c, entries.c,
- find_names.c, hash.c, hash.h, history.h, import.c, lock.c, log.c,
- login.c, logmsg.c, main.c, mkmodules.c, modules.c, myndbm.c, no_diff.c,
- parseinfo.c, patch.c, rcs.c, rcs.h, rcscmds.c, recurse.c, remove.c,
- repos.c, root.c, root.h, server.h, stack.c, stack.h, status.c, subr.c,
- tag.c, update.c, vers_ts.c, version.c: Update copyright notices.
-
-2005-01-29 Derek Price <derek@ximbiot.com>
-
- * log.c (log_usage): Add note about using -S with revision info
- supression and selection.
- (Suggestion from Dan Peterson <dbpete@aol.com>.)
-
-2004-12-19 Larry Jones <lawrence.jones@ugs.com>
-
- * expand_path.c (expand_path): Rewrite using offsets instead of
- pointers to simplify and avoid reallocation bugs.
- (Inspired by Jeremy Bopp <jeremy@motive.com>.)
-
-2004-12-09 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (tests): Add modules7.
-
-2004-12-09 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (modules7): New test group.
- (Based on a patch from Mark D. Baushke <mdb@cvshome.org>, based on a
- report from Richard Verhoeven <Richard_Verhoeven@WestLB.de>.)
-
-2004-11-18 Mark D. Baushke <mdb@cvshome.org>
-
- * checkout.c (checkout_proc): Passing the repository to
- tag_check_valid seems to stop the assertion failure in recurse.c
- do_recursion.
- * sanity.sh (basic2-21a): Removed.
- (basic2-21b): Fixed.
-
-2004-11-17 Mark D. Baushke <mdb@cvshome.org>
-
- * sanity.sh (basic2-21a): The val-tags file should have
- at least 'rtagged-by-head y' in it.
- (basic2-21b): New test showing a cvs bug when val-tags
- is not properly updated.
- (Report from "John Elgin" <John@JCElgin.com>.)
-
-2004-11-17 Mark D. Baushke <mdb@cvshome.org>
-
- * client.c (handle_m, handle_e): Winsock is returning
- SOCK_ERRNO == WSAENOTSOCK for select() problems and not
- setting errno. Do not bother with printing an error from a
- select() that is not returning an non-zero errno.
- (Report from Conrad T. Pino <Conrad@Pino.com>.)
-
-2004-11-10 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: Maintain pass/skip/warn status and output at end.
- (usage): Note new functionality of -e.
- (warn): New function.
- (verify_tmp_empty): Warn instead of failing. Delete turds if warn()
- doesn't exit.
-
-2004-11-10 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (verify_tmp_empty): New function.
- (dotest_internal_*): Call verify_tmp_empty as needed.
-
-2004-11-09 Mark D. Baushke <mdb@cvshome.org>
-
- * sanity.sh: Backport find_tool changes from 1.12.9.1.
- (SEARCHPATH): New list of PATH directories to search.
- (Which): Use $SEARCHPATH. Support -a switch.
- (badtools,set_bad_tool,is_bad_tool): Keep track of tools that do
- not work for us.
- (version_test): Obtain the version of tools under test if
- possible.
- (tool_find): Rewrite. API changed to allow a list of
- tests to be used against a list of possible command names found on
- the SEARCHPATH.
- (id_tool_test): Check that 'id -u' and 'id -un' work.
- (expr_tooltest1): Check for NextStep 3.3 expr bug.
- (expr_tooltest2): Check for SunOS expr multi-line pattern bug.
- (expr_create_bar): Create a test file for expr testing.
- (expr_tooltest3): Use it and test for big multi-line identity
- matches.
- (expr_set_ENDANCHOR): Find and set the right value for ENDANCHOR.
- (expr_set_DOTSTAR): Find and set the right value for DOTSTAR.
- (expr_tooltest_DOTSTAR): Ensure that DOTSTAR works with big
- matches.
- (tr_tooltest1): Verify that tr handles NUL bytes.
- (awk_tooltest1): Verify that awk the BEGIN clause works properly.
- (awk_tooltest2): Verify that print %c format item works properly.
-
-2004-11-02 Mark D. Baushke <mdb@cvshome.org>
-
- * filesubr.c (MAXSIZE): New macro.
- (xreadlink): Ensure initial buffer size does not exceed MAXSIZE.
- Avoid cast. If readlink fails with buffer size just under MAXSIZE,
- try again with MAXSIZE.
-
-2004-11-02 Mark D. Baushke <mdb@cvshome.org>
-
- * filesubr.c (xreadlink): AIX and HP-UX readlink() returns ERANGE
- when there is not enough room in the buffer.
-
-2004-11-01 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (rcslib): Fix typo in path.
-
-2004-11-01 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (rcslib): Test a link to a path longer than 128
- characters.
-
-2004-10-29 Derek Price <derek@ximbiot.com>
-
- * filesubr.c (xreadlink): Make sure allocation is tried once at the
- maximum buffer size. Protect against overflow.
-
-2004-10-29 Mark D. Baushke <mdb@cvshome.org>
-
- * filesubr.c (SIZE_MAX, SSIZE_MAX): Use #include "xsize.h" instead.
- (xreadlink): Use xrealloc instead of xmalloc/free.
-
-2004-10-29 Mark D. Baushke <mdb@cvshome.org>
-
- * filesubr.c (SIZE_MAX, SSIZE_MAX): New constants.
- (xreadlink): Deal with symlinks longer than 127 bytes.
- (Problem reported as issue 190 by Gottfried Ganssauge
- <gotti@cvshome.org>.)
-
-2004-10-28 Mark D. Baushke <mdb@cvshome.org>
-
- * release.c (release): Allow builds of cvs with --disable-server
- --disable-client both used for local installation configuration.
- * root.c (Name_Root): Ditto.
- * update.c (checkout_file): Ditto.
- (Problem reported by Jean Olivier Caron <jecar@mlab.t.u-tokyo.ac.jp>.)
-
-2004-10-27 Mark D. Baushke <mdb@cvshome.org>
-
- * cvs.h (RCS_FLAGS_USETIME): New flag.
- * rcs.c (RCS_checkin): Add citime argument.
- * rcs.h (RCS_checkin): Ditto.
- * checkin.c (Checkin): Pass new RCS_checkin argument.
- * commit.c (remove_file, checkaddfile): Ditto.
- * import.c (add_rev): Ditto.
-
- * sanity.sh (tagdate): Delete tagdate-19b as an incorrect test.
-
-2004-10-27 Mark D. Baushke <mdb@cvshome.org>
-
- * sanity.sh (tagdate): Provide more output.
-
-2004-10-26 Mark D. Baushke <mdb@cvshome.org>
-
- * commit.c (checkaddfile): Create a dead version for a new file
- added to a branch. Fixes FIXCVS for tagdate tests.
- * sanity.sh (tagdate): Update to expect correct results.
- (death2, branch-after-import, join, ignore-on-branch): Ditto.
-
-2004-10-26 Derek Price <derek@ximbiot.com>
-
- * client.c (connect_to_gserver): Avoid truncating error messages from
- the GSSAPI server.
- (Report from Dan Peterson <dbpete@aol.com>.)
-
-2004-10-26 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (import-quirks): Test an even branch number.
-
-2004-10-25 Derek Price <derek@ximbiot.com>
-
- * import.c (import): Repair regex for regressions introduced in last
- commit.
- * sanity.sh (import-quirks): Test a few branch numbers import shouldn't
- have a problem with.
-
-2004-10-25 Derek Price <derek@ximbiot.com>
-
- * import.c (import): Anchor and simplify branch verification regex.
- * sanity.sh (import-quirks): Test another pattern that should fail.
-
-2004-10-25 Mark D. Baushke <mdb@cvshome.org>
-
- * sanity.sh (tagdate): Added some additional tests and FIXCVS
- comments for dealing properly with a 'cvs add' of a file to
- a branch that already exists on the mainline.
- (Problem reported by Renny Barrett <rbarrett@curamsoftware.com>.)
-
- * sanity.sh (getrlogdate): New shell function.
- (tagdate-{13,14,16}): Use it to avoid 'sleep 60' by using
- the exact 1.1.4.1 timestamp for tagdate-14 and tagdate-16.
-
-2004-10-22 Mark D. Baushke <mdb@cvshome.org>
-
- * sanity.sh (tagdate): Fix typo.
-
-2004-10-19 Derek Price <derek@ximbiot.com>
-
- * add.c (add): Avoid attempting to resurrect a dead rev 1.1.
- * sanity.sh (resurrection): Add test for the above.
- (Report from Dan Peterson <dbpete@aol.com>.)
-
-2004-10-14 Derek Price <derek@ximbiot.com>
-
- * import.c (import): Verify branch specifications more thoroughly.
- * sanity.sh (importb): Adapt to new error message.
- (import-quirks): New test.
-
-2004-10-04 Derek Price <derek@ximbiot.com>
-
- * cvs.h (CVSROOT_DFLT): Undef rather than defining to NULL.
- * main.c (main): Untangle parsing of CVSROOT, eliminating several
- variables in the process. Simplify xmalloc/sprintf with asnprintf.
-
-2004-10-01 Mark D. Baushke <mdb@cvshome.org>
-
- * main.c (main): Initialize CVSroot before it is used.
- (Report and patch by Martin Neitzel <neitzel@sco.gaertner.de>.)
- * sanity.sh (status): Test it.
-
-2004-09-25 Mark D. Baushke <mdb@cvshome.org>
-
- * sanity.sh (parseroot2): Correct two test names. Restore CVSROOT.
-
- * sanity.sh (parseroot2): Expand dokeep inline.
-
-2004-09-24 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (tests): Add parseroot2.
-
-2004-09-24 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (parseroot2): New test for root parsing consistency.
- (Original patch from Alexander Taler <dissent@cvshome.org>.)
-
- * cvs.h (Name_Root, free_cvsroot_t, parse_cvsroot, local_cvsroot,
- Create_Root, root_allow_add, root_allow_free, root_allow_ok): Move
- these protos to...
- * root.h: ...here.
- * client.c (arg_should_not_be_sent_to_server), recurse.c
- (start_recusrion, do_recursion): Use new Name_Root API.
- * main.c (current_root): Remove global.
- (set_root_directory): Set current_parsed_root directly.
- (main): Use new Name_Root API. Restore deletion of root directories
- list.
- * root.c (Name_Root): Return a parsed cvsroot_t rather than a string.
-
-2004-09-23 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (depends_on_ssh, sshstdio): Don't use skip() to skip
- remote-only tests.
-
-2004-09-23 Mark D. Baushke <mdb@cvshome.org>
-
- * server.c (cvs_output, cvs_output_binary): fflush (stderr)
- here to avoid problems with 'cvs status 2>&1'.
- (Report by Frank Hemer <frank@hemer.org>.)
-
-2004-09-23 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (crerepos, sshstdio): Minor modifications to make use of
- the new depends_on_?sh API.
-
-2004-09-23 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: Accept new -e option to interpret non-fatal calls to skip
- as errors.
- (skip, depends_on_rsh, depends_on_ssh): New functions.
-
-2004-09-12 Mark D. Baushke <mdb@cvshome.org>
-
- * rcs.c (RCS_checkout): Allow noexec to do checkouts when
- server_active is true.
- * sanity.sh (join7): Test above change (fixes a FIXCVS).
-
-2004-09-08 Mark D. Baushke <mdb@cvshome.org>
-
- * sanity.sh (join7): Fix if-then-else conditional.
-
- * server.c (server_updated): Deal with cvs -n update -jt1 -jt2
- "protocol error: uncounted data discarded" problem.
- * sanity.sh (join7): New test for this case.
-
-2004-08-24 Derek Price <derek@ximbiot.com>
-
- * recurse.c (start_recursion): Don't shorten //. to / (use //).
-
-2004-08-24 Derek Price <derek@ximbiot.com>
-
- * recurse.c (start_recursion): Strip trailing CWD indirections on
- repository.
- * sanity.sh (rstar-toplevel): Update to account for new behavior.
- (Report from Dan Peterson <dbpete@aol.com>.)
-
-2004-08-24 Mark D. Baushke <mdb@cvshome.org>
-
- * recurse.c (do_recursion): Correct test for calling
- server_pause_check to occur when locktype != CVS_LOCK_WRITE.
- (Patch suggested by Ian Lance Taylor <ian@wasabisystems.com>
- in bug#198).
-
-2004-08-24 Derek Price <derek@ximbiot.com>
-
- * rcs.c (translate_symtag): Prevent infinite loop.
- * tag.c (tag_check_valid): Check tag syntax before searching for tags.
- * sanity.sh (tag-space): Some tests for the above.
- (Report from Dan Peterson <dbpete@aol.com>.)
-
-2004-08-24 Mark D. Baushke <mdb@cvshome.org>
-
- * ignore.c (ignore_directory): Include the terminating NUL
- character in the directory name comparison to avoid matching
- substrings of directories by accident.
- (Report and suggested fix from James E Wilson
- <wilson@specifixinc.com>.)
- * sanity.sh (modules4): Add some more tests testing the above
- change.
-
-2004-08-17 Mark D. Baushke <mdb@cvshome.org>
-
- * sanity.sh (sshstdio): Fix comment typo plus gratuitous
- reformatting.
-
- * client.c (handle_m): Workaround to deal with stdio getting put
- into non-blocking via redirection of stderr and interaction with
- ssh on some platforms. On those boxes, stdio can put stdout
- unexpectedly into non-blocking mode which may lead to fwrite() or
- fflush() failing with EAGAIN, but cvs not checking for the error.
- (Patch suggested by Frank Hemer <frank@hemer.org>.)
-
- * client.c (handle_e): Similar fix for stderr.
- * sanity.sh (sshstdio): New test for non-blocking stdio via ssh.
-
-2004-08-11 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (basicc): Work around a problem in Linux 2.2 & Bash 2.05b
- which prevents a `cd ..' from a deleted directory from working.
- (Original patch from Matthew Ogilvie <mmo9317bd@mailcan.com>.)
-
-2004-06-22 Derek Price <derek@ximbiot.com>
-
- * wrapper.c: Add explicit "void" return type to "wrap_clean_fmt_str"
- definition.
- (Patch from Conrad T. Pino <Conrad@Pino.com>.)
-
-2004-06-09 Derek Price <derek@ximbiot.com>
-
- * commit.c, filesubr.c, history.c, server.c, wrapper.c: Various
- security fixes.
- (Original patch from Stefan Essler <s.esser@e-matters.de> & Sebastian
- Krahmer <krahmer@suse.de>.)
-
- * cvs.h: Include xsize.h.
-
-2004-06-09 Derek Price <derek@ximbiot.com>
-
- * server.c (serve_entry, serve_is_modified, serve_unchanged): Protect
- against malformed entries.
- * sanity.sh (server): Tests for same.
-
-2004-06-07 Larry Jones <lawrence.jones@ugsplm.com>
-
- * sanity.sh (basica): More tests for string-based revision inc.
-
-2004-06-04 Larry Jones <lawrence.jones@ugsplm.com>
-
- * subr.c (increment_revnum): Rewrite ala RCS to work directly on
- the string rather than converting to int to avoid overflow.
- * sanity.sh (basica): New tests for above, update others to match.
-
-2004-05-19 Derek Price <derek@ximbiot.com>
-
- * server.c (serve_unchanged, serve_is_modified): Overwrite existing
- data in timefields. Fixes CAN-2004-0396.
-
-2004-05-14 Derek Price <derek@ximbiot.com>
-
- * subr.c (file_has_conflict), vers_ts.c (time_stamp_server): Don't
- require '=' to be the only character here, as this is potentially
- destabilizing.
-
-2004-05-14 Mark D. Baushke <mdb@cvshome.org>
-
- * sanity.sh (trailingslashes): During cleanup remove topfile,v to
- avoid problems in later tests (editor-1).
-
-2004-05-13 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (trailingslashes): Note TODO item #205 in the comment.
-
-2004-05-13 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (trailingslashes): New tests to expose a bug in CVS when
- paths are specified with trailing slashes. This relates to TODO #205.
-
-2004-05-12 Derek Price <derek@ximbiot.com>
-
- * subr.c (file_has_conflict), vers_ts.c (time_stamp_server): Only
- special case "=" when it is the only character in a timestamp field.
- Gratuitous reformatting.
- * vers_ts.c (time_stamp_server): Check for NULL in a consistent manner.
- Gratuitous reformatting.
-
-2004-05-10 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (top-level): Rename to...
- (rstar-toplevel): ...this for clarity.
-
-2004-05-10 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (dirs2-10ar): Remove unnecessary empty argument.
-
-2004-05-02 Larry Jones <lawrence.jones@ugsplm.com>
-
- * log.c (log_expand_revlist): Suppress warnings if really_quiet.
-
-2004-05-07 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (basica): Remove unnecessary empty arguments.
-
-2004-05-07 Derek Price <derek@ximbiot.com>
-
- * cvs.h (fopen_case): Remove obsolescent prototype.
-
-2004-05-05 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: Wait a second and retry if cvs-serv* directories are
- discovered to avoid race conditions on some systems.
- (Patch from Pavel Roskin <proski@gnu.org>.)
-
-2004-05-05 Derek Price <derek@ximbiot.com>
-
- * commit.c: Some gratuitous reformatting.
-
-2004-05-04 Derek Price <derek@ximbiot.com>
-
- * update.c: Some gratuitous reformatting.
-
-2004-05-04 Derek Price <derek@ximbiot.com>
-
- * add.c (add): Remove obsolete FIXME comment.
- (*): Some gratuitous reformatting.
-
-2004-04-26 Derek Price <derek@ximbiot.com>
-
- * client.c (start_rsh_server): Don't rely on GNU argument processing
- capabilities in the RSH command.
- (Report from Mark Andrews <Mark_Andrews@isc.org>.)
-
-2004-04-19 Derek Price <derek@ximbiot.com>
-
- * ignore.c: Gratuitous reformatting.
-
-2004-04-11 Derek Price <derek@ximbiot.com>
-
- * client.c (call_in_directory): Check paths the server sends us to make
- sure they are within a sandbox the user requested be updated.
- (is_valid_client_path, path_list_prefixed): New functions.
-
-2004-04-11 Derek Price <derek@ximbiot.com>
-
- * modules.c (do_module): Don't allow up-level references in paths to
- step out of the repository.
- * sanity.sh (multiroot3): Update tests and add a few more.
-
-2004-04-07 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (parseroot): Replace hard path with $HOME.
-
-2004-04-07 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (parseroot): s/oberon/$username/.
-
-2004-04-07 Derek Price <derek@ximbiot.com>
-
- * client.c (start_tcp_server): Use xstrdup rather than
- xmalloc(strlen)/strcpy.
-
-2004-04-07 Derek Price <derek@ximbiot.com>
-
- * root.c (parse_cvsroot): Ignore method options.
- * sanity.sh (parseroot): Verify that method options are ignored.
-
-2004-04-06 Derek Price <derek@ximbiot.com>
-
- * root.h (cvsroot_t): Move username, password, hostname, port inside
- CLIENT_SUPPORT ifdefs.
- * buffer.c, root.c, server.c: Add #ifdefs as necessary so that this
- will compile without client support and the root.h change. Some
- gratuitous restyling.
-
-2004-04-06 Derek Price <derek@ximbiot.com>
-
- * log.c, tag.c: Gratuitous restyling.
-
-2004-04-04 Derek Price <derek@ximbiot.com>
-
- * filesubr.c (isabsolute): Move...
- * subr.c: ...here and use new ISABSOLUTE macro.
-
-2004-04-04 Derek Price <derek@ximbiot.com>
-
- * client.c (send_file_names): Cast out an unneeded const to avoid a
- warning.
-
-2004-04-03 Larry Jones <lawrence.jones@ugsplm.com>
-
- * client.c (send_file_names): Remove unused variables.
-
-2004-04-02 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (client): Honor $keep.
-
-2004-04-02 Derek Price <derek@ximbiot.com>
-
- * log.c, patch.c, rcs.c: Gratuitous restyling.
-
-2004-04-02 Derek Price <derek@ximbiot.com>
-
- * import.c (import): Use ISDIRSEP rather than testing paths against `/'
- directly. Some gratuitos reformatting.
-
-2004-04-02 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: Note the effectiveness of `tail -f check.log' in providing
- running status.
-
-2004-04-02 Derek Price <derek@ximbiot.com>
-
- * client.c (send_file_names): Move code which calculates and sends
- Max-dotdot...
- (send_max_dotdot): ...to this new function.
- (send_files): Call send_max_dotdot.
- * sanity.sh (files-14): Expect .. in paths to work now.
- (status): Add a few new tests using `..'.
-
-2004-04-01 Derek Price <derek@ximbiot.com>
-
- * lock.c: Gratuitous restyling.
-
-2004-04-01 Derek Price <derek@ximbiot.com>
-
- * cvs.h, server.c: Gratuitous restyling.
- * run.c (run_exec): Ditto, plus call cvs_flush{out,err}() instead of
- flushing stderr & stdout directly.
-
-2004-03-29 Derek Price <derek@ximbiot.com>
-
- * server.c: Gratuitous restyling.
-
-2004-03-29 Derek Price <derek@ximbiot.com>
-
- * login.c: Gratuitous restyling.
-
-2004-03-22 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (toplevel): Remove FIXME type comment and unneeded
- Emtptydir removal.
-
-2004-03-22 Derek Price <derek@ximbiot.com>
-
- * update.c: Some minor style cleanup.
-
-2004-03-22 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (top-level): Don't match most of the assertion since this
- string is often system dependent.
- (Thanks to Larry Jones <lawrence.jones@ugsplm.com>.)
-
-2004-03-22 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (top-level): Don't match the assertion's line number.
-
-2004-03-22 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (top-level): New test to confirm assertion failure.
-
-2004-03-22 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: Only verify argument to -f when -f was passed. Check for
- $TMPDIR/cvsXXXXXX temp files after each test.
-
-2004-03-22 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: Verify that the argument to -f is really a test.
-
-2004-03-20 Larry Jones <lawrence.jones@ugsplm.com>
-
- * cvs.h: Change command_name to cvs_command_name to avoid conflict
- on HP-UX (incredibly, it declares a global command_name in prot.h,
- which is included from shadow.h, which we include in server.c).
- Change all references.
-
- * subr.c (previous_rev): Fix == vs = typo.
-
- * buffer.h: Add prototype for buf_empty.
-
- * add.c (add): Remove unused variable.
-
-2004-03-20 Derek Price <derek@ximbiot.com>
-
- * add.c (add, add_directory, build_entry), admin.c (admin_dirproc),
- checkin.c (Checkin), checkout.c (safe_location, build_dirs_and_chdir),
- client.c (add_prune_candidate, send_repository, send_a_repository,
- send_to_server, start_rsh_server, send_arg, send_modified,
- send_ignproc, send_filesdone_proc, send_dirent_proc,
- send_dirleave_proc, client_notify), commit.c (check_direntproc,
- check_filesdoneproc, checkaddfile, commit_direntproc,
- commit_dirleaveproc, lock_RCS, precommit_proc, find_data,
- find_dirent_proc, find_ignproc, find_filesdoneproc), create_adm.c
- (Create_Admin), cvsrc.c (read_cvsrc), diff.c (diff_dirproc,
- diff_filesdoneproc, diff_dirleaveproc), edit.c (onoff_filesdoneproc,
- mark_up_to_date, editor_set, notify_proc_args, notify_proc, notify_do,
- notify_check), entries.c (Scratch_Entry, Register, WriteTag),
- expand_path.c (expand_variable, expand_path), fileattr.c
- (fileattr_startdir), filesubr.c (mkdir_if_needed, xchmod,
- last_component), history.c (history_write), ignore.c (ignore_directory,
- ignore_files), import.c (get_comment, add_rcs_file, expand_at_signs),xi
- lock.c (lock_filesdoneproc), log.c (log_dirproc), logmsg.c
- (logfile_write, rcsinfo_proc, update_logfile_proc, editinfo_proc,
- verifymsg_proc, do_editor, do_verify, Update_Logfile), main.c (main
- program_name, program_path, command_name), parseinfo.c (Parse_Info),
- patch.c (patch_dirproc), rcs.c (RCS_getdatebranch, rcs_lockfilename,
- RCS_parse, RCS_setattic, RCS_getversion, RCS_gettag, RCS_getbranch,
- RCS_getdate, RCS_datecmp, RCS_getrevtime, RCS_setexpand,
- expand_keywords, RCS_checkout, RCS_addbranch, RCS_checkin, RCS_lock,
- RCS_cmp_file, RCS_deltas, rcs_lockfilename, make_file_label),
- rcscmds.c (RCS_output_diff_options, call_diff, RCS_merge,
- RCS_exec_rcsdiff, diff_exec), recurse.c (start_recursion, do_recursion,
- do_file_proc), remove.c (remove_dirproc), repos.c (Name_Repository,
- Short_Repository), root.c (Name_Root, Create_Root), run.c
- (piped_child), server.c (output_dir, server_register,
- server_checked_in, server_update_entries, server_copy_file,
- server_set_entstat, server_clear_entstat, server_set_sticky,
- server_template, cvs_output_tagged), status.c (status_dirproc), subr.c
- (make_message_rcslegal), tag.c (pretag_proc, tag_dirproc,
- check_fileproc, check_filesdoneproc, tag_fileproc, val_direntproc),
- update.c (update_dirent_proc, update_dirleave_proc, update_ignproc,
- update_filesdone_proc, isemptydir), vers_ts.c (time_stamp_server,
- time_stamp), watch.c (watch_modify_watchers, addremove_filesdoneproc),
- zlib.c (read_and_gzip): Make most string args const, mainly in the
- interest of preserving repository & updatedir but including some
- collateral damage. Update a few functions to comply with new
- requirement. Some style fixes.
- * client.h, cvs.h, edit.h, fileattr.h, rcs.h, server.h, update.h,
- watch.h: Update prototypes to match.
-
-2004-03-20 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (conflicts2): s/cvs/$testcvs/.
-
-2004-03-20 Derek Price <derek@ximbiot.com>
-
- * add.c (add): Correct longstanding resurrection bugs. Remove FIXME
- comment to this effect. Set mode and Entries timestamps of resurrected
- files correctly.
- * sanity.sh (basica, binfiles, conflicts2, recase, resurrection,
- update-p): Update tests to compensate. Remove FIXCVS comments.
-
-2004-03-19 Mark D. Baushke <mdb@cvshome.org>
-
- * server.c (gserver_authenticate_connection): Handle large
- GSSAPI packets dynamically.
- (Bug report from Douglas Engert <DEEngert@anl.gov>)
-
-2004-03-19 Derek Price <derek@ximbiot.com>
-
- * cvs.h (pathname_levels, previous_rev): Remove leading underscore from
- prototype arguments to avoid potential conflicts with implementations.
-
-2004-03-18 Derek Price <derek@ximbiot.com>
-
- * cvs.h (pathname_levels): Make string argument const.
- * subr.c (pathname_levels): Simplify function.
-
-2004-03-17 Derek Price <derek@ximbiot.com>
-
- * subr.c (pathname_levels): Get it right this time.
-
-2004-03-17 Derek Price <derek@ximbiot.com>
-
- * subr.c (pathname_levels): Remove incorrect assertion and just
- return 0 when pathname is NULL.
-
-2004-03-17 Derek Price <derek@ximbiot.com>
-
- * subr.c (pathname_levels): Use ISDIRSEP() instead of strchr('/')
- and remove FIXME comment to that effect.
-
-2004-03-16 Derek Price <derek@ximbiot.com>
-
- * main.c (main): Update the --version Copyright (c) string to
- include 2004.
-
-2004-03-15 Mark D. Baushke <mdb@cvshome.org>
-
- * release.c (release): Add missing xmalloc of update_cmd.
-
-2004-03-15 Derek Price <derek@ximbiot.com>
-
- * release.c (release): Enable authentication and encryption for a child
- update process when necessary.
- (Original patch from Dan Russell <russelld@aol.net> via Hal Mahaffey
- <HMahaffey@aol.com>.)
-
-2004-03-14 Derek Price <derek@ximbiot.com>
-
- * add.c (add): Only call server_updated() when we actual have a new
- resurrected file for the client.
-
-2004-03-14 Derek Price <derek@ximbiot.com>
-
- * cvs.h (previous_rev, write_letter): New prototypes.
- (struct file_info): Move to before the write_letter prototype.
- * add.c (add): Allow resurrection of files which used to exist on a
- branch.
- * subr.c (previous_rev): New function.
- * update.c: Consolidate like pragmas.
- (write_letter): Remove prototype. Remove static declaration.
- * sanity.sh (resurrection): New tests.
-
-2004-03-14 Derek Price <derek@ximbiot.com>
-
- * commit.c (remove_file): Print the actual previous revision instead of
- a branch number.
- * sanity.sh: Update to match.
-
-2004-03-14 Derek Price <derek@ximbiot.com>
-
- * rcs.c (RCS_cmp_file): Print the actual name of the file we failed to
- open in the error message.
-
-2004-03-14 Derek Price <derek@ximbiot.com>
-
- * diff.c (diff_fileproc): Allow diffing of new files against arbitrary
- revisions instead of assuming that there is no RCS archive file.
-
-2004-03-03 Derek Price <derek@ximbiot.com>
-
- * import.c (import): Check that the module name specified by the user
- does not contain `CVS' as a directory name.
- * ignore.c (ign_add): Never cease ignoring "CVS" - it is a reserved
- name.
- (Original patch from Dan Peterson <dbpete@aol.com>.)
-
- * sanity.sh (import-CVS): New tests for the above.
-
-2004-02-29 Larry Jones <lawrence.jones@ugsplm.com>
-
- * import.c (expand_at_signs): Change type of len to size_t.
- * subr.c (resolve_symlink): Move declaration of newname inside
- #ifdef, clean up coding style.
- * zlib.c (gunzip_and_write): Fix up potential overlow problems.
- (read_and_gzip): Add explicit casts to placate paranoid compilers.
-
-2004-02-28 Larry Jones <lawrence.jones@ugsplm.com>
-
- * sanity.sh (join6): New tests for previous fix.
-
- * update.c (join_file): One more fix to avoid dereferencing NULL.
- (Reported by Steve McIntyre <steve@einval.com>.)
- * sanity.sh (join6): New tests for above.
-
-2004-02-25 Larry Jones <lawrence.jones@ugsplm.com>
-
- * update.c (join_file): Fix optimization to avoid dereferencing NULL.
- (Reported by Steve McIntyre <steve@einval.com>.)
-
-2004-02-25 Derek Price <derek@ximbiot.com>
-
- * buffer.c (buf_empty): New function.
- * server.c (server): Check for unread data in buffer before closing.
-
-2004-02-25 Derek Price <derek@ximbiot.com>
-
- * release.c (release): Restore the initial directory before and after
- calling various sections of code that expect it to prevent corruption
- of CVS/Entries files on release of a subdir and tell unedit() what to
- release.
- * sanity.sh: Add test case for release.c fix.
- (Original patch from Matthew Ogilvie <mmo9317bd@mailcan.com>.)
-
- * client.c (last_entries): Move global variable...
- (call_in_directory): ...here (now a local variable). Remove test that
- always evaluates to true.
- (last_dir_name): Remove unused global variable.
-
-2004-02-24 Larry Jones <lawrence.jones@ugsplm.com>
-
- * filesubr.c (xresolvepath): Fix crash in error case.
- (Reported by Reinhard Zierke <zierke@informatik.uni-hamburg.de>.)
-
-2004-02-24 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (crerepos): Minor stylistic changes to previous change.
-
-2004-02-24 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (crerepos): Fix it so that it ignores the user's
- .cvsrc file (.cvsrc "checkout -r" used to cause the "rm -r 1"
- command to print warnings and wait for input).
- (Original patch from Matthew Ogilvie <mmo9317bd@mailcan.com>.)
-
- * sanity.sh (reposmv, parseroot, devcom3, binwrap3):
- s/_SAVED\>/_save/ for consistency.
-
-2004-02-20 Derek Price <derek@ximbiot.com>
-
- * subr.c (set_nonblock_fd): Move back to...
- * server.c: ...here.
- * cvs.h: Remove protos for the above two functions.
- * buffer.c (stdio_buffer_shutdown): Remove unexessary and possibly
- dangerous check for unread data on a pipe with a nonblock read.
-
-2004-02-20 Derek Price <derek@ximbiot.com>
-
- * ChangeLog, commit.c, filesubr.c, rcs.c, root.c, sanity.sh, subr.c,
- update.c: Remove VIM editor commands.
-
-2004-02-20 Larry Jones <lawrence.jones@ugsplm.com>
-
- * hash.h (struct node): Change data from char * to void *, change
- all callers.
-
-2004-02-19 Larry Jones <lawrence.jones@ugsplm.com>
-
- * login.c (password_entry_operation): Initialize line.
-
-2004-02-19 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (crerepos): Correct comment.
-
-2004-02-19 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (crerepos): Don't create directories named `tmp' in
- $TESTDIR to avoid conflicts with the default value of $TMPDIR.
-
-2004-02-19 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (directory_cmp): Use $TESTDIR for temporary files, like the
- dotest functions.
-
-2004-02-19 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: No longer allow user override of $tmp. Set $TMPDIR to a
- directory under $TESTDIR, as for $HOME, but still allowing for user
- override. Check for cvs-serv* directories under $TMPDIR rather than
- $tmp at the end of the script.
-
-2004-02-17 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: Check for $PWD != $TESTDIR after each set of tests rather
- than once at the end. Check that there are no cvs-serv* directories in
- $tmp after each set of remote tests.
-
-2004-02-17 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: Don't check for an empty $TESTDIR - if $TESTDIR was empty
- then the preceding call to mkdir would have failed anyhow.
-
-2004-02-17 Larry Jones <lawrence.jones@ugsplm.com>
-
- * log.c (rlog_proc): Fix (harmless) uninitialized variable.
-
- * sanity.sh (basicc): Add tests pointing out defective handling
- of the Entries file.
-
-2004-02-17 Derek Price <derek@ximbiot.com>
-
- * checkout.c (build_dir_and_chdir): Expand header comment.
-
-2004-02-15 Mark D. Baushke <mdb@cvshome.org>
-
- * annotate.c (rannotate_proc): Plug a memory leak.
- * log.c (log_fileproc): Ditto.
- * tag.c (tag_fileproc): Ditto.
- * update.c (checkout_file): Ditto.
- * server.c (server_updated): Do not buf_free (filebuf) here.
-
-2004-02-13 Larry Jones <lawrence.jones@ugsplm.com>
-
- * rcs.c (locate_rcs): Remove unused variables.
-
-2004-02-12 Mark D. Baushke <mdb@cvshome.org>
-
- * lock.c (readers_exist): Plug a memory leak.
-
-2004-02-12 Mark D. Baushke <mdb@cvshome.org>
-
- * server.c (do_cvs_command): Plug a memory leak.
-
-2004-02-12 Derek Price <derek@ximbiot.com>
-
- * modules.c: Reformat comment and line to fit in 80 chars.
-
-2004-02-12 Larry Jones <lawrence.jones@ugsplm.com>
-
- * modules.c (_do_module): Rename to my_module to avoid reserved name.
- * stack.c (_push, _pop, _unshift, _shift): Rename to do_*.
-
-2004-02-11 Larry Jones <lawrence.jones@ugsplm.com>
-
- * root.c (parse_cvsroot): Set hostname in fork mode for error messages.
- * buffer.c (stdio_buffer_shutdown): Undo previous change.
-
-2004-02-11 Mark D. Baushke <mdb@cvshome.org>
-
- * buffer.c (buf_free): Plug a memory leak.
- * commit.c (checkaddfile): Ditto.
-
- * server.c (fd_buffer_shutdown): Avoid a double free().
-
- * parseinfo.c (parse_config): Fix comments.
-
-2004-02-11 Derek Price <derek@ximbiot.com>
-
- * buffer.c (stdio_buffer_shutdown): Add logic to avoid attempting to
- print current_parsed_root->hostname when using the fork method.
-
-2004-02-11 Derek Price <derek@ximbiot.com>
-
- * server.c (do_cvs_command): Simplify stream & pipe closing.
- (Suggestion from Eric Siegerman <erics@telepres.com>.)
-
- * cvs.h, subr.c (set_block_fd): Remove this unnecessary function.
-
-2004-02-11 Derek Price <derek@ximbiot.com>
-
- * checkout.c (checkout_proc): s/is_absolute/isabsolute/.
-
-2004-02-11 Derek Price <derek@ximbiot.com>
-
- * checkout.c (checkout_proc): Remove unneeded variable and enclosing
- block.
- * modules.c (_do_modules): Minor whitespace change.
-
-2004-02-10 Derek Price <derek@ximbiot.com>
-
- * server.c (do_cvs_command): s/FIXCVS/FIXME/ in comment.
- (set_block_fd, set_nonblock_fd): Move to...
- * subr.c: ...here.
- * cvs.h: Add protos for the above two functions.
- * buffer.c (stdio_buffer_shutdown): Replace fgetc() which checked for
- unread data on a pipe with a nonblock read.
-
-2004-02-10 Derek Price <derek@ximbiot.com>
-
- * server.c (do_cvs_command): Have the server child close all the pipes
- but the flow control pipe and wait on an EOF on the flow control pipe
- from the parent when done to avoid a race condition that could
- otherwise generate a SIGPIPE for the parent before the SIGCHILD when
- the other pipes were so full after a child exited that the parent
- attempted to write a stop byte to the flow control pipe.
- (Original report from <jesse_off@stchome.com>.)
-
-2004-02-10 Derek Price <derek@ximbiot.com>
-
- * buffer.c (stdio_buffer_shutdown): Add a helpful comment.
-
-2004-02-09 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (co-d): Update comments and tests to reflect the current
- state of my side of my discussion with Larry Jones on how these
- commands should behave.
-
-2004-02-09 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (emptydir): Add two new tests for how modules -d behaves
- when a directory already exists in the user's workspace.
- (emptydir): Add --keep functionality.
-
-2004-02-09 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (co-d): New test to prove `co -d' failure case.
-
-2004-02-05 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (recase): Fix typo that creeped in somehow between my last
- test run and my commit.
-
-2004-02-04 Derek Price <derek@ximbiot.com>
-
- * stack.c (shift, shift_string): Make sure these functions return their
- result.
-
-2004-02-04 Derek Price <derek@ximbiot.com>
-
- * modules.c (do_modules): Move content to and make this function a
- wrapper for...
- (_do_modules): ...this new function which can watch for infinite loops
- in alias modules.
- * stack.c (_push, _pop, _unshift, _shift, push_string, pop_string,
- unshift_string, shift_string): New
- functions.
- * stack.h (push_string, pop_string, unshift_string, shift_string: New
- prototypes.
- * sanity.sh (modules): Add check for nested alias loops.
-
-2004-02-04 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (recase): Update test names and comments for clarity and
- consistency.
-
-2004-02-03 Derek Price <derek@ximbiot.com>
-
- Preserve the case of checked out directories in a path as well as file
- names for client communication with the server.
-
- * Makefile.am (cvs_SOURCES): Add stack.c & stack.h.
- * stack.c, stack.h: New files.
- * cvs.h: Include stack.h.
- * client.c (send_file_names): Preserve the case of directories in a
- path as well as file names for communication with the server.
-
- * Makefile.in: Regenerated.
-
-2004-02-02 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (join-rm): New test for issue #104 & #159.
-
-2004-02-02 Derek Price <derek@ximbiot.com>
-
- Continue removal from server of handling of case insensitive clients.
-
- * cvs.h: Remove extern declaration of ign_case.
- * ignore.c (ign_case): Remove declaration.
- (ign_name): Remove support for ign_case.
- * server.c (serve_case): Ditto.
- (requests): No longer support the "Case" request.
- * rcs.c (locate_rcs): Remove reference to GLOBAL in function header
- comment.
-
-2004-02-02 Derek Price <derek@ximbiot.com>
-
- * add.c, client.c, cvs.h, rcs.c, subr.c: Remove server support for case
- insensitivity.
-
-2004-01-25 Derek Price <derek@ximbiot.com>
-
- * server.c (kserver_authenticate_connection): Fix call to
- switch_to_user().
- (Original patch from Alexey Mahotkin <alexm@hsys.msk.ru>.)
-
-2004-01-22 Derek Price <derek@ximbiot.com>
-
- * modules.c (do_module): Strip trailing slashes before checking for
- infinite alias loops.
- * sanity.sh (modules): Tests for response to infinite alias loops.
-
-2004-01-17 Mark D. Baushke <mdb@cvshome.org>
-
- * logmsg.c (do_verify): Eliminate double-free bug.
- (Original patch from Gerald Combs.)
-
-2004-01-07 Larry Jones <lawrence.jones@ugsplm.com>
-
- * checkout.c (safe_location): Remove unused variable(s).
- * lock.c (lock_tree_for_write): Ditto.
- * rcs.c (RCS_checkin): Ditto.
- * subr.c (compare_revnums): Ditto.
- * tag.c (tag_check_valid): Ditto.
- * mkmodules.c (init): Initialize err and return it rather than 0.
- * server.c (do_cvs_command): Only define and set max_command_fd if
- we're actually going to use it.
-
-2004-01-01 Larry Jones <lawrence.jones@ugsplm.com>
-
- * zlib.c (read_and_gzip, gunzip_and_write): Fix potential buffer
- overruns, use names for magic numbers.
- (Original patch from Jeff Downs <heydowns@borg.com>.)
-
-2003-12-18 Derek Price <derek@ximbiot.com>
-
- * server.c (switch_to_user): SysLog attempts to root from pserver.
-
-2003-12-18 Derek Price <derek@ximbiot.com>
-
- * server.c (switch_to_user): Don't allow CVS to run as root in pserver
- mode.
- (Original patch from Wichert Akkerman via Bradley M Kuhn
- <bkuhn@fsf.org>.)
- * sanity.sh (pserver): Check for bad root error message.
-
-2003-12-17 Larry Jones <lawrence.jones@eds.com>
-
- * run.c (close_on_exec): fcntl is not documented to return 0 for
- success (and QNX doesn't), only -1 for error.
- (Patch from George Refseth <george.refseth@arxi.no>.)
-
-2003-12-09 Mark D. Baushke <mdb@cvshome.org>
-
- * server.c (template_proc): Fix broken Template protocol code.
- Must call send buf_send_counted() for Template files to avoid
- "Protocol error: uncounted data discarded" messages in some
- circumstances.
- (Problem reported by "Jim.Hyslop" <Jim.Hyslop@Leitch.com>.)
-
-2003-12-03 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (recase-8csss): rename to...
- (recase-8sscs): ...this to match the convention.
-
-2003-12-03 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (recase): Add some clarifying comments.
-
-2003-12-03 Larry Jones <lawrence.jones@eds.com>
-
- * expand_path.c (expand_variable): Expand ${CVSROOT} to just the
- directory like it's supposed to be.
- (Reported by Michael S. Tsirkin <cvs1@misha.eml.cc>.)
-
-2003-11-26 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (modules3-2): Simplify syntax that may have given Cygwin
- intermittent conniptions.
-
-2003-11-25 Mark D. Baushke <mdb@cvshome.org>
-
- * sanity.sh (recase-17sscs): Use ${CVSROOT_DIRNAME} in pattern.
-
-2003-11-25 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (release): Perform forgotten cleanup.
-
-2003-11-25 Derek Price <derek@ximbiot.com>
-
- * commit.c (commit_fileproc): Reword comment.
-
-2003-11-25 Derek Price <derek@ximbiot.com>
-
- * add.c (add): Disable ign_case for the purposes of adding a file so
- that recasing the name of a file is possible from a case insensitive
- client.
- * sanity.sh (recase): New tests for behavior which varies when the
- client and/or the server are case insensitive.
-
-2003-11-25 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (devcom3-9ar): Ignore the stderr output since it varies
- considerably between platforms.
-
-2003-11-24 Larry Jones <lawrence.jones@eds.com>
-
- * diff.c (diff_file_nodiff): use_rev1 does *not* imply that diff_rev1
- is not null, diff_date1 could be set instead (ditto for use_rev2).
- (Reported by <jnelson-cvsbug@jamponi.net>.)
-
-2003-11-24 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (modes3): Skip modes3-5 entirely under Cygwin since
- permisions are broken there. This change removes most of the earlier
- Cygwin differentiation in this test ($cygwin_hack & $cygwin_hack2) in
- favor of skipping the test entirely.
-
-2003-11-21 Larry Jones <lawrence.jones@eds.com>
-
- * hash.c (printnode, printlist): Cast %p arguments to void * as
- required by the C standard.
-
-2003-11-21 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: Add `-h <hostname>' option to enable testing across a
- :ext: connection to another host. Warn when `-h' is specified without
- $TESTDIR. Leave $TESTDIR intact when it looks absolute since it may
- contain symlinks. Allow $CVS_SERVER to be overridden via the
- environment for `-h'. Default $CVS_RSH to `rsh'.
- (*): Use $CVS_RSH to perform certain commands on the remote host (esp.
- `ln -s' and `chmod') when `-h' is specified to work around
- incompatibilities with CygWin & Samba. Add a few other minor
- workarounds for Cygwin bugs.
-
- (newroot): New function.
- (*): Use newroot when appropriate.
-
-2003-11-19 Larry Jones <lawrence.jones@eds.com>
-
- * rcs.c (RCS_getrevtime): Add error checking; cleanup.
-
-2003-11-18 Derek Price <derek@ximbiot.com>
-
- * modules.c (do_module): Reject absolute paths.
- (Report and suggested fix from Tony Hoyle <tmh@nodomain.org>.)
-
- * sanity.sh (abspath2): Check for the above.
- (spacefiles): Remove tests that expect absolute paths to files in the
- top level repository directory to work.
- (tests): Add abspath2.
-
-2003-11-13 Derek Price <derek@ximbiot.com>
-
- * rcs.c (RCS_delete_revs): It's `&&', not `and'.
-
-2003-11-13 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: Create the empty log to make it easier to tail immediately
- after the script is started.
-
-2003-11-13 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (exit_help): Correct help to specify `-H' and not `-h' as
- the help option.
-
-2003-11-13 Derek Price <derek@ximbiot.com>
-
- * rcs.c (RCS_delete_revs): Don't use the WOE32 kludge which refuses to
- delete revisions from bvinary files on Cygwin. I'm not sure what the
- kludge was trying to avoid, but commenting it out causes the test suite
- to pass.
-
-2003-11-10 Derek Price <derek@ximbiot.com>
-
- * commit.c (check_fileproc, find_fileproc): Don't leak memory.
-
-2003-11-10 Derek Price <derek@ximbiot.com>
-
- * commit.c (find_fileproc, check_fileproc): Refuse to remove files
- when the file exists in the sandbox. This used to cause data loss.
- (Report from Andreas Reifschneider <andyreif@studcs.uni-sb.de>.)
-
- * sanity.sh (rmadd3): Update to match. Expand comments.
-
-2003-11-10 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (rmadd3): Test the behavior of commit after the
- add/replace.
- (Report from Andreas Reifschneider <andyreif@studcs.uni-sb.de>.)
-
-2003-11-10 Mark D. Baushke <mdb@cvshome.org>
-
- * Backport symlink bugfix from cvs 1.12.1.1 feature release
- as written by Derek Price <derek@ximbiot.com>. (This fixes
- the Issue 142 bug.)
-
- * recurse.c (start_recursion): Accept new repository argument so
- that the working directory may be tracked by do_recursion without
- using xgetwd(), which returned a value different from the one the
- user requested when symlinks were in use. Pass repository_in to
- do_recursion() as part of the recursion frame.
-
- * cvs.h (xreadlink): #ifdef HAVE_READLINK proto.
- (xresolvepath): New proto.
- (start_recursion): Add repository to proto.
-
- * checkout.c (safe_location): Add more complete header comment.
- Add trace. Use new xresolvepath() function. Always return true
- in client mode since checking our destination path against the
- CVSROOT path is usually meaningless in client/server mode.
- (checkout_proc): Pass repository to do_update() for later use with
- start_recursion().
-
- * admin.c (admin): Use new definition of start_recursion().
- * annotate.c (rannotate_proc): Ditto.
- * client.c (send_files): Ditto.
- * commit.c (commit): Ditto.
- * diff.c (diff): Ditto.
- * edit.c (watch_onoff, send_notifications, edit, unedit, editors):
- Ditto.
- * lock.c (lock_tree_for_write): Ditto.
- * log.c (rlog_proc): Ditto.
- * patch.c (patch_proc): Ditto.
- * remove.c (cvsremove): Ditto.
- * tag.c (rtag_proc): Ditto.
- * update.c (do_update): Ditto.
- * watch.c (watch_addremove, watchers): Ditto.
-
- * patch.c (patch_proc): Call tag_check_valid with repository
- instead of NULL.
-
- * filesubr.c (xreadlink): #ifdef HAVE_READLINK this function. Add
- more complete header comment.
- (xresolvepath): New function.
-
- * recurse.c (do_recursion): Call Lock_Cleanup() only repository
- was set.
-
- * update.c (do_update): Accept new repository argument so that the
- working directory may be tracked.
- (update): Pass NULL repository to do_update().
- * update.c (do_update): Add repository to proto.
-
- * checkout.c (checkout_proc): Use new definition of do_update().
- * update.c (update): Ditto.
-
- * sanity.sh: Add new -l option to test symlinked roots.
- (checkout_repository-1): Add server error messages about absolute
- paths since the client now skips destination validity checks.
- (check_repository-2): Test renamed to checkout_repository-2.
- (checkout_repository-2): Process client error messages about
- CVSROOT files being in the way since the client skips destination
- validity checks since it should be rare that a client is running
- in client/server mode on the server and CVS has no current way to
- check if it is running on the server.
- (check_repository-3): Test renamed to checkout_repository-3.
- (dottedroot): New test to check that a CVSROOT with a "." in the
- name will work.
-
-2003-11-10 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (rmadd3): Add whitespace after end of test for readability.
-
-2003-11-10 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (rmadd3): New tests that confirms that CVS refuses to
- delete a file it thinks was already removed.
- (Report and test from Andreas Reifschneider
- <andyreif@studcs.uni-sb.de>.)
-
-2003-11-03 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (server): Test that the global `-l' option is ignored
- nonfatally.
-
-2003-11-01 Larry Jones <lawrence.jones@eds.com>
-
- * ignore.c (ignore_files): Use CVS_LSTAT() instead of lstat().
- * filesubr.c (xcmp): Make sure S_ISLNK exists before calling it.
- (Reported by Paul Edwards <fight.subjugation@gmail.com>.)
-
-2003-10-31 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (checkout_repository): Name tests consistently.
-
-2003-10-31 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: s/${TESTDIR}/cvsroot/${CVSROOT_DIRNAME}/.
-
-2003-10-28 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (devcom): s/cvs/$PROG/.
-
-2003-10-28 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (devcom): Renumber tests and use dotest function.
-
-2003-10-28 Derek Price <derek@ximbiot.com>
-
- * sever.h: Add the standard copyright notice.
-
-2003-10-28 Derek Price <derek@ximbiot.com>
-
- * lock.c: Remove some suggestions which have already been implemented
- or which have become obsolete from the header comment.
-
-2003-10-26 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (join6): Fix a few typos in the last test and remove a
- misplaced test.
-
-2003-10-25 Mark D. Baushke <mdb@cvshome.org>
-
- * sanity.sh (parseroot): Perform this test in a subdirectory.
- It should avoid problems on case-insensitive systems where
- CVSROOT and cvsroot are the same directory (eg, MacOS X).
-
-2003-10-24 Derek Price <derek@ximbiot.com>
-
- * update.c (join_file): Restore the optimization Mark recently removed,
- but fix it. Move one other optimization up since it needs to be
- checked for first. Add bew status messages like merge_file produces
- when the requested diff has already been applied to the destination.
- Expand header comment.
- * sanity.sh (join6): Add tests for the new error messages.
- (import-113, join-admin-2, diffmerge1): Fix collateral damage.
-
-2003-10-23 Mark D. Baushke <mdb@cvshome.org>
-
- * update.c (join_file): Do the -jrev1 -jrev2 merge even when
- the file is already at rev2.
- * sanity.sh (join6): New testcase for above.
- (Suggested by Paul Edwards, from somewhere in Australia.)
- (import): Fix collateral damage.
-
-2003-10-23 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (fail): Refer the user to the `TESTS' and `check.log' files
- on failure.
-
-2003-10-19 Mark D. Baushke <mdb@cvshome.org>
-
- * sanity.sh (admin-31): Fix more typos.
-
-2003-10-18 Mark D. Baushke <mdb@cvshome.org>
-
- * sanity.sh (admin): Fix a typo.
-
- * admin.c (admin_fileproc): Restore the ':' character in the
- -mtag:message admin argument even if the tag does not exist so
- that other files with the tag will be found. Also, be more
- paranoid that a symbolic tag actually points to a version that
- exists.
- (Reported by Rodolfo Schulz de Lima <rodolfo@rodsoft.org>.)
- * sanity.sh (admin): Test these changes.
-
-2003-10-17 Mark D. Baushke <mdb@cvshome.org>
-
- * admin.c (admin_fileproc): Force tag match on admin
- -mversion:message rather than altering the wrong log message.
- (Patch from "Rodolfo Schulz de Lima" <rodsoft@uol.com.br>.)
- * sanity.sh (admin): Test case for it.
-
-2003-10-15 Larry Jones <lawrence.jones@eds.com>
-
- * commit.c (commit_fileproc, finaladd): Don't call fixaddfile()
- if the RCS file didn't get created at all.
- (Reported by David Wood <David.Wood@thestreet.com>.)
-
-2003-10-14 Derek Price <derek@ximbiot.com>
-
- Port to pedantic POSIX 1003.1-2001 hosts, such as Debian GNU/Linux
- testing with _POSIX2_VERSION=200112 in the environment.
-
- * sanity.sh: Use 'sed 1q', not 'head -1'.
- (Patch from Paul Eggert <eggert@twinsun.com>.)
-
-2003-10-10 Derek Price <derek@ximbiot.com>
-
- * lock.c (set_lock): Clarify comment.
-
-2003-10-08 Derek Price <derek@ximbiot.com>
-
- * Makefile.am (cvs_SOURCES): Add history.h.
- * history.c: Include history.h. Add the `P' record types to more
- comments. s/ALL_REC_TYPES/ALL_HISTORY_REC_TYPES/.
- (usage): Reference ALL_HISTORY_REC_TYPES rather than using a separate
- string literal.
- (report_hrecs): Handle `P' record type.
- (ALL_REC_TYPES): Rename and move...
- * history.h (ALL_HISTORY_REC_TYPES): ...here.
- * mkmodules.c: Include history.h.
- (config_contents): Update contents of and references to LogHistory
- records to use ALL_HISTORY_REC_TYPES.
- * sanity.sh (basic2-64): Update to include history records of type `P'.
-
- * Makefile.in: Regenerated.
-
-2003-10-08 Derek Price <derek@ximbiot.com>
-
- * update.c (patch_file): Correct spelling and punctuation in comment.
- Update some lines to fit in 80 characters.
-
-2003-10-08 Larry Jones <lawrence.jones@eds.com>
-
- * history.c (history): Don't conflate -e with -x since the client's
- idea of what -e means may not match the server's.
- (Reported by Frank Hemer <frank@hemer.org>.)
-
-2003-10-07 Larry Jones <lawrence.jones@eds.com>
-
- * sanity.sh: Use dotest_fail instead of dotest_status for diff tests
- since CVS only returns success/fail rather than 0/1/2 like diff does.
-
-2003-10-07 Derek Price <derek@ximbiot.com>
-
- Fix a client/server bug introduced via the data loss fix of 2003-03-17.
- Basically, the server was reporting ambiguous filename requests when it
- should have been trusting the user to type the intended case or using
- the case the client preserved in CVS/Entries before it tried to look
- anything up in case insensitive mode.
-
- * rcs.c (locate_rcs): Use the filename exactly as cased before
- investigating a case insensitive lookup, per the client/server protocol
- specification. Expand comments.
- * subr.c (locate_file_in_dir): This function only needs to locate files
- case insensitively. Expand comments.
- * cvs.h (locate_file_in_dir): Only prototype when servers which need to
- handle case insensitivity are being compiled.
-
-2003-10-07 Derek Price <derek@ximbiot.com>
-
- * rcs.c (locate_rcs): Declare static. Move to an earlier location in
- file to avoid prototyping.
- * rcs.h (locate_rcs): Remove proto.
-
-2003-10-03 Derek Price <derek@ximbiot.com>
-
- * server.c (serve_global_option): Warn that -l is being ignored rather
- than exiting fatally due to backwards compatibility complaints from
- administrators.
-
-2003-09-29 Derek Price <derek@ximbiot.com>
-
- * rcs.c (make_file_label): Make a failure to stat a file a fatal error
- since it signals that a later read will also fail.
-
-2003-09-26 Derek Price <derek@ximbiot.com>
-
- * diff.c (diff): Add a FIXME re spaces in diff arguments.
-
-2003-09-25 Mark D. Baushke <mdb@cvshome.org>
-
- * rcs.c (make_file_label): Do not return an uninitialized label.
- (Reported by "Todd C. Miller" <Todd.Miller@courtesan.com>)
-
-2003-09-12 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (mkmodules): Correct comments.
-
-2003-09-12 Derek Price <derek@ximbiot.com>
-
- * mkmodules.c (mkmodules): Do not pass a string which came from the
- checkoutlist file directly to error as a format string since we don't
- want to trust any user with access to checkoutlist with creating printf
- format strings. I already claimed I did this in the NEWS file.
- (Thanks to Larry Jones for spotting my mistake.)
- * sanity.sh (mkmodules): Test for the above.
-
-2003-09-12 Derek Price <derek@ximbiot.com>
-
- * mkmodules.c (checkoutlist_contents): Document the optional portions
- of this file format more accurately.
- (mkmodules): Ditto, in comments. Fix bug that always failed to ignore
- whitespace before error messages.
- * sanity.sh (mkmodules-temp-file-removal): Rename to...
- (mkmodules): ...this and add a test of the checkoutlist error message.
- Add cleanup step to restore checkoutlist.
-
-2003-08-27 Larry Jones <lawrence.jones@eds.com>
-
- * history.c: 'P' is a valid record type and has been for a long time.
- Add it to the comments, usage message, and, most important,
- ALL_REC_TYPES so it gets recorded by default.
- * server.c (do_cvs_command): Set global command_name to the real
- command name rather than leaving it set to "server".
- * sanity.sh: Update to match.
- (Reported by Dmitry Ryzhkov <rdim_outside@softhome.net>.)
-
-2003-08-13 Larry Jones <lawrence.jones@eds.com>
-
- * server.c (server_cleanup): Don't shutdown buf_from_net if it's
- null.
- (Reported by Scott Mitchell <scott@fishballoon.org>.)
-
-2003-08-01 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (join5): Use $PROG consistently and escape a `.'.
-
-2003-08-01 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (join5): Use `[a-z]*' as opposed to `update'.
-
-2003-07-31 Derek Price <derek@ximbiot.com>
-
- * add.c (add_directory): Restore a malloc I shouldn't have altered on
- the stable branch.
-
-2003-07-31 Derek Price <derek@ximbiot.com>
-
- * rcscmds.c (RCS_merge): Pass `--' before the filename arguments to
- diff so that filenames starting with `-' can be merged.
- * sanity.sh (join5): New test for same.
-
-2003-07-31 Derek Price <derek@ximbiot.com>
-
- * add.c (add_directory): Don't print status information in really_quiet
- mode.
-
-2003-07-29 Derek Price <derek@ximbiot.com>
-
- * commit.c (checkaddfile): Simplify the logic here, using assumptions
- already made later in the function to remove calls to locate_rcs and
- some conditionals. Use same assumptions to remove some variables.
-
-2003-07-29 Derek Price <derek@ximbiot.com>
-
- * login.c: Remove GETPASS & HAVE_GETPASSPHRASE cruft in favor of always
- using the GNULIB getpass since the system getpass was removed from the
- POSIX.2 specification.
-
-2003-07-28 Derek Price <derek@ximbiot.com>
-
- * subr.c (strip_trailiing_newlines): Use size_t rather than int to
- count string length.
- (Suggestion from Paul Edwards, who provides a broken return email
- address in Tonga. I believe he is actually from Australia.)
-
-2003-07-28 Derek Price <derek@ximbiot.com>
-
- * checkout.c (checkout): Remove out-of-date comment about Checkin.prog
- and Update.prog.
-
-2003-07-25 Derek Price <derek@ximbiot.com>
-
- * rcs.c (RCS_parsercsfile): Declare rcsfile argument as const.
- * rcs.h (RCS_parsercsfile): Update prototype to match.
- * commit.c (fixaddfile): Accept a single path to an rcs file as an
- argument rather than trying to look it up again when it is not
- necessary.
-
-2003-07-25 Derek Price <derek@ximbiot.com>
-
- * commit.c (finaladd): But don't free variables we no longer allocate.
-
-2003-07-25 Derek Price <derek@ximbiot.com>
-
- * checkin.c (Checkin): The rcs argument is unecessary since we know
- that the parsed RCS data always exists as part of finfo by the time
- this function gets called.
- * commit.c (commit_fileproc, finaladd): Use new Checkin() API.
- * cvs.h (Checkin): Update prototype.
-
-2003-07-25 Derek Price <derek@ximbiot.com>
-
- * subr.c (strip_trailing_newlines): Check len b4 str[len] to avoid
- exceeding the array bounds when the string length == 0.
- (Report from John Tytgat <JoTy@esko-graphics.com>.)
-
-2003-07-25 Derek Price <derek@ximbiot.com>
-
- * subr.c (strip_trailing_newlines): Generalize this function to watch
- len so that it cannot walk past the beginning of the string passed in.
- (Report from John Tytgat <JoTy@esko-graphics.com>.)
-
-2003-07-25 Derek Price <derek@ximbiot.com>
-
- * subr.c (strip_trailing_newlines): Leave the K&R function decl on this
- branch.
-
-2003-07-25 Derek Price <derek@ximbiot.com>
-
- * cvs.h (strip_trailing_newlines): Update prototype.
- * subr.c (strip_trailing_newlines): Return true when newlines are
- removed.
- * server.c (pserver_authenticate_connection): Don't give a DOS attack a
- chance to authenticate accidentally because I like to be paranoid.
- * sanity.sh (pserver): New test for same.
-
-2003-07-20 Derek Price <derek@ximbiot.com>
-
- * wrapper.c: Remove mention of obsolete -f and -t wrapper options from
- a comment.
-
-2003-07-12 Larry Jones <lawrence.jones@eds.com>
-
- * sanity.sh (diffnl): New tests for diff on files with no newline
- at end.
- (Patch from Andrew Moise <chops@demiurgestudios.com>.)
-
-2003-07-09 Larry Jones <lawrence.jones@eds.com>
-
- * add.c (add): Update "re-adding" message to have quotes around
- the file name like all the other similar messages.
- * sanity.sh: Update to match.
-
- * update.c (join_file): Handle locally removed but not yet committed
- files.
- (Reported by Larry Lords <LordsLL@ldschurch.org>.)
- * sanity.sh (join, join4): New tests for above.
-
-2003-06-28 Larry Jones <lawrence.jones@eds.com>
-
- * commit.c (fixaddfile): Bail out if locate_rcs() fails. Make
- parameters const.
-
- * add.c (add): Fix -Wall complaints.
- * diff.c (diff_file_nodiff): Ditto.
- * filesubr.c (cvs_casecmp): Ditto.
- * patch.c (patch_fileproc): Ditto.
- * rcs.c (RCS_cmp_file): Ditto.
- * root.c (parse_cvsroot): Ditto.
- * subr.c (locate_file_in_dir): Ditto.
- * cvs.h (cvs_casecmp, locate_file_in_dir): Update prototypes.
-
-2003-06-27 Larry Jones <lawrence.jones@eds.com>
-
- * lock.c (readers_exist): Use LockDir rather than always looking
- in the repository.
- (Original patch from Robert Ambalu <Robert.Ambalu@gs.com>.)
- Remove vestigial lock promotion code.
-
-2003-06-26 Larry Jones <lawrence.jones@eds.com>
-
- * hash.c (sortlist): Avoid crash when list is null.
-
-2003-06-23 Derek Price <derek@ximbiot.com>
-
- * patch.c (patch_fileproc): Output revision number of the original
- revision in the removed case.
- (Idea from Paul Edwards <kerravon@w3.to>.)
-
- * sanity.sh (rdiff-add-remove-nodiff): Rename to...
- (rdiff-short): ...this. Test for the above changes. Add some tests
- for when rev2 defaults to the trunk. Expand comments.
-
-2003-06-23 Derek Price <derek@ximbiot.com>
-
- * add.c (add): Fix xmalloc's strlen() of wrong variable.
- * checkout.c (safe_location): leak: reused where_location without free.
- * log.c (rlog_proc): leak: free where before exit.
- * logmsg.c (do_verify): leak: free verifymsg_script before exit.
- (Original patch from Kenneth Lorber <keni@his.com>.)
-
-2003-06-20 Derek Price <derek@ximbiot.com>
-
- * client.c: Remove silly comment.
- (Patch from Alexey Mahotkin <alexm@hsys.msk.ru>.)
-
-2003-06-13 Derek Price <derek@ximbiot.com>
-
- * subr.c (file_has_conflict): Fix comment.
- (Patch from Paul Edwards <kerravon@w3.to>.)
-
-2003-06-13 Derek Price <derek@ximbiot.com>
-
- * subr.c (xrealloc): Trivial comment fix.
- (Patch from Kenneth Lorber <keni@his.com>.)
-
-2003-06-13 Derek Price <derek@ximbiot.com>
-
- * diff.c (diff_fileproc): Fix memory leak.
- (Patch from Kenneth Lorber <keni@his.com>.)
-
-2003-06-12 Derek Price <derek@ximbiot.com>
-
- * root.c (parse_cvsroot, local_cvsroot): Parse trailing '/'s off the
- end of cvsroots. Make arguments const.
- * cvs.h: Update prototypes to match.
- (Idea from Miles Zarathustra <shiva@aranyaka.org>.)
-
-2003-06-11 Larry Jones <lawrence.jones@eds.com>
-
- * sanity.sh: Change warning messages to note that defective tools
- can result in defective results, both pass and fail. Also change
- "which" to "that" for errant grammar pedants.
-
-2003-06-09 Derek Price <derek@ximbiot.com>
-
- * rcs.c (RCS_delete_revs): Reference WOE32 rather than WIN32 in
- accordance with the GNU convention to avoid implying that we consider
- the Microsoft Windows Operating Environment any sort of "win".
-
-2003-06-09 Derek Price <derek@ximbiot.com>
-
- * filesubr.c (cvs_temp_file): Tidy a comment.
-
-2003-06-09 Derek Price <derek@ximbiot.com>
-
- * patch.c (patch_fileproc): Don't assume the content of files is
- different just because the revision number is different.
- * sanity.sh (rdiff-add-remove-nodiff): New tests for the above.
- (Report & original patches from Paul Edwards <kerravon@w3.to>.)
-
-2003-06-04 Derek Price <derek@ximbiot.com>
-
- * cvs.h (locate_file_in_dir): New proto.
- (locate_rcs): Move proto...
- * rcs.h: ...here.
- * filesubr.c (locate_rcs): Move function...
- * rcs.c: ...here for Windows.
- * filesubr.c (locate_file_in_dir): Move function...
- * subr.c: ...here for Windows.
-
-2003-06-02 Derek Price <derek@ximbiot.com>
-
- * diff.c (diff_file_nodiff): Don't assume that because two specified
- revision numbers are different, the contents are different.
- (Original report & patch from Paul Edwards <kerravon@w3.to>.)
-
- * diff.c (diff_file_nodiff): Pass through rev1_cache to be filled in
- by RCS_cmp_file when it needs to check out revision 1 into a file. Add
- some more informative error messages. Cleanup for efficiency &
- readability.
- (diff_fileproc): Pass the cached revision to RCS_exec_diff(). Clean up
- the error exit code. Remove code killed by the changes to
- diff_file_nodiff().
- * rcscmds.c (RCS_exec_rcsdiff): Accept and use new cached revision text
- if present.
- * rcs.c (RCS_cmp_file): Accept a second revision number and cache the
- first revision if it needs to be checked out.
-
- * checkin.c (Checkin): Use new RCS_cmp_file().
- * import.c (update_rcs_file): Ditto.
- * no_diff.c (No_Difference): Ditto.
-
- * cvs.h (RCS_exec_rcsdiff): New proto to match above changes.
- * rcs.h (RCS_cmp_file): Ditto.
-
- * sanity.sh: Minor corrections to handle the above changes.
-
-2003-05-29 Derek Price <derek@ximbiot.com>
-
- * client.c (start_server): Don't send -l to server.
- * history.c (history_write): Fix comment.
- * main.c (main): Don't process -l.
- * server.c (serve_global_option): Ditto.
- (Suggestion from Rob Lanphier <robla@real.com>.)
-
-2003-05-23 Larry Jones <lawrence.jones@eds.com>
-
- * sanity.sh (info-cleanup-verifymsg): Avoid race in output.
-
-2003-05-22 Larry Jones <lawrence.jones@eds.com>
-
- * commit.c (commit): Fix leading zero stripping code to not strip
- unless there's a following digit.
-
- * parseinfo.c (Parse_Info): Warn if multiple DEFAULT lines found.
- * sanity.sh (info): New test for above.
-
-2003-05-21 Derek Price <derek@ximbiot.com>
-
- * Makefile.in: Regenerate with Automake version 1.7.5.
-
-2003-05-20 Larry Jones <lawrence.jones@eds.com>
-
- * parseinfo.c (Parse_Info): Fix stupid memory management error.
-
- * logmsg.c (do_verify): Treate Parse_Info errors as failure.
- * parseinfo.c (Parse_Info): Don't call expand_path until executing
- the command so that errors in unexecuted commands aren't reported.
- * sanity.sh (info): New tests for above.
-
-2003-05-18 Mark D. Baushke <mdb@gnu.org>
-
- * Makefile.am (localcheck,remotecheck): Use cvs$(EXEEXT) not cvs.
- * Makefile.in: Regenerated.
- * sanity.sh (status-init-7): Use ${PROG} not cvs in tests.
- (branch-after-import-5): Ditto.
- (keywordname-update-11): Ditto.
-
-2003-05-18 Larry Jones <lawrence.jones@eds.com>
-
- * server.h (kserver_authenticate_connection,
- pserver_authenticate_connection): Add prototypes.
-
- * client.c (update_entries): Set file's access time to the current
- time rather than the same as the modification time.
- * vers_ts.c (Version_TS): Ditto.
-
-2003-05-01 Derek Price <derek@ximbiot.com>
-
- * main.c (main): Ignore -z when CLIENT_SUPPORT is not defined.
- (Report from Jim Salter <jsalterjim@earthlink.net>.)
-
-2003-05-01 Derek Price <derek@ximbiot.com>
-
- * repos.c (Sanitize_Repository_Name): Remove some old comments about
- the defunct RELATIVE_REPOS macro.
- * server.c (outside_root): Ditto.
-
-2003-04-30 Derek Price <derek@ximbiot.com>
-
- * add.c (add): Fix a possible, if unlikely, memory out of bounds error.
-
-2003-04-28 Derek Price <derek@ximbiot.com>
-
- * client.c (save_prog): Remove unneeded struct.
- (checkin_progs, update_progs): Remove these unneeded globals.
- (handle_set_checkin_prog, handle_set_update_prog, do_deferred_progs):
- Remove these functions.
- (send_repository): Remove checkin and update prog support.
- (responses): Remove Set-checkin-prog and Set-update-prog.
- (get_responses_and_close): Don't call do_deferred_prog().
- * commit.c (commit_usage): Remove reference to -n.
- (commit): Don't set and send run_module_prog via -n. Don't run
- Checkin.prog or Checkout.prog in local mode.
- * modules.c (CVSMODULE_OPTS): Remove -i and -u.
- (do_module): Don't process -i and -u options to set checkin and update
- progs, respectively.
- * server.c (server_prog, serve_checkin_prog, server_update_prog):
- Remove unused functions.
- (requests): Remove Checkin-prog and Update-prog.
- * update.c (update_dirleave_proc): Remove update prog functionality.
-
- * cvs.h (CVSADM_CIPROG, CVSADM_UPROG): Remove unneeded defines.
- * server.h (server_prog): Remove proto.
- (progs): Remove enum.
-
- * sanity.sh (modules5): Remove tests for checkin and update programs.
-
-2003-04-10 Larry Jones <lawrence.jones@eds.com>
-
- * Makefile.in: Regenerated.
-
-2003-03-27 Mark D. Baushke <mdb@cvshome.org>
-
- * sanity.sh (rdiff2): Add new test case for SEGV problem reported
- against cvs 1.11.5.
- (Report from James Cribb)
-
-2003-03-26 Derek Price <derek@ximbiot.com>
-
- * client.c: Fix, reorganize, and comment ifdefs for AUTH_CLIENT_SUPPORT
- and HAVE_GSSAPI.
- * client.h: Ditto. Remove some unecessary server function prototypes.
-
-2003-03-26 Derek Price <derek@ximbiot.com>
-
- * client.c: Include the net headers for HAVE_GSSAPI.
- (Report from Jim Salter <jsalterjim@earthlink.net>.)
-
-2003-03-26 Derek Price <derek@ximbiot.com>
-
- * main.c (main): Verify the argument to -z when running without
- CLIENT_SUPPORT since Eric Siegerman complained about being bit
- by a run of `cvs -z -n up' which parsed the -n as the argument to
- -z.
- * sanity.sh (opterrmsg): New tests for -z argument checking.
-
-2003-03-26 Larry Jones <lawrence.jones@eds.com>
-
- * main.c (main): Use strtol() instead of atoi() when parsing -z
- to detect errors.
- (Reported by Eric Siegerman <erics@telepres.com>.)
-
-2003-03-24 Derek Price <derek@ximbiot.com>
-
- * Makefile.am: Update copyright notice.
-
- * Makefile.in: Regenerated.
-
-2003-03-19 Larry Jones <lawrence.jones@eds.com>
-
- * filesubr.c (mkdir_if_needed): Save errno since isdir() can clobber.
- (Patch from Brian Poole <raj@cerias.purdue.edu>.)
- * sanity.sh (abspath-4): Update to match.
-
- * filesubr.c (locate_rcs): Fix gcc warning.
-
-2003-03-17 Derek Price <derek@ximbiot.com>
-
- * add.c: Correct comment.
- * client.c: Ditto.
- * checkin.c (Checkin): Pass work file name to RCS_checkin so that this
- function works properly in the case insensitive mode.
- * commit.c (checkaddfile): Fix and factor add logic so that the
- correct files and directories are created in the case insensitive mode.
- Reuse code in RCS_parse() below. This avoids a problem that could
- cause corrupted RCS files to be created on an add from a case
- insensitive system. Corrupted RCS files could cause later assertion
- failures for everyone.
- (locate_rcs): Move this function...
- * filesubr.c (locate_rcs): ...here and rewrite it.
- (fopen_case): Remove this function.
- (locate_file_in_dir): New function.
- * cvs.h (locate_rcs): Prototype new function.
- * rcs.c (RCS_parse): Factor out file location into locate_rcs.
-
-2003-03-17 Larry Jones <lawrence.jones@eds.com>
-
- * server.c (switch_to_user): Add syslog calls for setgid/setuid
- failure.
-
-2003-03-07 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (help): Add explanation of CVS-TO-TEST and edit for
- consistency.
-
-2003-03-07 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (usage): Show users long --help rather than less
- informative -h.
-
-2003-03-07 Derek Price <derek@ximbiot.com>
-
- * sanity.sh: Add support for long options.
- (exit_usage): Move the actual generation of usage text to...
- (usage): ...this new function and improve the usage message.
- (exit_help): New function.
-
-2003-03-07 Larry Jones <lawrence.jones@eds.com>
-
- * commit.c (check_fileproc): Remove unused variables.
-
- * patch.c (patch): Pass local to do_module so that -l actually works.
- (Reported by John Coers <coers@intrinsity.com>.)
- (patch_fileproc): Fix uninitialized variables.
- * sanity.sh: Define a DATE pattern for rdiff and use it.
- (basic2-24a): New test for above.
-
-2003-03-06 Derek Price <derek@ximbiot.com>
-
- * subr.c (file_has_conflict): New file.
- * commit.c (check_fileproc): Factor code into new file_has_conflict()
- function.
- * update.c (update_fileproc): Ditto.
- * status.c (status_fileproc): Use new file_has_conflict() function.
- (Report from Bernd Kuemmerlen <bkuemmer@mevis.de>.)
-
- * sanity.sh (status): New test for same.
-
-2003-03-05 Mark D. Baushke <mdb@cvshome.org>
-
- * rcs.c (RCS_magicrev): Backout CVS_LOCAL_BRANCH_NUM feature.
-
- * rcs.c (RCS_magicrev): CVS_LOCAL_BRANCH_NUM feature.
- Port of the FreeBSD hack for setting the next magic branch number
- to be used. The original patch was written by Peter Wemm
- <peter@FreeBSD.org> and may be found by visiting the URL:
- http://www.freebsd.org/cgi/cvsweb.cgi/src/contrib/cvs/src/rcs.c.diff?r1=1.1&r2=1.2
- Implement a horrible (but simple) hack to allow some control over the
- branch number that is assigned. This is specifically to support the
- local commit feature of cvsup. If one sets $CVS_LOCAL_BRANCH_NUM to
- (say) 1000 then branches the local repository, the revision numbers
- will look like 1.66.1000.xx. This is almost a dead-set certainty that
- there will be no conflicts with version numbers.
- (This needs to be something more than an option to 'cvs tag' or 'cvs
- rtag' as various parts of cvs "know" how to automatically branch files
- (eg: cvs add). Trying to remember state is getting "Too Hard (TM)")
- * sanity.sh (branches3): Test the CVS_LOCAL_BRANCH_NUM feature.
-
-2003-03-04 Derek Price <derek@ximbiot.com>
-
- * history.c (history_write): Remove unneeded O_CREAT in the call to
- open() since we abort a few lines earlier if the file doesn't exist.
- Add a comment to the effect that this is not the optimal method of
- doing things and needs fixed.
-
-2003-02-28 Derek Price <derek@ximbiot.com>
-
- * root.c (parse_cvsroot): s/no_passwd/no_password/ in comments.
-
-2003-02-28 Derek Price <derek@ximbiot.com>
-
- * root.c (parse_cvsroot): Set no_password for :gserver: and :kserver:
- as tokens should already be obtained via external sources.
- * update.c (update_fileproc): Remove redundant code.
-
-2003-02-28 Larry Jones <lawrence.jones@eds.com>
-
- * lock.c (set_lock): If possible, try a short wait with no message
- before calling lock_wait() to optimize master lock contention.
-
-2003-02-26 Larry Jones <lawrence.jones@eds.com>
-
- * checkout.c (checkout): Send "--" before file names.
- * sanity.sh (spacefiles): Remote now works just like local.
-
-2003-02-25 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (rcs4): Use UTC to work across timezones.
-
-2003-02-25 Derek Price <derek@ximbiot.com>
-
- * rcs.c (RCS_getdate): Fix a bug that shows up when checking out
- files by date with the "-D date" command line option. There is
- code in the original to handle a special case. If the date search
- finds revision 1.1 it is supposed to check whether revision
- 1.1.1.1 has the same date stamp, which would indicate that the
- file was originally brought in with "cvs import". In that case it
- is supposed to return the vendor branch version 1.1.1.1.
-
- However, there was a bug in the code. It actually compares the date
- of revision 1.1 for equality with the date given on the command
- line -- clearly wrong. This commit fixes the coding bug.
-
- Note: There is an additional bug which is _not_ fixed in this
- commit. The date comparison should not be a strict equality test.
- It should allow a fudge factor of, say, 2-3 seconds. Old versions
- of CVS created the two revisions with two separate invocations of
- the RCS "ci" command. We have many old files in the tree in which
- the dates of revisions 1.1 and 1.1.1.1 differ by 1 second.
-
- This bug was discovered and fixed for FreeBSD cvs. See v 1.21 of
- <http://www.freebsd.org/cgi/cvsweb.cgi/src/contrib/cvs/src/rcs.c.diff>
- for more information.
-
- * sanity.sh (rcs4): Tests for same.
- (Patch from Mark D. Baushke <mdb@cvshome.org>.)
-
-2003-02-25 Derek Price <derek@ximbiot.com>
-
- * logmsg.c (logfile_write): Do not pass a NULL pointer to
- fprintf() when we have an empty log message.
- * sanity.sh (editor): Add new tests to verify correct behavior of
- empty log messages.
- (Patch from Mark D. Baushke <mdb@cvshome.org>, original report from
- Piotr KUCHARSKI <chopin@sgh.waw.pl>.)
-
-2003-02-25 Derek Price <derek@ximbiot.com>
-
- * cvsbug.in: Import use of mktemp function from RedHat 8.0's
- CVS 1.11.2 RPM. Use new MKTEMP configure variable. Use new
- SENDMAIL from configure.
-
- * Makefile.in: Regenerated.
-
-2003-02-25 Derek Price <derek@ximbiot.com>
-
- * watch.c (watch_usage): Use {} rather than () for literals.
-
-2003-02-14 Derek Price <derek@ximbiot.com>
-
- * watch.c (watch_usage): Make the repeatability of -a part of the
- usage spec.
-
-2003-02-14 Derek Price <derek@ximbiot.com>
-
- * watch.c (watch_usage): Mention default for -a. Mention multiple
- invocations of -a. Mention -R as default. Use required () rather than
- optional [] around watch subcommand list in invocation spec. Use
- `path' instead of `file'. Put variable <> around `action' and `path'.
-
-2003-02-07 Derek Price <derek@ximbiot.com>
-
- * commit.c (checkaddfile): Do not lose the vendor branch when
- adding files to a new branch. Avoids extranious conflicts for
- future vendor imports. This was found and fixed in FreeBSD cvs.
- See http://www.freebsd.org/cgi/query-pr.cgi?pr=4033 for details.
- * sanity.sh (branch-after-import): New test.
- (Thanks to Mark D Baushke <mdb@cvshome.org> for forwarding the
- patch and writing the test cases!)
-
- * sanity.sh (branch-after-import): Misc portablility and standard
- changes.
-
-2003-02-12 Derek Price <derek@ximbiot.com>
-
- * main.c (main): Update copyright message to 2003.
-
-2003-02-21 Larry Jones <lawrence.jones@eds.com>
-
- * server.c (switch_to_user): Update comment, change error message
- so it's not an exact duplicate of the one in check_password.
- (check_repository_password): Add syslog call for password mismatches.
- (check_password): Add syslog call for password mismatches, rearrange
- code to simplify and eliminate redundancy.
- (pserver_authenticate_connection): Remove syslog call, now done by
- lower-level routines.
-
-2003-02-19 Larry Jones <lawrence.jones@eds.com>
-
- * sanity.sh (admin-10): Add test for repository files not in
- working directory.
-
- * admin.c (admin_fileproc): Fix crash when no rcs file, return
- failure status for bogus files.
- * sanity.sh (admin-4a): Test for above.
- (Original patch submitted by Mark D. Baushke <mdb@cvshome.org>).
-
-2003-02-14 Larry Jones <lawrence.jones@eds.com>
-
- * log.c (log_expand_revlist): Fix crashes in error cases.
- (Reported by Bart Santy <Bart.Santy@switch.be>.)
- * sanity.sh (log): New tests for above.
-
-2003-02-01 Larry Jones <lawrence.jones@eds.com>
-
- * buffer.c (stdio_buffer_shutdown): Handle EINTR from waitpid.
- (Patch from Johannes Grødem <johs+n@ifi.uio.no>.)
-
-2003-02-08 Derek Price <derek@ximbiot.com>
-
- * rcs.c (RCS_checkout): Supply the full function name in the trace
- output.
- * update.c (checkout_file, join_file): Supply tag properly to
- RCS_checkout more often.
- (patch_file): Ditto. Fill out comments.
- * sanity.sh (keyword, keywordname): Some changes to accomodate the fact
- that the above changes cause patches generated by patch_file to fail
- occassionally.
-
-2003-02-06 Derek Price <derek@ximbiot.com>
-
- * client.c: Use the complete path to the CVSADM_TEMPLATE file in
- error messages. Remove related FIXME.
-
-2003-01-31 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (keywordname): Change a "FIXME" comment to "FIXCVS".
-
-2003-01-30 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (keywordname): New test.
-
-2003-01-23 Larry Jones <lawrence.jones@eds.com>
-
- * diff.c (diff_fileproc): Restructure code to simplify and eliminate
- redundant tests.
-
- * server.c (do_cvs_command): Use WCOREDUMP macro rather than hard
- coding test for core file.
-
-2003-01-21 Larry Jones <lawrence.jones@eds.com>
-
- * root.c (method_name): Redefine as a 2D array.
- * root.h (method_name): Ditto.
-
-2003-01-21 Jim Meyering <jim@meyering.net>
-
- * add.c (add): Rename local-shadowing `i' to `j'.
-
- * root.c (method_names): Declare to be a const array of const strings.
- (Name_Root): Save errno so it doesn't get clobbered
- by the intervening error call.
- Use getline's return value, mainly to save a call to strrchr.
-
-2003-01-20 Larry Jones <lawrence.jones@eds.com>
-
- * myndbm.c (O_ACCMODE): Parenthesize the replacement string so that
- it parses correctly.
- (Reported by Andres Bertens <abertens@entelchile.net>.)
-
-2003-01-15 Karl Fogel <kfogel@collab.net>
-
- * server.c (dirswitch): Don't free dir_name until right before
- allocating it again. This removes a potential double-free
- problem, whereby this function could free dir_name and then
- immediately return due to invalid directory syntax (without ever
- reassigning dir_name), then reenter and free dir_name again.
-
- Thanks to Stefan Esser <s.esser@e-matters.de> for the fix.
-
-2003-01-08 Larry Jones <lawrence.jones@eds.com>
-
- * client.c (update_entries): Only "0" is a special version number;
- other numbers starting with 0 (like 0.1) are normal version numbers.
- * commit.c (find_fileproc): Ditto. Also reorganize the code to
- simplify the conditions.
- (Reported by Michele Zamparelli <michele.zamparelli@eso.org>.)
-
-2003-01-02 Larry Jones <lawrence.jones@eds.com>
-
- * rcs.c (getdelta): Use RCSDEAD rather than literal "dead".
-
-2002-12-27 Derek Price <derek@ximbiot.com>
-
- * admin.c: s/LOCK_(NONE|WRITE|READ)/CVS_$&/g; since the definition of
- LOCK_WRITE clashes with a definition in objidl.h on Windoze platforms.
- * annotate.c: Ditto.
- * client.c: Ditto.
- * commit.c: Ditto.
- * cvs.h: Ditto.
- * diff.c: Ditto.
- * edit.c: Ditto.
- * lock.c: Ditto.
- * log.c: Ditto.
- * patch.c: Ditto.
- * recurse.c: Ditto.
- * remove.c: Ditto.
- * status.c: Ditto.
- * tag.c: Ditto.
- * update.c: Ditto.
- * watch.c: Ditto.
- * myndbm.c: Ditto & define O_ACCMODE when it isn't defined, as under
- Windoze.
- (Thanks to Stephane Rouleau <s.rouleau@videotron.ca>,
- Cristopher Seawood <cls@seawood.org>, and
- Frederico Costa <frederico.costa@tiscali.no> for all their hints,
- tips, and patches for this problem.)
-
-2002-12-20 Derek Price <derek@ximbiot.com>
-
- * client.c (send_a_repository): Suppress a warning under Windoze.
-
-2002-12-19 Derek Price <derek@ximbiot.com>
-
- * Makefile.am: Remove reference to options.h.
- * cvs.h: Ditto.
- * options.h: Remove this obsolete file.
- * sanity.sh: Remove comment about external diffs causing tests to fail
- since CVS hasn't used external diffs in years.
-
- * Makefile.in: Regenerated.
-
-2002-12-16 Derek Price <derek@ximbiot.com>
-
- * admin.c: Disable cvsadmin group checking on the client.
- (Reported by Dan Peterson <dbpete@aol.com>.)
-
-2002-12-06 Derek Price <derek@ximbiot.com>
-
- * buffer.c: Replace calls to malloc with calls to xmalloc and calls to
- realloc with calls to xrealloc.
- * parseinfo.c: Ditto.
- * root.c: Ditto.
- * server.c: Ditto.
- * zlib.c: Ditto.
- * scramble.c: Change some comments to refer to xmalloc rather than
- malloc.
- (Reported by Dan Peterson <dbpete@aol.com>.)
-
-2002-12-04 Derek Price <derek@ximbiot.com>
-
- * options.h: Remove CVS_ADMIN_GROUP.
-
-2002-12-02 Larry Jones <lawrence.jones@eds.com>
-
- * commit.c (commit): Strip leading zeros from numeric revision
- in addition to trailing dots.
- (Reported by Peter Meszaros <pme@prolan.hu>.)
-
-2002-11-22 Larry Jones <lawrence.jones@eds.com>
-
- * sanity.sh: Note that the tests run for a long time.
-
- * checkout.c (safe_location): Use xstrdup, not strdup.
- (Reported by Terrence Enger <tenger@iSeries-guru.com>.)
-
-2002-11-19 Larry Jones <lawrence.jones@eds.com>
-
- * log.c (log_expand_revlist): Fix cross-branch correction code.
-
- * sanity.sh: Set $LANG for systems that ignore $LC_ALL.
- (rcs2-7): Change date offset from 100 months to 96 months to reduce
- periodic problems with invalid dates.
-
-2002-11-12 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (rcslib-symlink): Use rm -f rather than a simple rm when
- removing links because under some configurations of RH Linux 8.0 the
- script pauses to ask for removal approval.
-
-2002-11-08 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (importc): Update the use of the touch command to be
- compliant with POSIX 1003.1-2001, SUS2, and SUS3 now that GNU touch
- supports this. If this breaks any test platforms we should test
- the behavior of touch like we do for other tools.
-
-2002-11-03 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (rcs2-7): Notate with a wild untested hypothesis.
-
-2002-11-03 Derek Price <derek@ximbiot.com>
-
- * sanity.sh (rcs2-7): Notate with three more failure dates.
-
-2002-10-25 Derek Price <derek@ximbiot.com>
-
- * root.c: Change some calls to SYSTEM_CLEANUP() and then exit() to
- more appropriate calls to error_exit().
- * server.c: Ditto.
- * tag.c: Ditto.
-
-2002-10-24 Derek Price <derek@ximbiot.com>
-
- * buffer.c (stdio_buffer_shutdown): Remove the getc() call used to
- detect spurious output from clients since getc() would sometimes
- block and hang indefinately if the client kept the conection open but
- sent no data. Bug reports state that this hapened frequently with
- older clients connecting to 1.11.2 servers, especially when
- compression is enabled.
- (Original report from Mark D. Baushke <mdb@juniper.net>.
- Original patch from Ralf S. Engelschall <rse@engelschall.com>
- via Peter Wemm <peter@freebsd.org>.)
-
-2002-10-05 Larry Jones <lawrence.jones@eds.com>
-
- * recurse.c (start_recursion, do_recursion): Allow write locking
- in addition to read locking. Change all callers.
- * cvs.h: Change prototype to match, add lock types.
- * tag.c (rtag_proc, rtag_fileproc, tag_fileproc): Have start_recursion
- use write locks rather than calling lock_dir_for_write to avoid deadly
- embrace.
-
-2002-10-04 Larry Jones <lawrence.jones@eds.com>
-
- * client.c (get_responses_and_close, connect_to_pserver): Set
- to_server and from_server to NULL after freeing.
- * main.c (main): Clear server_active when finished. Also neaten
- up the SERVER_SUPPORT ifdef's.
- * server.c (do_cvs_command): Set protocol_inbuf, stderrbuf, and
- stdoutbuf to NULL after freeing.
- (server_cleanup): Free buf_from_net and buf_to_set and set to NULL.
- Also reset error_use_protocol.
- (server): Don't SIG_register server_cleanup. main_cleanup (which
- is already registered) outputs a fatal error which causes it to
- be called; registering it directly results in it being called twice.
- (cvs_output): Don't try to use buf_to_net or protocol if they're NULL.
-
-2002-10-03 Larry Jones <lawrence.jones@eds.com>
-
- * lock.c (readers_exist): Ignore our own read lock, if any, to
- allow upgrading an existing read lock to a write lock.
- * tag.c (rtag_proc, rtag_fileproc, tag_fileproc): Rather than
- locking the entire tree, have start_recursion establish read
- locks and then upgrade the read lock to a write lock (so only
- one directory is locked at a time).
-
-2002-09-27 Larry Jones <lawrence.jones@eds.com>
-
- * add.c (add): Send "--" before file names.
- * admin.c (admin): Ditto.
- * annotate.c (annotate): Ditto.
- * commit.c (commit): Ditto.
- * diff.c (diff): Ditto.
- * edit.c (watch_onoff, editors): Ditto.
- * log.c (cvslog): Ditto.
- * remove.c (cvsremove): Ditto.
- * status.c (cvsstatus): Ditto.
- * tag.c (cvstag): Ditto.
- * update.c (update): Ditto.
- * watch.c (watch_addremove, watchers): Ditto.
-
- * sanity.sh (client-9): Update to match.
-
-2002-09-24 Derek Price <derek@ximbiot.com>
-
- * options.h: Remove prototype of STDC exit() function. If this breaks
- a build, this should be detected in configure.in somehow rather than
- restoring the line to this file.
-
-2002-09-24 Derek Price <derek@ximbiot.com>
-
- * options.h: Move definition of AUTH_CLIENT_SUPPORT into configure.in.
-
-2002-09-24 Derek Price <derek@ximbiot.com>
-
- * options.h: Move definition of FORCE_USE_EDITOR into configure.in.
-
-2002-09-24 Derek Price <derek@ximbiot.com>
-
- * options.h: Move definition of UMASK_DFLT into configure.in.
-
-2002-09-24 Derek Price <derek@ximbiot.com>
-
- * Makefile.in: Regenerated using Automake 1.6.3.
-
-2002-09-24 Larry Jones <lawrence.jones@eds.com>
-
- * filesubr.c, history.c, import.c, rcs.c, update.c: Use
- HAVE_STRUCT_STAT_ST_BLKSIZE and HAVE_STRUCT_STAT_ST_RDEV instead of
- the obsolete HAVE_ST_BLKSIZE and HAVE_ST_RDEV.
-
-2002-09-24 Derek Price <derek@ximbiot.com>
-
- * options.h: Move definition of TMPDIR_DFLT into configure.in.
-
-2002-09-24 Derek Price <derek@ximbiot.com>
-
- * options.h: Move defininition of EDITOR_DFLT into configure.in.
-
- * Makefile.in: Regenerated.
-
-2002-09-23 Jim Meyering <meyering@lucent.com>
-
- If `cvs -d REPO commit ...' was used to override CVS/Root,
- then modified files in the directory from which cvs is invoked
- would not be committed.
- * client.c (arg_should_not_be_sent_to_server): The above would happen
- because this function would throw out a file name when CVS/Root
- did not match the current server. Fix by allowing the command-line-
- specified repository to take precedence over the value returned
- by Name_Root. Patch by Simon Walton <simonw@lucent.com>.
- * sanity.sh (commit-d): New tests for the above.
- Patch by Simon Walton <simonw@lucent.com>.
-
-2002-09-20 Derek Price <derek@ximbiot.com>
-
- * options.h: Move definition of SERVER_FLOWCONTROL, SERVER_HI_WATER,
- and SERVER_LO_WATER into configure.in.
-
-2002-09-20 Derek Price <derek@ximbiot.com>
-
- * options.h: Move definition of PATCH_PROGRAM to configure.in.
-
-2002-09-18 Larry Jones <lawrence.jones@eds.com>
-
- * client.c (call_in_directory): Don't create admin directory when
- exporting into an existing directory.
- (Reported by Jens Engel <Jens.Engel@marconi.com>.)
- * sanity.sh (basic2): New tests for above.
-
-2002-09-16 Jim Meyering <meyering@lucent.com>
-
- * server.c (do_cvs_command): Move declarations of locals, timeout and
- timeout_ptr, `up', out of enclosing `#ifdef SERVER_FLOWCONTROL' block.
- Otherwise, this file would not compile with SERVER_FLOWCONTROL
- turned off. Patch by Ed Santiago <esm@ascend.com>.
-
-2002-09-15 Larry Jones <lawrence.jones@eds.com>
-
- * myndbm.c (mydbm_open): Open the file read/write rather than read-
- only if that's what the user asked for to ensure that the later open
- for write will succeed.
- (Patch submitted by Josh Lehan <cvs@krellan.com>.)
-
-2002-08-28 Larry Jones <lawrence.jones@eds.com>
-
- * logmsg.c (do_editor): Fix bug which prevented reusing log messages.
- (Reported by Eric Siegerman <erics@telepres.com>.)
-
-2002-08-16 Derek Price <derek@ximbiot.com>
-
- * create_adm.c (Create_Admin): Assume RELATIVE_REPOS is set.
- * server.c (outside_root): Add comment.
- * options.h: Remove RELATIVE_REPOS & CVS_BADROOT.
- * sanity.sh: Remove a lot of !RELATIVE_REPOS cruft from tests.
-
-2002-08-14 Derek Price <oberon@umich.edu>
-
- * server.c (server): Dispose of the correct pointer. Tidy comment.
-
-2002-08-13 Derek Price <oberon@umich.edu>
-
- * client.c (get_cvs_port_number): Fix typo in comment. Add comments.
- * server.c (server): Fix a FIXME. Remove an errant "const" directive.
- Remove some redundant memory allocation and error handling code.
-
-2002-08-08 Derek Price <oberon@umich.edu>
-
- * import.c (import): Surrounded `server_active' with
- #ifdef SERVER_SUPPORT/#endif.
- * commit.c (commit_fileproc, commit_direntproc): Likewise.
- (Patch from John Tytgat <John.Tytgat@aaug.net>.)
-
-2002-07-31 Derek Price <oberon@umich.edu>
-
- * filesubr.c: Add a line so VIM can determine tab stops and shift widths.
- * root.c: Ditto.
- * (parse_cvsroot): Add comments and tidy slightly.
-
-2002-07-31 Derek Price <oberon@umich.edu>
-
- * sanity.sh: Add another date to the comment about rcs2-7 failing.
-
-2002-07-26 Jim Meyering <meyering@lucent.com>
-
- * commit.c (find_fileproc): When committing in client mode,
- arrange to fail if a `cvs add'ed file no longer exists in the
- working directory.
- * sanity.sh (commit-add-missing): New test for above.
-
-2002-07-25 Larry Jones <lawrence.jones@eds.com>
-
- * sanity.sh: Set $TMPDIR if it's not already set and use it rather
- than /tmp for the expected server temp directory path.
-
-2002-07-09 Larry Jones <lawrence.jones@eds.com>
-
- * vers_ts.c (time_stamp_server, time_stamp): Eliminate unneeded
- struct_tm copying.
-
- * lock.c (lock_wait, lock_obtained): Display time in UTC if possible
- to reduce confusion in client/server mode.
- (Original patch from Eduardo Perez Ureta <eperez@it.uc3m.es>.)
-
-2002-06-26 Larry Jones <lawrence.jones@eds.com>
-
- * tag.c (check_fileproc): When checking up-to-date, T_REMOVE_ENTRY
- is also a valid status.
- (Reported by David Everly <David.Everly@wcom.com>.)
- * sanity.sh (tagc): New tests for above.
-
-2002-06-18 Larry Jones <lawrence.jones@eds.com>
-
- * update.c (patch_file): Don't patch if diff bigger than file.
- Don't bother adjusting the permission on the diff output if
- we're not going to use it.
-
-
-2002-06-18 Derek Price <oberon@umich.edu>
-
- * server.c: Handle HPUX password expiration fields in the passwd
- string in case we are set up on a server with NIS passwords served
- from HPUX.
- (Original patch from John Cavanaugh <john_cavanaugh@agilent.com>.)
-
-2002-06-17 Larry Jones <lawrence.jones@eds.com>
- and Jonathan Kamens <jik@kamens.brookline.ma.us>
-
- * commit.c (commit_fileproc, commit_direntproc): Don't try to call
- an editor to get the log message if running as a server. Instead,
- just use an empty log message.
- * import.c (import): Ditto.
-
- * import.c (import): In client mode, always send a message to the
- server, even if it's empty (this parallels a change made by Larry
- Jones to commit.c on May 7).
-
-2002-05-31 Larry Jones <lawrence.jones@eds.com>
-
- * rcs.c: Conditionally define MAP_FAILED for old systems that don't
- have it in <mman.h>.
- (Reported by jeremy brand <jeremy@earth.care2.com>.)
-
-2002-05-24 Larry Jones <lawrence.jones@eds.com>
-
- * rcscmds.c (diff_exec): Add a -- before the first file name just
- in case it looks like an option.
- (Reported by Zooko <zooko@zooko.com>.)
-
- * rcscmds.c (diff_execv): Remove -- same as diff_exec. Change
- only caller.
- * cvs.h: Ditto.
-
-2002-05-23 Larry Jones <lawrence.jones@eds.com>
-
- * cvs.h (strcat_filename_onto_homedir): Make arguments const.
- * filesubr.c (strcat_filename_onto_homedir): Make arguments const,
- move more code here from callers, change all callers.
-
-2002-05-22 Derek Price <oberon@umich.edu>
-
- * cvs.h: Add prototype for this...
- * filesubr.c (strcat_filename_onto_homedir): new function.
- * login.c (): Use new function.
-
- * cvsrc.c (read_cvsrc): Use new function due to problems on VMS.
- * ignore.c (ign_setup): Ditto.
- * wrapper.c (wrap_setup): Ditto.
- (Original patch from Karsten Spang <ksp@dannet.dk>.)
-
-2002-05-21 Larry Jones <lawrence.jones@eds.com>
-
- * rcs.c (rcsbuf_getkey): Correct off-by-one error in ptr assertion
- and add a similar assertion for ptrend.
- (Reported by Rebecca Young <raygirl@cvshome.org>.)
- (rcsbuf_fill): Remove redundant code.
-
-2002-05-20 Derek Price <oberon@umich.edu>
-
- * buffer.h: New prototype for...
- * buffer.c (stdio_buffer_get_file): this new function to abstract
- access to a buffer's file descriptor.
- * client.c (auth_server): Use the new function.
- (Original patch from Jonathan Kamens <jik@kamens.brookline.ma.us>.)
-
-2002-05-20 Derek Price <oberon@umich.edu>
-
- * main.c (main): Add 2002 to the copyright years output with the
- version string.
-
-2002-05-15 Larry Jones <lawrence.jones@eds.com>
-
- * log.c (log_parse_list): Fix off-by-one error which caused
- incorrect handling of 'cvs log -wuser1,user2 foo.c' command.
- (Patch from Alexey Mahotkin <alexm@hsys.msk.ru>,
- reported by Alex Morozov <morozov@novosoft.ru>.)
-
-2002-05-09 Larry Jones <lawrence.jones@eds.com>
-
- * login.c (password_entry_operation): Get cvsroot_canonical before
- trying to read the user's password file so we have it even if the
- file doesn't exist.
- (Reported by Sarah Thompson <sthompson@fsl.noaa.gov>.)
-
-2002-05-08 Derek Price <oberon@umich.edu>
-
- * Makefile.am (cvs_SOURCES): Add options.h explicitly - since we
- stopped generating it dynamically, Automake stopped noticing it and
- including it in dists. See TODO item #214 for notes.
-
-2002-05-08 Derek Price <oberon@umich.edu>
-
- * cvs.h: Use the HAVE_CONFIG_H define.
-
-2002-05-07 Larry Jones <lawrence.jones@eds.com>
-
- * filesubr.c (isaccessible): Set errno before returning failure
- in the SETXID_SUPPORT code.
-
- * logmsg (do_verify): Avoid even more work if there's no verifymsg
- script to run.
-
- * logmsg: Use fputs/putc rather than fprintf where appropriate.
- (do_verify): Run the verifymsg script even if there's no log
- message. (Reported by Andy Baker <Andy.Baker2@t-mobile.co.uk>.)
- Don't reread the log message unless a verifymsg script was run.
-
- * commit.c (commit): Always send -m to the server, even if there's
- no message.
-
- * create_adm.c (Create_Admin): Add dotemplate parameter to trace.
- Remove unreachable code.
-
-2002-05-03 Larry Jones <lawrence.jones@eds.com>
-
- * server.c (serve_watch_on, serve_watch_off, serve_watch_add,
- serve_watch_remove): Just pass "watch" as the command name
- to do_cvs_command to avoid unknown command errors.
- (Reported by Gary Hennigan <gary@ieee.org>.)
-
- * rcs.c (RCS_checkin): Fix bad call to error () in buggy
- PRESERVE_PERMISSIONS code.
- (rcs_internal_unlockfile): Include current value of errno in error
- message even though it may well be irrelevant (it's still better
- than nothing).
-
-2002-05-02 Derek Price <oberon@umich.edu>
-
- * .cvsignore: Remove lines for files obsoleted by new autotools.
-
-2002-05-02 Derek Price <oberon@umich.edu>
-
- * stamp-h2.in: Remove this uneeded file.
-
-2002-05-01 Derek Price <oberon@umich.edu>
-
- * options.h.in: Move to...
- * options.h: here.
-
-2002-04-30 Derek Price <oberon@umich.edu>
-
- * version.h.in: Remove this file.
- * version.h: Ditto.
-
- * Makefile.am: Remove references to version.h.
- * cvs.h: Use <> rather than "" around the config.h #include. I didn't
- quite bother to understand why, but autoconf recommends it.
- * cvsbug.in: Use PACKAGE_BUGREPORT defined by configure for the bug
- report email address.
- * version.c (version): Use PACKAGE_STRING defined in config.h instead
- of the version_string that used to be defined in version.h.
-
- * Makefile.in: Regenerated with automake 1.6.
-
-2002-04-28 Derek Price <oberon@umich.edu>
-
- * cvs.h: Use `"'s around includes when we mean a local file.
-
-2002-04-28 Derek Price <oberon@umich.edu>
-
- * cvs.h: #define new names for functions and variables when they
- might conflict with system definitions (namely on Mac OS X 10.1 with
- the most recent dev packages - This should be removable after the Mac
- dev packages are fixed.).
-
-2002-04-26 Larry Jones <larry.jones@sdrc.com>
-
- * logmsg.c (do_editor): Fix assertion when CLIENT_SUPPORT not defined.
- (Reported by Matthias Andree <matthias.andree@stud.uni-dortmund.de>.)
-
-2002-04-19 Larry Jones <larry.jones@sdrc.com>
-
- * log.c (log_expand_revlist): First cut at code to allow logging
- between a revision and *any* ancestor, not just one explicitly on
- the same branch (e.g., from 1.1 to 4.1.2.3.6.1).
-
- * subr.c (gca): Simplify and optimize.
-
-2002-04-19 Jim Meyering <meyering@lucent.com>
- and Ed Santiago <easm@lucent.com>
-
- * classify.c (Classify_File): Fix it so that `cvs update -p -r...'
- works, even under some slightly unusual (though perfectly legitimate)
- circumstances.
- * sanity.sh (update-p): New tests for this.
-
-2002-04-18 Derek Price <oberon@umich.edu>
-
- * sanity.sh: Move test for regex metacharacters in username until
- after we're sure we found the version of expr that we're going to use.
-
-2002-04-18 Larry Jones <larry.jones@sdrc.com>
-
- * admin.c (admin_fileproc): Allow admin to be used on RCS files with
- no local version (e.g., removed files) like most other subcommands.
-
- * wrapper.c (wrap_add): Update URL of -t/-f wrapper discussion.
-
-2002-04-18 Derek Price <oberon@umich.edu>
-
- * version.h: Regenerated for 1.11.2.1 version update.
-
-2002-04-17 Derek Price <oberon@umich.edu>
-
- * version.h: Regenerated for 1.11.2.
-
-2002-04-03 Derek Price <oberon@umich.edu>
-
- * stamp-h2.in: Regenerate with recent version of Autoconf.
-
-2002-04-03 Derek Price <oberon@umich.edu>
-
- * sanity.sh (TR): Send the stderr of one of the tool setup (tr) tests
- to /dev/null to avoid spurious output on some operating systems
- (notably Mac OS X).
-
-2002-03-22 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (rcslib): Correct new tests to use ${testcvs} instead
- of cvs.
-
-2002-03-21 Derek Price <oberon@umich.edu>
-
- * vers_ts.c (time_stamp): Return the timestamp for the newer of the
- link and the link's source when the file is a link.
- (Patch from RedHat cvs-1.11.1p1-7 SRPM.)
-
- * sanity.sh (rcslib): Test for same.
-
-2002-03-17 Larry Jones <larry.jones@sdrc.com>
-
- * log.c (cvslog, log_fileproc): Add -S option to suppress head or
- file name if no revisions selected.
- * sanity.sh (log): New tests for above.
-
-2002-03-13 Derek Price <oberon@umich.edu>
-
- * main.c (usg): Correct a spelling mistake in a comment.
- (Thanks to Matt Kraai <kraai@alumni.cmu.edu>.)
-
-2002-03-09 Larry Jones <larry.jones@sdrc.com>
-
- * import.c (import): Change the suggested merge message to use
- rev tags instead of the branch tag with a date.
- * sanity.sh (import, importb): Change to match.
-
- * remove.c (remove_fileproc): Disallow removing files with sticky
- dates for the same reason we already disallow sticky numeric tags.
- * sanity.sh (sticky): New test for above.
-
-2002-02-27 Larry Jones <larry.jones@sdrc.com>
-
- * diff.c (diff_fileproc): Treat dead revisions as nonexistent.
-
-2002-02-26 Larry Jones <larry.jones@sdrc.com>
-
- * diff.c (diff): Remove -V and --paginate options: they aren't valid.
- (diff_usage): Document all the diff options.
-
-2002-02-13 Larry Jones <larry.jones@sdrc.com>
-
- * rcs.c (RCS_gettag): Do not interpret an empty tag as HEAD (nothing
- else does and I don't see any documentation that says it should).
- (translate_symtag): Break out of loop at end of symbols to prevent
- looping forever when tag is "".
- (Reported by Alain ENOUT <aln00@udcast.com>
- via Eric Gillespie <epg@pretzelnet.org>.)
-
-2002-02-11 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (server_cleanup): Set buf_to_net back to blocking mode
- and flush it (in case there are any error messages pending) before
- shutting down buf_from_net and again right before shutting it down.
-
-2002-02-08 Larry Jones <larry.jones@sdrc.com>
-
- * main.c (lookup_command_attribute): Throw a fatal error if the
- command is not found.
- * server.c (server_tag): Use the correct command name.
-
-2002-01-30 Larry Jones <larry.jones@sdrc.com>
-
- * error.h (error_exit): Remove unintended prototype.
-
- * server.c (serve_root): Remove check for impossible condition.
- (serve_init): Save and restore current_parsed_root.
-
-2002-01-29 Larry Jones <larry.jones@sdrc.com>
-
- * error.h (error_exit): Declare __noreturn__ to avoid spurious
- warnings.
-
- * server.c (serve_root): If the specified root doesn't match the
- pserver root, return before changing current_parsed_root to prevent
- subsequent commands from accessing an unchecked root directory.
- (server_init): Check specified root against the pserver root and
- complain if they don't match. Also, if there are pending errors,
- print them and return before changing current_parsed_root to prevent
- subsequent commands from accessing an unchecked root directory.
- * sanity.sh (pserver): New tests for above.
-
-2002-01-10 Larry Jones <larry.jones@sdrc.com>
-
- * log.c (log_version_requested): Change :: in revision spec to be
- exclusive just on the low end (so -r tag1::tag2 gives revisions
- after tag1 but up to and including tag2), which is much more useful
- than the previous (exclusive at both ends) behavior.
- (log_usage): Update to match.
- * sanity.sh (log): Update to match.
-
-2002-01-02 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (LOG_DAEMON): Define if needed.
- (Patch from John David Anglin <dave@hiauly1.hia.nrc.ca>.)
-
- * server.c (pserver_authenticate_connection): Add a specific error
- message for EOF at protocol start and syslog if available.
- * sanity.sh (pserver-bufinit): Update to match.
-
-2001-12-10 Larry Jones <larry.jones@sdrc.com>
-
- * log.c (log_usage): Note that -r and -d take lists, not just a
- single specification.
- (log_expand_revlist): Don't dereference null pointers when one end
- of a revision range is a non-existent tag.
-
-2001-12-03 Larry Jones <larry.jones@sdrc.com>
-
- * annotate.c (annotate, annotate_fileproc): Don't annotate binary
- files unless new -F option given.
- * sanity.sh (basica, ann, ann-id, rcs, keywordlog, tagdate): Update
- to match.
-
-2001-11-30 Larry Jones <larry.jones@sdrc.com>
-
- * admin.c (admin): Allow unrestricted usage of -q in addition to -k.
-
-2001-10-25 Larry Jones <larry.jones@sdrc.com>
-
- * log.c (log_expand_revlist): Make erroneous or inconsistent revision
- specs select no revisions rather than all revisions.
-
-2001-10-23 Larry Jones <larry.jones@sdrc.com>
-
- * import.c (add_rcs_file): Don't put an expand entry into the file
- for the default expansion mode (kv).
- * wrapper.c (wrap_send, wrap_unparse_rcs_options): Process entries
- with default expansion mode since they may be needed to avoid matching
- a more general entry later.
- (wrap_add): Set rcsOption to NULL for default (kv).
- (wrap_add_entry): Use structure assignment to copy entries rather
- that copying members by hand.
- * sanity.sh (binwrap3): Revise to test wrapper entries that don't
- specify any non-default options but just prevent matching later,
- more general entries.
-
-2001-10-02 Larry Jones <larry.jones@sdrc.com>
-
- * rcs.c (RCS_fully_parse): Add revision number to more error messages.
-
-2001-09-27 Larry Jones <larry.jones@sdrc.com>
-
- * rcs.c (RCS_fully_parse, RCS_getdeltatext): Add the missing revision
- number to the "mismatch" error message.
-
- * sanity.sh (multiroot2-9a): Update to match changes to lock.c.
-
-2001-09-26 Larry Jones <larry.jones@sdrc.com>
-
- * lock.c (Lock_Cleanup, Reader_Lock, write_lock): Add trace messages.
-
-2001-09-24 Derek Price <dprice@collab.net>
-
- * find_names.c (add_entries_proc): Leave closure specified as such in the
- function definition for clarity.
-
- * find_names.c (Find_Names): Use 'closure' feature of walklist()
- to eliminate the static variable.
- (add_entries_proc): Expect closure to be the file list.
- (Patch from Alexey Mahotkin <alexm@hsys.msk.ru>.)
-
-2001-09-19 Derek Price <dprice@collab.net>
-
- * rcs.c (rcsbuf_valpolish_internal): Restore one of the
- "if ( ... ) abort();" sequences since it seems to check the validity of
- the RCS file rather than for a programming error. Also added a FIXME
- comment to the effect that we should explain the RCS file error to the
- user as such if it is such.
- (Thanks to Larry Jones <scjones@sdrc.com>.)
-
-2001-09-19 Derek Price <dprice@collab.net>
-
- * rcs.c (rcsbuf_getkey, rcsbuf_valpolish_internal): Replace some code
- of the form "if ( ... ) abort();" with equivalent calls to assert().
-
-2001-09-17 Derek Price <dprice@collab.net>
-
- * myndbm.c (mydbm_load_file): Fix buffer overflow error and make error
- messages more informative.
- * sanity.sh (modules6): New test.
- (Original report from Taska <taska@collab.net> and others.)
-
-2001-09-14 Derek Price <dprice@collab.net>
-
- * logmsg.c (do_verify): Dispose memory when finished with it.
-
-2001-09-07 Larry Jones <larry.jones@sdrc.com>
-
- * mkmodules.c (notify_contents): In the example, move the %s to
- the end since many, if not most, versions of mail insist on
- options coming before addresses.
-
-2001-09-06 Derek Price <dprice@collab.net>
-
- * login.c (login): Deal with NULL return value from getpass.
-
-2001-09-04 Derek Price <dprice@collab.net>
-
- * Makefile.in: Regenerated with automake 1.5.
- * stamp-h2.in: Ditto.
-
-2001-09-04 Derek Price <dprice@collab.net>
-
- * main.c (main): Fix empty CVSROOT message to specify `valid' instead
- of `legal'.
-
-2001-09-04 Derek Price <dprice@collab.net>
-
- * server.c (pserver_authenticate_connection): Back out changes from the
- 30th and...
- * getline.c (getstr): init the buffer instead.
-
-2001-08-31 Derek Price <dprice@collab.net>
-
- * Makefile.in: Backed out accidental commit from yesterday.
-
-2001-08-30 Derek Price <dprice@collab.net>
-
- * server.c (pserver_authenticate_connection): Don't print from the
- NULL pointer in the error message string in the case where the client
- didn't send any data.
- * sanity.sh (pserver): Test for this case.
- (Report from Mark Welch <mark@collab.net>).
-
-2001-08-24 Derek Price <dprice@collab.net>
-
- * logmsg.c (do_editor): Add comment and assertion.
- * import.c (import): Don't call do_editor with a repository argument
- in client mode.
- (Report and original patch from darkness <darkness@invado.com>.)
-
-2001-08-24 Larry Jones <larry.jones@sdrc.com>
-
- * log.c (log_expand_revlist): Arrange for nil revision specs to
- select nothing instead of everything.
- * sanity.sh (log): New tests for above.
-
-2001-08-24 Derek Price <dprice@collab.net>
-
- * parseinfo.c (Parse_Info): Change the function name in the trace
- and add the client/server string.
-
-2001-08-24 Derek Price <dprice@collab.net>
-
- * Implement RereadLogAfterVerify CVSROOT/config option to control
- FreeBSD read-write of log messages in the verification script.
- * logmsg.c: RereadLogAfterVerify defaults to LOGMSG_REREAD_NEVER
- to preserve the status quo.
- * parseinfo.c (parse_config): Add parsing for RereadLogAfterVerify
- option. Possible values are: no | never | yes | always | stat
- * cvs.h: Add extern for RereadLogAfterVerify and new value macros
- LOGMSG_REREAD_NEVER, LOGMSG_REREAD_ALWAYS, LOGMSG_REREAD_STAT for
- its values.
- (Patch from Mark D. Baushke <mdb@cvshome.org>.)
-
- * Apply changes from FreeBSD cvs sources to implement a read-write
- user-defined verification script.
- * logmsg.c (do_verify): Update do_verify to expect a pointer
- to the saved message. The log file passed to the verifymsg_script
- should be re-read after the user-defined verification script has
- been run. The user-defined verification script is allowed to
- modify the message. This allows the script to add extra
- information to the log message or to remove template lines that
- are not needed.
- * cvs.h: Update prototype for do_verify prototype to expect a
- pointer to the saved_message.
- * commit.c (commit, commit_fileproc, commit_direntproc): Update
- calls to do_verify as the saved_message arg is now read-write.
- * import.c (import): Update calls to do_verify as the
- saved_message arg is now read-write.
- * sanity.sh (info-v4-[12]): Rename the old info-v4 test to info-v5
- and add a new info-v4 test case have the verification script
- modify the log message to test the above changes.
- (Patch from Mark D. Baushke <mdb@cvshome.org>.)
-
- * logmsg.c: Change RereadLogAfterVerify default to always.
- (do_verify): Reformat and make minor fixes to Mark's patch.
- * mkmodules.c (config_constants): Add comment about
- RereadLogAfterVerify.
- * sanity.sh (info-rereadlog): Rename the tests from Mark's patch and
- reformat them a bit.
-
-2001-08-23 Derek Price <dprice@collab.net>
-
- * sanity.sh (info): Demonstrate that the verifymsg scripts can
- sometimes, but not always, retreive information on which directory is
- being committed to.
-
-2001-08-22 Derek Price <dprice@collab.net>
-
- * logmsg.c: Back out the last change - the repository which is passed
- in is actually the directory and changes with each call to do_verify.
- If a verifymsg script is using `pwd`, this could change the operation.
- * cvs.h: Ditto.
- * commit.c: Ditto.
- * import.c: Ditto.
-
-2001-08-22 Derek Price <dprice@collab.net>
-
- * logmsg.c (do_editor): Return reused_message.
- (do_verify): Don't verify the same log message more than once.
- * cvs.h: Update prototypes for do_verify and do_editor.
- * commit.c (commit_fileproc, commit_direntproc): Use the new functionality.
- * import.c (import): Ditto.
-
-2001-08-22 Derek Price <dprice@collab.net>
-
- * logmsg.c (do_verify): Remove an unecessary "else" clause following an
- exit and unindent the former contents.
-
-2001-08-22 Derek Price <dprice@collab.net>
-
- * commit.c (commit): Don't call do_verify in client mode since we know
- do_verify will just return anyhow.
-
-2001-08-20 Derek Price <dprice@collab.net>
-
- * Makefile.am (cvs_SOURCES): Add version.c and version.h.
- (BUILT_SOURCES): Add version.h.
- (Maintainer Targets): Remove version.h.
- * version.c: Remove @VERSION@ dependant bits.
- * version.c.in: Removed.
- * version.h.in: New file.
- (Original patch from Alexey Mahotkin <alexm@hsys.msk.ru>.)
-
- * Makefile.am: Various modifications to make Automake, make dist, and
- windows targets work like they are supposed to.
- * version.h: New (generated) file.
-
- * Makefile.in: Regenerated.
-
-2001-08-09 Derek Price <dprice@collab.net>
-
- * client.c (socket_buffer_shutdown): Use recv instead of read and
- return 0 on success.
- (Patch from "Manfred Klug" <manklu@web.de>.)
-
-2001-08-09 Derek Price <dprice@collab.net>
-
- * buffer.c (stdio_buffer_shutdown): Assume the buffer is not a socket
- when NO_SOCKET_TO_FD is defined.
- * client.c (make_bufs_from_fds): Add is_sock argument and remove fstat
- call and reference to S_ISSOCK since these functions aren't available
- under Windows.
- (connect_to_forked_server, connect_to_pserver, start_tcp_server,
- start_server, start_rsh_server): Use new argument.
- (Patch from "Manfred Klug" <manklu@web.de>.)
-
- * buffer.c (stdio_buffer_shutdown): Various reformattings, fix bug
- where rsh pipes weren't being closed.
-
-2001-08-09 Derek Price <dprice@collab.net>
-
- * sanity.sh (rmadd, rm-update-message, join-two-branch,
- ignore-on-branch): Change a few references to `cvs' to `$PROG'.
-
-2001-08-07 Derek Price <dprice@collab.net>
-
- * build_src.com: Add annotate.c/annotate.obj,verify, correct zlib name.
- * patch.c: VMS time_t appears to be unsigned. Add a cast when testing
- for (time_t)-1.
- * subr.c: #else,#endif for no symlinks should be moved.
- (Patch from Mike Marciniszyn <Mike.Marciniszyn@sanchez.com>.)
-
-2001-08-06 Derek Price <dprice@collab.net>
-
- * Makefile.in: Regenerated.
-
-2001-08-01 Derek Price <dprice@collab.net>
-
- * diff.c (diff): Send long option for side-by-side diffs to the server
- rather than '-y', for backwards compatibility with old servers.
- (Original patch from Peter Mathiasson <peter@mathiasson.nu>.)
-
-2001-07-19 Larry Jones <larry.jones@sdrc.com>
-
- * mkmodules.c (cvswrappers_contents): Remove -t/-f since they're
- disabled in wrapper.c.
-
- * checkout.c (checkout): Don't complain about checking out into the
- repository when piping output.
- (Reported by der Mouse <mouse@Rodents.Montreal.QC.CA>.)
- * sanity.sh (checkout_repository): New tests for above.
-
-2001-07-10 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (importc-7): Now works correctly in local mode.
-
- * commit.c (commit_dirleaveproc): We're still in the directory when
- this is called, so the first argument to Name_Repository needs to
- be NULL, not dir.
- * sanity.sh (rmadd): New tests for above.
-
- * commit.c (commit): Reword error messages for committing as root.
-
-2001-07-08 Larry Jones <larry.jones@sdrc.com>
-
- * rcs.c (RCS_checkout): Correct scanf format to allow for trailing
- NUL terminator.
- * update.c (special_file_mismatch): Ditto.
- (Reported by Pekka Savola <pekkas@netcore.fi>.)
-
-2001-07-05 Larry Jones <larry.jones@sdrc.com>
-
- * client.c, root.c: Fix -Wall warnings.
-
- * buffer.c: #include socket header to declare shutdown().
-
- * rcs.c (rcsbuf_open): Use getpagesize() instead of sysconf() for
- portability.
- (RCS_copydeltas, rcsbuf_fill): Fix -Wall warnings.
-
-2001-07-04 Derek Price <dprice@collab.net>
-
- * Makefile.in: Regenerated with new Automake release candidate 1.4h.
-
-2001-07-03 Derek Price <dprice@collab.net>
-
- * rcs.c (rcsbuf_open): Reduce memory consumption still further by not
- mmapping the entire file when pos is specified.
- (rcsbuf_cache_open): Add FIXME comment wrt read-only mmaps and rcsbuf
- caching.
-
-2001-07-03 Derek Price <dprice@collab.net>
-
- * rcs.c (rcsbuf_open): Use mmap when possible to reduce memory
- consumption, especially with large (e.g. binary) files.
- (rcsbuf_close): Call munmap.
- (rcsbuf_getkey): Remove the buffer fill code when using mmap.
- (rcsbuf_getrevnum): Ditto.
- (rcsbuf_fill): Remove this function when using mmap.
- (rcsbuf_cache_open): Mostly don't use this function with mmap.
- (RCS_copydeltas): Don't depend on the file pointer with mmap.
-
- * stamp-h2.in: Regenerated.
-
-2001-07-03 Derek Price <dprice@collab.net>
-
- * update.c: Indent compiler directives.
-
-2001-07-02 Larry Jones <larry.jones@sdrc.com>
-
- * import.c (update_rcs_file): Use -kb instead of -ko when comparing
- binary files.
- (Reported by Gyula Faller <gfaller@graphisoft.hu>.)
-
-2001-06-28 Larry Jones <larry.jones@sdrc.com>
-
- * checkout.c (checkout): Explicitly initialize all the static options
- so that multiple calls work right. Also fix potential memory leaks.
- (Reported by Dr. Dieter Maurer <dieter@sz-sb.de>.)
-
-2001-06-28 Derek Price <dprice@collab.net>
-
- * Makefile.in: Regenerated with new version of Automake.
-
-2001-06-28 Larry Jones <larry.jones@sdrc.com>
-
- * checkout.c (checkout): Set history_name for export as well as
- checkout.
- (checkout_proc): Use it.
-
- * checkout.c (safe_location): Add missing argument in error message.
-
-2001-06-26 Larry Jones <larry.jones@sdrc.com>
-
- * recurse.c (start_recursion): Use strip_trailing_slashes instead
- of doing it by hand.
-
- * server.c (pserver_authenticate_connection): Don't clear out
- descrambled_password until *after* it's (potentially) logged.
- (Reported by Eric Hanchrow <offby1@blarg.net>.)
-
-2001-06-25 Larry Jones <larry.jones@sdrc.com>
-
- * recurse.c (start_recursion): Deal with at least some of the cases
- where trailing slashes cause confusion.
- (Reported by Malcolm Fernandes <fernande@redback.com>.)
- * sanity.sh (basica, basicb): Tweak existing tests to check this.
-
-2001-06-22 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (modules5): New tests with -d on command line.
-
-2001-06-21 Larry Jones <larry.jones@sdrc.com>
-
- * modules.c (do_module): Use run_module_prog and server_active to
- determine when to call server_prog instead of using server_expanding
- so that we get the right paths in the replies as long as we take
- mwhere into account in addition to where.
- (Reported by Pascal Bourguignon <pjb@informatimago.com>.)
- * server.c (server_prog): Use protocol pipe instead of buf_to_net.
- * sanity.sh (modules5): Remove FIXCVS comment and update to match.
- * server.c, server.h: Remove server_expanding since now unused.
-
-2001-06-21 Larry Jones <larry.jones@sdrc.com>
- for Stephen Rasku <stephen@tgivan.com>
-
- * admin.c: Corrected spelling mistakes in help.
-
-2001-06-20 Derek Price <dprice@collab.net>
-
- * client.c (socket_buffer_shutdown): Fix untested typos.
- (Reported by "Jerzy Kaczorowski" <jerzyk@wndtabs.com>.)
-
- * buffer.c (stdio_buffer_shutdown): Put the call to SHUTDOWN_SERVER in
- the correct place.
-
-2001-06-20 Derek Price <dprice@collab.net>
-
- * logmsg.c (do_editor): Abort in the case that the file has only
- comment lines.
- (Original patch from Mark Valentine <mark@thuvia.demon.co.uk>.)
-
- * logmsg.c (do_editor): Fix rare memory leak.
- * sanity.sh (editor): Add tests for aborted log messages.
-
-2001-06-20 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (switch_to_user): Only set $CVS_USER if
- AUTH_SERVER_SUPPORT is defined.
- (Reported by Nalin Dahyabhai <nalin@blade.devel.redhat.com>.)
-
-2001-06-13 Derek Price <dprice@collab.net>
-
- * client.c: Fix incorrect fixed-size buffer usage in
- connect_to_gserver().
- (Minor changes to a patch from Alexey Mahotkin <alexm@hsys.msk.ru>.)
-
-2001-06-11 Derek Price <dprice@collab.net>
-
- * main.c (main): Always print $CVSROOT when parse_cvsroot fails.
- * root.c (parse_cvsroot): Tidy error messages and provide more
- consistent behavior.
- * sanity.sh (crerepos): Adapt to new error messages.
- (Suggested by Alexey Mahotkin <alexm@hsys.msk.ru>.)
-
-2001-06-08 Derek Price <dprice@collab.net>
-
- * sanity.sh (tagf-28): Use $CVSROOT_DIRNAME.
-
-2001-06-07 Larry Jones <larry.jones@sdrc.com>
-
- * rcs.c (RCS_unlock): Reverse kj's change of 1999-10-18: a bare -u
- should never break locks, you have to specify a specific revision
- to do that. Also add an informative message for a bare -u when
- the user doesn't hold any locks.
- * commit.c (unlockrcs): Make RCS_unlock quiet, like RCS_lock.
- * sanity.sh (rmadd-24): Update to match.
-
- * sanity.sh (crerepos-6a): Set CVS_RSH for ${testcvs}, not for
- dotest_fail. Allow for "broken pipe" rather than "end of file".
-
-2001-06-07 Derek Price <dprice@collab.net>
-
- * sanity.sh (tagf): Use $CVSROOT_DIRNAME rather than
- /tmp/cvs-sanity/cvsroot.
-
-2001-06-06 Derek Price <dprice@collab.net>
-
- (Reformatting, bug fixes, tests, and comments to a
- patch from Stephen Cameron <steve.cameron@compaq.com>.)
-
- * tag.c: (rtag_fileproc, rtag_delete, tag_fileproc)
- Changed behavior of "cvs tag -F", "cvs tag -d", "cvs rtag -F"
- and "cvs rtag -d" so that they will not disturb existing
- branch tags unless a new "-B" option is given.
- * sanity.sh (tagf-16 - tagf-33): Added tests for new -B option
- to "cvs tag" and "cvs rtag"
-
-2001-06-06 Derek Price <dprice@collab.net>
-
- * sanity.sh (crerepos-6a): Set CVS_RSH=false and only for the actual
- test call at Larry's suggestion. Also, test the error message since
- it's fixed now.
-
-2001-06-05 Larry Jones <larry.jones@sdrc.com>
-
- * rcs.c (RCS_unlock): Note when breaking someone else's lock.
- (Reported by MURVAI-BUZOGANY Laszlo
- <Laszlo.MURVAI-BUZOGANY@gt-systems.hu>.)
- * sanity.sh (reserved-14): Update to match.
-
-2001-06-05 Derek Price <dprice@collab.net>
-
- * sanity.sh (crerepos-6a): Set CVS_RSH=/bin/false... this is a local
- mode only test anyhow.
- (Thanks to Larry Jones and Morgan Burke <morgan@sitka.triumf.ca>.)
-
-2001-05-31 Derek Price <dprice@collab.net>
-
- * sanity.sh (rcs2-7): Add today to the list of failure dates for rcs2-7
- in the hopes that the data will eventually prove useful to someone
- motivated enough to fix the problem.
-
-2001-05-30 Derek Price <dprice@collab.net>
-
- * stamp-h2.in: Regenerated.
-
-2001-05-30 Derek Price <dprice@collab.net>
-
- * *: Various bug fixes and comments for the following
- patch from Donald Sharp <sharpd@cisco.com>:
-
- * checkout.c (safe_location): cvs co -d <directory> still had
- failure modes from the way the -d option works.
- * sanity.sh: Misc error message resynching.
-
-2001-05-29 Derek Price <dprice@collab.net>
-
- * Makefile.am (cvs_SOURCES): Add root.h.
-
- * Makefile.in: Regenerated.
- * stamp-h2.in: Regenerated.
-
-2001-05-29 Derek Price <dprice@collab.net>
-
- * checkout.c (safe_location): Correct formatting.
-
-2001-05-29 Derek Price <dprice@collab.net>
-
- * root.c (parse_cvsroot): Fix a comment.
-
-2001-05-26 Larry Jones <larry.jones@sdrc.com>
-
- * checkout.c (safe_location): Use old-style definition to keep
- non-ANSI compilers happy.
-
- * sanity.sh (check_respository): Use ${CVSROOT_DIRNAME} instead
- of /tmp/cvs-sanity/cvsroot.
-
-2001-05-25 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (modules5): Add sleep to script to help avoid out of
- order messages.
-
- * filesubr.c (mkdir_if_needed): Return 1 if the directory exists
- reguardless of what errno is set to.
- (Reported by "Robinson, Greg" <greg.robinson@dsto.defence.gov.au>.)
-
-2001-05-25 Derek Price <dprice@collab.net>
- for Donald Sharp <sharpd@cisco.com>
-
- * checkout.c: Modified safe_location() to refuse checkout if
- the -d option to co specifies inside of the repository.
- * import.c: New parameter to safe_location needed to be added.
- * cvs.h: New parameter to safe_location needed to be added.
- * sanity.sh: Test case to test for failure mode.
-
-2001-05-23 Larry Jones <larry.jones@sdrc.com>
-
- * checkout.c (checkout_proc): Don't build top_level_admin directory
- when exporting.
- (Reported by Tony Byrne <tonyb@directski.com>.)
-
-2001-05-21 Derek Price <dprice@collab.net>
-
- * client.c: Fix a mispelling in a comment.
- (Patch from Alexey Mahotkin <alexm@hsys.msk.ru>).
-
-2001-05-05 Larry Jones <larry.jones@sdrc.com>
-
- * login.c (password_entry_operation): Only warn if unable to open
- .cvspass for reading: may be initial login and it doesn't exist yet.
-
-2001-05-15 Derek Price <dprice@collab.net>
-
- * client.c (start_tcp_server): Use the struct sockaddr_in declared in
- the function.
- (Reported by Emil Isberg <isberg@dynarc.se>.)
-
-2001-05-05 Larry Jones <larry.jones@sdrc.com>
-
- * annotate.c (annotate): Pass local to do_module and rannotate_proc
- so that -l actually works.
- * log.c (cvslog): Ditto.
- * patch.c (patch): Ditto; make local local instead of global.
- (patch_proc): Use local_specified parameter instead of global.
- * tag.c (cvstag, rtag_proc): Ditto.
-
-2001-05-05 Larry Jones <larry.jones@sdrc.com>
-
- * client.h: Declare "struct buffer" outside prototype for __STDC__
- compilers.
-
-2001-05-04 Derek Price <dprice@collab.net>
-
- * client.c: General refactoring. Removed several global variables in
- favor of passing locals and/or dynamic evaluation.
- (recv_line): Removed this function.
- (make_bufs_from_fds): New function with factored code.
- (connect_to_forked_server): New prototype. Use new functions.
- (connect_to_pserver): New prototype. Use new functions.
- (connect_to_gserver): New prototype. Use new API.
- (auth_server): Factored this portion of the pserver code so it can be
- shared. Rewrote to use buffers rather than depending on a socket.
- (start_rsh_server): New prototype. Use new API.
- (start_tcp_server): New prototype. Use new API.
- (start_server): Factor some code. Use new API.
- * client.h: New prototypes.
- * cvs.h: Gratuitous reformatting. Use new root.h.
- * login.c (login): Use new connect_to_pserver API.
- * root.h: New file. Contains some code that used to be in cvs.h.
-
-2001-05-04 Derek Price <dprice@collab.net>
-
- * client.c: Gratuitous reformatting.
- * client.h: Ditto.
-
-2001-05-04 Derek Price <dprice@collab.net>
-
- * zlib.c (compress_buffer_shutdown_input): Use new buffer shutdown
- prototype.
- (compress_buffer_shutdown_output): Ditto.
- (Thanks to Pavel Roskin <proski@gnu.org>.)
-
-2001-05-03 Derek Price <dprice@collab.net>
-
- * buffer.c (struct stdio_buffer_closure): New structure to hold a
- FILE * and the child's PID when necessary.
- (stdio_buffer_initialize): Change proto to accept PID. Set up new
- closure. Pass new stdio_buffer_shutdown to buf_initialize.
- (stdio_buffer_input): Use new closure.
- (stdio_buffer_output): Ditto.
- (stdio_buffer_flush): Ditto.
- (stdio_buffer_shutdown): New function. Teach buffer to close itself.
- (packetizing_buffer_shutdown): Use new buffer shutdown proto.
- * buffer.h (struct buffer): New buffer shutdown proto.
- (stdio_buffer_initialize): New proto.
- * client.c (log_buffer_shutdown): Use new proto.
- (socket_buffer_initialize): Pass shutdown func.
- (socket_buffer_shutdown): New function.
- * server.c (get_responses_and_close): Remove most of the guts. Rely
- on the buffer shutdown function from now on.
- (start_rsh_server): Return child PID.
-
-2001-05-03 Larry Jones <larry.jones@sdrc.com>
-
- * history.c (history_write): Handle the case where the user's home
- directory doesn't exist gracefully instead of erroring out.
- (Reported by David Hoover <dhoover@cadence.com>.)
-
-2001-05-03 Derek Price <dprice@collab.net>
-
- * cvs.h: s/allocate_and_strcat/xrealloc_and_strcat/ since that is what
- I wrote in the ChangeLog, oh, so long ago.
- * diff.c (diff): Ditto.
- * subr.c (allocate_and_strcat, xrealloc_and_strcat): Ditto.
-
-2001-05-02 Larry Jones <larry.jones@sdrc.com>
-
- * rcs.c (RCS_getdate): Handle the (unusual!) case where we
- can't find any revisions at all.
- (Reported by Ryan Grow <rgrow@Dbdoctor.net>.)
-
-2001-04-30 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (multiroot2-9a): Rename (from multiroot2-9) to avoid
- duplicate names; fix to work without SERVER_SUPPORT defined.
- (Reported by Pavel Roskin <proski@gnu.org>.)
-
-2001-04-29 Derek Price <dprice@collab.net>
-
- * Makefile.am (check-local): Make dependent on localcheck and
- remotecheck and move old check target...
- (localcheck): here.
-
- * Makefile.in: Regenerated.
-
-2001-04-27 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (pserver): Add tests for readers and writers.
-
-2001-04-27 Derek Price <dprice@collab.net>
-
- * sanity.sh (version-2r): Update to handle patch releases in version
- numbers.
-
-2001-04-27 Derek Price <dprice@collab.net>
-
- * version.c: Regenerated.
-
-2001-04-27 Derek Price <dprice@collab.net>
-
- * version.c: Regenerated.
-
-2001-04-27 Larry Jones <larry.jones@sdrc.com>
-
- * main.c (lookup_command_attribute): Lookup specified command, not
- whatever's in the global command_name.
-
-2001-04-25 Derek Price <dprice@collab.net>
-
- * Makefile.in: Regenerated using AM 1.4e as of today at 18:10 -0400.
- * version.c: Regenerated.
-
-2001-04-22 Larry Jones <larry.jones@sdrc.com>
-
- * tag.c (tag_check_valid): Make an unwritable val-tags file a
- warning instead of a fatal error.
-
-2001-04-20 Larry Jones <larry.jones@sdrc.com>
-
- * annotate.c (annotate_usage): -r and -D are not mutually exclusive.
- * main.c (cmd_usage): Add missing version subcommand.
- * update.c (update_usage): Add missing -C option.
-
- * sanity.sh (death2): New tests for previous change.
-
- * classify.c (Classify_File): Treat a dead revision like the RCS
- file doesn't exist.
- * sanity.sh: Update to match.
-
-2001-04-16 Larry Jones <larry.jones@sdrc.com>
-
- * checkout.c, update.c: Fix usage messages: -r and -D are not
- mutually exclusive.
- (Suggested by David L. Martin <dlmart2@home.com>.)
-
- * logmsg.c (do_editor): Don't add a blank line to the message.
- * sanity.sh (editor-log-file*): Update to match.
-
- * checkout.c, update.c: Note in usage message that -k is sticky.
-
- * server.c: (server_cleanup, wait_sig): Remove ancient SunOS kludge.
- (Suggested by Rob Saccoccio <robs@chelsea.net>.)
-
-2001-04-04 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (dotest, dotest_lit, dotest_fail, dotest_status,
- dotest_sort): Don't count on $? being set in then or else clauses.
-
- * ignore.c (ignore_files): Collect unignored files into a list and
- sort it before calling PROC to avoid order dependencies. Rewrite
- the while loop to allow normal continues instead of goto.
-
-2001-04-04 Derek Price <dprice@collab.net>
-
- * sanity.sh (ignore-on-branch-3): Fix in the remote case.
-
-2001-04-03 Larry Jones <larry.jones@sdrc.com>
-
- * update.c (update_fileproc): Remove unused variable (resurrecting).
-
-2001-04-03 Derek Price <dprice@collab.net>
- Larry Jones <larry.jones@sdrc.com>
- reported by Jakob Bøhm <JB@Danware.dk>
-
- * update.c (update_fileproc): Don't store a file with T_UNKNOWN status
- in ignlist if present in the sandbox.
- * sanity.sh (ignore-on-branch): New test.
- (ignore): Tidy this test.
-
-2001-04-02 Derek Price <dprice@collab.net>
-
- * sanity.sh: Make sure the test for `id' fails when a nonstandard `id'
- is used and the user is root. Fix some quoting in error messages.
- (fork): Take `cvs' out of the PATH.
- (TODO): Add note about the test suite not working with user names over
- eight characters in length.
-
-2001-04-02 Derek Price <dprice@collab.net>
-
- * sanity.sh (fork): New test for CVS_SERVER default.
- (TODO): Note about eventually removing most of the references to
- CVS_SERVER.
-
-2001-04-02 Larry Jones <larry.jones@sdrc.com>
-
- * client.c (connect_to_forked_server): Use program_path as the default
- server instead of "cvs".
-
-2001-04-02 Derek Price <dprice@collab.net>
-
- * sanity.sh: Use less obfuscated English in my comment about sanity
- checking sanity.sh.
-
-2001-04-02 Derek Price <dprice@collab.net>
-
- * sanity.sh (rm-update-message): Create a test directory again but
- change back to the correct directory upon completion this time.
-
-2001-04-02 Derek Price <dprice@collab.net>
-
- * sanity.sh: Change last two '[.*]'s to 'test's for
- consistency and remove...
- (TODO): the note from the TODO list.
-
-2001-04-02 Derek Price <dprice@collab.net>
-
- * sanity.sh: Add test for PWD before successful exit.
-
-2001-03-30 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (rm-update-message): Remove duplicate code.
-
-2001-03-30 Derek Price <dprice@collab.net>
-
- * sanity.sh (rm-update-message): New test for local/client-server
- warning message discrepency.
-
-2001-03-30 Larry Jones <larry.jones@sdrc.com>
-
- * annotate.c: Move annotate() here from rcs.c, support rannotate.
- * Makefile.am, Makefile.in: Add annotate.c.
- * main.c (cmds[], cmd_usage[]): Add rannotate.
- * rcs.c: Move declarations of rcs_delta_op and RCS_deltas to...
- * rcs.h: ... here.
- * server.c (serve_rannotate): New.
- (requests[]): Add rannotate.
- * sanity.sh (ann): New tests for rannotate.
-
- * log.c (rlog_proc): Remove dead code.
-
-2001-03-30 Derek Price <dprice@collab.net>
-
- * sanity.sh (join-readonly-conflict): Run more of this through dotest.
-
-2001-03-30 Larry Jones <larry.jones@sdrc.com>
-
- * log.c (log_fileproc): Don't output working file for rlog.
- * sanity.sh (log): New tests for rlog.
-
- * cvs.h (mtype): Add MISC type.
- * log.c (cvslog): Support rlog as well as log.
- (rlog_proc): New.
- * main.c (cmds[], cmd_usage[]): Add rlog.
- (main): Remove old rlog warning message.
- * server.c (serve_rlog): New.
- (requests[]): Add rlog.
-
-2001-03-29 Derek Price <dprice@collab.net>
-
- * sanity.sh: cd to $TESTDIR once after it is normalized. Make TODO
- on history and symlinks more specific. Tested properly this time.
-
-2001-03-29 Larry Jones <larry.jones@sdrc.com>
-
- * main.c (cmds[], lookup_command_attribute, main): Include the
- command attributes in the global command table instead of inferring
- them from the command names. Change the sense of the
- CVS_CMD_IGNORE_ADMROOT attribute to match its name.
-
-2001-03-29 Derek Price <dprice@collab.net>
-
- * sanity.sh (*, basic2-64): Remove references to TMPPWD. Fix FIXME
- at end of script now that $TESTDIR can't be relative.
-
-2001-03-29 Derek Price <dprice@collab.net>
-
- * sanity.sh: Normalize TESTDIR even when the user set it.
-
-2001-03-29 Larry Jones <larry.jones@sdrc.com>
-
- * client.c (connect_to_pserver, start_tcp_server): Add IP address
- to connect failed message.
- (connect_to_forked_server, connect_to_pserver, start_tcp_server): Add
- trace messages ala start_rsh_server.
- (start_rsh_server): Include entire command in trace message for
- START_RSH_WITH_POPEN_RW like ! START_RSH_WITH_POPEN_RW does.
-
-2001-03-29 Derek Price <dprice@collab.net>
-
- * sanity.sh: Global search & replace ${TESTDIR}/cvsroot with
- ${CVSROOT_DIRNAME} for consistency.
-
-2001-03-29 Derek Price <dprice@collab.net>
-
- * sanity.sh (conflicts-12[68].5): Remove sanity hack which has allowed
- for a CVS bug since May 96/97. Not sure when the bug went bye-bye, but
- the tests broke when $TESTDIR != $TMPPWD.
-
-2001-03-26 Larry Jones <larry.jones@sdrc.com>
-
- * classify.c (Classify_File): Don't report a conflict for a removed
- file when piping. Also simplify the code structure.
- (Reported by Milos Kleint <milos.kleint@netbeans.com>.)
- * sanity.sh (rmadd2-14[abc]): New tests for above.
-
-2001-03-24 Noel Cragg <noel@shave.cnet.com>
-
- * diff.c: mods to allow `-T' and `-y' options to be passed through
- to the diff library. This wasn't allowed earlier because of a
- similarly named options that got passed through to the old rcs
- programs. We've long since stopped sending `-T' to any rcs
- utility and have never used `-y'. Any users of moldly CVS
- versions which used to support `-T' have (hopefully) upgraded to
- one where that option isn't supported. It seems reasonable to
- enable them again and pass them through. (sanity.sh still works
- anyways...)
- (longopts): add short option equivalents for --initial-tab and
- --side-by-side.
- (diff): add new short options to getopt string and switch
- statement.
-
-2001-03-22 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh: Add check for ${DOTSTAR} with large matches.
-
-2001-03-23 Derek Price <dprice@collab.net>
-
- * sanity.sh: Do the same as below for $keep.
-
-2001-03-23 Derek Price <dprice@collab.net>
-
- * sanity.sh: Replace 'remote=(yes|no)' with 'remote=(:|false)' since
- often 'false' and more often ':' are shell builtins. This makes the
- succinct, 'if $remote; then' faster than 'if test $remote = yes; then'.
- Alter tests in the rest of the script to match the new usage. Added
- a suffix of 'r' to remote test names when it was appropriate and I
- remembered. Some reformatting.
-
-2001-03-22 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (diffmerge1_yours, diffmerge1_mine): Check for exact
- output instead of using wildcards to avoid buffer overflows in some
- versions of expr.
-
-2001-03-21 Derek Price <dprice@collab.net>
-
- * sanity.sh: cd to '/tmp' again rather than $HOME since HOME was set to
- a value inside ${TESTDIR} by the script.
-
-2001-03-20 Derek Price <dprice@collab.net>
-
- * sanity.sh (diffmerge1): Minor formatting and syntax changes.
-
- for Jacob Burckhardt <bjacob@ca.metsci.com>
-
- * sanity.sh (diffmerge1): More merging behavior tests. Specifically,
- test some cases which broke before in Karl Tomlinson's diff fix was
- checked in today.
-
-2001-03-20 Derek Price <dprice@collab.net>
-
- * sanity.sh: Don't use unescaped parens in sh outside of quotes.
-
-2001-03-20 Derek Price <dprice@collab.net>
-
- * sanity.sh: Don't remove ${TESTDIR} when -k (keep) set.
-
-2001-03-20 Derek Price <dprice@collab.net>
-
- * sanity.sh: Change usage to match the new getopts format and comment.
-
-2001-03-16 Derek Price <dprice@collab.net>
-
- * sanity.sh (modules2-nestedrename): New test. Verifies behavior of
- renames nested under an ampersand module.
- (modules2-ampertag): New test. Verifies an error condition which
- prevents some ampersand modules from being checked out when a tag
- is specified.
-
-2001-03-16 Derek Price <dprice@collab.net>
-
- * sanity.sh (modules2): Additional test for ampersand module behavior
- with '-d'.
-
- for Greg Klanderman <greg@itasoftware.com>
-
- * checkout.c (build_one_dir): Fix typo where clauses of two
- conditionals were reversed in call to Create_Admin. This caused
- the CVS/Tag file to be removed in cases where it should have been
- set, and vice-versa. It only surfaced in rare cases as this code
- is only invoked when using the -d option to build the path to
- check out in. Further, the bug would only matter when checking
- out a module containing ampersand modules within it, via
- client/server CVS.
-
-2001-03-16 Derek Price <dprice@collab.net>
-
- * sanity.sh (admin-28-5): Confirm that a missing tag during an
- 'admin -n' operation is not a fatal error.
-
-2001-03-16 Derek Price <dprice@collab.net>
-
- * admin.c (admin_data): Remove 'quiet' member.
- (admin_fileproc): Use global 'really_quiet' rather than
- admin_data->quiet.
-
-2001-03-16 Derek Price <dprice@collab.net>
-
- * sanity.sh (admin): Replace hardcoded testdir path with the variable.
-
-2001-03-15 Derek Price <derek.price@openavenue.com>
-
- * sanity.sh (basica, binfiles, head, admin): Adjust for new messages.
- * admin.c (admin_fileproc): Only print messages when not in
- really_quiet mode.
-
- for Stephen Rasku <stephen@tgivan.com>
-
- * rcs.c (RCS_tag2rev): Make a missing tag a survivable error.
-
-2001-03-15 Larry Jones <larry.jones@sdrc.com>
-
- * subr.c (sleep_past): Fix various bugs that would result in a
- negative sleep time if it weren't unsigned; since it is, it would
- result in a very large sleep time. Ensure that us is always less
- than 1000000. Don't try to sleep for more 1 sec with usleep.
- Cast NULL select arguments to correct type just in case.
-
-2001-03-14 Derek Price <derek.price@openavenue.com>
-
- * subr.c (sleep_past): New function.
- * client.c (get_responses_and_close): Use new function.
- * commit.c (commit): Ditto.
- * update.c (do_update): Ditto.
- * cvs.h: Prototype new function.
-
- * stamp-h2.in: Regenerated.
-
-2001-03-14 Derek Price <derek.price@openavenue.com>
-
- * Makefile.in: Regenerated.
- * stamp-h2.in: Ditto.
-
-2001-03-14 Larry Jones <larry.jones@sdrc.com>
-
- * commit.c (check_fileproc): Allow adding on the trunk when there's
- an existing non-Attic RCS file as long as the head revision is dead.
- This can happen due to an aborted resurrection.
- (commit_fileproc): When resurrecting, consider the dead revision
- along with the other files' revisions.
- (findmaxrev): Avoid unnecessary work.
- (checkaddfile): Only warn if file isn't in Attic as expected.
- (Reported by Ross Burton <r.burton@180sw.com>.)
- * sanity.sh (basica-r*): New tests for above.
- (basica-o4): Update to match.
-
-2001-03-09 Larry Jones <larry.jones@sdrc.com>
-
- * edit.c (edit_fileproc, unedit_fileproc): Some implementations of
- asctime/ctime apparently use a leading zero on the date instead
- of the space required by the C Standard. Correct for this so that
- shared working directories work without hassle.
- (Reported by David L. Martin <dlmart2@home.com>.)
- * entries.c (fgetentent): Ditto.
- * vers_ts.c (time_stamp_server, time_stamp) Ditto.
-
-2001-03-07 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (basica, binfiles2, head, admin): Update to match
- change to admin.c.
-
-2001-03-06 Larry Jones <larry.jones@sdrc.com>
-
- * client.c (recv_bytes): Handle EOF as in recv_line().
- (Reported by Pavel Roskin <proski@gnu.org>.)
-
- * admin.c (admin_fileproc): Change final error message to clarify
- that CVS refused to modify the RCS file rather than being unable to.
-
-2001-02-28 Jim Meyering <meyering@lucent.com>
-
- * commit.c (commit_usage): Use `-F logfile' (rather than -F file') in
- the description of that option, to be consistent with the `-F logfile'
- in the Usage: line. Use spaces instead of TAB characters, and realign.
-
-2001-03-02 Derek Price <derek.price@openavenue.com>
-
- * sanity.sh (crerepos): Make failed ${CVS_RSH-rsh} attempt print the
- name of the command it actually used rather than 'rsh'.
-
-2001-02-27 Derek Price <derek.price@openavenue.com>
-
- * sanity.sh (modules2-ampermod-*): Added these tests to make sure the
- top level directory is created in an ampermodule when '-n' is passed to
- checkout.
-
- original bug report from
- Wolfgang Haefelinger <Wolfgang.Haefelinger@Dresdner-Bank.com>
-
-2001-02-27 Derek Price <derek.price@openavenue.com>
-
- * sanity.sh (version-[12]): replace ' (client/server)' with .* in these
- two tests so that 'make check' works with whatever client/server
- options the executable was compiled with.
-
-2001-02-23 Derek Price <derek.price@openavenue.com>
-
- * main.c (main): Only check a cvsroot_t's isremote member when client
- support is enabled.
- * server.c: Include GSSAPI headers with client support as well as
- server support.
-
-2001-02-21 Larry Jones <larry.jones@sdrc.com>
-
- * modules.c, cvs.h (do_module): Add build_dirs argument and use it
- instead of run_module_prog. Change all callers.
- * tag.c (cvstag): For rtag, don't build directories.
- * sanity.sh (modules3): Update to match.
-
-2001-02-20 Derek Price <derek.price@openavenue.com>
-
- * client.c: Use xgssapi.h.
- * server.c: Ditto.
-
-2001-02-15 Derek Price <derek.price@openavenue.com>
-
- * Makefile.am (cvs_SOURCES): Correct error from yesterday.
- * Makefile.in: Regenerated.
-
-2001-02-14 Derek Price <derek.price@openavenue.com>
-
- * server.c: Include xselect.h.
- * update.c (do_update): Use best available sleep function.
-
-2001-02-14 Derek Price <derek.price@openavenue.com>
-
- * Makefile.am (cvs_SOURCES): Alphabetize and split to one/line.
- (cvs_LDADD): Alphabetize and split to one/line.
- * Makefile.in: Regenerated.
-
-2001-02-14 Larry Jones <larry.jones@sdrc.com>
-
- * build_src.com: Remove references to rtag.c & rtag.obj.
-
-2001-02-13 Derek Price <derek.price@openavenue.com>
-
- * main.c (date_to_tm): New function to convert an RCS date string to a
- struct tm.
- (tm_to_internet): New function to convert a struct tm to a date string
- as specified by RFC822 and amended by RFC 1123.
- (date_to_internet): Use the above two functions and a struct tm
- intermediary for conversion.
- * patch.c (patch_fileproc): Answer somebody's comment and use the new
- diff_exec API.
- * rcs.c (RCS_checkin): Use new diff_exec API.
- (RCS_delete_revs): Use new diff_exec API.
- (make_file_label): If the file name is DEVNULL, date it the Epoch for
- compatibility with the POSIX.2 spec and Larry Wall's patch
- implementation.
- * rcscmds.c (diff_exec): Accept new label arguments.
- * sanity.sh (death2): Update some diff tests to accept the new format.
- * update.c (patch_file): Use new diff_exec API.
- * diff.c (diff_fileproc): Create header labels appropriate for
- compatibility with the Larry Wall version of patch.
- (diff): Rename calls to strcat_and_allocate.
- (strcat_and_allocate): Rename and move...
- * subr.c (xrealloc_and_strcat): here.
- * cvs.h: Update prototypes to match.
-
-2001-02-13 Derek Price <derek.price@openavenue.com>
-
- * Makefile.am (cvs_SOURCES): Remove rtag.c.
-
-2001-02-07 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (directory_cmp): Return status rather than setting ISDIFF.
- (basic2): Rewrite using dotest.
-
-2001-02-06 Larry Jones <larry.jones@sdrc.com>
-
- * tag.c, rtag.c: Merge with tag.c being the surviving file.
- * Makefile.in: Update to match.
- * main.c (cmds): rtag() => cvstag().
- * server.c (serve_rtag): Ditto, and set command name.
-
-2001-02-06 Derek Price <derek.price@openavenue.com>
- Rex Jolliff <Rex_Jolliff@notes.ymp.gov>
- Shawn Smith <Shawn_Smith@notes.ymp.gov>
-
- * add.c: Replace opendir, closedir, & readdir calls with CVS_OPENDIR,
- CVS_CLOSEDIR, & CVS_READDIR in support of changes to handle VMS DEC C
- 5.7 {open,read,close}dir problems. Check today's entry in the vms
- subdir for more.
- * filesubr.c: ditto
- * find_names.c: ditto
- * ignore.c: ditto
- * import.c: ditto
- * lock.c: ditto
- * update.c: ditto
-
-2001-02-02 Larry Jones <larry.jones@sdrc.com>
-
- * error.h: Changed include guard macro from _error_h_ to ERROR_H;
- names beginning with underscore are reserved.
- * login.c (password_entry_parseline, password_entry_operation,
- password_entry_operation_e, password_entry_operation_t): Removed
- leading underscore(s).
- (password_entry_parseline): Corrected error messages.
- (password_entry_operation): Fixed uninitialized variable (password).
- (login): Removed unused variable (found_password).
-
- * rtag.c (rtag_proc): Call lock_tree_for_write() before calling
- start_recursion. This fixes a serious problem where do_recursion
- was reading and caching RCS files without any locks in place and
- that information was subsequently being used to rewrite the file
- causing any intermediate changes to be lost.
- (rtag_filesdoneproc): Defunct.
- (Reported by Karl Tomlinson <k.tomlinson@auckland.ac.nz>.)
- * tag.c (cvstag, tag_filesdoneproc): Ditto.
- * lock.c (lock_tree_for_write): Add which argument, change all
- callers to pass W_LOCAL.
- * rcs.h: Ditto.
-
-2001-01-29 Derek Price <derek.price@openavenue.com>
-
- * client.c (get_cvs_port_number): change the prototype to accept a
- const cvsroot_t * as input and add a FIXME comment
- * cvs.h: new prototypes for get_cvs_port_number & normalize_cvsroot
- * login.c (_password_entry_operation): consolidate all the ~/.cvspass
- access into a single new function which reads ~/.cvspass in a backwards
- compatible manner
- (logout): use the new _password_entry_operation function
- (login): ditto
- (get_cvs_password): ditto
- * root.c (normalize_cvsroot): move knowledge of default port & username
- values inside
-
-2001-01-29 Larry Jones <larry.jones@sdrc.com>
-
- * subr.c (shell_escape): New function.
- * cvs.h: Declare it.
- * logmsg.c (logfile_write): Use it to avoid problems with filenames
- containing "'".
- (Reported by Gerhard Ahuis <gerhard@ats.xs4all.nl>.)
-
- * server.c (outbuf_memory_error, pserver_authenticate_connection,
- kserver_authenticate_connection): If available, use syslog() to
- record some errors.
-
-2001-01-25 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (do_cvs_command): If there's a partial output line left
- over and the client doesn't support MT, go ahead and send it in an
- M response instead of just dropping it.
- (Reported by Milos Kleint <Milos.Kleint@netbeans.com>.)
-
- * update.c (update_fileproc): Handle toss_local_changes in the
- T_NEEDS_MERGE case.
- (Inspired by Noel L Yap <yap_noel@jpmorgan.com>.)
- * sanity.sh (clean): New tests for above.
-
-2001-01-23 Derek Price <derek.price@openavenue.com>
-
- * run.c (run_exec): flush, if used, stderr and stdout before exit
- * server.c (cvs_flusherr): flush stderr & send a stderr flush command
- on the protocol pipe
- (cvs_flushout): like above, for stdout
- (do_cvs_command): handle flushes properly
- * sanity.sh (reserved): make the commitinfo script echo errors to
- stderr rather than stdin
-
-2001-01-18 Larry Jones <larry.jones@sdrc.com>
-
- * log.c (option_revlist, revlist, log_usage, cvslog,
- log_parse_revlist, log_expand_revlist, log_version_requested): Add
- support for :: for exclusive ranges.
- * admin.c (admin_usage): Reorder -o to be parallel to log -r.
- * sanity.sh (log): New tests for above.
-
-2001-01-18 Derek Price <derek.price@openavenue.com>
-
- * main.c: Add '2001' to the range of copyright years listed by the
- --version option
- * version.c.in (version): check current_parsed_root before its isremote
- member to avoid a core dump
- * sanity.sh (version): add a test for the version command
-
- * version.c: regenerated
-
-2001-01-12 Larry Jones <larry.jones@sdrc.com>
-
- * rcs.c, rcs.h (RCS_lock, RCS_unlock): Use RCS_gettag to find the
- correct revision so that symbolic tags work correctly. (This
- requires removing the "const" from the rev parameter since it's
- passed to RCS_gettag which might modify it.)
- (Reported by irina sturm <irina.sturm@st.com>.)
-
-2001-01-11 Larry Jones <larry.jones@sdrc.com>
-
- * run.c (close_on_exec): Remove check for FD_CLOEXEC. As far as I
- can see, it's *never* been defined, which defeats the whole point.
- If F_SETFD is defined, it's probably safe to use it.
-
- * server.c (do_cvs_command): Call close_on_exec on the protocol and
- flow control pipes in the child process so they don't get inherited
- by any subsidiary processes.
- (Reported by Tristan Gingold <tgi@netgem.com>.)
-
- * cvs.h (free_cvsroot_t): Spell correctly (was free_CVSroot_t).
-
-2001-01-10 Derek Price <derek.price@openavenue.com>
- Rex Jolliff <Rex_Jolliff@notes.ymp.gov>
-
- * build_src.com: VMS changes
- * filesubr.c: replace calls to unlink() with CVS_UNLINK() for VMS
- * rcs.c: ditto
-
-2001-01-10 Derek Price <derek.price@openavenue.com>
-
- * main.c (current_root): explicitly list this as a static global
-
-2001-01-10 Derek Price <derek.price@openavenue.com>
-
- * cvs.h (get_cvs_port_number): change name & prototype from
- get_port_number
- * client.c (get_cvs_port_number): new function which returns a port
- number based on a cvsroot_t rather than requiring all possible sources
- passed in
- (connect_to_pserver): use new get_cvs_port_number function
- (connect_to_server): ditto
- * login.c (get_password): use new get_cvs_port_number function
- (login): ditto
- (logout): ditto
-
-2001-01-10 Derek Price <derek.price@openavenue.com>
-
- * Makefile.am ($(srcdir)/version.c): specify $(srcdir) for all subparts
- of the build since some systems don't allow mv's across partitions
- * Makefile.in: regenerated
-
-2001-01-10 Derek Price <derek.price@openavenue.com>
-
- * Makefile.am (version.c): specify $(srcdir) explicitly in target rule
- so version.c gets built properly for all makes.
- (version.o): specify $(srcdir)/version.c explicitly so dependency is
- found and built properly
- * Makefile.in: regenerated
-
-2001-01-09 Derek Price <derek.price@openavenue.com>
-
- * version.c: updated timestamp
-
-2001-01-09 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (server): Change to server_temp_dir immediately after
- creating it so that any stray files that happen to be created go
- there instead of in the server's initial directory, wherever that
- may be.
- * sanity.sh (modules5-15): Update to match.
-
- * version.c.in: Update to match Derek's change to version.c.
-
-2001-01-09 Derek Price <derek.price@openavenue.com>
-
- * cvs.h: Remove the various CVSroot_* bits and replace them with a
- single structure of type cvsroot_t (current_parsed_root)
-
- * root.c (parse_cvsroot): return pointer to a new cvsroot_t rather than
- altering global variables
- (local_cvsroot): return a pointer to a new cvsroot_t rather than
- setting globals. changed the name of this function from
- set_local_cvsroot to better explain new functionality
- (new_cvsroot_t): new initializer function
- (free_cvsroot_t): new function
- (others): use current_parsed_root rather than the old CVSroot_* globals
-
- * add.c: use current_parsed_root rather than the old CVSroot_* globals
- * admin.c: ditto
- * checkout.c: ditto
- * client.c: ditto
- * commit.c: ditto
- * create_adm.c: ditto
- * diff.c: ditto
- * edit.c: ditto
- * expand_path.c: ditto
- * find_names.c: ditto
- * history.c: ditto
- * ignore.c: ditto
- * import.c: ditto
- * lock.c: ditto
- * log.c: ditto
- * login.c: ditto
- * logmsg.c: ditto
- * main.c: ditto
- * mkmodules.c: ditto
- * modules.c: ditto
- * parseinfo.c: ditto
- * patch.c: ditto
- * rcs.c: ditto
- * recurse.c: ditto
- * release.c: ditto
- * remove.c: ditto
- * repos.c: ditto
- * rtag.c: ditto
- * server.c: ditto
- * status.c: ditto
- * tag.c: ditto
- * update.c: ditto
- * version.c: ditto
- * watch.c: ditto
- * wrapper.c: ditto
-
-2001-01-05 Derek Price <derek.price@openavenue.com>
-
- * cvs.h (enum CVSmethod): add null_method
- * root.c (method_names): correlate null_method & "undefined"
- (parse_cvsroot): make two error cases non fatal
- * sanity.sh (crerepos-6b): account for new error message, re above
-
-2001-01-05 Derek Price <derek.price@openavenue.com>
-
- * src/Makefile.am (cvsbug, cvsbug_EXTRA_DIST, EXTRA_DIST): move cvsbug
- target to configure.in - see ../ChangeLog for more
- * src/cvsbug.in: Rename from cvsbug.sh
- * src/cvsbug.sh: Rename to cvsbug.in
-
-2001-01-04 Larry Jones <larry.jones@sdrc.com>
-
- * Makefile.am (cvsbug): Explicitly list input file ($< is only
- valid in inference rules).
- * Makefile.in: Ditto.
-
-2001-01-04 Derek Price <derek.price@openavenue.com>
-
- * sanity.sh: use getopts rather than getopt for portability reasons
-
-2001-01-03 Derek Price <derek.price@openavenue.com>
-
- * Makefile.am (remotecheck): depend on 'all'
- * Makefile.in: regenerated
-
-2000-12-29 Derek Price <derek.price@openavenue.com>
-
- * sanity.sh: remove explicit "$@" from last checkin and move the 'do'
- to the line following the 'for'. Apparently this is more portable.
-
-2000-12-29 Derek Price <derek.price@openavenue.com>
-
- * sanity.sh: make "$@" explicit in 'for' statement since Solaris 5.6's
- implementation of Bourne shell doesn't seem to implement this default
- behavior.
-
-2000-12-27 Derek Price <derek.price@openavenue.com>
-
- * sanity.sh: add a -f option for continuing from a particular test
- and shorten --keep to -k so we can use the getopt function.
-
-2000-12-27 Derek Price <derek.price@openavenue.com>
-
- * Makefile.am (remotecheck): Make remotecheck dependant on all
- * Makefile.in: regenerated
-
-2000-12-26 Derek Price <derek.price@openavenue.com>
-
- * Makefile.in: update timestamp
- * stamp-h2.in: ditto
- * version.c: ditto
-
-2000-12-26 Derek Price <derek.price@openavenue.com>
-
- * Makefile.am: new target for version.c
- (EXTRA_DIST): add version.c.in & version.c so builds work when
- configure doesn't
- * Makefile.in: Regenerated
- * stamp-h2.in: update timestamp
- * version.c: ditto
-
-2000-12-26 Derek Price <derek.price@openavenue.com>
-
- * Makefile.am (INCLUDES): add zlib
- * Makefile.in: Regenerated
-
-2000-12-22 Derek Price <derek.price@openavenue.com>
-
- * Makefile.am (DISTCLEANFILES): added a few files
- (INCLUDES): commented
- * Makefile.in: Regenerated
-
-2000-12-21 Derek Price <derek.price@openavenue.com>
-
- * .cvsignore: Added .deps directory and a new stamp file
- * Makefile.am: New file needed by Automake
- * Makefile.in: Regenerated
- * stamp-h2.in: New stamp file created by Automake
- * version.c.in: use configure to generate version.c
-
-2000-12-16 Derek Price <derek.price@openavenue.com>
-
- * server.c (server_update): Keep the vers structure up to date after
- sending a Remove or Remove-entry command to the client
- * update.c (update): remove call to server_updated() after
- scratch_file()
- (scratch_file): in server mode, call server_updated(), otherwise keep
- the vers structure up to date
- (join_file): add a trace, save the revision to Register() on a remove
- before calling server_scratch & server_updated
- * sanity.sh (join): Add test for a remove/add caused by an update
- to a new branch and a join in the same step.
-
-2000-12-15 Larry Jones <larry.jones@sdrc.com>
-
- * error.c (error): Add %ld and %lu.
-
- * history.c: Change hrec.idx from int to long, reformat NEXT_BAR
- for readability, add hrec_idx.
- (fill_hrec): Change initialization to be portable and always set
- idx so it can be used as a line number in error messages; improve
- parsing and error checking.
- (read_hrecs): Initialize hrec_idx, handle embedded NULs, warn about
- no newline at end of file.
- (select_hrec): Add basic validity checking.
-
-2000-12-07 Larry Jones <larry.jones@sdrc.com>
-
- * history.c (history): Allow multiple -m options as documented.
-
-2000-11-29 Derek Price <derek.price@openavenue.com>
-
- * root.c (parse_cvsroot): back out yesterday's redundant changes
- * main.c (main): fix CVSROOT trace message to look like other trace
- messages
- * sanity.sh (multiroot2-9): expect new trace message
-
-2000-11-28 Derek Price <derek.price@openavenue.com>
-
- * root.c (parse_cvsroot): add trace on this function
- * client.c (get_port_number): make trace print look like others
-
-2000-11-16 Derek Price <derek.price@openavenue.com>
-
- * filesubr.c (cvs_temp_file): back out the previous change in the
- interests of portability, add an assertion, and fix the header comment
-
-2000-11-16 Derek Price <derek.price@openavenue.com>
-
- * filesubr.c (cvs_temp_file): refine the exit behavior to notice if
- the out param was passed in NULL and, if so, avoid setting it and delete
- the temp file for later
-
-2000-11-16 Derek Price <derek.price@openavenue.com>
-
- * filesubr.c (cvs_temp_file): fixed a garble or two, added some
- additional error checking, and added a comment
-
-2000-11-15 Derek Price <derek.price@openavenue.com>
-
- * filesubr.c (cvs_temp_file): added cvs_temp_file
- function to use mkstemp rather than one of the other temp file
- generators as gcc keeps complaining I should.
- (cvs_temp_name): altered this function to simply wrap cvs_temp_file
- and deprecated it
- * cvs.h: added prototype for cvs_temp_file
- * commit.c (commit): use the new function instead of the old and plug
- an old (though related) memory leak.
- * import.c (import): use the new function
- * login.c (login): Ditto
- * logmsg.c (do_editor, do_verify): Ditto
- * patch.c (patch_fileproc): Ditto
-
-2000-11-14 Larry Jones <larry.jones@sdrc.com>
-
- * update.c, update.h (do_update): Add xdotemplate parameter.
- Change all callers.
- (update_dirent_proc): Use dotemplate for Create_Admin, not 1.
- * checkout.c (checkout_proc): Don't create CVS/Template if
- exporting.
- (Reported by Andrey Podkolzin <mdh@zenon.net>.)
-
-2000-11-08 Larry Jones <larry.jones@sdrc.com>
-
- * admin.c (admin): Use getgroups() to check for membership in
- CVS_ADMIN_GROUP if it exists. In any event, check the user's
- primary group in addition to any additional groups.
- (Reported by Thomas Okken <TOkken@refco.com>.)
-
-2000-11-06 Jim Meyering <meyering@lucent.com>
-
- Compile with gcc's -Wformat and fix the exposed problems.
- * root.c (parse_cvsroot) [! HAVE_KERBEROS]: Provide an argument
- for the %s error format spec.
- [! HAVE_GSSAPI]: Likewise.
- (normalize_cvsroot): Put comment delimiters around token after `#endif'.
-
-2000-11-03 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh: Some versions of sed require a space between -e and
- the value.
-
-2000-10-27 Larry Jones <larry.jones@sdrc.com>
-
- * checkout.c (checkout): Don't check for a safe location if just
- cat'ing the module database.
- (Reported by Ilya Martynov <m_ilya@agava.com>.)
- Have -s set cat as well as status; it simplifies the code.
-
-2000-10-26 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (join-admin-2): Check output from all commands instead
- of (mostly) discarding. (Some of the tests used to produce stray
- output in remote mode.)
-
- * sanity.sh (dotest_line_by_line): Handle empty lines in pattern
- (expr doesn't distingish between successfully matching nothing
- and failing to match anything).
-
- * sanity.sh (dotest_internal): Rearrange and use elif to simplify.
-
-2000-10-24 Jim Meyering <meyering@lucent.com>
-
- Fix a bug, introduced with my fix of 2000-07-10, whereby -kk would
- sometimes be ignored for some of the files involved in an update.
-
- * update.c (join_file): Restore the original value of `options'
- right after calling checkout_file.
- * sanity.sh (join-admin-2): New test for this.
-
-2000-10-23 Derek Price <derek.price@openavenue.com>
- James Youngman <jay@gnu.org>
-
- * sanity.sh: it's /gnu/bin, not /gun/bin. Thanks go to James Youngman
- <jay@gnu.org> for the bug report and patch.
-
-2000-10-20 Jim Kingdon <http://sourceforge.net/users/kingdon/>
-
- * server.c (switch_to_user): Set CVS_USER. Patch from Sudish
- Joseph and popularized by dozens (e.g. mozilla.org, also others).
-
-2000-10-20 Derek Price <derek.price@openavenue.com>
- KOIE Hidetaka <hide@koie.org>
-
- * root.c (normalize_cvsroot): plug a memory leak. Thanks to
- KOIE Hidetaka <hide@koie.org>
-
-2000-10-18 Derek Price <derek.price@openavenue.com>
-
- * client.c (connect_to_pserver): added a close brace the lack of which
- was preventing compilation when gssapi was enabled. Removed a
- redundant check for HAVE_KERBEROS.
-
-2000-10-18 Derek Price <derek.price@openavenue.com>
-
- * root.c (normalize_cvsroot): removed references to free_port_s and the
- now useless call to free now that port_s is on the stack. Thanks to
- Jon Miner.
-
-2000-10-18 Derek Price <derek.price@openavenue.com>
-
- * root.c (normalize_cvsroot): remove calls to snprintf for
- compatibility with M$ Windoze.
-
-2000-10-18 Derek Price <derek.price@openavenue.com>
-
- * sanity.sh (crerepos-6a, crerepos-6a-r): fix a "?" in a regex & pipe
- the output of a test to /dev/null since we don't know what error
- messages specific rsh implementations will output.
-
-2000-10-17 Derek Price <derek.price@openavenue.com>
-
- * cvs.h: added CVSroot_password variable. Provided prototypes for
- get_port_number & normalize_cvsroot.
- * client.c (get_port_number): Fixed an ANSI prototype I had included
- for get_port_number.
- * login.c (login, logout): Removed two checks for a non-null
- CVSroot_username since parse_cvsroot now supplies a default in pserver
- mode. allow for a password in CVSROOT
- (get_cvs_passsword): return CVSroot_password if it was supplied
- in the CVSROOT.
- * root.c (parse_cvsroot): Changed CVSROOT spec from
- :method:user@host/port:/cvsroot to
- :method:[[user][:password]@]host[:[port]]/cvsroot
- Removed the xstrdup function since we'd rather have the error checking
- from the version in subr.c anyhow. Moved some error messages which
- looked like they would print the wrong error message after a failed
- connect_to_gserver call.
- (normalize_cvsroot): return a normalized CVSROOT for use in the
- .cvspass file.
- * sanity.sh (crerepos-6): fix a test which was expecting an old error
- message.
-
- * client.c (connect_to_pserver): Moved some error messages which looked like they
- would print the wrong error message after a failed connect_to_gserver
- call.
-
- * login.c (login): Paranoiacly zero a password in memory.
-
-2000-10-12 Derek Price <derek.price@openavenue.com>
-
- * client.c (auth_server_port_number -> get_port_number, start_pserver,
- start_tcp_server): use a port specified in CVSROOT instead of the
- default port. Failing that, use the CVS_CLIENT_PORT environment
- variable.
- * cvs.h: Added global CVSroot_port & renamed auth_server_port_number.
- * root.c (parse_cvsroot): Parse the new CVSROOT format properly.
- Incidentally reformated some error messages for uniformity and
- readability.
- * sanity.sh (crerepos): fix two tests which were now expecting the
- wrong error message.
-
-2000-10-11 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (pserver_authenticate_connection): Fix stupid mistake
- in previous change.
-
-2000-10-11 Derek Price <derek.price@openavenue.com>
-
- * main.c (main): Dispose old CVSroot when parsing a '-d' option if
- free_CVSroot is set.
- * root.c (parse_cvsroot): remove references to 'cvsroot_parsed', a
- static boolean I expect hasn't been used since CVS learned to handle
- multiple CVSROOTs.
-
-2000-10-10 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (print_error): Make up a message if strerror fails.
-
- * server.c (pserver_authenticate_connection): Give a real error
- message for an invalid repository.
-
-2000-10-06 Derek Price <derek.price@openavenue.com>
-
- * add.c (add): Made quiet mode affect some warning messages as seemed
- appropriate. Specifically, some of the messages which a user might
- want to ignore so they don't have to be quite so specific on the
- command line: files added twice, files already in the repository and
- check out properly (i.e. but picked up by 'cvs add *'), & files which
- are readded in place of a dead revision or onto a branch. '-q' will
- not change the non-zero exit code for the cases where at least one
- passed in file name was already in the Entries file. There seems to
- be a precedent in remove.c.
- * remove.c (cvsremove): switched the "use cvs ci to make these changes
- permanent message" to only print w/o '-Q' to match the new behavior of
- add. This seems appropriate as '-Q' is defined to restrict messages
- to critical errors.
- * sanity.sh (adderrmsg): Added some tests for the above behavior.
-
-2000-10-05 Larry Jones <larry.jones@sdrc.com>
-
- * client.c (call_in_directory): Create CVSADM directory if it doesn't
- exist in the directory. This makes client/server work more like
- standalone when checking out into an existing (non-CVS) directory.
- * sanity.sh (dirs2, conflicts3, toplevel): Update to match.
-
-2000-10-03 Larry Jones <larry.jones@sdrc.com>
-
- * filesubr.c (get_homedir): Ignore $HOME when running in server mode.
-
-2000-10-02 Larry Jones <larry.jones@sdrc.com>
-
- * cvs.h: Define (and use) T_PATCH as a valid file classification
- even when SERVER_SUPPORT isn't defined -- it simplifies the code.
- * classify.c (Classify_File): Ditto.
- * commit.c (check_fileproc): Ditto.
- * status.c (status_fileproc): Ditto.
- * update.c (update_fileproc): Ditto.
- * tag.c (check_fileproc): Accept T_PATCH in addition to T_CHECKOUT.
- * sanity.sh (tagc-10): Update to match.
-
-2000-09-29 Larry Jones <larry.jones@sdrc.com>
-
- * client.c (get_responses_and_close): Reset server_fd to -1 after
- shutting down.
- (Reported by Joerg Thoennes <Joerg.Thoennes@data-sciences.de>.)
-
-2000-09-27 Larry Jones <larry.jones@sdrc.com>
-
- * commit.c (commit): Don't sleep before returning in server mode,
- just let the client do it.
- * update.c (do_update): Ditto.
-
- * sanity.sh (find_tool): Correct method of checking for GNU tools.
-
- * checkout.c (checkout_proc): Match up user directories with
- repository directories instead of using Emptydir.
- * sanity.sh (cvsadm, emptydir): Update to match.
-
-2000-09-19 Larry Jones <larry.jones@sdrc.com>
-
- * version.c: Push version number to 1.11.0.1.
-
- * version.c: Version 1.11.
-
-2000-09-07 Larry Jones <larry.jones@sdrc.com>
-
- * Makefile.in: Use @bindir@, @libdir@, @infodir@, and @mandir@
- from autoconf.
-
-2000-08-23 Larry Jones <larry.jones@sdrc.com>
-
- * mkmodules.c (init): Create an empty val-tags file if it doesn't
- already exist to avoid problems with users not having sufficient
- permissions to create it later.
-
-2000-09-06 Jim Kingdon <jkingdon@dhcp-net200-89.su.valinux.com>
-
- * main.c (lookup_command_attribute): Add "release" to commands
- which can be done by a read-only user.
-
-2000-08-23 Larry Jones <larry.jones@sdrc.com>
-
- * repos.c (Name_Repository): Use pathname_levels to detect attempts
- to get above the repository instead of checking for leading ..
- which isn't reliable.
- * sanity.sh (multiroot3-12 to multiroot3-15): New tests for above.
-
-2000-08-21 Larry Jones <larry.jones@sdrc.com>
-
- * rcs.c (expand_keywords): Handle the unusual case of log == NULL.
- (Reported by Craig Metz <cmetz@inner.net>.)
-
-2000-08-01 Larry Jones <larry.jones@sdrc.com>
-
- * subr.c (pathname_levels): Fix bug that miscounts adjacent
- slashes.
- (Patch submitted by Tanaka Akira <akr@m17n.org>.)
-
- * loginc.c (login): If available, use getpassphrase instead of
- getpass to support long passwords on Solaris.
-
-2000-07-28 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (server_noop): Avoid do_cvs_command() overhead.
- (requests): Make noop RQ_ROOTLESS.
-
-2000-07-27 Noel Cragg <noel@red-bean.com>
-
- * root.c (parse_cvsroot): change fork method to behave like other
- remote methods -- let the server check that the repository
- directory is an absolute pathname.
-
-2000-07-27 Larry Jones <larry.jones@sdrc.com>
-
- * lock.c (set_lock): Include actual lock directory in error message.
- * sanity.sh (multiroot3-10): Change to match.
-
- * sanity.sh (client-3): Allow for a potential "broken pipe".
-
-2000-07-26 Larry Jones <larry.jones@sdrc.com>
-
- * commit.c (commit_filesdoneproc): Flush stdout before running script.
- * modules.c (do_module): Ditto.
- * update.c (update_dirleave_proc): Ditto.
- * server.c (do_cvs_command): Give input from the protocol pipe
- precedence over input from stdout/stderr. There's no particularly
- good justification for this other than helping to avoid out-of-order
- messages in sanity.sh.
-
- * admin.c (admin_usage): Add the supported options.
-
- * sanity.sh (info): Try to avoid out-of-order messages.
-
- * sanity.sh (info): Fix problems when running twice in a row.
-
-2000-07-17 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (modules5-7, cvsadm-1e, emptydir-2): Allow for a nil
- commit (can happen if the test is run twice in a row).
-
-2000-07-19 Pavel Roskin <proski@gnu.org>
- and Larry Jones <larry.jones@sdrc.com>
-
- * mkmodules.c (config_contents): Add a commented out example for
- LockDir. Don't suggest PreservePermissions unless it's enabled.
-
-2000-07-17 Larry Jones <larry.jones@sdrc.com>
-
- * login.c (get_cvs_password): Handle malformed ~/.cvspass more
- gracefully.
-
-2000-07-12 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (modules5): New tests for module programs.
-
-2000-07-11 Larry Jones <larry.jones@sdrc.com>
-
- * filesubr.c (copy_file, xcmp): Handle systems (like Plan 9) that
- don't support mknod() and/or st_rdev.
- * import.c (add_rcs_file): Ditto.
- * rcs.c (RCS_checkout, RCS_checkin): Ditto.
- * update.c (special_file_mismatch): Ditto.
-
-2000-07-10 Larry Jones <larry.jones@sdrc.com>
-
- * zlib.c (gunzip_and_write): Fix type clashes.
-
- * main.c (main): Remove unused variables.
-
-2000-07-10 Jim Meyering <meyering@lucent.com>
-
- When a command like `cvs update -kk -jT1 -jT2' creates a new file
- (because it had the T2 tag, but not T1), the subsequent commit of
- that just-added file would effectively set the admin `-kk' option
- for that file in the repository.
-
- * update.c (join_file): Rename global-shadowing local `options'
- to `t_options'.
- Set file-scoped global `options' to NULL just before
- check-out.
- * sanity.sh (join-admin): New test for this.
-
-2000-07-08 Larry Jones <larry.jones@sdrc.com>
-
- * version.c, cvs.h (version): New function.
- * main.c (cmds[]): Add version command to invoke it.
- (main): Also use it in -v.
- * server.c (serve_version): New function.
- (requests[]): Add version command to invoke it.
-
-2000-07-06 Karl Fogel <kfogel@red-bean.com>
-
- * sanity.sh (pserver-14): remove this test for portability
- reasons (it was only recently added for the 2000-07-04 change).
-
-2000-07-06 Larry Jones <larry.jones@sdrc.com>
-
- sanity.sh (modules-148): Don't test for specific revisions.
-
- * main.c (main): Catch SIGABRT to try to clean up after assertion
- failures. Don't bother SIG_register'ing Lock_Cleanup because
- main_cleanup calls it indirectly anyway.
- * patch.c (patch): Catch SIGABRT.
- * rcs.c (rcs_internal_lockfile): Ditto.
- * server.c (server): Ditto.
-
- * fileattr.c (fileattr_write): Don't delete the unrecog_head list
- when writing...
- (fileattr_free): Delete it when freeing!
-
-2000-07-05 Larry Jones <larry.jones@sdrc.com>
-
- * admin.c (admin): Handle -t in client so reading from files works
- correctly in client/server mode.
- * sanity.sh (log2): Update to match.
-
-2000-07-04 Karl Fogel <kfogel@red-bean.com>
-
- * server.c (pserver_authenticate_connection): use new
- getline_safe() during authentication phase, to avoid a
- denial-of-service attack in which client sends arbitrary
- amounts of data with no newlines.
- (Reported by <jpmg@eng.cam.ac.uk>.)
-
- * sanity.sh: new test pserver-14 for above.
-
- * myndbm.c: #include getline.h.
- (mydbm_load_file): pass new GETLINE_NO_LIMIT flag to getstr().
-
-2000-07-03 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (modules): Rewrite using dotest. Add "modules-"
- prefix to test names.
-
-2000-06-28 Larry Jones <larry.jones@sdrc.com>
-
- * error.c (error_exit): Call rcs_cleanup () to release any rcs locks.
- * rcs.c, rcs.h (rcs_cleanup): Make public, close file before trying
- to remove (some systems won't remove open files).
- (RCS_putdtree): Don't worry about cleaning up before call error
- since it now does it for us.
- (rcs_internal_lockfile, rcs_internal_unlockfile): Keep track of
- lock file fd for rcs_cleanup ().
-
- * client.c (handle_set_checkin_prog, handle_set_update_prog):
- Just ignore the request when exporting.
-
-2000-06-27 Larry Jones <larry.jones@sdrc.com>
-
- * create_adm.c, cvs.h (Create_Admin): Add dotemplate argument.
- Change all callers.
- * checkout.c (checkout_proc): Don't create CVS/Template if
- exporting.
-
-2000-06-26 Pavel Roskin <proski@gnu.org>
- and Larry Jones <larry.jones@sdrc.com>
-
- * server.c (switch_to_user): Only set CVS_Username if
- AUTH_SERVER_SUPPORT is defined.
-
-2000-06-23 Larry Jones <larry.jones@sdrc.com>
-
- * client.c (send_dirent_proc): Don't allocate ignlist if you're
- going to skip the directory (plugs memory leak).
- (send_dirleave_proc): New function.
- (send_files): Use it (plugs memory leak).
- * root.c (root_allow_free): Plug memory leaks.
- * server.c (serve_directory, serve_notify, check_password,
- pserver_authenticate_connection): Ditto.
- * update.c (update): Ditto.
-
- This completes the memory leak shoot-out -- the Purify'ed version
- of CVS now runs the entire test suite, both local and remote (except
- for remote crerepos, which causes Purify to choke) with *no* memory
- leaks.
-
- * server.c (pserver_authenticate_connection): Don't free null pointer.
-
-2000-06-21 Larry Jones <larry.jones@sdrc.com>
-
- * client.c (update_entries, get_responses_and_close): Plug memory leaks.
- * commit.c (find_fileproc, commit): Ditto.
- * import.c (import): Ditto.
- * log.c (cvslog): Ditto.
- * recurse.c (start_recursion): Ditto.
- * remove.c (cvsremove): Ditto.
- * server.c (fd_buffer_initialize, server_notify, do_cvs_command): Ditto.
- (fd_buffer_shutdown): New function.
-
-2000-06-20 Larry Jones <larry.jones@sdrc.com>
-
- * root.c (parse_cvsroot): Put the terminating NUL byte into the
- string *before* copying it, not after. :-(
-
-2000-06-19 Larry Jones <larry.jones@sdrc.com>
-
- * main.c (main): Plug memory leaks.
- * root.c (parse_cvsroot, set_local_cvsroot): Ditto.
- * server.c (serve_root): Ditto.
-
-2000-06-16 Larry Jones <larry.jones@sdrc.com>
-
- * fileattr.c (fileattr_read): Plug memory leak.
- * rcs.c (RCS_whatbranch): Ditto.
- * update.c (update_dirleave_proc): Ditto.
-
- * ignore.c (ign_dir_add): Duplicate string so caller can free.
-
- * modules.c (do_module): Don't write into dbm's memory!
-
-2000-06-15 Larry Jones <larry.jones@sdrc.com>
-
- * checkout.c (checkout_proc): Fix non-ANSI code in call to
- findslash(), minor cleanups.
-
-2000-06-14 Larry Jones <larry.jones@sdrc.com>
-
- * tag.c (val_direntproc): Return R_PROCESS instead of 0.
-
- * client.c (update_entries): Fix type clash calling gunzip_and_write().
- * server.c (receive_file): Fix type clash calling gunzip_and_write().
- (server_updated): Fix type clash calling buf_output().
- * error.c (error): Make buf char instead of unsigned char to avoid
- type clashes.
-
- * modules.c (do_module): Change callback_proc to pass argc by
- value instead of by reference: callback procs shouldn't be
- messing with the callers argc/argv, it makes correct memory
- management impossible. Plug memory leaks.
- * cvs.h: Change to match.
- * checkout.c (checkout_proc): Ditto; use a local argv array instead
- of messing with caller's.
- * modules.c (callback_proc): Ditto.
- * patch.c (patch_proc): Ditto; use a local argv array instead
- of messing with caller's.
- * rtag.c (rtag_proc): Ditto; use a local argv array instead
- of messing with caller's.
- * server.c (expand_proc): Ditto.
- * subr.c (line2argv): Change initial argv_allocated back to 1.
-
- * checkout.c (findslash): Fix non-ANSI code.
-
- * sanity.sh (modes3): Fix test names.
-
-2000-06-13 Larry Jones <larry.jones@sdrc.com>
-
- * add.c (add): Plug memory leaks.
- * admin.c (admin_fileproc): Ditto.
- * checkout.c (build_dirs_and_chdir): Ditto.
- * edit.c (editors_fileproc): Ditto.
- * log.c (cvslog, log_parse_revlist, log_parse_date): Ditto.
- * rcs.c (RCS_addaccess): Ditto.
- * tag.c (check_fileproc): Ditto.
- * vers_ts.c (Version_TS): Ditto.
- * watch.c (watchers_fileproc): Ditto.
-
-2000-06-12 Larry Jones <larry.jones@sdrc.com>
-
- * rcs.c (rcsbuf_valword): Set rcsbuf->vlen to keep rcsbuf_valcopy()
- from allocating more memory than needed for @ strings. Don't declare
- unless PRESERVE_PERMISSIONS_SUPPORT (since not defined).
-
- * rcs.c (RCS_abandon): New function to abandon changes.
- * rcs.h: Declare it.
- * admin.c (admin_fileproc): Use it instead of RCS_reparsercsfile.
-
- * commit.c (commit_fileproc): Fix memory leaks.
- * patch.c (patch_fileproc): Ditto.
- * rcs.c (RCS_nodeisbranch, RCS_copydeltas): Ditto.
- * tag.c (tag_fileproc): Ditto.
- * update.c (update): Ditto.
-
-2000-06-09 Larry Jones <larry.jones@sdrc.com>
-
- * rcs.c (RCS_reparsercsfile, RCS_fully_parse, getdelta,
- RCS_getdeltatext): Handle newphrases with composite values.
- (rcsbuf_getkey): Don't remove @s in composite values -- it makes
- it impossible to parse the value! Set special flag to indicate
- a composite value.
- (rcsbuf_valcopy, rcsbuf_valpolish_internal): Handle composite values.
- (putrcsfield): Write composite values.
- (RCS_checkin): Set node types in other_delta list.
- * hash.h: Add RCSCMPFLD.
- * hash.c (nodetypestring): Ditto.
-
- * rcs.c (getdelta): Never allocate space for value, just return
- pointer into rcsbuf (fixes memory leaks). Use rcsbuf_getkey to
- read a key and value and then parse the value if needed rather
- than trying to read it in bits and pieces with rcsbuf_getid,
- rcsbuf_getstring, and rcsbuf_getword.
- (RCS_reparsercsfile): Change callers to compensate.
- (rcsbuf_valcmp, rcsbuf_valword): New functions.
- (rcsbuf_getid, rcsbuf_getstring, rcsbuf_getword): Deleted.
- * sanity.sh (rcs3-1): Now get slightly different error message.
-
-2000-06-08 Larry Jones <larry.jones@sdrc.com>
-
- * main.c (usg): Update CVS home page URL.
-
- * main.c (main): Provide an actual error message for an unknown
- command in addition to the usage message.
-
-2000-06-07 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (serve_root, dirswitch, serve_repository,
- serve_static_directory, serve_sticky, receive_partial_file,
- receive_file, serve_modified, server_write_entries, serve_notify,
- serve_checkin_prog, serve_update_prog, server): Don't set
- pending_error before calling alloc_pending, it makes it fail;
- use alloc_pending instead of malloc when reasonable; be sure to
- save errno before calling functions that might change it.
- (Patch submitted by Dietmar Petras <dietmar.petras@elsa.de>.)
-
-2000-06-03 Larry Jones <larry.jones@sdrc.com>
-
- * commit.c (checkaddfile): Plug memory leak.
- * rcs.c (RCS_checkin): Plug memory leaks.
- * server.c (do_cvs_command): Plug file descriptor leaks.
- * tag.c (check_fileproc): Plug memory leak.
-
-2000-05-26 Larry Jones <larry.jones@sdrc.com>
-
- * recurse.c (unroll_files_proc): Plug memory leak.
-
- * recurse.c (addfile): Fix nonportable pointer cast.
-
- * rcs.c (rcsbuf_getstring, rcsbuf_getword, getdelta): Plug memory
- leaks.
-
-2000-05-25 Larry Jones <larry.jones@sdrc.com>
-
- * checkout.c (checkout, build_one_dir, checkout_proc): Move m_type
- to file scope and use it instead of continually doing strcmp on
- command_name.
- (build_one_dir, checkout_proc): Don't allow export if CVSADM
- directory already exists.
-
-2000-05-23 Larry Jones <larry.jones@sdrc.com>
-
- * rcs.c (RCS_checkin, RCS_cmp_file): Plug memory leaks. (Patch
- submitted by Chris G. Demetriou <cgd@sibyte.com>.)
-
-2000-05-20 Ian Lance Taylor <ian@zembu.com>
-
- * client.c (connect_to_gserver): Handle server error messages
- reasonably.
-
-2000-05-19 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (requests): Make Global_option RQ_ROOTLESS so it can be
- used with init.
-
-2000-05-18 Larry Jones <larry.jones@sdrc.com>
-
- * client.c (start_server): Don't do encryption, authentication,
- compression, or case insensitivity when doing init because init
- is ROOTLESS and they're not.
-
- * client.c (connect_to_pserver): Include repository and username in
- authorization failed message -- if a directory tree crosses multiple
- repositories, it can be quite difficult for the user to figure out
- which one is the problem.
-
-2000-05-17 Larry Jones <larry.jones@sdrc.com>
-
- * main.c (main): Use full set of options when looking for -f to
- avoid misparsing options that take values (previously, -sVAR=foo
- was incorrectly parsed as though it were -s -V -A -R -= -f -o -o
- because it didn't know that -s takes a value).
- * sanity.sh (info-6b): New test for above.
-
- * sanity.sh (conflicts-status): Fix tests so they work remotely, too.
-
-2000-05-17 Jim Meyering <meyering@lucent.com>
-
- * sanity.sh (TESTDIR): Fix braino in last change:
- cd to /tmp before invoking pwd.
-
- * sanity.sh: Set TESTDIR so that `make check' passes even when /tmp
- is a symlink.
- (join-36): Use $TESTDIR rather than hard-coding `/tmp/cvs-sanity'.
- (conflicts-132): Remove unnecessary `rm aa'.
-
-2000-05-16 Jim Kingdon <kingdon@redhat.com>
-
- * cvs.h, checkout.c (safe_location): Make extern.
- * import.c (import): Call it rather than reimplementing
- (incompletely) the same check.
-
-2000-05-16 Larry Jones <larry.jones@sdrc.com>
-
- * rcs.h, subr.c (file_has_markers): Check for any of the three
- conflict marker lines, not just one.
- * sanity.sh (conflicts-status): New tests for above.
- * sanity.sh: Revise to avoid tripping the above check when merging
- changes into sanity.sh itself.
-
-2000-05-15 Larry Jones <larry.jones@sdrc.com>
-
- * update.c (join_file): When registering the result of the merge,
- make sure that the version number is valid (vers->vn_rcs may be
- null if the file doesn't exist on the branch yet). (Patch submitted
- by Robert de Vries <rhdv@rhdv.cistron.nl>.)
- * update.c (join_file): Correct diagnostics (previous change was not
- correct -- the file *does* exist in the specified revision, it just
- doesn't exist in the sandbox).
- * sanity.sh (import-113, join): New tests and changes for above.
-
-2000-05-04 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh: Look for a useful id program. Since we're getting
- the real username for some tests anyway, use it for all the
- tests instead of a generic regular expression that may or may
- not match the actual username.
-
-2000-05-04 Larry Jones <larry.jones@sdrc.com>
-
- * server.c: More error messages.
-
-2000-05-02 Donald Sharp <sharpd@cisco.com>
- and Larry Jones <larry.jones@sdrc.com>
-
- * history.c (report_hrecs): Added code to print out year instead of
- just month/day.
- * sanity.sh (basic2-64, history): Update to match.
-
-2000-04-19 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (dirswitch): Set pending_error_text in addition to
- pending_error to aid in problem determination.
-
-2000-03-23 Larry Jones <larry.jones@sdrc.com>
-
- * mkmodules.c (mkmodules): Return without doing anything if noexec
- is set to avoid trashing existing files.
-
-2000-03-23 Larry Jones <larry.jones@sdrc.com>
-
- * main.c: Alphabetize cmds[] and cmd_usage[] and add server
- commands to cmd_usage[].
-
-2000-03-21 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (client-1): May get "Broken pipe" message from the
- "server" in addition to the expected output.
-
-2000-03-17 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (switch_to_user): Set CVS_Username if it hasn't already
- been set elsewhere. (Patch submitted by Gordon Matzigkeit
- <gord@fig.org>).
-
-2000-03-13 Larry Jones <larry.jones@sdrc.com>
-
- * parseinfo.c: Add extern to logHistory declaration. (Reported by
- <John.Tytgat@aaug.net>.)
- (parse_config): Reformat logHistory code.
-
-2000-03-10 Larry Jones <larry.jones@sdrc.com>
-
- * add.c (add): Don't try to set cvsroot_len until after checking
- for help only -- CVSroot_directory isn't set in that case.
-
-2000-03-03 Larry Jones <larry.jones@sdrc.com>
-
- * mkmodules.c (init): Use mkdir_if_needed to create CVSROOT/Emptydir
- so we don't fail if run multiple times. (Reported by KOIE Hidetaka
- <hide@koie.org>.)
- * sanity.sh (1a): New test for above.
-
-2000-03-02 Larry Jones <larry.jones@sdrc.com>
-
- * main.c: Use identical #if's in the command table and the code
- for pserver and kserver to prevent "peculiar" configurations from
- having really perverse behavior because the command table entries
- are present but the related code isn't.
-
-2000-03-01 Larry Jones <larry.jones@sdrc.com>
-
- * import.c (import): Don't allow importing the repository.
- * sanity.sh (errmsg2-20, errmsg2-21): New tests for above.
-
-2000-03-01 Larry Jones <larry.jones@sdrc.com>
-
- * main.c (main): Update year in copyright message.
-
-2000-03-01 Larry Jones <larry.jones@sdrc.com>
-
- * logmsg.c (do_editor): Correct previous change.
-
-2000-02-29 Larry Jones <larry.jones@sdrc.com>
-
- * logmsg.c (do_editor): When reading temp file, check that message
- buffer is large enough to hold the next line and expand if needed.
-
-2000-02-28 Larry Jones <larry.jones@sdrc.com>
-
- * commit.c (commit): Use get_file() to read log file correctly
- and in text mode rather than binary mode.
-
- * subr.c (get_file): Ignore bufsize if buf is NULL. Include
- terminating NUL byte when estimating required buffer size.
-
-2000-02-28 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (find_tool): New function to replace duplicated code.
-
-2000-02-25 Larry Jones <larry.jones@sdrc.com>
-
- * import.c (add_rcs_file): Don't abort just because lstat fails.
-
-2000-02-16 Jim Meyering <meyering@lucent.com>
-
- Avoid race condition whereby a catchable signal could
- end up corrupting the repository.
- * commit.c (checkaddfile): Put a critical section around the code
- that handles the first commit on the trunk of a file that's already
- been committed on a branch.
- * cvs.h (Sig_inCrSect): Declare new function.
-
-2000-02-21 Karl Fogel <kfogel@red-bean.com>
-
- * main.c (main): still check for repository, but not history file
- (correction to 2000-02-18 change -- that's what I get for
- believing the comment rather than the code).
-
-2000-02-21 K.J. Paradise <kj@sourcegear.com>
-
- * history.c mkmodules.c parseinfo.c: control which actions
- get logged to the cvs history file via CVSROOT/config file
- and LogHistory keyword. (John P Cavanaugh <cavanaug@sr.hp.com>)
-
-2000-02-18 Karl Fogel <kfogel@red-bean.com>
-
- * history.c (history_write): don't die if history file not
- writable, just warn (unless `really_quiet') and skip out.
-
- * main.c (main): don't bother checking if history file is
- writable.
-
- * server.c (serve_root): same.
-
-2000-02-17 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (perms symlinks symlinks2 hardlinks): Don't run by
- default since PreservePermissions code is now disabled.
-
-2000-02-17 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (import-113): Revise to match Jim Meyering's fix.
-
-2000-02-16 Larry Jones <larry.jones@sdrc.com>
-
- * add.c (add): Don't allow adding files or directories to Emptydir.
- (Patch submitted by Chris Cameron <chris.cameron@ot.co.nz>.)
- * sanity.sh (emptydir): Revise (emptydir-7 and emptydir-8) for this.
-
-2000-02-16 Jim Meyering <meyering@lucent.com>
-
- * update.c (join_file): Correct typo in diagnostic:
- change `file %s is present...' to `file %s is not present...'.
-
-2000-02-10 Larry Jones <larry.jones@sdrc.com>
-
- * parseinfo.c (Parse_Info): Treat matching lines with bad expansions
- as errors rather than just ignoring.
-
-2000-02-10 Larry Jones <larry.jones@sdrc.com>
-
- * edit.c (edit): Check for invalid characters in hostname and CurDir.
- (Reported by "Andrew S. Townley" <atownley@informix.com>.)
- * sanity.sh (devcom2): New tests for above.
-
-2000-02-10 Larry Jones <larry.jones@sdrc.com>
-
- * cvs.h: Always #include "server.h" to prevent compile errors when
- neither CLIENT_SUPPORT nor SERVER_SUPPORT is defined.
- (Reported by "Crow, Ian" <ian.crow@linklaters.com>.)
- * log.c (send_one, send_arg_list): Only define when CLIENT_SUPPORT
- is defined to prevent link errors.
-
- * server.c (server): Always create a new temporary directory, don't
- try to reuse an existing one since we might not have correct
- permissions. Also, include directory name in error messages.
-
-2000-01-29 Jim Kingdon <http://developer.redhat.com/>
-
- * ignore.c (ignore_files): Correctly set errno to 0 when we go
- back to the top of the loop. Fixes spurious errors like "cvs
- update: error reading current directory: No such file or
- directory".
-
-2000-01-26 Larry Jones <larry.jones@sdrc.com>
-
- * run.c (run_exec): Conditionalize K.J.'s change so that it only
- applies when SETXID_SUPPORT is defined since some platforms don't
- have setegid().
-
-2000-01-26 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh: Make TESTDIR earlier then use it to check for versions
- of expr that don't work right with long expressions.
-
- * sanity.sh (dotest_line_by_line): Have wc read from stdin so it
- doesn't output the file name and confuse expr. Make the output a
- bit less verbose and easier to read.
-
-2000-01-24 K.J. Paradise <kj@sourcegear.com>
-
- * run.c :> prevents a user from creating a privileged shell from the
- text editor when the SETXID_SUPPORT option is selected. This came from
- Bob Colle <bcolle@ilx.com>, and is his completely.
-
-2000-01-22 Jim Kingdon <http://developer.redhat.com/>
-
- * sanity.sh (emptydir): Add a case in which one might hope for a
- non-Emptydir result, but which result?
-
-2000-01-18 Larry Jones <larry.jones@sdrc.com>
-
- * main.c (main): Allow -z0 to disable gzip compression.
-
-2000-01-17 Larry Jones <larry.jones@sdrc.com> for
- K.J. Paradise (kj@sourcegear.com)
-
- * version.c: Push version number to 1.10.8.1.
-
- * version.c: Version 1.10.8.
-
-2000-01-17 Larry Jones <larry.jones@sdrc.com>
-
- * mkmodules.c (init): Create CVSROOT/Emptydir to avoid problems
- with users not having sufficient permissions to create it later.
-
-2000-01-04 Larry Jones <larry.jones@sdrc.com>
-
- * client.c (get_responses_and_close): Simplify time-stamp race
- avoidance code.
- * commit.c (commit): Ditto.
- * update.c (do_update): Ditto.
- (Prompted by patch submitted by Pavel Roskin
- <pavel_roskin@geocities.com>.)
-
- * hardlink.c: sizeof (char) is 1, by definition.
- * logmsg.c: Ditto.
- * rcs.c: Ditto.
-
-2000-01-03 Karl Fogel <kfogel@red-bean.com>
-
- * filesubr.c, subr.c (backup_file): moved this function from
- filesubr.c to subr.c, at JimK's suggestion.
-
-2000-01-03 Jim Kingdon <http://developer.redhat.com/>
-
- * sanity.sh (clean): Test the contents of the .#cleanme.txt.1.1
- file, not just its existence.
-
-2000-01-03 Karl Fogel <kfogel@red-bean.com>
-
- * cvs.h, filesubr.c (backup_file): use `const' for suffix too;
- correct suffix length calculation and appending behavior; discard
- unnecessary `void' cast. Thanks to Jim Meyering for noticing.
-
-2000-01-03 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (clean): Fix up expected output.
-
-2000-01-02 John P Cavanaugh <cavanaug@sr.hp.com>
- and Karl Fogel <kfogel@red-bean.com>
-
- New -C option to update: overwrites local changes with clean
- copies from the repository. (This is an unreversion of the
- 1999-12-10 change, further modified to work remotely.)
-
- * client.h (BACKUP_MODIFIED_FILES): new #define.
-
- * client.c (struct send_data): new element `backup_modified'.
- (send_files): set above element if BACKUP_MODIFIED_FILES flag is
- present.
-
- * filesubr.c (backup_file): new function.
-
- * cvs.h: prototype for new function `backup_file'.
-
- * update.c (toss_local_changes): new file-scoped global.
- (update): set toss_local_changes if -C flag seen. If
- client_active, send "-C" to server, and set SEND_NO_CONTENTS and
- BACKUP_MODIFIED_FILES flags before calling send_files().
-
- (update_fileproc): if file is modified and toss_local_changes is
- set, then back the file up and then check out a fresh copy from
- the repository. Also, fixed indentation and formatting for a
- particularly bad stretch of code near (but unrelated to) these
- changes.
-
- * sanity.sh: new test `clean', for update -C option.
-
-1999-12-29 Jim Kingdon <http://developer.redhat.com/>
-
- * history.c (read_hrecs): st_blksize is unsigned long, not int.
- This isn't just cosmetic - getting it wrong will cause coredumps
- and such on 64 bit machines.
-
- * import.c (import_descend), ignore.c (ignore_files): Placate gcc
- -Wall by parenthesizing foo || (bar && baz).
-
-1999-12-24 Larry Jones <larry.jones@sdrc.com>
-
- * release.c (release): Use fputs to echo lines from update instead
- of printf to avoid problems with lines containing "%". (Reported
- by Jean-Luc Simard <Jean-Luc.Simard@matrox.com>.)
-
- * history.c (read_hrecs): Allocate a single 2-block buffer instead
- of allocating and freeing a buffer for each block.
- (fill_hrec): Remove redundant code.
- (select_hrec): Plug memory leak.
-
-1999-12-22 Larry Jones <larry.jones@sdrc.com>
-
- * history.c (history): For "modified" or "checkout", sort on
- file if user specified -l, even if user also specified a date-
- oriented flag.
- * sanity.sh (history): Update to match; add new tests.
-
-1999-12-15 Pavel Roskin <pavel_roskin@geocities.com>
- and Larry Jones <larry.jones@sdrc.com>
-
- * lock.c (lock_name): fixed assertion failure for the
- top-level CVS directory when LockDir is used
- * sanity.sh (lockfiles-9): new test for this case
-
-1999-12-11 Karl Fogel <kfogel@red-bean.com>
-
- * Revert previous change -- it doesn't work remotely yet.
-
-1999-12-10 John P Cavanaugh <cavanaug@sr.hp.com>
- and Karl Fogel <kfogel@red-bean.com>
-
- * update.c: new -C option to update, overwrites local changes with
- clean copies from the repository.
- Also, fixed indentation and formatting for a particularly bad
- stretch of code near these changes in update_fileproc().
-
- * sanity.sh: test new update -C option.
-
-1999-12-10 Larry Jones <larry.jones@sdrc.com>
-
- * commit.c (remove_file): Call history_write with update_dir NULL
- like Checkin() does for add and modify.
- * sanity.sh (basic2-64): Update to match, add "R" records to expected
- remote output.
-
-1999-12-09 K.J. Paradise (kj@sourcegear.com)
-
- * history.c, commit.c, sanity.sh: found (I think) final
- cause of seg fault in history command. Also, added the "R"
- history functionality. Fixed basic2-64 so it looks correct for
- the change.
-
-1999-11-30 K.J. Paradise (kj@sourcegear.com)
-
- * history.c: fixed seg fault caused by 11-03 changes.
- off by one in block memory allocations.
-
-1999-11-29 Karl Fogel <kfogel@red-bean.com>
-
- * login.c (logout): free `tmp_name' when done.
- Correct a comment.
-
-1999-11-29 Larry Jones <larry.jones@sdrc.com>
-
- * cvs.h, error.c, import.c: Rename fperror to avoid name clash
- on LynxOS. (Reported by Markus Braun <MarkusBraun@gmx.de>.)
-
-1999-11-23 Larry Jones <larry.jones@sdrc.com>
-
- * checkout.c (checkout_proc): Split declaration and initialization
- of rp to placate neurotic compilers that gripe about jumping past
- an initialization, even when the variable is not subsequently used.
-
-1999-11-19 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (switch_to_user): Correct setgid error messages.
-
-1999-11-19 Karl Fogel <kfogel@red-bean.com>
-
- * edit.c (unedit_usage, unedit): new struct, use it. Now "cvs
- unedit" prints an accurate usage message (formerly it printed the
- message for "cvs edit", even though the two commands do not have
- identical usages).
-
-1999-11-19 Larry Jones <larry.jones@sdrc.com>
-
- * history.c: Move -e documentation from Flags to Reports.
- (history): Add -e to list of report types in error message.
-
- * history.c (history): Process file arguments before client/server
- processing so they get sent to the server.
- * sanity.sh (history): New tests for above. (Also remove comments
- about variable spacing -- history output is in variable-width
- columns with exactly one space between.)
-
-1999-11-19 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh: Reestablish check for running as root (using ``id -u''
- instead of ``whoami'').
-
- * sanity.sh(dotest, dotest_lit, dotest_fail, dotest_status,
- dotest_sort): Eval the command so quoting and pipes work right.
- (spacefiles, dirs, rcslib, modules, unedit-without-baserev,
- ignore, rcs, rcs2, history, tagdate, pserver, server, server2)
- Simplify various tests based on above.
-
-1999-11-19 Karl Fogel <kfogel@red-bean.com>
-
- * mkmodules.c (init): make history file world-writeable after
- creating it, since it needs to be writeable for virtually any
- CVS operation.
-
-1999-11-10 Jim Kingdon <http://developer.redhat.com/>
-
- * admin.c: Revert change to add -H command option. The help
- invocation is "cvs -H admin" not "cvs admin -H" (see cvs.texinfo,
- basicb-21 in sanity.sh; fix to cvs.1)
-
-1999-11-08 Jim Kingdon <http://developer.redhat.com/>
-
- * log.c (cvslog): If client_active, send options to the server
- based on our parsed options rather than trying to send the exact
- strings specified (using canonical forms, like RFC822/1123
- dates, in the protocol is just cleaner).
- (send_one, send_arg_list): New functions, helpers for above.
- * sanity.sh (logopt-6a): New test, for this fix.
-
-1999-11-09 K.J. Paradise <kj@sourcegear.com>
-
- * admin.c: made the -H option do what it is documented to
- do. a
-
-1999-11-08 Tom Tromey <tromey@cygnus.com>
-
- * client.c (connect_to_gserver): Print more error text if gssapi
- initialization fails. From Assar Westerlund <assar@sics.se>.
-
-1999-11-06 Larry Jones <larry.jones@sdrc.com>
-
- *sanity.sh(rcs3-5): Remote output can be out-of-order, so need a
- more general pattern to match the assertion failure.
-
-1999-11-05 K.J. Paradise (kj@sourcegear.com)
-
- * history.c: Added a trap to verify that if a
- read(file, buffer,blocksize) returns less than blocksize,
- that we really are at the end of the file. I can't easily
- come up with a test case where this code gets touched, so
- it may cause problems. All sanity tests still pass though.
-
-1999-11-05 Jim Kingdon <http://developer.redhat.com/>
-
- * sanity.sh (logopt): New test, for Larry's fix.
- * sanity.sh (log-18a, rcs-15 to rcs-19): New tests, to test -d
- and -r more thoroughly.
-
-1999-11-05 Larry Jones <larry.jones@sdrc.com>
-
- * log.c (cvslog): Fix -s and -d with spaces on client side.
- (log_usage): Revert Karl's change once again.
- sanity.sh(rcs3-5): No longer get different results from local
- and client/server.
-
-1999-11-04 Karl Fogel <kfogel@red-bean.com>
-
- * log.c (log_usage): Revert Jim Kingdon's reversion of my change
- of 1999-11-03. Allowing a space between option and argument
- results in lossage; here is a reproduction recipe: run this from
- the top of a remote copy of the cvs source tree
-
- cvs log -d '>1999-03-01' > log-out.with-space
-
- and then run this (note there's no space after -d now):
-
- cvs log -d'>1999-03-01' > log-out.no-space
-
- The resulting files differ; furthermore, a glance at the output of
- cvs shows that the first command failed to recurse into
- subdirectories. Until this misbehavior can be fixed in the source
- code, the documentation should reflect the true state of affairs:
- if one simply omits the space, everything works fine.
-
-1999-11-04 Jim Kingdon <http://developer.redhat.com/>
-
- * log.c (log_usage): Revert Karl's change regarding -d and
- -s. A space is allowed (see sanity.sh for example).
-
-1999-11-03 K.J. Paradise (kj@sourcegear.com>
-
- * history.c: cleaned up my prior change a bit, per Larry Jones'
- comments, and John O'Conner's additional comments about bits of
- non MS-Visual C++ compliancy of my code.
-
-1999-11-04 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh: Check that tr that correctly handles NULs; if not, try
- to find a version that does; if none can be found, warn user.
- Also fix warnings for defective expr.
-
-1999-11-04 Karl Fogel <kfogel@red-bean.com>
-
- Changes for empty/random passwords in anon pserver access:
-
- * server.c (check_repository_password): if password empty, grant
- access no matter what password is received; this is so anon CVS no
- longer requires a password but remains backwards-compatible with
- all those clients out there.
-
- * client.c (connect_to_pserver): proceed with login even if
- password not found in .cvspass file -- just use empty string as
- password. And if such a login fails, print a descriptive error.
-
- * login.c (get_cvs_password): don't complain if file or password
- not found. That condition is no longer a showstopper, now that
- empty passwords are permissible.
- Cleaned up conditional chaining a bit, too.
-
- * sanity.sh (pserver-9, pserver-10, pserver-11, pserver-12,
- pserver-13): new tests, about empty-password pserver access.
-
-1999-11-03 K.J. Paradise (kj@sourcegear.com>
-
- * history.c: modify parsing routines to parse the history
- file a block at a time, rather than all at once. This allows
- people with large history files and small amount of memory
- to still get some functionality out of the history file.
-
-1999-11-03 Karl Fogel <kfogel@red-bean.com>
-
- * log.c (log_usage): correct usage message for -d and -s options.
- Because the space between the option letter and its argument has
- been eliminated, I capitalized the argument portion to distinguish
- it from the option letter. This makes it slightly inconsistent
- with other such usage summaries, but at least it is now both
- correct and readable.
-
-1999-10-22 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (dotest_sort): Old versions of tr don't understand \t
- so use a literal tab instead.
-
-1999-10-21 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (dotest_sort): Convert any tabs in the output into spaces
- before sorting to avoid POSIX.2 sort weirdness.
- (import-106, importb-2): Change expected output per above.
-
-1999-10-18 K.J. Paradise <kj@sourcegear.com>
-
- Bug: users 'stan' and 'cartman' both have full read/write access
- to the cvs repository. 'cartman' does a 'cvs admin -l foo.c'.
- 'stan' then does a 'cvs admin -u foo.c'. The lock wouldn't be
- removed, and no warning/error would be given. This is now fixed.
- * rcs.c:(c.6157) remove caller/user check on the multiple lock
- detection routines. Sanity.sh runs with no errors after this fix.
-
-1999-10-14 Larry Jones <larry.jones@sdrc.com>
-
- Make "cvs admin -e" (with no list of users) work:
- * admin.c (admin): Remove error message.
- (admin_fileproc): If no args for -e, call RCS_delaccess with NULL user.
- * rcs.c (RCS_delaccess): Interpret NULL user as request to delete
- entire access list.
- * sanity.sh (admin-19a-*): Test.
-
-1999-09-29 Larry Jones <larry.jones@sdrc.com>
-
- * entries.c (Subdirs_Known): Use entfilename when opening CVSADM_ENTLOG
- like everywhere else. Although this isn't strictly necessary (since
- we immediately close it again), it keeps the code consistent and fixes
- a bug where an open error reported the wrong file name.
-
-1999-09-16 Larry Jones <larry.jones@sdrc.com>
-
- * log.c (log_parse_revlist): Handle peculiar revision specs like
- "-r.", "-r:", and "-r," correctly. (Thanks to Pavel Roskin
- <pavel_roskin@geocities.com> for submitting a patch, this fix is
- somewhat different.)
- * sanity.sh (log): New tests for above.
-
-1999-09-15 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (basica-8b1): New test to check fix for bad diff options
- causing cvs to crash.
-
-1999-09-02 Larry Jones <larry.jones@sdrc.com>
-
- * modules.c (do_module): Handle case where module definition has
- options and special options but no directory; fix potential problems
- running off beginning of string while stripping trailing blanks.
- * sanity.sh (modules2): New tests for above.
-
-1999-08-26 Larry Jones <larry.jones@sdrc.com>
-
- * lock.c (lock_name): Remove side-effects from assert() expression
- since they won't occur if NDEBUG is defined (not that that's a good
- thing to do). (Reported by KOIE Hidetaka <hide@koie.org>.)
-
-1999-08-25 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh: Use "${AWK}" instead of "awk" to make it easier for
- people to use nawk/gawk/etc.; use an explicit "-print" with find
- since some older version don't assume it; rename tests to avoid
- duplicate importc-8. (Changes along these lines suggested by
- Chris Cameron <chris.cameron@ot.co.nz>.)
-
-1999-08-24 Larry Jones <larry.jones@sdrc.com>
-
- * commit.c (check_fileproc): Don't crash when a file has no
- repository, just treat it as unknown. (Reported by Stefaan
- Diericx <stefaan.diericx@argenta.be>.)
- * sanity.sh (errmsg2): New tests, for this fix.
-
-1999-08-18 Larry Jones <larry.jones@sdrc.com>
-
- * update.c (special_file_mismatch): Initialize *_hardlinks to
- avoid trying to free garbage later on. (Reported by Jan
- Scheffczyk <herta@Xterminator.StudFB.UniBw-Muenchen.de>.)
-
-1999-08-17 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (basicc-11): Older versions of sh don't understand
- ``if ! test...''. (Patch submitted by David J N Begley
- <david@avarice.nepean.uws.edu.au>.)
-
-1999-08-17 Larry Jones <larry.jones@sdrc.com>
-
- * client.c, hardlink.c, hash.c, hash.h, main.c, recurse.c: Change
- enum constant UNKNOWN to avoid conflicts on HPUX 11.0. (Reported
- by Laurent Duperval <laurent.duperval@cgi.ca>.)
-
-1999-08-16 Larry Jones <larry.jones@sdrc.com>
-
- client.c: Eliminate redundant #if. (Patch submitted by Assar
- Westerlund <assar@sics.se>.)
-
-1999-07-30 Larry Jones <larry.jones@sdrc.com>
-
- * rcs.c (RCS_checkin): Terminate cleanly if RCS_addbranch fails
- rather than blithely continuing on and crashing.
- * sanity.sh (basica): New tests, for this fix.
-
-1999-07-29 Larry Jones <larry.jones@sdrc.com>
-
- * import.c (add_rcs_file): change "cannot lstat" message to include
- userfile (the actual file causing the problem) instead of user
- (which may or may not be the same).
-
-1999-07-29 Eric Sink <eric@sourcegear.com>
-
- * version.c: Push version number to 1.10.7.1.
-
- * version.c: Version 1.10.7.
-
-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'.
-
- * sanity.sh (rcslib): new tests to check behavior of symlinks in
- the repository.
-
-Wed Aug 12 15:39:38 1998 Noel Cragg <noel@swish.red-bean.com>
-
- * main.c (lookup_command_attribute): the `annotate' command
- shouldn't require access to the repository. Add comment about
- commands that do not use the working directory.
-
-Mon Aug 10 10:26:38 1998 Noel Cragg <noel@swish.red-bean.com>
-
- * version.c: Change version number to 1.9.30.
-
-Thu Aug 6 17:44:50 1998 Noel Cragg <noel@swish.red-bean.com>
-
- * server.c (serve_rdiff): change the name of the command (for
- error reporting, etc.) from "patch" to "rdiff."
- (serve_remove): rename from "cvsremove" to "remove."
-
- * main.c (lookup_command_attribute): the `rdiff' command shouldn't
- require write access to the repository.
-
-1998-08-06 David Masterson of kla-tencor.com
- and Jim Kingdon
-
- * commit.c (commit_filesdoneproc): Don't call strlen ("CVSROOT")
- from within the assert statement. Apparently HP's cc compiler on
- HPUX 10.20 has trouble with that.
-
-1998-08-06 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_checkin): When adding branch, if there is a lock on
- the branchpoint owned by someone else, leave it alone. This
- restores CVS 1.9 (RCS 5.7) behavior, fixing a core dump.
- * sanity.sh (reserved): New tests reserved-16 through reserved-19
- test for this fix.
-
-1998-08-05 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (unedit-without-baserev): Use ${QUESTION} not "?".
- This makes it work with GNU expr 1.12 as well as 1.16.
-
-Sun Aug 2 20:27:44 1998 Noel Cragg <noel@swish.red-bean.com>
-
- * mkmodules.c: add comment about TopLevelAdmin for the initial
- contents of CVSROOT/config.
-
-1998-07-29 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_checkin): Only try to call xreadlink if HAVE_READLINK
- is defined.
-
-Tue Jul 28 19:33:08 1998 Noel Cragg <noel@swish.red-bean.com>
-
- * version.c: Change version number to 1.9.29.
-
- * rcs.c (RCS_checkin): add code to follow symbolic links in the
- repository.
-
-Sun Jul 26 05:14:41 1998 Noel Cragg <noel@swish.red-bean.com>
-
- * This set of changes reverts the code to pre-1.9.2 behavior and
- 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.
-
- * checkout.c (checkout_proc): only generate the top-level
- directory when the TopLevelAdmin=yes. Also send a message to the
- client to do the same.
-
- * parseinfo.c (parse_config): handle TopLevelAdmin option. Set
- top_level_admin.
-
- * main.c: add new variable top_level_admin.
- * cvs.h: add extern definition for above.
-
- * sanity.sh: since we're reverting to pre 1.9.2 behavior for
- top-level CVS directories, I needed to make changes to a bunch of
- tests that made assumptions about said directories.
- (preamble): make sure to add read and execute access to everything
- in TMPDIR before removing, since some tests make things read-only.
- (basicb-1a, basicb-1b, basicb-9a, basicb-9b): use dotest_fail
- because these tests check for the non-existant top-level CVS
- directory.
- (basicc-3, emptydir-6, emptydir-7, crerepos-6): use "rm -rf" so it
- won't complain when trying to remove the non-existant top-level
- CVS directory.
- (106.5): remove imported-f2-orig.tmp.
- (modules2-10, emptydir-4, abspath-1ba, abspath-1bb): cd into the
- directory where files exist before using the "add" command so cvs
- can find CVSROOT in CVS/Root.
- (cvsadm-2): look at a different CVS/Repository file, since the
- top-level one doesn't exist.
- (taginfo-3): create the directory in the repository directly
- rather than relying on the fact that the top-level CVS directory
- was created in a previous test.
- (serverpatch-6): update first-dir explicity, rather than relying
- on the non-existant top-level CVS/Entries file.
- (crerepos-18): look at CVS/Repository in a subdirectory rather
- than in the non-existant top-level CVS directory.
- (toplevel): add code to set TopLevelAdmin=yes.
- (toplevel2): new tests -- same as toplevel, but TopLevelAdmin=no.
-
-1998-07-21 Jim Meyering <meyering@ascend.com>
-
- * rcs.c (RCS_checkout): Hoist frees of rev and value.
- Warn and return 1 in several cases rather than exiting via
- `error (1, ...'. The latter could abort a multi-file commit
- in mid-stream, leaving stale locks in the repository.
-
-1998-07-16 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * build_src.com (rcscmds.c): Also look for include files in
- [-.diff], just like Ian's 1998-06-18 change to Makefile.in
-
-1998-07-14 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * tag.c (pretag_proc), rtag.c (pretag_proc): Don't pass RUN_REALLY
- to run_exec. This means that taginfo does not get executed if the
- global -n option is specified. Which makes it like loginfo, -i,
- -e, -o, -t, -u in modules, editinfo, and verifymsg and unlike
- commitinfo. The old behavior was pretty bad in the sense that it
- doesn't provide any way to log only the tags which actually
- happen.
- * sanity.sh (taginfo): New tests taginfo-11 to taginfo-13, for this.
-
-1998-07-12 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (ann-id): Write the test so that it tests for the
- current (buggy) behavior.
-
- * sanity.sh (taginfo): Also clean up cvsroot/first-dir.
-
-1998-07-12 Jim Meyering <meyering@ascend.com>
-
- * sanity.sh (ann-id): New (currently failing) test for bug in how
- rcs keywords are expanded in the output of `cvs annotate'.
-
-1998-07-12 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (taginfo): Write the TESTDIR into the script rather
- than having the script look at the environment. This means that
- it will work if TESTDIR is set by sanity.sh as well as if
- sanity.sh finds TESTDIR in the environment.
-
-1998-07-11 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * tag.c (check_fileproc): Calculate the revision to be tagged the
- same way that tag_fileproc does.
- * sanity.sh (taginfo): New tests, test for this (before this fix,
- brtag had said 1.1 not 1.1.2.1).
-
-1998-07-10 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (unedit-without-baserev): Also clean up "2" directory.
-
-1998-07-08 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * edit.c (unedit_fileproc): If the Baserev file is missing, don't
- get the working file from CVS/Base. The previous code could get
- you version 1.1 of the working file and put 1.2 in CVS/Entries.
- * sanity.sh (unedit-without-baserev): New tests test for this.
-
-1998-07-02 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (unedit-without-baserev): Move the test itself to be
- in the same order as in the "tests" variable.
-
-1998-07-02 Ian Lance Taylor <ian@cygnus.com>
-
- * rcscmds.c: Don't include <stdarg.h> or <vasprintf.h>. Don't
- declare vasprintf.
- (call_diff_printf_output): Remove.
- (call_diff_stdout_callbacks): Don't initialize printf_output
- field--it has been removed from the interface.
- (call_diff_file_callbacks): Likewise.
-
-1998-07-01 Jim Meyering <meyering@ascend.com>
-
- * edit.c (unedit_fileproc): Handle the case in which base_get
- returns a NULL baserev. That happens when a file being `unedit'ed
- exists in the CVS/Base directory, but isn't listed in the CVS/Baserev
- file. The one case I've seen had no Baserev file at all. The symptom
- (if you're lucky) is a segmentation fault upon unedit. If you use
- SunOS4.1.4 for which printf prints NULL pointers as `(null)', your
- unedit command will complete normally, but it will have corrupted
- your CVS/Entries file and a subsequent update may result in an
- assertion failure, a core dump, and a stale lock in the repository.
- * sanity.sh (unedit-without-baserev): New test for this.
-
-1998-07-01 Andy Mortimer of aeat.co.uk
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (server_updated): Use a prototype if we are using them
- for declarations.
-
-1998-06-29 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (commit-readonly): Protect keyword against expansion
- in sanity.sh itself. Keep the keyword in the file which we check
- in (or else this fails to test for the RCS_checkout change).
-
-1998-06-27 Jim Meyering <meyering@ascend.com>
-
- * rcs.c (RCS_checkout): If opening the local workfile fails due to
- lack of write access, try to chmod the file and retry the open.
- Before, a commit could fail part way through merely because the
- open to rewrite with newly expanded rcs keywords would fail. It's
- easy to make this happen if you use `cvs -r' or CVSREAD and you
- apply a patch to one of your read-only source files -- patch
- preserves the read-only setting for the file and your next commit
- will fail after committing that file, but before rewriting
- (checking out) your working copy.
- * sanity.sh (commit-readonly): New test for this.
-
-1998-06-25 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (patch_file): Update comments regarding context diffs
- to reflect diff library.
-
-1998-06-23 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (modules4): Add tests for reversing the order of the
- "!first-dir/sdir" and "first-dir".
-
-1998-06-23 Jim Kingdon <kingdon@harvey.cyclic.com>
- and Dave Wolfe@Motorola.
-
- * sanity.sh (modes2): Touch the file before chmod'ing it.
-
-1998-06-21 Ian Lance Taylor <ian@cygnus.com>
-
- * update.c (merge_files): Revert changes of 1998-06-19. Instead,
- register a merged file with a dummy time stamp. Only set
- last_register_time if we need to.
- (join_file): Likewise. Always register a merged file, not just
- when the merge fails.
-
-1998-06-21 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * call_diff_write_output, call_diff_printf_output,
- call_diff_flush_output, call_diff_write_stdout, call_diff_error,
- call_diff_stdout_callbacks, call_diff_file_callbacks): Re-indent.
-
-1998-06-19 Ian Lance Taylor <ian@cygnus.com>
-
- * update.c (merge_file): Make sure the time stamp of the file is
- different from the time stamp we register in the Entries file.
- (join_file): Likewise.
-
-1998-06-18 Ian Lance Taylor <ian@cygnus.com>
-
- * rcscmds.c: Include <stdio.h>. Include either <stdarg.h> or
- <varargs.h>. Declare vasprintf.
- (call_diff_write_output): New static function.
- (call_diff_printf_output): New static function.
- (call_diff_flush_output): New static function.
- (call_diff_write_stdout): New static function.
- (call_diff_error): New static function.
- (call_diff_stdout_callbacks): New static variable.
- (call_diff_file_callbacks): New static variable.
- (call_diff): Don't sleep. Use a callback structure when calling
- the diff library.
- (call_diff3): Likewise.
-
- * rcscmds.c: Include diffrun.h.
- (call_diff, call_diff3): Pass NULL callback parameter.
- (diff_run, diff3_run): Don't declare.
- * Makefile.in (rcscmds.o): New target, to use -I for diff
- directory.
- (zlib.o): Depend upon zlib.h.
-
-1998-06-09 Mike Sutton@SAIC
-
- Make it compile with Sun's bundled K&R C compiler:
- * rcs.c (count_delta_actions): Change to static to match
- declaration.
- * client.c (handle_wrapper_rcs_option): Rename error label to
- handle_error to avoid clash with function name.
-
-1998-06-09 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_delete_revs): If we are trying to delete all
- revisions, give an error rather than assertion failed.
- * sanity.sh (basicb): New tests basicb-o* test for this.
-
-1998-06-04 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c (add): Only send "Directory" requests if we need to.
-
-1998-06-02 Assar Westerlund <assar@sics.se>
-
- * client.c: Check for HAVE_GSS_C_NT_HOSTBASED_SERVICE rather than
- assuming that GSS_C_NT_HOSTBASED_SERVICE is a macro.
- * server.c: Likewise.
-
-1998-06-02 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * fileattr.c (fileattr_read): Check for NULL return from strchr.
- * sanity.sh (devcom3): New test devcom3-10 checks for this.
-
-1998-06-01 Assar Westerlund <assar@sics.se>
- and Ian Lance Taylor <ian@cygnus.com>
-
- * client.c: If HAVE_GSSAPI_H, include <gssapi.h>. Only include
- <gssapi/gssapi.h> if HAVE_GSSAPI_GSSAPI_H. Only include
- <gssapi/gssapi_generic.h> if HAVE_GSSAPI_GSSAPI_GENERIC_H.
- (GSS_C_NT_HOSTBASED_SERVICE): Define if not defined.
- (connect_to_gserver): Use GSS_C_NT_HOSTBASED_SERVICE instead of
- gss_nt_service_name.
- * server.c: Same header file changes.
- (GSS_C_NT_HOSTBASED_SERVICE): Define if not defined.
- (gserver_authenticate_connection): Use GSS_C_NT_HOSTBASED_SERVICE
- instead of gss_nt_service_name.
-
-1998-06-01 Jim Meyering <meyering@ascend.com>
-
- * sanity.sh (tag8k): Add a test for the 1998-05-02 rcs.c bug fix.
-
-1998-05-26 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (annotate): Call tag_check_valid like the other functions
- which have a -r option.
- * sanity.sh (ann): New test ann-14 tests for this.
-
-1998-05-24 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (importc): New tests importc-5 through importc-8 test
- for a (fairly obscure) regression from CVS 1.9.
-
-1998-05-23 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (modules2): Add comment listing cvs release tests.
- (info): New test info-cleanup-0 tests "cvs -n release".
-
- * rcs.c (rcsbuf_getid): Remove semicolon at end of #undef. I'm
- kind of surprised that compilers accepted this at all, but
- removing it squelches a warning for some compilers.
-
- * version.c: Change version number to 1.9.28.1.
-
- * Version 1.9.28.
-
-1998-05-22 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_cmp_file): Check for errors from CVS_FOPEN. This
- restores the CVS 1.9 behavior (fatal error if we can't open the
- file), and corrects an apparent oversight in Ian's 13 Apr 1997
- change.
- * sanity.sh (modes2): New test, tests for this.
-
-1998-05-22 Ian Lance Taylor <ian@cygnus.com>
-
- * server.c (server_updated): Correct test for whether to unlink
- the file.
-
-1998-05-20 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * wrapper.c (wrap_add): Disable -t/-f wrappers at least until the
- serious bug can be fixed.
-
-1998-05-15 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * checkout.c (checkout): Call server_pathname_check on the
- argument to "cvs co -d".
- * server.c (server_pathname_check): Add comment about how we could
- be handling absolute pathnames.
- * sanity.sh (abspath): Rewrite the tests which run "cvs co -d /foo"
- for remote, to reflect this.
-
- * sanity.sh (abspath): Also do the "cannot rename" work-around for
- abspath-7d.
-
-1998-05-13 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c (commit_filesdoneproc): Free admin_dir when done with it.
-
-1998-05-13 Jim Meyering <meyering@ascend.com>
-
- * sanity.sh (editor): Change bogus sed command, `s/^/x&/g', to `s/^/x/'.
- The former exercised a bug in GNU sed-3.01-beta3.
- (emptydir-8): Add `Rebuilding administrative file database' message,
- since now it does that.
- * commit.c (commit_filesdoneproc): Pass only the admin directory
- pathname to mkmodules.
- Remove #if 0, now that it's fixed.
-
- * status.c (cvsstatus): Rename from `status' to avoid shadowing
- lots of locals and parameters by the same name.
- * server.c (serve_status): Update caller.
- * main.c (cmds[]): Update table entry.
- * cvs.h: Update prototype.
-
- * commit.c (commit_filesdoneproc): Remove trailing blanks.
- (commit) [CLIENT_SUPPORT]: Remove unnecessary (and local-shadowing)
- declaration of `err'.
- Rename global `tag' to `saved_tag' to avoid overshadowing `tag'
- parameters of three functions.
- Rename global `message' to `saved_message' to avoid overshadowing
- `message' parameter of a function.
- Rename global `ulist' to `saved_ulist' and move dcl up with others.
-
-1998-05-12 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c (commit_filesdoneproc): #if 0 the new code until it can
- be fixed.
-
- * commit.c (commit_filesdoneproc): Add comment explaining last
- change.
-
-1998-05-12 Jim Meyering <meyering@ascend.com>
-
- * commit.c (commit_filesdoneproc): Call mkmodules not just when
- committing a file directly under CVSROOT, but also when committing
- files in subdirectories of CVSROOT.
-
-1998-05-08 Jim Meyering <meyering@ascend.com>
-
- * filesubr.c (xreadlink): NUL-terminate the symbolic link name.
- Use a much smaller initial buffer length.
- Test errno only if readlink fails.
- Use xstrdup then free the original link name so we don't waste space.
-
-1998-05-02 Jim Meyering <meyering@ascend.com>
-
- * rcs.c (rcsbuf_getword): Fix off-by-one error that would result in
- an abort (the first one in rcsbuf_getkey) when operating on on some
- ,v files with over 8192 bytes of tag and branch info.
-
-1998-05-04 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (ann): New tests ann-12 and ann-13 test for specifying
- a numeric branch.
-
-1998-05-02 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c: Add comments about getting rid of rcsbuf_getid,
- rcsbuf_getword, and rcsbuf_getstring.
-
- * sanity.sh (abspath): Revise the workarounds to deal with exit
- status.
-
-1998-04-30 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (abspath): Work around the "cannot rename" bug.
-
-1998-04-27 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * classify.c (Classify_File): Add comments about checking whether
- command name is "update".
-
-1998-04-22 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Change version number to 1.9.27.1.
-
- * Version 1.9.27.
-
-1998-04-20 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- (This diff was run by devel-cvs and everyone seemed to like it).
- * diff.c (diff_file_nodiff): Make HEAD mean the head of the branch
- which contains the sticky tag, not the sticky tag itself.
- * rcs.c, rcs.h (RCS_branch_head): New function.
- * sanity.sh (head): Update for this changed behavior.
-
-1998-04-19 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Move emptydir tests from basicb to new test emptydir.
- This is because we now need a module definition to create Emptydir;
- "co -d" doesn't cut it anymore.
-
-1998-04-17 Petri Virkkula
-
- * server.c (mkdir_p): Ignore EROFS error (like for EACCES).
-
-1998-04-16 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * checkout.c (checkout_proc): Don't create directories above the
- last one specified in "co -d".
- (build_dirs_and_chdir): Revert Noel's change of 17 Feb 1998.
- (struct dir_to_build): New field just_chdir.
- (build_dirs_and_chdir): Test it.
- * sanity.sh (abspath): New tests abspath-7* test for a bug which
- we fix, in which CVS would create bogus "D/////" entries in
- CVS/Entries.
- (abspath): Revise abspath-3* tests to test for the fact that we no
- longer create directories above the last one specified in "co -d".
- I checked that CVS 1.9 gives an error on this, so changing this
- behavior back should be OK.
- (cvsadm-2d3): Likewise (also checked CVS 1.9 for this case).
- (cvsadm-2d3d): Likewise (also checked CVS 1.9 for this case).
- (cvsadm-2d{4,5,6,7,8}, cvsadm-N2d{3,4,5,6,7,8}): Adjust for new
- behavior (same case as cvsadm-2d3).
- (cvsadm-2d{4,5,6,7,8}d, cvsadm-N2d{3,4,5,6,7,8}d): Remove test
- (same case as cvsadm-2d3d).
- (cvsadm): For remote, skip most these tests.
- (abspath): When cleaning up, delete mod1 and mod2 rather than mod1
- twice (longstanding bug, apparently only becomes visible if you
- run the tests in a certain order).
-
-1998-04-14 Wilfredo Sanchez <wsanchez@apple.com>
-
- * rcs.c: variable "lockfile" was being referenced after being
- free'd. Bad. Moved the free() call down.
-
-1998-04-12 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (rcs): Add test for annotate and the year 2000.
-
- * server.c (do_cvs_command): If there are partial lines left when
- the child process is done, send them along.
- * sanity.sh (rcs, rcs2): Enable all tests for remote; tests for
- this fix.
-
-1998-04-11 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (client_senddate): Pass SDATEFORM not DATEFORM to
- sscanf. This fixes a Y2K bug.
-
- * history.c (history, select_hrec): Change since_date from time_t
- to RCS format. Use the usual machinery (in particular, Make_Date
- and client_senddate) so that it will work on VMS too.
- * main.c, cvs.h (date_from_time_t): New function.
- * sanity.sh (history): New test, to test that this didn't break
- anything (also tests client_senddate fix).
-
-1998-04-11 Norbert Kiesel <nk@iname.com>
-
- * server.c (cvs_output_binary): Shut up "gcc -Wall" by removing
- unnecessary else if test.
- * server.c (check_password): Fix uninitialized memory read if
- shadow passwords are used. Also added some comments.
- * rcs.c (RCS_checkout): Make sure to call chown with -1 for uid or
- gid if they should not be changed
-
-1998-04-10 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (rcs2): New test, tests for various Y2K cases.
- * rcs.c (getdelta): Value for "state" keyword is optional (bug
- discovered incidentally in writing rcs2 test).
-
-1998-04-09 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * filesubr.c, cvs.h (link_file): Remove; no longer used.
-
-1998-04-08 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * recurse.c (do_dir_proc): Restore update_dir rather than a
- computation which appears to, but does not necessarily, restore it
- (reported by various people; this fix is from Greg Hudson).
- * sanity.sh (importc): New test, tests for this fix.
-
-1998-03-27 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_lock): If the revision is already locked, give an
- error rather than dumping core.
- * sanity.sh (reserved): New test reserved-13c tests for this.
-
-1998-03-25 Loren J. Rittle
-
- * import.c (add_rev): Rewrite to use RCS_FLAGS_KEEPFILE option
- of RCS_checkin() to avoid damage to imported files instead of
- externally undoing damage after the fact. The side effect is
- that callers of add_rev() may now incrementally walk the
- entries of the current directory without seeing gratuitous
- changes to the directory structure (under at least one file
- system under at least one OS).
-
-1998-03-18 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * error.c (error): Save and restore errno. Should fix test case
- conflicts3-23 on SCO 5.0.2. Reported by Steve Cameron.
-
- * sanity.sh (admin): Rename admin-26-o* to admin-26-*; the "o"
- stands for "cvs admin -o". Add comment about length of tests.
- Use ${PLUS}.
-
-1998-03-05 Dan Wilder <dan@gasboy.com>
-
- * Fix problem with cvs admin in which -ntag:branch
- option associated tag with the branch's head revision.
- Should have used branch number. Entailed in this fix,
- the following.
-
- * Add new functions "RCS_exist_rev", "RCS_exist_tag",
- "RCS_tag2rev", and "RCS_valid_rev" to rcs.c. RCS_tag2rev
- is similar to RCS_gettag, but does less interpretation.
-
- * Plug a small memory leak.
-
- * Add tests admin-26 through admin-29 to sanity.sh,
- to test "cvs admin -n".
-
-1998-03-17 Samuel Tardieu <sam@inf.enst.fr>
-
- * server.c (server_register): protect dereferencing timestamp in
- the trace message when it is null, to avoid a segmentation fault.
-
-1998-03-16 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * options.h.in (MY_NDBM): Rewrite the comment explaining this
- option. It was not clear to everyone who "my" referred to, for
- example.
-
- * hardlink.c (list_linked_files_on_disk): Remove unused variables
- err and p.
- (list_linked_files_on_disk): Add comment about memory allocation
- of return value.
- * rcs.c (rcsbuf_getword): Shut up gcc -Wall with a "return 0".
- (RCS_checkin): Remove unused variable fullpath.
- * sanity.sh (hardlinks): Remove comment about spurious warnings;
- the warnings are gone.
-
-1998-03-12 Tim Pierce <twp@skepsis.com>
-
- New functions for parsing and writing hardlink fields.
- * rcs.c [PRESERVE_PERMISSIONS_SUPPORT] (puthardlink_proc): New
- function.
- (putdelta) [PRESERVE_PERMISSIONS_SUPPORT]: Use it.
- (rcsbuf_getid, rcsbuf_getstring, rcsbuf_getword): New functions.
- (getdelta): Call them, storing `hardlinks' field in vnode->hardlinks.
- (RCS_reparsercsfile): When setting rdata->desc, xstrdup value
- rather than rcsbuf_valcopying it (due to changes in how getdelta
- handles keys and values in newphrases).
-
- * sanity.sh (hardlinks): Use uglier filenames. Checking out
- hardlinked files no longer produces the same spurious diagnostics,
- so fix that test.
- (hardlinks-2.3): Renamed from hardlinks-2.2 (duplicate test name).
-
- New infrastructure for managing hardlink lists internally...
- * hardlink.c, hardlink.h (list_linked_files_on_disk,
- compare_linkage_lists, find_checkedout_proc): New functions.
- * rcs.h (struct rcsversnode) [PRESERVE_PERMISSIONS_SUPPORT]: New
- member `hardlinks'.
- * update.c (special_file_mismatch): Get hardlinks from
- vp->hardlinks instead of from vp->other_delta.
- * rcs.c (free_rcsvers_contents): Comment about freeing hardlinks
- member.
- (RCS_checkout) [PRESERVE_PERMISSIONS_SUPPORT]: Get hardlinks from
- vers->hardlinks list instead of vers->other_delta.
-
- ... and removed obsolete code from earlier revs.
- * hardlink.c, hardlink.h (list_files_linked_to,
- cache_hardlinks_proc, list_files_proc, set_hardlink_field_proc):
- Removed.
- * hardlink.h: Removed `links' member from hardlink_info struct.
- * commit.c (commit): Remove the call to cache_hardlinks_proc.
- (check_fileproc) [PRESERVE_PERMISSIONS_SUPPORT]: Removed reference
- to hlinfo->links.
- * hardlink.c (update_hardlink_info): Same.
- * update.c (get_linkinfo_proc): Same.
-
- * rcs.c (RCS_checkout) [PRESERVE_PERMISSIONS_SUPPORT]: Use
- vp->hardlinks and find_checkedout_proc to find recently-updated
- files that may be hardlinked.
- * update.c (special_file_mismatch): Use List * structures and
- compare_linkage_lists for rev1_hardlinks and rev2_hardlinks.
-
-1998-03-16 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (check_password): If shadow passwords are supported but no
- entry is found in the shadow file, check the regular password file.
-
-1998-03-07 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Rename permissions test to perms since that is what
- each of its individual tests are named.
- * sanity.sh (perms symlinks hardlinks): Change CVSROOT to
- CVSROOT_DIRNAME where appropriate.
- (perms symlinks hardlinks): Disable/adjust the meat of the tests for
- remote.
- (symlinks): Link to ${TESTDIR}/fumble rather than
- /fumble/mumble/grumble. We shouldn't be making assumptions about
- what might exist in random directories outside ${TESTDIR}.
- * hardlink.c (cache_hardlinks_proc): Add comment about trimming
- whitespace.
-
-1998-03-07 Tim Pierce <twp@skepsis.com>
-
- * rcs.c (RCS_checkout): Negation bug when checking out symlinks:
- existence_error should be !existence_error.
- * sanity.sh (permissions symlinks hardlinks): New tests, for
- PreservePermissions.
-
-1998-03-04 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Change version number to 1.9.26.1.
-
- * Version 1.9.26.
-
- * entries.c, cvs.h (Entries_Open): New argument update_dir; use it
- in error message.
- * add.c, checkout.c, client.c, find_names.c, import.c, recurse.c,
- update.c: Pass it (as NULL except in call_in_directory).
- * entries.c (Subdirs_Known): Just return if there is no CVSADM
- directory (as in subdir_record).
- * sanity.sh (conflicts3): New tests conflicts3-20a and
- conflicts3-23 test for these fixes.
-
- * commit.c (commit): Only set up hardlist if preserve_perms.
-
- * commit.c, import.c, no_diff.c, parseinfo.c, rcs.c, rcscmds.c,
- update.c: Omit the preserve_perms code if
- PRESERVE_PERMISSIONS_SUPPORT is not defined. Much of that code
- won't even compile on non-unix systems.
-
- * hardlink.c, hardlink.h: Use the 'standard' copyright (as found
- in server.c).
- * commit.c, rcs.c: Minor whitespace changes to Tim's submission.
- * commit.c (check_fileproc), update.c (get_linkinfo_proc): Remove
- unused variable delta.
- * hardlink.c (set_hardlink_field_proc), update.c
- (get_linkinfo_proc): Return a value rather than falling off the
- end of the function.
-
-1998-03-02 Tim Pierce <twp@skepsis.com>
-
- * update.c (special_file_mismatch): Compare the hard links of the
- two revisions.
-
- * rcs.c (RCS_checkout):
-
- * hardlink.c, hardlink.h: New files.
- (hardlink_info): New struct.
- (hardlist, working_dir): New variables.
- (list_files_proc, cache_hardlinks_proc, set_hardlink_field_proc,
- lookup_file_by_inode, update_hardlink_info, list_files_linked_to):
- New functions.
-
- * Makefile.in (SOURCES): Add hardlink.c.
- (OBJECTS): Add hardlink.o.
- (HEADERS): Add hardlink.h.
- * commit.c: Include hardlink.h.
- (commit): Save the working directory before recursing. Walk the
- hardlink list, calling set_hardlink_field_proc on each node.
- (check_fileproc): Add each file's link information to hardlist.
- * rcs.c: Include hardlink.h.
- (RCS_checkin): Save list of hardlinks in delta node.
- (RCS_checkout): Look up the file's `hardlinks' delta field, and
- see if any of the files linked to it have been checked out
- already. Link to one of those files if so.
- * update.c: Include hardlink.h.
- (get_linkinfo_proc): New function.
- (do_update): Extra recursion to collect hardlink info.
- (special_file_mismatch): Reparse the RCS file if necessary.
-
- fsortcmp is now used by several files, so let's make it extern.
- * hash.c, hash.h (fsortcmp): New function.
- * find_names.c (fsortcmp): Removed.
- * lock.c (fsortcmp): Removed.
-
-1998-03-03 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (conflicts3): New tests conflicts3-14a,
- conflicts3-14b, and conflicts3-21, conflicts3-22 test that we can
- skip over a working directory with a CVSADM directory missing.
-
-1998-02-26 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (conflicts3): Tests conflicts3-16 and conflicts3-20
- test that we include update_dir in messages. Rename test
- conflicts3-14 to fix typo.
-
-Sun Feb 22 23:14:25 1998 Steve Cameron <steve.cameron@compaq.com>
- and Ian Lance Taylor <ian@cygnus.com>
-
- * update.c (tag_update_dir): New static variable.
- (update_dirent_proc): If no tag or date were specified when
- creating a subdirectory, use the tag and/or date of the parent
- directory.
- (update_dirleave_proc): If we set the tag and/or date in
- update_dirent_proc, reset them when we leave the directory.
- * sanity.sh (branches2): New set of tests for above patch, and
- related behaviour.
-
-Sun Feb 22 13:31:51 1998 Ian Lance Taylor <ian@cygnus.com>
-
- * commit.c (lock_RCS): Don't call RCS_rewrite.
-
- * update.c (patch_file): If the revision is dead, let
- checkout_file handle it.
- * sanity.sh (death2): Add test for above patch: add
- death2-10a, death2-10b, death2-13a, and adjust
- death2-{2,4,5,11,14,diff-11,diff-12,19}.
-
- * cvs.h (RCS_FLAGS_KEEPFILE): Define.
- * rcs.c (RCS_checkin): If RCS_FLAGS_KEEPFILE is set in the flags
- parameter, don't unlink the working file.
- * checkin.c (Checkin): Don't copy the file. Instead pass
- RCS_FLAGS_KEEPFILE to RCS_checkin, and only check the file out
- again if it has changed.
-
-1998-02-21 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (rcs_internal_unlockfile, RCS_rewrite): Don't assume errno
- means anything just because ferror is set.
-
-Sat Feb 21 20:02:24 1998 Ian Lance Taylor <ian@cygnus.com>
-
- * Makefile.in (clean): Change "/bin/rm" to "rm".
-
- * buffer.c (buf_append_buffer): Correct typo in comment.
- * rcs.c (RCS_putadmin): Likewise.
-
-Fri Feb 20 17:53:06 1998 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (rcs_internal_unlockfile): Pass errno when calling error
- because ferror is true.
-
-1998-02-20 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (abspath): Don't assume that we can't write to /; this
- is the kind of thing that is sure to break sooner or later
- (especially on Windows).
-
- * sanity.sh: Add summary of which modules tests are which (at
- "modules"). Move cvsadm, abspath, and toplevel next to modules.
- Add comments to clarify the structure (such as it is).
-
-Fri Feb 20 12:47:14 1998 Larry Jones <larry.jones@sdrc.com>
-
- * admin.c (admin_fileproc): Better fix for -b.
-
- * rcs.c (RCS_whatbranch): Back out previous change.
- (RCS_getversion): Ditto.
- (RCS_setbranch): Treat an empty revision string like a null pointer.
-
-1998-02-18 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_whatbranch): Fix indentation.
-
- * patch.c (patch_fileproc): Check for errors from fclose; check
- for errors from fopen properly.
-
-Wed Feb 18 16:03:37 1998 Larry Jones <larry.jones@sdrc.com>
-
- * admin.c (admin_fileproc): Convert -b argument from symbolic name
- to revision number before storing in the RCS file.
- * rcs.c (RCS_whatbranch): Allow numeric as well as symbolic revision.
- (RCS_getversion): Take advantage of above.
- * sanity.sh (admin): Add/revise/renumber admin-10c, admin-11a,
- admin-12, and admin-12a to check above.
-
- * commmit.c (lock_RCS): Minor clean-up.
-
- * sanity.sh (abspath-6a): Don't depend on the sepcific contents of
- CVSROOT, it depends on which other tests have been run.
-
-Wed Feb 18 01:56:04 1998 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (putsymbol_proc): Use putc and fputs rather than fprintf.
- (RCS_putadmin): Don't call RCS_symbols if the symbols have not yet
- been converted to a list.
-
- * rcs.c (rcsbuf_cache, rcsbuf_cache_open, rcsbuf_cache_close): New
- static functions to avoid closing and reopening the RCS file.
- (cached_rcs, cached_rcsbuf): New static variables.
- (RCS_parse): Call rcsbuf_cache_close. Don't call fclose.
- (RCS_parsercsfile): Likewise.
- (RCS_parsercsfile_i): Call rcsbuf_cache rather than
- rcsbuf_close. Call fclose on error. Remove comment about
- inefficiency of opening file twice.
- (RCS_reparsercsfile): Call rcsbuf_cache_open rather than fopen and
- rcsbuf_open. Call rcsbuf_cache rather than rcsbuf_close and
- fclose.
- (RCS_fully_parse, RCS_checkout, RCS_deltas): Likewise.
- (RCS_rewrite): Likewise.
- (RCS_checkin): Call rcsbuf_cache_close.
-
- * rcs.c (RCS_copydeltas): Fix code which checks for an extra
- newline in buffered data.
-
- * rcs.c (rcsbuf_getkey): Save an indirection by using start rather
- than *valp when trimming trailing whitespace from value.
-
- * rcs.c (rcsbuf_get_buffered): New static function.
- (RCS_copydeltas): After we have done all the required special
- actions, and inserted any new revision, just copy the file bytes
- directly, rather than interpreting all the data.
- (count_delta_actions): New static function.
- * sanity.sh (rcs): Add rcs-6a and rcs-6b to commit a new branch
- revision, to force CVS to interpret all the data, rather than just
- copying it. Adjust rcs-5 to add a branch tag. Adjust rcs-8a and
- rcs-14 for the changes created by rcs-6b.
-
-Tue Feb 17 18:34:01 1998 Ian Lance Taylor <ian@cygnus.com>
-
- * sanity.sh (cvsadm, diffmerge2): Remove directories at the end of
- the test.
-
- * import.c (expand_at_signs): Rewrite to use memchr and fwrite
- rather than putc.
-
- Rewrite RCS file reading routines for speed:
- * rcs.c (struct rcsbuffer): Define.
- (rcsbuf_open, rcsbuf_close, rcsbuf_getkey, rcsbuf_getrevnum,
- rcsbuf_fill, rcsbuf_valcopy, rcsbuf_valpolish,
- rcsbuf_valpolish_internal, rcsbuf_ftell): New static functions.
- (getrcskey, getrcsrev, getrevnum): Remove.
- (many functions): Change to use new rcsbuf functions instead of
- old getrcskey/getrcsrev/getrevnum functions.
- (RCS_reparsercsfile): Add rcsbufp parameter. Change all callers.
- (RCS_deltas): Add rcsbuf parameter. Change all callers.
- (getdelta): Change fp parameter to rcsbuf parameter. Change all
- callers.
- (RCS_getdeltatext): Add rcsbuf parameter. Change all callers.
- (RCS_copydeltas): Add rcsbufin parameter. Change all callers.
- * rcs.h (RCS_reparsercsfile): Update declaration.
- * admin.c (admin_fileproc): Update calls to RCS_reparsercsfile for
- new parameters.
-
-1998-02-17 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (toplevel): Also clean up second-dir (not a new
- bug, but triggered by running tests as "toplevel abspath").
-
- * create_adm.c (Create_Admin): Just print update_dir to tell the
- user where we are; not the whole xgetwd. Cleaner than
- Noel's change (which also had problems in errno handling).
- * sanity.sh (toplevel-12): Update accordingly.
-
-Tue Feb 17 02:32:21 1998 Noel Cragg <noel@swish.red-bean.com>
-
- [These mods make "checkout" work with "-d /absolute/pathname"
- once again.]
-
- * checkout.c (checkout_proc): the -d flag on the command line
- should override the -d flag in the modules file if the latter is
- an absolute path. The loop that assembles the list of directories
- to build has been reorganized slightly to prepare for rewriting
- with last_component rather than assuming '/' as a path separator.
- Also added to that loop was some code to handle absolute
- pathnames.
- (build_dirs_and_chdir): add a new argument that tells this routine
- whether or not to check before it creates and populates
- directories or not.
-
- * filesubr.c (last_component): return the top-level directory when
- asked about the top-level directory.
-
- * sanity.sh (toplevel-12): change test to reflect the new style of
- this error message.
-
- * create_adm.c (Create_Admin): include the directory in the error
- message.
-
-1998-02-16 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * diff.c (diff_fileproc), import.c (import, add_rcs_file), rcs.c
- (RCS_cmp_file): Don't ignore errors from CVS_UNLINK and fclose.
-
- * patch.c (patch_fileproc): Check for errors from fclose; if we
- get -1 from getline check for end of file vs. error.
-
- * rcs.c (RCS_checkout): Comment return value (0/1, not -1).
- * commit.c, diff.c, mkmodules.c, patch.c, rcs.c, update.c: Update
- to match this convention. Don't suppress errors based on
- quiet or really_quiet variables.
-
- Fix a longstanding bug which also makes stamps-8kw in make
- remotecheck work again (it stopped working with Ian's 8 Feb 98
- checkin):
- * client.c, client.h (change_mode): If new argument respect_umask
- is set, then honor the umask.
- * client.c, server.c: Update callers.
-
- Cleanups to Tim's checkin:
- * rcs.c (RCS_checkout): Use existence_error not ENOENT.
- * commit.c (checkaddfile): Remove comment about whether we want to
- check for errors from fclose; there is no reason not to.
- * rcs.c (RCS_checkout), update.c (special_file_mismatch): sscanf
- on %ld requires an unsigned long, not a dev_t.
- * update.c (special_file_mismatch): Remove unused variable
- check_devnums.
- * mkmodules.c (config_contents): Between two settings, use a blank
- line not a "#" line.
-
-1998-02-15 Tim Pierce <twp@skepsis.com>
-
- [This is the code as submitted. I'll be checking in my cleanups
- shortly. This work sponsored by Abbott Labs. -kingdon]
-
- Support for device special files, symbolic links, user and group
- ownerships, and file permissions.
-
- * parseinfo.c: (parse_config): Handle new config variable
- `PreservePermissions'.
- * mkmodules.c (config_contents): Add new PreservePermissions var.
-
- * rcs.c, rcs.h (preserve_perms): New variable.
- (RCS_checkout, RCS_checkin): Support for newphrases `owner',
- `group', `permissions', `special', `symlink'.
- (RCS_checkout): If `workfile' and `sout' are symlinks, remove them
- before attempting to open them for writing.
- * import.c (add_rcs_file): Support for newphrases. Do not attempt
- to read data from special files or symlinks. Error message
- `cannot fstat' is now `cannot lstat'.
-
- New metrics for deciding when two files are different:
-
- * update.c, cvs.h (special_file_mismatch): New function.
- (merge_file, join_file): Call it.
- * no_diff.c (No_Difference): Call it.
-
- * filesubr.c (xcmp): Consider files to be different if they are of
- different types; if they are symlinks which link to different
- pathnames; or if they are devices with different device numbers.
- Error message is now `cannot lstat'.
- * rcs.c (RCS_cmp_file): Use `xcmp' to compare files, simplifying
- the special handling for nonregular files.
-
- * rcscmds.c (diff_exec, diff_execv): If asked to obtain diffs for
- special files, report no differences.
-
- Miscellaneous changes to make special file support possible:
-
- * commit.c (fix_rcs_modes): Don't attempt to `fix' permissions on
- a symlink.
-
- * import.c (add_rcs_file): Don't try to close fpuser if it was
- never opened (e.g. when operating on a symlink).
-
- * filesubr.c, cvs.h (isdevice, xreadlink): New functions.
- * filesubr.c (copy_file): Handle special files and symlinks.
- (xchmod): Do nothing if `preserve_perms' is set.
-
- * commit.c (checkaddfile): Replace `copy_file (DEVNULL, ...)' with
- fopen/fclose calls. Copy_file no longer attempts to read data
- from device files.
-
- * filesubr.c (islink): Use CVS_LSTAT, not lstat.
- * vers_ts.c (time_stamp, time_stamp_server): Use CVS_LSTAT, not stat,
- to get symlinks right.
- * subr.c (get_file): Same. Don't attempt to read from special
- files or symlinks.
-
- * classify.c (Classify_File): Doc fix.
-
-Fri Feb 13 17:07:32 1998 Eric Mumpower <nocturne@cygnus.com>
- and Ian Lance Taylor <ian@cygnus.com>
-
- Fix some file system ordering problems found on Irix 6.4:
- * sanity.sh (basic2): Use dotest_sort for test 56.
- (importb): Use dotest_sort for tests importb-1 and importb-2.
- (head): Use dotest_sort for test head-1.
-
-Thu Feb 12 15:15:33 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * import.c (add_rcs_file): If add_logfp is NULL, don't call fperror.
-
-11 Feb 1998 Andy Piper
-
- * server.c (cvs_output_binary): Use OPEN_BINARY not _O_BINARY.
-
-Mon Feb 9 18:34:39 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- Tweaks to Ian's checkin:
- * update.c (merge_file): Remove comment about sending file to
- client before the message. It doesn't apply to this code any more
- (it does apply to checkout_file, but I'm not sure it is important
- to have such a comment anyway).
- * buffer.c (buf_default_memory_error, buf_length): Reindent.
- * server.h: Declare struct buffer before use.
-
-Mon Feb 9 21:05:28 1998 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (RCS_fully_parse): Call getrevnum rather than getrcsrev.
- Don't bother with ungetc.
-
- * rcs.c (getrcsrev): Rewrite to simply call getrevnum.
-
-Sun Feb 8 15:49:39 1998 Ian Lance Taylor <ian@cygnus.com>
-
- Don't have the server check out a revision into a file and then
- immediately read the file; just read into a buffer instead.
- * update.c: Include buffer.h.
- (update_fileproc): Let checkout_file call server_updated.
- (checkout_file): Add merging and update_server parameters. Change
- all callers. If server_active, don't mess with backup files. If
- server_active, copy the revision into a buffer rather than a file
- when possible. If update_server, call server_updated. Fix
- handling of error status.
- (checkout_to_buffer): New static function used by checkout_file.
- (merge_file): Let checkout_file call server_updated.
- (join_file): Likewise.
- * server.c (server_updated): Change file_info parameter to mode
- parameter. Add filebuf parameter. Change all callers. If
- filebuf is not NULL, don't read the file.
- * server.h (server_updated): Update declaration.
- * buffer.c (buf_free): New function.
- (buf_append_buffer): New function.
- (buf_length): New function.
- * buffer.h (buf_free, buf_append_buffer, buf_length): Declare.
-
- * buffer.c: (buf_initialize): If the memory parameter is NULL, use
- buf_default_memory_error.
- (buf_default_memory_error): New static function.
- * buffer.h (BUFMEMERRPROC): Define typedef.
- * client.c (buf_memory_error): Remove.
- (start_server): Pass NULL rather than buf_memory_error as buffer
- memory error function.
-
-Sat Feb 7 16:27:30 1998 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (RCS_parsercsfile_i): Read the expand keyword from the RCS
- file. We do this because Version_TS calls RCS_getexpand in many
- common cases, and we don't want to reopen the file just for that.
- (RCS_reparsercsfile): Skip the expand keyword.
- (RCS_getexpand): Don't call RCS_reparsercsfile.
-
- * rcs.c (STREQ): New macro. In all string equality tests in the
- file, replace strcmp with STREQ.
-
-Fri Feb 6 16:14:49 1998 Ian Lance Taylor <ian@cygnus.com>
-
- * update.c (checkout_file): If we've already removed the backup
- file once, don't try to remove it again.
-
- * filesubr.c (unlink_file_dir): Call stat rather than isdir, and
- don't call unlink if the file does not exist.
-
- * myndbm.c (mydbm_load_file): Rename line_len to line_size. Call
- getstr rather than getline, to avoid any confusion between \n and
- \012. Use the line length returned by getstr rather than calling
- strlen. Remove local variable len.
-
-Fri Feb 6 13:23:46 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_parsercsfile_i): Don't suppress errors on
- really_quiet.
- (RCS_parsercsfile_i, RCS_reparsercsfile, RCS_fully_parse,
- RCS_deltas, getdelta, getrcskey, RCS_getdeltatext):
- Check for errors. Include errno in error messages. Include
- filename in error messages. Pass new argument to getrcskey.
- (getrcskey): New argument NAME, so we can report errors ourself.
-
-Fri Feb 6 12:10:18 1998 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (RCS_reparsercsfile): Don't use ftell/fseek; just keep
- track of whether we've already read a key/value pair. Use sizeof
- rather than strlen for a constant string. Pass the current key
- and value to getdelta, and get them back as well.
- (getdelta): Add keyp and valp parameters. Don't use ftell/fseek;
- just return the key/value pair to the caller. Don't allocate
- vnode before we know we need it. Check one getrcskey return
- value. Use sizeof rather than strlen for a constant string.
-
- * rcs.c (getrcskey): Correct comment describing return value.
-
-Thu Feb 5 22:51:13 1998 Ian Lance Taylor <ian@cygnus.com>
-
- * subr.c (getcaller): Cache the result, so that we don't keep
- searching the password file.
-
-Wed Feb 4 23:31:08 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (max_rev): Don't prototype. Interesting that noone
- complained about this until now.
-
-4 Feb 1998 Jim Kingdon
-
- * rcs.c (RCS_checkin): When adding a new file, read it
- with "rb" if binary.
-
-Fri Jan 30 11:32:41 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Also test "first-dir" as the regexp in loginfo in
- addition to ALL.
-
- * main.c (main): Update year in copyright notice to 1998.
-
-Thu Jan 29 00:01:05 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Change version number to 1.9.25.
-
- * Version 1.9.24.
-
- * sanity.sh (multibranch2): File file2 and tests multibranch2-13
- through multibranch2-15 test a slightly different case than the
- rest of multibranch2.
-
- * mkmodules.c (cvswrappers_contents): Rewrite. The text didn't
- describe -k and had various other problems.
-
-28 Jan 1998 Karl Fogel and Jim Kingdon
-
- New feature to let server tell client about wrappers.
- * client.h (struct response): Add comment about args being
- '\0' terminated when passed to handle_* functions.
- * client.c (start_server): send "wrapper-sendme-rcsOptions" to
- server iff supported.
- (responses): new response "Wrapper-rcsOption"; allows the server
- to send certain lines from its cvswrappers file.
- (handle_wrapper_rcs_option): new func, handles "Wrapper-rcsOption"
- response from server.
- * server.c (serve_wrapper_sendme_rcs_options): new func, sends
- server side CVSROOT/cvswrappers rcs option lines to client.
- (requests): new request "wrapper-sendme-rcsOptions"; if received,
- we know we can send "Wrapper-rcsOption..." to the client.
- * wrapper.c (wrap_unparse_rcs_options): new func; repeated calls
- step down the wrapper list returning rcs option entries, but
- repackaged as cvswrappers lines.
- (wrap_setup): new guard variable `wrap_setup_already_done'; if
- this function has run already, just return having done nothing.
- Add comment concerning environment variable.
- * cvs.h: declare wrap_unparse_rcs_options().
-
-Tue Jan 27 18:27:19 1998 Ian Lance Taylor <ian@cygnus.com>
-
- * rtag.c (rtag_dirproc): Call ignore_directory, and skip the
- directory if it returns true.
- * sanity.sh (modules4): New set of tests to test some aspects of
- excluding directories in the modules file, including the above
- patch.
-
-Thu Jan 22 10:05:55 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (serve_kopt): Check for length of arg. Based on
- inspection of the code, plugs a buffer overrun security hole which
- was introduced Monday.
-
- * server.c (serve_is_modified): Don't call xmalloc; we aren't
- allowed to call error() here. Remove duplicate (and potentially
- confusing) variable 'p'.
-
- * log.c (log_fileproc): Look for first character of version
- '0' AND second character '\0', rather than OR. I didn't try to
- come up with a test case but this looks like a simple thinko
- (albeit one which would show up in obscure cases if at all).
-
-Tue Jan 20 19:37:53 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (send_dirent_proc): Don't send nonexistent directories
- unless noexec.
- * sanity.sh (modules2): New tests modules2-13 through modules2-18
- test for this fix.
-
-Mon Jan 19 11:17:51 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (serve_kopt): New function.
- (requests): Add "Kopt" request.
- (kopt): New variable.
- (serve_is_modified): Write kopts from there into entries.
- (serve_modified): Call serve_is_modified so we do the same.
- Declare serve_modified and serve_is_modified.
- * vers_ts.c (Version_TS): Set ->options even for a dummy ("D"
- timestamp) entry.
- * import.c (process_import_file): Check for -k options.
- * client.c (client_process_import_file): Send Kopt request.
- (send_fileproc): Likewise, for "cvs add".
- * sanity.sh: Enable test binwrap3-sub2-add1 for remote.
- Add -I .cvswrappers to binwrap3-2a; adjust binwrap3-2d
- accordingly. Tests for this fix.
-
-Mon Jan 19 08:48:59 1998 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (errmsg1): Append test 168 output to log file.
-
-Sat Jan 17 08:01:51 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (ann-10, ann-11): Don't make assumptions about the
- number of characters in the username.
-
-Fri Jan 16 15:34:02 1998 Larry Jones <larry.jones@sdrc.com>
-
- * diff.c (diff_fileproc): Free label1 and label2 when finished.
-
- * edit.c (editor_set): Don't free edlist until after we're
- done using it.
-
- * rcscmds.c (RCS_merge): Free xrev1 and xrev2 when finished.
-
- * subr.c (make_message_rcslegal): Don't access uninitialized or
- unallocated memory; only strip trailing blank lines.
- * sanity.sh (log-3): Enhance to test this fix.
-
-Fri Jan 16 12:41:03 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Add keywordlog to list of tests run by default.
-
- * rcs.c (RCS_deltas): Don't call cvs_output if length is zero;
- passing zero length to cvs_output does not mean output zero
- bytes. The 27 Dec 1997 change to no longer '\0'-terminate the
- ->text field turned this from a time bomb to a user-visible bug.
- * sanity.sh (ann): New tests, test for this fix and other annotate
- behaviors.
-
-Thu Jan 15 23:52:00 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * root.c (root_allow_ok): If inetd.conf didn't specify an
- --allow-root options at all, we know we are in trouble. Give a
- specific error message.
-
-Thu Jan 15 21:24:59 1998 Ian Lance Taylor <ian@cygnus.com>
-
- * sanity.sh (dotest_sort): New variant of dotest which sorts the
- output, for use when the output depends upon details of the file
- system, typically when doing an import.
- (rdiff): Use dotest_sort for rdiff-1.
- (ignore): Use dotest_sort for 188a, 188b, 189d, 190, and 191.
-
- * sanity.sh: (TESTSHELL): New variable.
- (editor, info, reserved): Use TESTSHELL in temporary script.
-
- * sanity.sh (ignore): Do all tests in subdirectory, to avoid
- conflict between cvsroot and CVSROOT on Windows.
- (binwrap3, mwrap, info, config): Likewise.
-
- * sanity.sh (binfiles2): Correct test name binfile2-7-brmod to
- binfiles2-7-brmod.
-
- * release.c (release_delete): If __CYGWIN32__ is defined, don't
- worry about mismatched inodes. This is a hack, but then I think
- the test is rather peculiar anyhow.
-
-Thu Jan 15 16:07:36 1998 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh (reserved-9): Use ${PROG} instead of "cvs".
-
-Wed Jan 14 15:43:13 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Split ChangeLog into ChangeLog-97 and ChangeLog.
- * Makefile.in (DISTFILES): Add ChangeLog-97.
-
-13 Jan 1998 Jim Kingdon
-
- * client.c: Declare handle_mt.
-
-Tue Jan 13 22:21:30 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Add comment about how pwd and /bin/pwd often differ
- in behavior (but are not guaranteed to).
-
-Tue Jan 13 13:49:53 1998 Ian Lance Taylor <ian@cygnus.com>
-
- * sanity.sh: When setting TMPPWD use just pwd, not /bin/pwd.
-
- * update.c (checkout_file): Don't pass set_time as true to
- Version_TS if the file is dead.
- * sanity.sh (modules): Add tests modules-155c6 through
- modules-155c8 to test for above patch (without the above patch,
- modules-155c8 will fail when remote).
-
-Tue Jan 13 10:37:02 1998 Larry Jones <larry.jones@sdrc.com>
-
- * client.c (send_modified): Change bufsize and newsize from int
- to size_t to avoid type clashes in call to read_and_gzip.
-
-Tue Jan 13 10:33:02 1998 Larry Jones <larry.jones@sdrc.com>
-
- * zlib.c (read_and_gzip): Set finish to 0; it was uninitialized.
-
-Tue Jan 13 10:26:43 1998 Larry Jones <larry.jones@sdrc.com>
-
- * add.c, rcs.c: Plug memory leaks.
-
-Mon Jan 12 10:45:27 1998 Larry Jones <larry.jones@sdrc.com>
-
- * server.c (mkdir_p): Don't try to create nameless directories
- (i.e., given "/foo//bar", don't try to create "/foo/",
- just "/foo" and "/foo//bar") since it isn't necessary and
- it fails on some systems in unexpected ways.
-
-1998-01-11 enami tsugutomo <enami@but-b.or.jp>
-
- * rcs.c (linevector_copy): Delete lines before overwriting them.
-
-Sat Jan 10 11:05:40 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * cvsrc.c, entries.c, login.c, logmsg.c, myndbm.c, patch.c,
- release.c, server.c: Check for errors from getline, CVS_FOPEN,
- fprintf, CVS_UNLINK and fclose. Note that the new errors are
- nonfatal. This is because of conservatism more than because
- it is always the best thing.
- * login.c (get_cvs_password): Close the file when done with it.
- * client.c (notified_a_file): If -1 return from getline, check
- feof rather than assuming errno is set.
-
-Fri Jan 9 14:38:54 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (expand_proc): Also output server_dir in
- "Module-expansion", not just in output_dir ("Created", &c).
- * sanity.sh (modules2): New tests modules2-9 through modules2-12
- test for this.
-
-Thu Jan 8 12:56:55 1998 Yasutoshi Hiroe <hiroe@rgk.ricoh.co.jp>
-
- * import.c (import): Don't strcat on uninitialized memory. Fixes
- possible SIGSEGV with zero-length message.
-
-Tue Jan 6 22:56:29 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (crerepos): Fix mistaken variable name which caused us
- not to clean up at the end of the test.
-
-Mon Dec 22 01:40:57 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c (add): Also look for .cvswrappers files.
- * sanity.sh (binwrap3): New tests binwrap3-2*, binwrap3-sub2-add*
- test for this.
-
-Tue Jan 6 11:50:38 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (crerepos): New tests crerepos-8 through crerepos-18
- test behaviors when mixing repositories.
-
-Sun Jan 4 17:40:22 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Change version number to 1.9.23.
-
- * Version 1.9.22.
-
-
-For older changes see ChangeLog-97.
diff --git a/contrib/cvs/src/ChangeLog-9194 b/contrib/cvs/src/ChangeLog-9194
deleted file mode 100644
index eb79efccd9b9..000000000000
--- a/contrib/cvs/src/ChangeLog-9194
+++ /dev/null
@@ -1,524 +0,0 @@
-Thu Sep 15 08:20:23 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * subr.c (run_setup, run_args): Check USE_PROTOTYPES if defined
- instead of __STDC__, just like cvs.h does.
-
-Thu Sep 15 00:14:58 1994 david d `zoo' zuhn <zoo@monad.armadillo.com>
-
- * main.c: rename nocvsrc to use_cvsrc, don`t read ~/.cvsrc when -H
- has been seen
-
-Wed Sep 14 21:55:17 1994 david d `zoo' zuhn <zoo@monad.armadillo.com>
-
- * cvs.h, subr.c: use size_t for xmalloc, xrealloc, and xstrdup
- parameters
-
- * cvsrc.c: optimize away two calls of getenv
-
- * commit.c, subr.c: use mode_t for file mode values (Thanks to jtc@cygnus.com)
-
- * main.c: update copyrights in -v message
-
-Tue Sep 6 10:29:13 1994 J.T. Conklin (jtc@rtl.cygnus.com)
-
- * hash.c (hashp): Replace hash function with one from p436 of the
- Dragon book (via libg++'s hash.cc) which has *much* better
- behavior.
-
-Wed Aug 17 09:37:44 1994 J.T. Conklin (jtc@cygnus.com)
-
- * find_names.c (find_dirs): Use 4.4BSD filesystem feature (it
- contains the file type in the dirent structure) to avoid
- stat'ing each file.
-
-Tue Aug 16 11:15:12 1994 J.T. Conklin (jtc@cygnus.com)
-
- * rcs.h (struct rcsnode): add symbols_data field.
- * rcs.c (RCS_parsercsfile_i): store value of rcs symbols in
- symbols_data instead of parsing it.
- (RCS_symbols): New function used for lazy symbols parsing.
- Build a list out of symbols_data and store it in symbols if it
- hasn't been done already, and return the list of symbols.
- (RCS_gettag, RCS_magicrev, RCS_nodeisbranch, RCS_whatbranch):
- Use RCS_symbols.
- * status.c: (status_fileproc): Use RCS_symbols.
-
-Thu Jul 14 13:02:51 1994 david d `zoo' zuhn (zoo@monad.armadillo.com)
-
- * src/diff.c (diff_fileproc): add support for "cvs diff -N" which
- allows for adding or removing files via patches. (from
- K. Richard Pixley <rich@cygnus.com>)
-
-Wed Jul 13 10:52:56 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
-
- * cvs.h: Add macro CVSRFLPAT, a string containing a shell wildcard
- expression that matches read lock files.
- * lock.c (readers_exist): Reorganized to use CVSRFLPAT and to not
- compute the full pathname unless the file matches.
-
- * rcs.h: Add macro RCSPAT, a string containing a shell wildcard
- expression that matches RCS files.
- * find_names.c (find_rcs, find_dirs): Use RCSPAT.
-
-Fri Jul 8 07:02:08 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * entries.c (Register): Pass two arguments to write_ent_proc, in
- accordance with its declaration.
-
-Thu Jun 30 09:08:57 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * logmsg.c (do_editor): Fix typo ("c)continue" -> "c)ontinue").
-
-Thu Jun 23 18:28:12 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
-
- * find_names.c (find_rcs, find_dirs): use fnmatch instead of
- re_comp/re_exec for wildcard matching.
- * lock.c (readers_exist): Likewise.
-
-Fri May 20 08:13:10 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * modules.c (do_module): If something is aliased to itself, print
- an error message rather than recursing.
-
-Fri May 6 19:25:28 1994 david d zuhn (zoo@monad.armadillo.com)
-
- * cvsrc.c (read_cvsrc): use open_file for error checking
-
-Sat Feb 26 10:59:37 1994 david d zuhn (zoo@monad.armadillo.com)
-
- * import.c: use $TMPDIR if available, instead of relying on /tmp
-
-Mon Jan 24 19:10:03 1994 david d zuhn (zoo@monad.armadillo.com)
-
- * update.c (joining): compare join_rev1 with NULL instead of
- casting pointer to an int
-
- * options.h: remove S_IWRITE, S_IWGRP, S_IWOTH macros
-
- * logmsg.c: #if 0 around gethostbyname prototype
-
- * hash.c (printnode), find_names.c (add_entries_proc),
- entries.c (write_ent_proc): correct declaration for function
- (added void *closure)
-
- * cvs.h: header include order reorganization: First include the
- program config headers (config.h, options.h). Then include any
- system headers (stdio.h, unistd.h). Last, get the program
- headers and any cvs supplied library support
-
- * commit.c: use xstrdup instead of strdup
-
- * cvs.h: redefined USE(var) macro; comment after an #endif
-
- * all .c files: remove the semicolon from after the USE(var)
-
-Sat Dec 18 00:17:27 1993 david d zuhn (zoo@monad.armadillo.com)
-
- * cvs.h: include errno.h if available, otherwise declare errno if
- it's not somehow else defined
-
- * commit.c (checkaddfile): remove unused file argument from
- RCS_nodeisbranch call
-
- * rcs.c (RCS_nodeisbranch): remove file from arguments (was unused)
-
- * rcs.h (RCS_nodeisbranch): remove file from prototype
-
- * main.c: don't use rcsid when printing version number (the CVS
- version number is independent of the repository that it comes
- from)
-
- * hash.c (printlist, printnode): use %p to print pointers, not %x
- (avoids gcc format warnings)
-
- * cvs.h: define USE if GCC 2, to avoid unused variable warning
-
- * all .c files: use USE(rcsid)
-
- * Makefile.in (VPATH): don't use $(srcdir), but @srcdir@ instead
- (COMMON_OBJECTS): define, and use in several places
- (OBJECTS): reorder alphabetically
-
- * hash.c (nodetypestring): handle default return value better
-
- * modules.c (do_module): remove extra argument to ign_dir_add
-
- * main.c (main): initialize cvs_update_env to 0 (zero)
-
- * modules.c (do_module): return error code when ignoring directory
- (instead of a bare return). error code should be zero here
-
- * cvs.h: add prototypes for ignore_directory, ign_dir_add
-
- * ignore.c: add comments about ignore_directory
-
- * root.c (Name_Root): remove unused variables has_cvsadm and path
-
- * checkin.c (Checkin): only use -m<message> when message is non-NULL
-
- * cvsrc.c (read_cvsrc): make sure homeinit is never used while
- uninitialized (could have happened if getenv("HOME") had failed)
-
- * cvs.h: include unistd.h if available
-
-Fri Dec 17 23:54:58 1993 david d zuhn (zoo@monad.armadillo.com)
-
- * all files: now use strchr, strrchr, and memset instead of index,
- rindex, and bzero respectively
-
-Sat Dec 11 09:50:03 1993 david d zuhn (zoo@monad.armadillo.com)
-
- * version.c (version_string): bump to +104z
-
- * Makefile.in: set standard directory variables, CC, and other
- variables needed to be able to do 'make all' in this directory
-
- * import.c: implement -k<subst> options, for setting the RCS
- keyword expansion mode
-
- * all files: use PROTO() macro for ANSI function prototypes
- instead of #ifdef __STDC__/#else/#endif around two sets of
- declarations
-
-Thu Nov 18 19:02:51 1993 K. Richard Pixley (rich@sendai.cygnus.com)
-
- * add.c (add), import.c (import), commit.c (commit): change
- xmalloc & strcpy to xstrdup.
-
- * commit.c (remove_file): correct another static buffer problem.
-
-Wed Nov 10 15:01:34 1993 K. Richard Pixley (rich@sendai.cygnus.com)
-
- * recurse.c (start_recursion): directories in repository but not
- in working directory should be added to dirlist. Fixes "update
- -d dir" case.
-
- * version.c (version_string): bump to +103r.
-
- * commit.c (checkaddfile): mkdir attic only if it does not already
- exist. comment changes. changed diagnostic about adding on a
- branch. if a file is added on a branch, remove and replace the
- internal representation of that rcs file.
-
-Tue Nov 9 18:02:01 1993 K. Richard Pixley (rich@sendai.cygnus.com)
-
- * add.c (add): if a file is being added on a branch, then say so;
- add quotes around file names in error messages.
-
-Thu Nov 4 16:58:33 1993 K. Richard Pixley (rich@sendai.cygnus.com)
-
- * version.c (version_string): bump to +102r.
-
- * recurse.c (unroll_files_proc, addfile): new files, forward
- decls, and prototypes.
- (recursion_frame): new struct.
- (start_recursion): rewrite to handle the case of "file1 file2
- dir1/file3".
-
- * rcs.c (RCS_parsercsfile): trap and error out on the case where
- getrcskey tells us it hit an error while reading the file.
-
- * commit.c (lock_filesdoneproc): add comment about untrapped error
- condition.
-
- * hash.c (addnode): comment change.
-
- * subr.c: add comment about caching.
-
- * sanity.sh: updated copyright.
-
-Wed Nov 3 14:49:15 1993 K. Richard Pixley (rich@sendai.cygnus.com)
-
- * version.c (version_string): bump to +101r.
-
- * hash.c (walklist): add a closure for called routines. All
- callers, callees, and prototypes changed.
-
- * hash.c (nodetypestring, printnode, printlist): new functions for
- dumping lists & nodes.
-
- * tag.c (tag_fileproc): fatal out on failure to set tag.
-
-Tue Nov 2 14:26:38 1993 K. Richard Pixley (rich@sendai.cygnus.com)
-
- * version.c (version_string): bump version to +99.
-
-Mon Nov 1 15:54:51 1993 K. Richard Pixley (rich@sendai.cygnus.com)
-
- Change buffer allocation for check in messages from static to
- dynamic.
- * add.c (add): dynamically allocate message.
- (build_entry): check (message != NULL) now that message is a
- pointer.
- * commit.c (got_message, commit, commit_fileproc,
- commit_filesdoneproc, commit_direntproc): removed. Replaced by
- (message != NULL). Dynamically allocate message.
- * cvs.h: adjust do_editor prototype and forward decl.
- (MAXMESGLEN): removed.
- * import.c (import): dynamically allocate message.
- * logmsg.c (do_editor): change return type to char *. Remove
- message parameter. Slight optimization to algorythm for
- removing CVSEDITPREFIX lines. Add comment about fgets lossage.
-
- * subr.c (xmalloc): change error message to print number of bytes
- we were attempting to allocate.
-
-Fri Oct 29 14:22:02 1993 K. Richard Pixley (rich@sendai.cygnus.com)
-
- * add.c (add): prevent adding a directory if there exists a dead
- file of the same name.
-
- * sanity.sh: update argument to diff from "+ignore-file" to
- "--exclude=".
-
- * Makefile.in (TAGS): extend to work from an objdir.
-
-Mon Oct 18 18:45:45 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
-
- * tag.c, rtag.c: change the default actions to make writing over
- existing tags harder (but not impossible)
-
-Thu Oct 14 18:00:53 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
-
- CVS/Root changes from Mark Baushke (mdb@cisco.com)
-
- * Makefile.in: added new file called root.c
-
- * create_adm.c: will create CVS/Root at the same time that the
- other CVS files are being created
-
- * cvs.h: new CVSADM_ROOT define plus new function externs
-
- * main.c: default to using CVS/Root contents for CVSROOT
- if neither the environment variable or the command line
- "-d" switch is given. If either are given, perform a
- sanity check that this directory belongs to that repository.
-
- * update.c: if CVS/Root does not exist, then create it
- during an update -- this may be removed if CVS/Root becomes a
- standard feature
-
- * root.c: implement new functions to manipulate CVS/Root
- [this may be integrated with other utility functions in
- a future revision if CVS/Root becomes a standard feature.]
-
-Wed Sep 29 17:01:40 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
-
- * patch.c (patch_fileproc): output an Index: line for each file
-
-Mon Sep 6 18:40:22 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
-
- * cvs.h: wrap definition of PATH_MAX in #ifndef PATH_MAX/#endif
-
-Tue Aug 9 21:52:10 1994 Mark Eichin (eichin@cygnus.com)
-
- * commit.c (remove_file): actually allocate space for the
- filename, not just the directory.
-
-Tue Jul 6 19:05:37 1993 david d `zoo' zuhn (zoo@cygnus.com)
-
- * diff.c: patches to print an Index: line
-
-Mon Jun 14 12:19:35 1993 david d `zoo' zuhn (zoo at rtl.cygnus.com)
-
- * Makefile.in: update install target
-
-Tue Jun 1 17:03:05 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
-
- * Makefile.in: link cvs against libiberty
-
-Wed May 19 14:10:34 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
-
- * ignore.c: add code for keeping lists of directories to ignore.
-
- * modules.c: new syntax for modules file, !dirname is added to
- the list of directories to ignore
-
- * update.c: don't process directories on the ignore list
-
-Tue Apr 6 14:22:48 1993 Ian Lance Taylor (ian@cygnus.com)
-
- * cvs.h: Removed gethostname prototype, since it is unnecessary
- and does not match prototype in <unistd.h> on HP/UX.
-
-Mon Mar 22 23:25:16 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
-
- * Makefile.in: rename installtest to installcheck
-
-Mon Feb 1 12:53:34 1993 K. Richard Pixley (rich@rtl.cygnus.com)
-
- * Makefile.in (check, installtest): set RCSBIN so that we
- explicitly test the appropriate version of rcs as well.
-
-Fri Jan 29 13:37:35 1993 K. Richard Pixley (rich@rtl.cygnus.com)
-
- * version.c: bump version to +2.
-
-Thu Jan 28 18:11:34 1993 K. Richard Pixley (rich@rtl.cygnus.com)
-
- * import.c (update_rcs_file): if a file was dead, be sure to check
- in the new version.
-
- * update.c (checkout_file): if file_is_dead and we *did* have an
- entry, scratch it.
-
-Tue Jan 26 16:16:48 1993 K. Richard Pixley (rich@rtl.cygnus.com)
-
- * sanity.sh: parcel into pieces for easier truncation when
- debugging.
-
- * update.c (checkout_file): print the "no longer pertinent"
- message only if there was a user file.
-
-Wed Jan 20 17:08:09 1993 K. Richard Pixley (rich@rtl.cygnus.com)
-
- * update.c (checkout_file): remove unused variable s.
- (join_file): remove unused variables rev & baserev. Fix a typo.
-
- * commit.c (commit_fileproc): remove unused variable magicbranch.
-
- * sanity.sh: bring back test 45 even though it fails. Update
- tests against imported files.
-
- * add.c (add_directory): move declaration of unused variable.
-
- * Makefile.in (xxx): when building in this directory, pass CC for
- the recursion.
-
-Mon Jan 18 13:48:33 1993 K. Richard Pixley (rich@cygnus.com)
-
- * commit.c (remove_file): fix for files removed in trunk
- immediately after import.
-
- * commit.c (remove_file): initialize some variables. Otherwise we
- end up free'ing some rather inconvenient things.
-
-Wed Jan 13 15:55:36 1993 K. Richard Pixley (rich@rtl.cygnus.com)
-
- * Makefile.in (check, install, installtest): use the sanity test.
-
- * sanity.el: make into real functions and bind to sun keys.
-
- * sanity.sh: bring back to working order. Add test for death
- after import.
-
-Tue Dec 22 17:45:19 1992 K. Richard Pixley (rich@cygnus.com)
-
- * commit.c (remove_file): when checking in a dead revision to a
- branch as we are creating the branch, do not lock the underlying
- revision. Also free some malloc'd memory.
-
-Wed Dec 2 13:09:48 1992 K. Richard Pixley (rich@cygnus.com)
-
- * RCS-patches: new file.
-
-Fri Nov 27 20:12:48 1992 K. Richard Pixley (rich@rtl.cygnus.com)
-
- Added support for adding previously removed files, as well as
- adding and removing files in branches.
-
- * add.c (build_entry): add new argument, tag, so as to store in
- Entries the per directory sticky tag under which a file is
- added. Changed prototype and caller.
- (build_entry): Do not prevent file additions if the file exists
- in the Attic.
- (add): if the file being adding was previously dead, say so, and
- mark the Entries file with the addition.
- * checkin.c (Checkin): adding with a tag no longer means to add,
- then tag. Hence, remove the tagging operation.
- * classify.c (Classify_File): if the base RCS version is dead,
- then the file is being added. If a file being added already
- exists in the attic, and the base RCS version is NOT dead, then
- we have a conflict.
- * commit.c (checkaddfile): add the list of srcfiles to calling
- convention. Change prototype and callers.
- (remove_file): add message and list of srcfiles to calling
- convention. Change prototype and callers. When removing a file
- with a tag, remove the tag only when the tag does not represent
- a branch. Remove files by committing dead revisions in the
- appropriate branch. When removing files from the trunk, also
- move the RCS file into the Attic.
- (check_fileproc): when adding, and looking for previously
- existing RCS files, do not look in the Attic.
- (commit_fileproc): adding files with tags now implies adding the
- file on a branch with that tag.
- (checkaddfile): When adding a file on a branch, in addition to
- creating the rcs file in the Attic, also create a dead, initial
- revision on the trunk and stub in a magic branch tag.
- * cvs.h (joining, gca): added prototypes.
- * rcs.c (RCS_getbranch): now global rather than static.
- remove prototype and forward decl.
- (parse_rcs_proc): use RCS_addnode.
- (RCS_addnode): new function.
- (RCS_parsercsfile): recognize the new RCS revision
- newphrase, "dead". Mark the node for the revision.
- (RCS_gettag): requesting the head of a file in the attic now
- returns the head of the file in the attic rather than NULL.
- (RCS_isbranch): use RCS_nodeisbranch.
- (RCS_nodeisbranch): new function.
- (RCS_isdead): new function.
- * rcs.h (RCSDEAD): new macro for new rcs keyword.
- (struct rcsversnode): new field to flag dead revisions.
- (RCS_nodeisbranch, RCS_isdead, RCS_addnode): new functions,
- new prototypes, new externs.
- (RCS_getbranch): now global, so prototype and extern moved
- to here.
- * subr.c (gca): new function.
- * update.c (join_file): add entries list to calling
- convention. Caller changed.
- (update): also search the Attic when joining.
- (checkout_file): when joining, checkout dead revisions too. If
- a file has died across an update then say so.
- (join_file): support joins of dead files against live ones, live
- files against dead ones, and added files. Change the semantic
- of a join with only rev specified to mean join specified rev
- against checked out files via the greatest common ancestor of
- the specified rev and the base rev of the checked out files.
- (joining): new function.
- * vers_ts.c (Version_TS): ALWAYS get the rcs version number.
-
- * update.c (update): write the 'C' letter for conflicts.
-
- * cvs.h (ParseTag): remove duplicate extern.
-
- * add.c (add_directory): do not prompt for interactive
- verification before adding a directory. Doing so prevents
- scripted testing.
-
-Wed Feb 26 18:04:40 1992 K. Richard Pixley (rich@cygnus.com)
-
- * Makefile.in, configure.in: removed traces of namesubdir,
- -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced
- copyrights to '92, changed some from Cygnus to FSF.
-
-Tue Dec 10 01:24:40 1991 K. Richard Pixley (rich at cygnus.com)
-
- * diff.c: do not pass an empty -r option to rcsdiff.
-
- * update.c: fix bug where return code from rcsmerge wasn't being
- handled properly.
-
- * main.c: "rm" and "delete" now synonyms for "remove".
-
- * commit.c: abort if editor session fails, but remember to clear
- locks.
-
- * Makefile.in: remove conf.h and checkin.configured on clean.
- infodir belongs in datadir.
-
-Thu Dec 5 22:46:03 1991 K. Richard Pixley (rich at rtl.cygnus.com)
-
- * Makefile.in: idestdir and ddestdir go away. Added copyrights
- and shift gpl to v2. Added ChangeLog if it didn't exist. docdir
- and mandir now keyed off datadir by default.
-
-Wed Nov 27 02:47:13 1991 K. Richard Pixley (rich at sendai)
-
- * brought Makefile.in's up to standards.text.
-
- * fresh changelog.
-
-
-For older changes, there might be some relevant stuff in the bottom of
-the NEWS file, but I'm afraid probably a lot of them are lost in the
-mists of time.
diff --git a/contrib/cvs/src/ChangeLog-9395 b/contrib/cvs/src/ChangeLog-9395
deleted file mode 100644
index c2d211198a1d..000000000000
--- a/contrib/cvs/src/ChangeLog-9395
+++ /dev/null
@@ -1,3731 +0,0 @@
-Note: this log overlaps in time with ChangeLog-9194. There was a time
-during which changes which had been merged into the official CVS
-(which produced releases such as 1.4A1 and 1.4A2) went into what has
-become ChangeLog-9194, and changes which existed only at Cygnus went
-into this file (ChangeLog-9395). Eventually the Cygnus release became
-Cyclic CVS (as it was then called), which became CVS 1.5, so probably
-all the changes in both (what are now) ChangeLog-9194 and
-ChangeLog-9395 made it into 1.5.
-
-Sun Dec 31 17:33:47 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * import.c (add_rev): Revert portion of 31 Aug 95 change which
- passes -u to ci instead of using a hard link.
- * sanity.sh (import): Add test for above-fixed bug.
-
-Sun Dec 31 16:40:41 1995 Peter Chubb <peterc@bookworm.sw.oz.au>
- and Jim Kingdon <kingdon@cyclic.com>
-
- * admin.c (admin_fileproc): Call freevers_ts before returning.
-
-Mon Dec 25 12:20:06 1995 Peter Wemm <peter@haywire.DIALix.COM>
-
- * logmsg.c (rcsinfo_proc): initialise line and
- line_chars_allocated so they dont cause malloc problems within
- getline(). This was causing rcsinfo templates to not work.
-
-Sun Dec 24 01:38:36 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * server.c (authenticate_connection): clarify protocol.
-
- * login.c (login): deprolixify the password prompt.
-
-Sat Dec 23 10:46:41 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * myndbm.h, myndbm.c (dbm_store): New function.
- * myndbm.h (DBM): Add modified and filename fields.
- * myndbm.c (dbm_open, dbm_close): Manipulate new fields. dbm_open
- no longer fails if the file doesn't exist and O_CREAT is set.
- * cvs.h (CVSROOTADM_VALTAGS): Added.
- * tag.c, cvs.h (tag_check_valid): New function.
- * update.c (update), checkout.c (checkout_proc), commit.c (commit),
- diff.c (diff), patch.c (patch_proc), rtag.c (rtag_proc), tag.c (tag):
- Call it.
- * sanity.sh: Test for rejection of invalid tagname.
-
-Fri Dec 22 18:21:39 1995 Karl Fogel <kfogel@csxt.cs.oberlin.edu>
-
- * client.c (start_server): don't use kerberos if authenticating
- server was specified.
-
-Fri Dec 22 16:35:57 1995 Karl Fogel <kfogel@csxt.cs.oberlin.edu>
-
- * login.c (login): deal with new scramble methods.
- (get_cvs_password): same.
-
- * server.c (check_repository_password): remove arbitrary limit on
- line length.
- (authenticate_connection): use a separate variable for the
- descrambled password, now that we no longer scramble in place.
- Set `error_use_protocol' to 1 and just use error() where used to
- do its job inline.
-
- * cvs.h (scramble, descramble): adjust prototype.
-
- * scramble.c (scramble, descramble): return char *.
-
-Fri Dec 22 13:00:00 1995 Jim Kingdon <kingdon@peary.cyclic.com>
-
- * release.c (release): If SERVER_SUPPORT is not defined, still
- set up arg_start_idx.
-
- * release.c (release): When calling unedit, set argv[1] to
- NULL (since argc is only 1).
-
- * edit.c: Pass dosrcs 0 to all calls to start_recursion.
- None of the fileprocs were using it, so it just slowed things
- down and caused potentially harmful checks for rcs files.
-
- * edit.c (send_notifications): In client case, do not readlock.
-
-Thu Dec 21 16:00:00 1995 Jim Kingdon <kingdon@peary.cyclic.com>
-
- Clean up Visual C++ lint:
- * client.c (read_line): Change input_index and result_size to size_t.
- (update_entries): Remove unused variables buf2, size_left, size_read.
- (handle_mode): Prototype.
- * client.c, client.h (send_to_server, read_from_server): Change
- len to size_t.
- * client.c (send_to_server): Change wrtn to size_t.
- (read_from_server): Change red to size_t.
- * client.c, myndbm.c, edit.c, fileattr.c: Include getline.h.
- * checkin.c, commit.c, update.c: Include fileattr.h.
- * commit.c, update.c: Include edit.h.
- * edit.c (onoff_filesdoneproc): Prototype.
- (ncheck_fileproc,edit_fileproc): Change "return" to "return 0".
- (notify_do): Cast a signed value to unsigned before comparing
- with unsigned value.
-
-Thu Dec 21 15:24:37 1995 Karl Fogel <kfogel@occs.cs.oberlin.edu>
-
- * client.c: don't include socket headers twice just because
- both HAVE_KERBEROS and AUTH_CLIENT_SUPPORT are set.
- (start_kerberos_server): if fail to connect to kerberos, print out
- a more specific error message, mainly so pcl-cvs can know what
- happened and not panic.
- (start_server): don't assume sprintf() returns len
- written (only some systems provide this); instead, have
- send_to_server() calculate the length itself.
- (send_modified): same.
- (send_fileproc): same.
- (send_file_names): same.
-
-Wed Dec 20 14:00:28 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (ignore_files): Move from here...
- * ignore.c (ignore_files): ...to here. No longer static. Take
- new argument PROC.
- * cvs.h (ignore_files): Declare.
- * client.c (send_filesdoneproc): Split off from
- update_filesdone_proc. Pass new function send_ignproc to
- ignore_files (to ask server about ignored file before printing
- "?").
- * server.c: Rename outbuf from but_to_net and take it from
- do_cvs_command to a global. Move initialization accordingly.
- (serve_questionable): New function.
- (requests): Add it.
- * update.c (update_filesdone_proc): Remove client stuff. Pass new
- function update_ignproc to ignore_files.
- * cvs.h (joining, do_update): Move declarations from here...
- * update.h: ...to here.
- * cvs.h: Include update.h.
- * update.c, client.c: Don't include update.h
- * ignore.c, cvs.h: New variable ign_inhibit_server, set on -I !.
- * import.c (import): Pass -I ! to server if specified.
- (import_descend): If server, ignore CVS directories even if -I !.
- * update.c (update), import.c (import): Only call ign_setup before
- argument processing; don't call it again afterwards in client case.
- * sanity.sh (ignore): Test above-fixed bugs and other ignore behaviors.
- (dotest): New function.
- Move modules checkin from modules test to start, so that other
- tests can use mkmodules without a warning message.
-
-Wed Dec 20 13:06:17 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (send_to_server): don't check string's length twice.
-
-Wed Dec 20 02:05:19 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * login.c (login): took out debugging printf's.
- (login): Removed unused variable `p'.
-
-Wed Dec 20 00:27:36 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * login.c (login): prefix scrambled password with 'A', so we know
- which version of scrambling was used. This may be useful in the
- future.
- (get_cvs_password): skip past the leading 'A'.
- Scramble $CVS_PASSWORD before returning it.
-
- * scramble.c: made this work.
-
-Tue Dec 19 17:45:11 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * login.c (cvs_password): new static var, init to NULL.
- (login): scramble() the password before using it.
- Verify the password with the server.
- Check CVSroot more carefully to insure that it is
- "fully-qualified".
- (get_cvs_password): if cvs_password is not NULL, just return it.
- Never prompt -- just tell user why failed, then exit.
- Try CVS_PASSWORD environment variable first.
- (construct_cvspass_filename): try CVS_PASSFILE environment
- variable first.
-
- * client.h (connect_to_pserver): update prototype.
-
- * client.c (cvsroot_parsed): new static var.
- (parse_cvsroot): set `cvsroot_parsed' to 1 when done.
- (connect_to_pserver): return int.
- Take `verify_only' arg. If it is non-zero, perform password
- verification with the server and then shut down the connection and
- return.
- Call parse_cvsroot() before doing anything.
-
- * server.c (authenticate_connection): deal with verification
- requests as well as authorization requests.
- descramble() the password before hashing it.
-
- * cvs.h: prototype scramble() and descramble().
-
- * Makefile.in: build scramble.o.
-
- * scramble.c: new file, provides trivial encoding but NOT real
- encryption.
-
-Mon Dec 18 20:57:58 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * login.c (login): don't insert extra newlines. They were
- harmless, but confusing.
-
-Mon Dec 18 15:32:32 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * hash.c, hash.h (findnode_fn): New function.
- * hash.c (hashp): Tweak hash function so that findnode_fn works.
- * update.c (ignore_files): Call findnode_fn, not findnode.
-
-Mon Dec 18 09:34:56 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * myndbm.c: Remove arbitrary limit.
-
- * client.c: Fix comment--Windows 95 requires NO_SOCKET_TO_FD, not
- Windows NT.
-
-Mon Dec 18 01:06:20 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (server_sock): replaces `server_socket'.
- (start_kerberos_server): added FIXME comment about how
- NO_SOCKET_TO_FD is not dealt with in the kerberos case.
- (connect_to_pserver): deal with NO_SOCKET_TO_FD case.
- (read_line): deal with NO_SOCKET_TO_FD case.
- (read_from_server): deal with NO_SOCKET_TO_FD case.
- (send_to_server): deal with NO_SOCKET_TO_FD case.
- (get_responses_and_close): deal with NO_SOCKET_TO_FD case.
-
- * client.c (send_to_server): error check logging.
- (start_server): error check opening of logfiles.
- (read_from_server): error check logging.
- (read_line): use fwrite() to log, & error_check it.
- Don't log if using socket style, because read_from_server()
- already logged for us.
-
-Mon Dec 18 00:52:26 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (use_socket_style): new static var, init to 0.
- (server_socket): new static var.
- (connect_to_pserver): don't deal with logging here.
- Caller changed.
- (start_kerberos_server): don't deal with logging here either.
- Caller changed.
-
-Mon Dec 18 00:40:46 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (send_modified): don't error-check `to_server';
- send_to_server() does that now.
-
-Mon Dec 18 00:19:16 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * login.c (get_cvs_password): Init `linebuf' to NULL.
- free() `linebuf' and reset it for each new line.
- (login): same as above.
-
- * client.c: Removed all the varargs prototyping gunk.
- (to_server, from_server): make these static.
- (from_server_logfile, to_server_logfile): new vars.
- (start_server): init above two new vars to NULL.
- (send_to_server): return void.
- Correct bug in which amount to be written would be too high if the
- loop ever ran more than once.
- Log to `to_server_logfile' if it's non-NULL.
- (read_from_server): new func, does raw reading from server.
- Logs to `from_server_logfile' if it's non-NULL.
- (update_entries): just use read_from_server() instead of looping
- to fread() directly from `from_server'.
- (read_line): Log to `from_server_logfile' if it's non-NULL.
-
- * client.h: send_to_server() returns void now.
- (read_from_server): prototype.
-
-Sun Dec 17 19:38:03 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * checkout.c (checkout_proc), client.c, lock.c (readers_exist),
- login.c, modules.c (cat_module, do_module): Remove arbitrary limits.
-
- * client.c (send_to_server): Fix typo (NULL -> '\0').
- (get_responses_and_close): Set server_started to 0 instead of
- setting to_server and from_server to NULL.
- * client.c: Make to_server and from_server static.
-
-Sun Dec 17 17:59:04 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.h (to_server, from_server): don't declare these anymore.
- They are now entirely private to client.c (and in fact will go
- away soon there too).
-
-Sun Dec 17 15:40:58 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.h: update prototype of send_to_server().
-
- * client.c, watch.c, update.c, tag.c, status.c, rtag.c, remove.c,
- release.c, patch.c, log.c, import.c, history.c, edit.c, diff.c,
- commit.c, client.c, checkout.c, admin.c, add.c:
- Convert all send_to_server() calls that used formatting to send
- pre-formatted strings instead. And don't error check
- send_to_server(), because it does its own error checking now.
-
- * client.c (send_to_server): don't use vasprintf(), just fwrite a
- certain number of bytes to the server. And do error checking
- here, so our callers don't have to.
- (send_arg): use send_to_server() instead of putc()'ing
- directly to `to_server'.
-
-Sun Dec 17 14:37:52 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * options.h.in (AUTH_CLIENT_SUPPORT, AUTH_SERVER_SUPPORT):
- Define to 1 but leave commented out, instead of #undef'ing them.
- This treats them like everything else in this file.
-
- * client.c: define server_started, init to 0.
- (start_server): set server_started to 1.
-
- * client.h: declare `server_started', extern.
- AUTH_CLIENT_SUPPORT moved here from cvs.h.
-
- * cvs.h: moved AUTH_CLIENT_SUPPORT stuff to client.h.
-
- * edit.c (notify_check): use new var server_started.
-
-Sun Dec 17 00:44:17 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (get_responses_and_close): Really stop ignoring ECHILD
- errors. The Nov 30 1995 change claimed to do this, but the code
- was not actually changed.
-
- * update.c (ignore_files): Revert H.J. Lu change; it was wrong for
- directories and sometimes looked at sb.st_mode when it wasn't set.
- * import.c (import_descend): Revert H.J. Lu change; it was wrong
- for directories and the extra lstat call was an unnecessary
- performance hit.
- * sanity.sh (import): Add test for the second of these two bugs.
-
-Sat Dec 16 17:26:08 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (send_to_server): Remove arbitrary limit. Also remove
- !HAVE_VPRINTF code; all relevant systems have vprintf these days.
-
-Sat Dec 16 21:35:31 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * checkout.c (checkout): use send_to_server() now.
-
-Sat Dec 16 21:18:16 1995 H.J. Lu (hjl@gnu.ai.mit.edu)
- (applied by kfogel@cyclic.com)
-
- * import.c (import_descend): We ignore an entry if it is
- 1. not a file, nor a link, nor a directory, or
- 2. a file and on the ignore list.
-
- * update.c (ignore_files): We ignore any thing which is
- 1. not a file, or
- 2. it is a file on the ignore list.
-
-Sat Dec 16 00:14:19 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (send_to_server): corrected comment.
-
- * client.h: prototype new func send_to_server().
-
- * add.c, admin.c, client.c, commit.c, diff.c, edit.c, history.c,
- import.c, log.c, patch.c, release.c, remove.c, rtag.c, status.c,
- tag.c, update.c, watch.c:
- Use send_to_server() instead of writing directly to to_server.
-
- * client.c: conditionally include the right stuff for variable arg
- lists.
- (send_to_server): new func.
-
-Fri Dec 15 23:10:22 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * error.c: expanded comments.
-
- * client.c (connect_to_pserver): verbosify errors.
- (connect_to_pserver): use send() and recv(), not write() and
- read(). Sockets are not file descriptors on all systems.
-
-Fri Dec 15 22:36:05 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (connect_to_pserver): oops, removed old debugging
- printf.
-
-Fri Dec 15 18:21:16 1995 Karl Fogel (kfogel@floss.cyclic.com)
-
- * client.c (auth_server_port_number): don't call htons();
- init_sockaddr() does that for us.
- (init_sockaddr): zero the sockadder_in struct before doing
- anything with it. IBM TCP/IP docs recommend this, and it can't
- hurt.
-
-Fri Dec 15 15:21:53 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (connect_to_pserver): new var `port_number', initialize
- with new func auth_server_port_number() and pass to
- init_sockaddr().
- (auth_server_port_number): new func. Right now it just returns
- `htons (CVS_AUTH_PORT)'. We'll probably add the ability to
- specify the port at run time soon, anyway, so having this function
- will make that easier.
-
-Wed Dec 6 18:08:40 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * cvs.h: Add CVSREP.
- * find_names.c (find_dirs): Skip CVSREP too.
- * fileattr.h, fileattr.c: New files, to manipulate file attributes.
- * hash.c (nodetypestring), hash.h (enum ntype): Add FILEATTR.
- * hash.c, hash.h (list_isempty): New function.
- * recurse.c (do_recursion): Call fileattr_startdir before
- processing files in a directory and fileattr_write and
- fileattr_free (after files, before recursing).
- * watch.c, watch.h: New files, to handle notification features.
- * edit.c, edit.h: New file, to handle new read-only checkout features.
- * client.c, server.c: Add "Mode" request, to change the mode of a file
- when it is checked in.
- * main.c (cmds): Add "watch", "edit", "unedit", "watchers", "editors".
- * main.c: Split command help from usg into new variable cmd_usage,
- which.
- (main): Add --help-commands option to print out cmd_usage.
- * cvs.h: Declare watch, edit, unedit, watchers, editors.
- * client.c, client.h: Add client_watch, client_edit, client_unedit,
- client_watchers, client_editors.
- * client.c, server.c: Add notification stuff.
- * update.c (checkout_file, patch_file), checkin.c (Checkin): Check
- _watched attribute when deciding read-only or read-write.
- * commit.c (checkaddfile): Call fileattr_newfile to set attributes
- on newly created files.
- * release.c (release):
- * cvs.h: Add CVSADM_NOTIFY and CVSADM_NOTIFYBAK.
- * recurse.c (do_recursion): Call notify_check.
- * commit.c (commit_fileproc): Call notify_do after committing file.
- * client.c (get_responses_and_close): Set to_server and from_server
- to NULL so that it is possible to tell whether we are speaking to
- the server.
- * cvs.h: Add CVSROOTADM_NOTIFY.
- * mkmodules.c (main): Add CVSROOTADM_NOTIFY to filelist.
- * Makefile.in (SOURCES,OBJECTS,HEADERS): Add new files mentioned above.
- * lock.c, cvs.h (lock_tree_for_write, lock_tree_cleanup): New
- functions, taken from old commit.c writelock code. As part of
- this, fsortcmp and lock_filesdoneproc go from commit.c to lock.c.
- So does locklist but it gets renamed to lock_tree_list.
- * commit.c: Use lock_tree_*.
-
-Fri Dec 15 10:37:00 1995 J.T. Conklin <jtc@slave.cygnus.com>
-
- * tag.c (tag_usage): Added -r and -D flags to usage string.
- (tag): Detect when user specifies both -r and -D arguments.
- Pass -r and -D arguments to server.
-
-Thu Dec 14 11:56:13 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (start_rsh_server): use RSH_NEEDS_BINARY_FLAG to
- conditionalize "-b" option to "rsh".
-
- * run.c (filter_stream_through_program): document return value and
- error behavior.
-
- * client.c (filter_through_gunzip): pass the supposedly
- superfluous "-d" option to gunzip, to avoid stimulating what seems
- to be an argument-passing bug in spawn() under OS/2 with IBM
- C/C++. Yucko.
-
-Wed Dec 13 20:08:37 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * options.h.in (RCSBIN_DFLT): Recommend specifying -b in
- inetd.conf for pserver. That is a pretty good solution.
-
-Wed Dec 13 18:29:59 1995 Preston L. Bannister <pbannister@ca.mdis.com>
- and Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (send_modified): make sure that vers and vers->options
- are non-NULL before strcmp()'ing them with "-kb".
- Initialize `bin' near where it is used, not at beginning of
- function.
- (update_entries): make sure `options' is non-NULL before
- strcmp()'ing with "-kb".
- Initialize `bin' near where it is used, not at beginning of
- function.
-
-Tue Dec 12 18:56:38 1995 Karl Fogel <kfogel@totoro.cyclic.com>
-
- * options.h.in (RCSBIN_DFLT): document the probable need for this
- to be set in the authenticating server.
-
-Tue Dec 12 11:56:43 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (expand_proc): If mfile is non-NULL, return it too as
- part of the expansion.
- * sanity.sh (modules): Add tests for above-fixed bug.
-
-Mon Dec 11 21:39:07 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * dog.c (flea_bath): Take `suds' arg.
- All collars changed.
-
-Mon Dec 11 15:58:47 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * login.c (login): if client password file doesn't exist, create
- it, duh.
-
- * main.c (main): die if CVSroot has access-method but no
- username.
-
- * root.c: added some comments.
-
- * main.c: removed all code pertaining to the "-a" option. We
- specify access-method in CVSroot now.
-
- * client.c (parse_cvsroot): new var, `access_method'. If CVSroot
- is prepended with an access method (i.e.,
- ":pserver:user@host:/path"), then handle it.
-
- * login.c (login): use || when checking if CVSroot is "fully
- qualified".
- Prepend ":pserver:" before writing to ~/.cvspass.
- (get_cvs_password): Take no parameters; we'll just use CVSroot to
- get the password.
-
-Mon Dec 11 12:43:35 1995 adamg <adamg@microsoft.com>
-
- * error.c, client.c, remove.c, main.c: Add explicit casts for some
- function pointers to remove warnings under MS VC.
- * main.c (main): remove use of NEED_CALL_SOCKINIT in favor of the
- more generic INITIALIZE_SOCKET_SUBSYSTEM. Note that the code assumes
- that if INITIALIZE_SOCKET_SUBSYSTEM() returns, socket subsystem
- initialization has been successful.
-
-Sat Dec 9 22:01:41 1995 Dan O'Connor <doconnor@tii.com>
-
- * commit.c (check_fileproc): pass RUN_REALLY flag to run_exec,
- because it's okay to examine the file with noexec set.
-
-Sat Dec 9 20:28:01 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (update_entries): new var, `bin, init to 0.
- Use it in determining whether to convert the file.
- (send_modified): same as above.
-
-Fri Dec 8 17:47:39 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * server.c (downcase_string): removed.
- (check_repository_password): don't deal with case-insensitivity
- anymore.
-
- * options.h.in (CVS_PASSWORDS_CASE_SENSITIVE): deleted this. No
- need for it anymore.
-
-Thu Dec 7 21:08:39 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * server.c (check_repository_password): when checking for false
- prefix-matches, look for ':', not '@'. Duh.
-
-Thu Dec 7 18:44:51 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * options.h.in (CVS_PASSWORDS_CASE_SENSITIVE): replaces
- CVS_PASSWORDS_CASE_INSENSITIVE; passwords are now insensitive by
- default. Expanded explanatory comment.
-
- * login.c (get_cvs_password): Use memset(), not bzero(). I
- botched this change earlier.
-
- * server.c (check_repository_password): no need to check
- xmalloc()'s return value.
- (check_repository_password): check for false prefix-matches (for
- example, username is "theo" and linebuf contains user
- "theocracy").
-
-Thu Dec 7 14:49:16 1995 Jim Meyering (meyering@comco.com)
-
- * filesubr.c (isaccessible): Rename from isaccessable.
- Update callers.
- * cvs.h: Update prototype.
- * main.c (main): Update callers.
- * server.c (main): Update callers.
-
-Thu Dec 7 12:50:20 1995 Adam Glass <glass@NetBSD.ORG>
-
- * cvs.h: "isaccessible" is the correct spelling.
- Also add "const" to second arg to make prototype match
- declaration.
-
-Thu Dec 7 11:06:51 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c, login.c: memset() instead of bzero().
-
-Thu Dec 7 00:08:53 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * server.c (authenticate_connection): document server's side of
- the Authentication Protocol too.
-
- * client.c (connect_to_pserver): when printing out "unrecognized
- response", also print out the offending response.
-
- * server.c (check_password): take `repository' arg too now.
- Call check_repository_password() before checking /etc/passwd.
- (check_repository_password): new func.
-
- * options.h.in (CVS_PASSWORDS_CASE_INSENSITIVE): new define, unset
- by default.
-
-Wed Dec 6 18:51:16 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * server.c (check_password): If user has a null password, then
- return 1 if arg is also null.
- Reverse sense of return value. Caller changed.
-
-Wed Dec 6 14:42:57 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * server.c (check_password): new func.
- (authenticate_connection): call above new func.
-
- * login.c (login): use construct_cvspass_filename().
- If CVSroot is not "fully-qualified", then insist the user qualify
- it before going on.
- (get_cvs_password): fleshed out. Now reads from ~/.cvspass, or
- prompts if no appropriate password found.
- (construct_cvspass_filename): new func.
-
- * server.c (authenticate_connection): send ACK or NACK to client.
-
- * client.c (connect_to_pserver): check for ACK vs NACK response
- from server after sending authorization request.
-
- * login.c (get_cvs_password): new func.
-
- * client.c (connect_to_pserver): use new func get_cvs_password().
- Prototype it at top of file. Hmmm.
-
-Wed Dec 6 13:29:22 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * server.c: same as below (AUTH_SERVER_SUPPORT).
-
- * main.c: same as below (AUTH_SERVER_SUPPORT where appropriate).
-
- * login.c: same same as below.
-
- * cvs.h: same as below.
-
- * client.c: use AUTH_CLIENT_SUPPORT, not CVS_LOGIN.
-
- * options.h.in (AUTH_CLIENT_SUPPORT, AUTH_SERVER_SUPPORT): these
- replace CVS_LOGIN.
-
-Wed Dec 6 00:04:58 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * server.c (authenticate_connection): expanded comment.
-
-Tue Dec 5 23:37:39 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (connect_to_pserver): read password from prompt for
- now.
-
- * server.c (authenticate_connection): if the password passes
- muster, then don't abort.
-
-Tue Dec 5 22:46:37 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * subr.c (strip_trailing_newlines): new func.
-
- * client.c (connect_to_pserver): took out print statements.
-
- * server.c (authenticate_connection): removed print statments.
- Use new func strip_trailing_newlines() to purify `repository',
- `username', and `password'.
- Run a primitive password check, just for testing.
-
- * client.c (connect_to_pserver): use CVS_AUTH_PORT.
- Take tofdp, fromfdp, and log args. Caller changed.
- (get_responses_and_close): either kerberos and CVS_LOGIN might
- have one fd for both directions, so adjust #ifdef accordingly.
-
- * cvs.h (CVS_AUTH_PORT): new define, default to 2401.
- Prototype strip_trailing_newlines().
-
-Tue Dec 5 16:53:35 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * server.c (authenticate_connection): new func.
-
- * client.c (init_sockaddr): func moved here from login.c.
- (connect_to_pserver): same as above. Take no args, now.
- Include <sys/socket.h>, <netinet/in.h>, <netdb.h>, if CVS_LOGIN.
-
- * cvs.h: Declare use_authenticating_server, as extern int.
- Declare connect_to_pserver().
-
- * main.c (main): call authenticate_connection(). Removed testing
- code.
- Add 'a' to the short-option string in the getopt() call.
-
- * login.c (connect_to_pserver): moved to client.c.
-
-Tue Dec 5 16:01:42 1995 Peter Chubb <peterc@bookworm.sw.oz.au>
- (patch applied by Karl Fogel <kfogel@cyclic.com>)
-
- * update.c (join_file): if vers->vn_user is "0", file has been
- removed on the current branch, so print an error and return.
-
-Mon Dec 4 14:27:42 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Version 1.6.3.
-
-Mon Dec 4 16:28:25 1995 Norbert Kiesel <nk@col.sw-ley.de>
-
- * release.c (release): add return (0) as last line
-
- * cvs.h: declare program_path
-
- * main.c define program_path
- (main): set program_path
-
- * release.c (release): use program_path for update_cmd
-
-Mon Dec 4 11:22:42 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Version 1.6.2.
-
-Sun Dec 3 20:02:29 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.h (struct rcsnode), rcs.c (freercsnode): Add expand field.
- * rcs.h (RCSEXPAND): New #define.
- * rcs.c (RCS_reparsercsfile): Record keyword expansion in expand
- field of struct rcsnode.
- * update.c (checkout_file): Set keyword expansion in Entries file
- from rcs file if there is nowhere else to set it from.
- * client.c (send_modified, update_entries) [LINES_CRLF_TERMINATED]:
- If -kb is in effect, don't convert.
-
- * update.c (update_file_proc), commit.c (check_fileproc),
- rcscmds.c (RCS_merge): Direct stdout to DEVNULL rather than
- passing -s option to grep. This avoids trouble with respect to
- finding a grep which support -s and whether we should use the (GNU
- grep) -q option if it exists.
- * options.h.in: Change "@ggrep_path@" to "grep".
-
-Fri Dec 1 11:53:19 1995 Norbert Kiesel <nk@col.sw-ley.de>
-
- * rcs.c (RCS_gettag): new parameter return_both force return both
- tags: the symbolic and the numeric one.
- (RCS_getversion): new parameter return_both is forwarded to
- RCS_gettag.
-
- * rtag.c, tag.c, commit.c, patch.c, update.c: pass 0 as additional
- last parameter to RCS_getversion and RCS_gettag
-
- * rcs.h (RCS_gettag): new parameter return_both.
- (RCS_getversion): new parameter return_both.
-
- * cvs.h (struct vers_ts): add vn_tag slot for symbolic tag name
-
- * vers_ts.c (Version_TS): call RCS_getversion with 1 for
- return_both and split output into vn_rcs and vn_tag
- (freevers_ts): free vn_tag
-
- * update.c (checkout_file): use vn_tag instead of vn_rcs when
- calling 'rcs co' to allow rcs expansion of :$Name :
-
-Thu Nov 30 20:44:30 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (get_responses_and_close): undo previous change
- regarding waitpid(). The problem has been solved by modifying
- os2/waitpid.c instead of its callers.
-
-Thu Nov 30 16:37:10 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c: All these changes are for OS/2, which will no longer have
- a separate client.c:
- (start_kerberos_server): new func, contains code that
- used to be in start_server().
- (start_server): moved kerberos code to above function, reorganized
- the rest. Added authentication clause.
- (call_in_directory): test errno against EACCESS, if EACCESS is
- defined (this is for OS/2's oddball mkdir).
- (change_mode): don't set execute permission on anything if
- EXECUTE_PERMISSION_LOSES is defined.
- (get_responses_and_close): if START_RSH_WITH_POPEN_RW, then use
- pclose() instead of fclose().
- If waitpid errors with ECHILD, don't die. This is okay.
- (start_rsh_server): alternate definition if
- START_RSH_WITH_POPEN_RW.
-
- * main.c: [all these changes conditional on CVS_LOGIN: ]
- Don't prototype connect_to_pserver, don't enter it in cmds[]
- (actually, it was never in there, I don't know why my previous
- change said it was).
- (use_authenticating_server): new global var.
- (main): if "-a", then set above new var to TRUE.
- (usg): document "-a" option.
-
-Wed Nov 29 12:55:10 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * main.c: Prototype connect_to_pserver(), and enter it in cmds[].
- (main): test some extremely primitive authentication.
-
- * login.c: Include <sys/socket.h>
- (connect_to_pserver): new func.
- (init_sockaddr): new func.
-
-Mon Nov 20 14:07:41 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Makefile.in (TAGFILES): Separate out from DISTFILES, for C code.
- (TAGS,tags): Use TAGFILES not DISTFILES.
-
-Sun Nov 19 11:22:43 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * recurse.c (do_recursion): Don't call server_pause_check if there
- are writelocks around. Revise comment to reflect fact we are no
- longer relying on a writelock'd operations being "unable" to
- generate enough data to pause.
-
-Sun Nov 19 10:04:50 1995 Peter Wemm <peter@haywire.DIALix.COM>
-
- * server.c, server.h, options.h.in: Implement hooks for doing
- simple flow control on the server to prevent VM exhaustion on a
- slow network with a fast server.
- * recurse.c: Call the flow control check at a convenient location
- while no locks are active. This is a convenience tradeoff against
- accurate flow control - if you have a large directory it will all
- be queued up, bypassing the flow control check until the next
- directory is processed.
-
-Sat Nov 18 16:22:06 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c, update.c, vers_ts.c, server.c, rcs.c, lock.c,
- ignore.c, entries.c, diff.c, commit.c, checkin.c:
- Use new macro `existence_error', instead of comparing errno to
- ENOENT directly.
-
-Fri Nov 17 14:56:12 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (start_server): removed alternate version of this func,
- since os2/client.c will now be used under OS/2.
-
-Thu Nov 16 22:57:12 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (start_server): ifdef HAVE_POPEN_RW, use a different
- version of start_server(). This is maybe not the cleanest cut to
- make, but it's better than mucking around with yet more #ifdefs in
- the middle of the old start_server() function. Once things are
- up, I may reposition this code.
-
-Wed Nov 15 15:33:37 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * main.c (main): ifdef NEED_CALL_SOCKINIT, then call SockInit().
- Only OS/2 needs this initialization.
-
-Tue Nov 14 18:54:01 1995 Greg A. Woods <woods@most.weird.com>
-
- * patch.c:
- - fix orientation of test for result of getline() call
- - use fputs() not printf() when just copying file out
-
- * cvsbug.sh:
- - add space after #!
- - new rcs id
- - allow version to be edited by Makefile.
-
- * Makefile.in:
- - make Makefile a dependent of all (this might not be perfect, but
- it at least gives you a chance to catch up on the second
- go-around).
- - filter cvsbug.sh in a manner similar to cvsinit.sh to get the
- version number set from version.c
-
-Tue Nov 14 13:28:17 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Call old log file check.plog, not check.olog.
-
- * sanity.sh: Convert remaining tests from old-style ('***' on fail
- and nothing on pass), to new-style (FAIL on fail and PASS on pass).
-
- * sanity.sh: Fix ability to run only some of the tests (always run
- tests 1-4.75 to set up repository, document better how it works).
-
- * sanity.sh: Change "completed successfully" to "completed" in
- message--many tests, but not all, exit if they fail.
-
-Tue Nov 14 15:10:00 1995 Greg A. Woods <woods@most.weird.com>
-
- * sanity.sh: test 63 doesn't work and probably can't
-
-Tue Nov 14 12:22:00 1995 Greg A. Woods <woods@most.weird.com>
-
- * sanity.sh: many minor tweaks:
- - make the optional arguments almost work
- - use a function 'directory_cmp' instead of 'diff -r'
- - fix up a few more tests that weren't working....
-
-Mon Nov 13 07:33:55 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * cvs.h: ifdef USE_OWN_POPEN, #include "popen.h". Only OS/2 has
- its own popen()/pclose() right now.
-
-Mon Nov 13 04:06:10 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * cvs.h: conform to 80 column standard (yes, I'm a pedant).
-
-Sat Nov 11 13:45:13 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * client.c (process_prune_candidates): use unlink_file_dir() to
- remove the directory, instead of invoking "rm" via run_exec().
-
-Fri Nov 10 14:38:56 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * main.c (main): removed "#define KF_GETOPT_LONG 1", since that
- change is no longer in testing.
-
-Thu Nov 9 20:32:12 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * release.c (release): Use Popen(), not popen().
-
-Wed Nov 8 10:20:20 1995 Jim Meyering (meyering@comco.com)
-
- * entries.c (ParseTag): Remove dcl of unused local.
-
- * patch.c: Include getline.h.
-
-Wed Nov 8 11:57:31 1995 Norbert Kiesel <nk@col.sw-ley.de>
-
- * options.h.in: add configuration option STEXID_SUPPORT (default
- is off i.e. old semantics)
-
- * filesubr.c (isaccessable): new function. Checks access-rights
- for files like access(), but is getxid-safe. Falls back to
- access() if SETXID_SUPPORT is not enabled.
- (isfile): replace stat() by isaccessable(file, F_OK)
- (isreadable): replace access() by isaccessable()
- (iswritable): ditto
- (make_directory): rename local variable buf to sb
-
- * cvs.h: add prototype for new function isaccessable.
-
- * server.c (serve_root): replace access() by isaccessable()
-
- * cvsrc.c (read_cvsrc): replace access() by isreadable()
-
- * main.c (main): replace access() by isaccessable()
-
-Wed Nov 8 10:22:41 1995 Greg A. Woods <woods@most.weird.com>
-
- * entries.c (fgetentent): change definition to static to match the
- declaration at the top of the file
-
-Tue Nov 7 16:59:25 1995 J.T. Conklin <jtc@lestat.cygnus.com>
-
- * rcs.c (RCS_getbranch, RCS_getdate, RCS_getrevtime, RCS_gettag,
- RCS_getversion, RCS_head): Use assert() instead of attempting to
- "do the right thing" with a bogus RCSNode argument.
-
-Mon Nov 6 14:24:34 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * vers_ts.c: Remove ctime define. It is just asking for trouble.
-
-Mon Nov 6 11:58:26 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * vers_ts.c: ifdef ctime, undef it before redefining it. It is a
- macro on some systems.
-
- * lock.c: don't prototype ctime() here. (See note below about
- fgetentent() in entries.c.)
-
-Sun Nov 5 16:06:01 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * entries.c (fgetentent): don't prototype ctime here; we include
- cvs.h, which includes system.h, which includes <time.h>
- unconditionally (either as <time.h> or <sys/time.h>). Anyway, IBM
- C/C++ chokes on mid-function, or even mid-file, prototypes. Sigh.
-
-Thu Nov 2 21:51:04 1995 Dan Wilder <dan@gasboy.com>
-
- * rtag.c (rtag): Fix typo ("-T" -> "-F").
-
-Tue Oct 31 19:09:11 1995 Dan Wilder <dan@gasboy.com>
-
- * diff.c (diff_dirproc): just return R_SKIP_ALL if dir not exist.
- (diff_file_nodiff): don't complain if file doesn't exist, just
- ignore.
-
-Tue Oct 31 09:25:10 1995 Norbert Kiesel <nk@col.sw-ley.de>
-
- * sanity.sh: Use absolute pathname for mkmodules.
-
-Sat Oct 28 01:01:41 1995 Jim Meyering (meyering@comco.com)
-
- * entries.c (ParseTag): Use getline instead of fgets.
-
-Fri Oct 27 13:44:20 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * cvs.h: do nothing about alloca ifdef ALLOCA_IN_STDLIB. I am
- rather suspicious of this solution, and will not be surprised to
- find out that there's a Right Way to handle this situation ("this
- situation" being that OS/2 simply declares alloca in <stdlib.h>).
- Suggestions are welcome; see src/cvs.h and lib/system.h to see why
- I was getting a conflict in the first place.
-
-Wed Oct 25 16:03:20 1995 J.T. Conklin <jtc@slave.cygnus.com>
-
- * cvs.h (struct entnode): Add user field.
- * entries.c (fputentent): New function, write entries line.
- (write_ent_proc): Call fputentent to write entries line.
- (Entnode_Create): New function, construct new Entnode.
- (Entnode_Destroy): New function, destruct old Entnode.
- (AddEntryNode): Changed to take an Entnode argument instead of
- separate user, version, timestamp, etc. arguments.
- (fgetentent): Changed to return Entnode.
- (struct entent, free_entent): Removed.
-
-Wed Oct 25 12:44:32 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * admin.c (admin): Don't rely on ANSI C string concatenation;
- SunOS 4.1.3 /bin/cc doesn't support it.
-
-Tue Oct 24 22:34:22 1995 Anthony J. Lill <ajlill@ajlc.waterloo.on.ca>
-
- * import.c (expand_at_signs): Check errno as well as return value
- from putc. Some systems bogusly return EOF when successfully
- writing 0xff.
-
-Tue Oct 24 14:32:45 1995 Norbert Kiesel <nk@col.sw-ley.de>
-
- * admin.c (admin): use getcaller() instead of getpwuid
-
- * subr.c (getcaller): prefer getlogin() to $USER and $LOGNAME
- (especially useful for NT where getuid always returns 0)
-
-Tue Oct 24 06:22:08 1995 Jim Meyering (meyering@comco.com)
-
- * cvsrc.c (read_cvsrc): Use getline instead of fgets.
- * patch.c (patch_fileproc): Use getline instead of fgets.
-
- * entries.c (fgetentent): Use getline instead of fgets.
- Use xmalloc to allocate space for each returned entry.
- Since LINE is no longer static, save it in struct entent.
- (struct entent): New member, line.
- (free_entent): New function.
- (Entries_Open): Call it after each call to fgetentent.
-
-Tue Oct 24 11:13:15 1995 Norbert Kiesel <nk@col.sw-ley.de>
-
- * cvs.h: Declare valloc again, but this time with the right
- signature (also changed in libs/valloc.c)
-
-Mon Oct 23 12:17:03 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * logmsg.c (do_editor): Check for errors from stdio calls.
-
-Mon Oct 23 12:37:06 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * cvs.h: Don't declare valloc. Some systems (e.g. linux) declare
- it in stdlib.h in a conflicting way.
-
-Mon Oct 23 08:41:25 1995 Jim Meyering (meyering@comco.com)
-
- * commit.c (commit_filesdoneproc): Use getline instead of fgets.
-
- * logmsg.c (do_editor): Use getline instead of fgets.
- (rcsinfo_proc): Likewise.
-
- * logmsg.c (do_editor): Lose if fclose of temp file output
- stream fails.
-
-Mon Oct 23 11:59:41 1995 Norbert Kiesel <nk@col.sw-ley.de>
-
- * cvs.h: add valloc declaration
-
- * server.h: add server_cleanup prototype
-
- * server.c: remove server_cleanup prototype
-
- * mkmodules.c (server_cleanup): fix parameter type
-
- * server.c: encapsulate wait_sig in #ifdef sun (it's only used in
- code which is also encapsulated in #ifdef sun)
-
- * rcscmds.c (RCS_deltag, RCS_lock): add definition of noerr
- parameter
-
- * error.c: include cvs.h instead of config.h, add USE(rcsid)
-
- * error.c (error): fix parameter type
-
- * update.c (join_file): encapsulate recent changes from garyo
- within #ifdef SERVER_SUPPORT
-
-Sun Oct 22 13:47:53 1995 J.T. Conklin <jtc@slave.cygnus.com>
-
- * client.c (update_entries): Fix memory leak; free mode_string and
- file_timestamp.
- (send_fileproc): Fix memory leak; call freevers_ts before exiting.
-
- * module.c (do_module): Partially fix memory leak; added
- variable so that the address of memory allocated by line2argv
- is retained, but comment out the call to free_names. Freeing
- the vector at that point loses because some of the elements
- may be used later in the function.
- (cat_module): fix memory leak.
-
- * recurse.c (start_recursion): Fix memory leak; free return
- value of Name_Repository after it has been used.
-
-Sat Oct 21 23:24:26 1995 Jim Meyering (meyering@comco.com)
-
- * client.c (send_modified) [LINES_CRLF_TERMINATED]: Comment text
- after #endif.
-
-Fri Oct 20 14:41:49 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Add test 87a, to test for bug fixed by garyo in
- change below.
-
-Fri Oct 20 10:59:58 1995 Gary Oberbrunner <garyo@darkstar.avs.com>
-
- * update.c (join_file): send file back to client even if no
- conflicts were detected, by calling Register().
-
-Fri Oct 20 10:46:45 1995 Norbert Kiesel <nk@col.sw-ley.de>
-
- * lock.c: Add prototype for Check_Owner
-
-Thu Oct 19 16:38:14 1995 Jim Meyering (meyering@comco.com)
-
- * lock.c (Check_Owner): Declare function `static int'.
-
-Thu Oct 19 14:58:40 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * expand_path.c (expand_variable): Fix typo ('*'->'(').
-
-Thu Oct 19 14:58:40 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c (commit_filesdoneproc): Check for errors from fopen,
- fgets, and fclose.
-
- * rcscmds.c (RCS_merge): Remove comment about rcsmerge -E.
- Hacking CVS was never a very good solution; the situation is fixed
- in RCS 5.7, and is documented in ../INSTALL.
-
-Thu Oct 19 15:06:15 1995 Jim Meyering (meyering@comco.com)
-
- * filesubr.c (xchmod): Parenthesize arithmetic in operand of |
- to placate gcc -Wall.
-
- * expand_path.c (expand_path): Parenthesize assignments used as
- truth values to placate gcc -Wall.
-
- * commit.c (checkaddfile): Remove dcls of unused variables.
- * lock.c (unlock): Remove dcl of unused variable.
-
-Thu Oct 19 14:58:40 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * root.c (Create_Root): If noexec, don't create CVS/Root.
-
-Wed Oct 18 11:19:40 1995 J.T. Conklin <jtc@slave.cygnus.com>
-
- * lock.c (unlock): Change order of comparison so that Check_Owner
- is called only if other conditions are true. This performance
- enhancement was broken when the AFS support was added.
-
-Wed Oct 18 12:51:33 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * main.c (main): check if argv[0] is "pserver" with else-if, not
- if, since we've already asked if it's "kserver".
-
-Tue Oct 17 18:09:23 1995 Warren Jones <wjones@tc.fluke.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Deal with supplying a relative cvs filename, or
- with a cvs filename which doesn't have basename "cvs".
-
-Mon Oct 16 15:58:31 1995 Vince Demarco <vdemarco@bou.shl.com>
-
- * parseinfo.c (Parse_Info): if the Keyword isn't ALL the current
- version doesn't use the expanded variable, It should.
-
-Mon Oct 16 15:58:31 1995 Gary Oberbrunner <garyo@avs.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (server_register): Don't pass NULL to printf if tag,
- date, or conflict is NULL.
-
-Thu Oct 12 12:13:42 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * main.c (main): begin to handle "pserver"; support not complete
- yet, however.
-
-Thu Oct 12 02:52:13 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * expand_path.c: Don't #include <pwd.h>, since cvs.h already does,
- and not all systems' <pwd.h>s are protected from multiple inclusion.
- * login.c: Likewise.
-
-Wed Oct 11 15:23:24 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * login.c (login): handle everything correctly now.
-
-Wed Oct 11 12:02:48 1995 Norbert Kiesel <nk@col.sw-ley.de>
-
- * rcs.c (RCS_gettag): support RCS keyword Name
-
-Tue Oct 10 19:11:16 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * options.h.in (CVS_LOGIN): discuss, but leave commented out.
- The "cvs login" command is still under construction; however, the
- repository was changing so fast that instead of creating a branch
- and dealing with the attendant hair, I'm just developing on the
- trunk, making sure that everything is surrounded by "#ifdef
- CVS_LOGIN ... #endif" so I don't get in anyone's way.
-
- * login.c: include cvs.h before checking CVS_LOGIN, so it has a
- chance to get defined before we ask if it's defined.
- (login): oops, use semi not comma in `for' loop init.
-
- * Makefile.in (SOURCES, OBJECTS): include login.c, login.o.
-
- * main.c: added protoype for login().
- Added "login" entry to cmds[].
- (usg): added line about "login".
-
- * login.c: new file.
-
-Tue Oct 10 18:33:47 1995 Karl Fogel <kfogel@totoro.cyclic.com>
-
- * Makefile.in (COMMON_OBJECTS): added error.o.
- (OBJECTS): took error.o out; it's in COMMON_OBJECTS now.
-
-Tue Oct 10 12:02:37 1995 Thorsten Lockert <tholo@sigmasoft.com>
-
- * cvsbug.sh: Cater to lame versions of sh (4.4BSD ash) by using
- ${foo-bar} instead of `if....`.
-
-Tue Oct 10 12:02:37 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * remove.c (remove_fileproc): If noexec, don't remove file. Check
- for error when removing file.
-
-Sun Oct 8 12:32:15 1995 Peter Wemm <peter@haywire.DIALix.COM>
-
- * run.c: detect/use POSIX/BSD style reliable signals for critical
- section masking etc. Helps prevent stray locks on interruption.
-
-Sat Oct 7 23:26:54 1995 Norbert Kiesel <nk@col.sw-ley.de>
-
- * admin.c (admin): If group CVS_ADMIN_GROUP exists, allow only
- users in that group to use "cvs admin".
- * options.h.in: Default CVS_ADMIN_GROUP to "cvsadmin".
-
-Sat Oct 7 23:05:24 1995 Norbert Kiesel <nk@col.sw-ley.de>
-
- * add.c, checkout.c, commit.c, cvs.h, filesubr.c, import.c,
- lock.c, main.c, modules.c, options.h.in: New variable cvsumask
- which is used to set mode of files in repository (regardless of
- umask in effect when cvs is run).
-
-Sat Oct 7 22:40:17 1995 Stephen Bailey <sjbailey@sand.npl.washington.edu>
-
- * lock.c: Include AFSCVS ifdefs to deal with AFS's lack of
- correspondance between userid's from stat and from geteuid.
-
-Sat Oct 7 22:28:49 1995 Scott Carson <sdc@TracerTech.COM>
-
- * add.c (add): Pass -ko, not -k -ko, to set keyword expansion options.
-
- * admin.c (admin): Don't skip first argument when sending to server.
-
-Fri Oct 6 21:45:03 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Version 1.6.1.
-
-Fri Oct 6 21:31:28 1995 Jeff Johnson <jbj@brewster.jbj.org>
-
- * cvs.h, admin.c, client.c, commit.c, log.c, modules.c,
- parseinfo.c, patch.c, recurse.c, rtag.c, status.c, tag.c:
- Prototype when dealing in pointers to functions.
-
-Fri Oct 6 21:07:22 1995 Mark H. Wilkinson <mhw@minster.york.ac.uk>
-
- * cvsrc.c (read_cvsrc): fix look up of command names in cvsrc file
- to use full name from command table rather than possible nickname
- in argv. Fixes errors with things like `cvs di' when cvsrc has
- `diff -u5' in it.
-
-Thu Aug 3 01:03:52 1995 Vince DeMarco <vdemarco@bou.shl.com>
-
- * parseinfo.c (Parse_Info): Add code to call expand_path function
- instead of using built in code.
-
- * wrapper.c (wrap_add): Add code to call expand_path function to
- expand all built in variables.
-
- * expand_path.c (New file): expand things that look like
- environmental variables (only expand local CVS environmental
- variables) and user names like ~/.
- * cvs.h: Declare expand_path.
-
- * Makefile.in (SOURCES, OBJECTS): Added expand_path.c,
- expand_path.o.
-
-Fri Oct 6 14:03:09 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * ignore.c (ign_setup): Don't try to look for a file in CVSroot if
- client. (The recent tightening of the error checking detects this).
-
- * commit.c (checkaddfile): Don't try to pass options if it is "".
-
-Thu Oct 5 18:04:46 1995 Karl Fogel <kfogel@totoro.cyclic.com>
-
- * sanity.sh: unset CVSREAD, since it causes the script to bomb.
-
-Thu Oct 5 18:29:17 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * remove.c, add.c, commit.c, cvs.h: Remove CVSEXT_OPT stuff; it
- has been broken for ages and the options are already stored in the
- Entries file.
-
-Thu Oct 5 18:20:13 1995 Norbert Kiesel <nk@col.sw-ley.de>
-
- * commit.c (checkaddfile): New argument options; pass it to RCS.
- (commit_fileproc): Pass it.
-
-Tue Oct 3 09:26:00 1995 Karl Fogel <kfogel@totoro.cyclic.com>
-
- * version.c: upped to 1.6.
-
-Mon Oct 2 18:10:35 1995 Larry Jones <larry.jones@sdrc.com>
-
- * server.c: if HAVE_SYS_BSDTYPES_H, include <sys/bsdtypes.h>.
-
-Mon Oct 2 10:34:53 1995 Karl Fogel <kfogel@totoro.cyclic.com>
-
- * version.c: Upped version to 1.5.95.
-
-Mon Oct 2 15:16:47 1995 Norbert Kiesel <nk@col.sw-ley.de>
-
- * tag.c, rtag.c: pass "mov" instead of "add" if tag will be moved
- (i.e. invoked with -F)
-
-Sun Oct 1 18:36:34 1995 Karl Fogel <kfogel@totoro.cyclic.com>
-
- * version.c: upped to 1.5.94.
-
- * server.c: reverted earlier ISC change (of Sep. 28).
-
- * version.c: upped to 1.5.93, for Peter Wemm's new SVR4 patch.
-
-Sun Oct 1 14:51:59 1995 Harlan Stenn <Harlan.Stenn@pfcs.com>
-
- * main.c: don't #include <pwd.h>; cvs.h does that already.
-
-Fri Sep 29 15:21:35 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * version.c: upped to 1.5.91 for another pre-1.6 release.
-
-Fri Sep 29 14:41:14 1995 <bmeier@rzu.unizh.ch>
-
- * root.c: start rcsid[] with "CVSid".
-
-Fri Sep 29 13:22:44 1995 Jim Blandy <jimb@totoro.cyclic.com>
-
- * diff.c (diff): Doc fix.
-
-Fri Sep 29 14:32:36 1995 Norbert Kiesel <nk@col.sw-ley.de>
-
- * repos.c (Short_Repository): chop superfluous "/".
-
- * tag.c (pretag_proc): correct user-visible string.
-
- * rtag.c (pretag_proc): correct user-visible string.
-
-Fri Sep 29 13:45:36 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * cvs.h (USE): if __GNUC__ != 2, expand to a dummy var instead of
- nothing.
-
-Thu Sep 28 13:37:05 1995 Larry Jones <larry.jones@sdrc.com>
-
- * server.c: ifdef ISC, include <sys/bsdtypes.h>.
-
-Fri Sep 29 07:54:22 1995 Mike Sutton <mws115@llcoolj.dayton.saic.com>
-
- * filesubr.c (last_component): Don't use ANSI style declaration.
-
-Wed Sep 27 15:24:00 1995 Del <del@matra.com.au>
-
- * tag.c, rtag.c: Pass a few extra options to the script
- named in taginfo (del/add, and revision number).
-
- * tag.c: Support a -r option (at long last). Also needs
- a -f option to tag the head if there is no matching -r tag.
-
-Tue Sep 26 11:41:08 1995 Karl Fogel <kfogel@totoro.cyclic.com>
-
- * version.c: Upped version to 1.5.89 for test release preceding
- 1.6.
-
-Wed Sep 20 15:32:49 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * ignore.c (ign_add_file): Check for errors from fopen and fclose.
-
-Tue Sep 19 18:02:16 1995 Jim Blandy <jimb@totoro.cyclic.com>
-
- * Makefile.in (DISTFILES): Remove sanity.el from this list; the
- file has been deleted.
-
-Thu Sep 14 14:17:52 1995 Peter Wemm <peter@haywire.dialix.com>
-
- * import.c: Recover from being unable to open the user file.
-
- * update.c (join_file): Print a message in the case where the file
- was added.
-
- * mkmodules.c: Deal with .db as well as .pag/.dir (for use with
- BSD 4.4 and real dbm support).
-
-Mon Sep 11 15:44:13 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * release.c (release): Revise comment regarding why and how we
- skip argv[0].
-
-Mon Sep 11 10:03:59 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * release.c (release): use return value of pclose to determine
- success of update.
-
-Mon Sep 11 09:56:33 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * release.c (release_delete): Fix comment.
-
-Sun Sep 10 18:48:35 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * release.c (release): made work with client/server.
- Don't ask if <arg> is mentioned in `modules'.
-
-Fri Sep 8 13:25:55 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: When committing a removal, send stdout to LOGFILE;
- this is no longer a silent operation.
-
- * sanity.sh: Remove OUTPUT variable; it is unused.
-
- * client.c: Add comment regarding deleting temp file.
- * main.c: Add comment regarding getopt REQUIRE_ORDER.
-
-Thu Sep 7 20:24:46 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * main.c (main): use getopt_long(), accept "--help" and
- "--version".
- Don't assume EOF is -1.
-
-Thu Sep 7 19:18:00 1995 Jim Blandy <jimb@cyclic.com>
-
- * cvs.h (unlink_file_dir): Add prototype for this.
-
-Thu Sep 7 14:38:06 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * ALL FILES: add semicolon, as indicated below.
-
- * cvs.h (USE): don't provide semicolon in the expansion of the USE
- macro; we'd rather the callers provided it themselves because that
- way etags doesn't get fooled.
-
-Mon Sep 4 23:30:41 1995 Magnus Hyllander <mhy@os.se>
-
- * checkout.c: cvs export now takes -k option and does not default
- to -kv.
- * checkout.c, cvs.h, modules.c: Modules file now takes -e option
- for cvs export.
-
-Mon Sep 4 23:30:41 1995 Kirby Koster <koster@sctc.com>
-
- * commit.c: When committing a removal, print a message saying what
- we are doing.
-
-Wed Aug 2 10:06:51 1995 Vince DeMarco <vdemarco@bou.shl.com>
-
- * server.c: fix compiler warnings (on NeXT) (declare functions as
- static inline instead of just static) functions: get_buffer_date,
- buf_append_char, and buf_append_data
-
-Mon Sep 4 22:31:28 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (update_entries), import.c (expand_at_signs): Check for
- errors from fread and putc.
-
-Fri Sep 1 00:03:17 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Fix TODO item pathname.
-
- * sanity.el: Removed. It was out of date, didn't do much, and I
- doubt anyone was using it.
-
- * no_diff.c (No_Difference): Don't change the modes of the files.
-
-Thu Aug 31 13:14:34 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Change version to 1.5.1.
-
- * client.c (start_rsh_server): Don't pass -d to "cvs server"
- invocation via rsh (restore change which was lost when NT stuff
- was merged in).
- * sanity.sh: Add TODO item suggesting test for bug which this fixes.
-
-Wed Aug 30 12:36:37 1995 Jim Blandy <jimb@totoro.cyclic.com>
-
- * sanity.sh (basic1): Make sure first-dir is deleted before
- running this set of tests.
-
- * subr.c: Extract file twiddling functions to a different file,
- because we want to use different versions of many of these
- routines under Windows NT.
- (copy_file, isdir, islink, isfile, isreadable, iswritable,
- open_file, make_directory, make_directories, xchmod,
- rename_file, link_file, unlink_file, xcmp, tmpnam,
- unlink_file_dir, deep_remove_dir): Moved to...
- * filesubr.c: ...this file, which is new.
- * Makefile.in (SOURCES): Mention filesubr.c.
- (COMMON_OBJECTS): Mention filesubr.o.
-
- * subr.c: Extract process execution guts to a different file,
- because we want to replace these routines entirely under
- Windows NT.
- (VA_START, va_alist, va_dcl): Move this stuff...
- (run_add_arg, run_init_prog): and these declarations...
- (run_prog, run_argv, run_argc, run_argc_allocated): and these
- variables...
- (run_setup, run_arg, run_args, run_add_arg, run_init_prog,
- run_exec, run_print, Popen): and these functions...
- * run.c: To this file, which is new.
- * Makefile.in (SOURCES): Mention run.c.
- (COMMON_OBJECTS): Mention run.o.
-
- * status.c (status): Call ign_setup, if client_active. Otherwise,
- we don't end up ignoring CVS directories and such.
-
- * server.c (mkdir_p, dirswitch): Use CVS_MKDIR instead of mkdir.
-
- * repos.c (Name_Repository): Use the isabsolute function instead of
- checking the first character of the path.
- * root.c (Name_Root): Same.
-
- * release.c (release): Use fncmp instead of strcmp to compare
- filenames.
-
- * rcs.c (RCS_parse, RCS_parsercsfile) [LINES_CRLF_TERMINATED]:
- Abort, because we have strong reason to believe this code is
- wrong.
-
- * patch.c (patch): Register signal handlers iff the signal name is
- #defined.
-
- * no_diff.c (No_Difference): Don't try to include server_active in
- trace message unless SERVER_SUPPORT is #defined.
-
- * modules.c (do_module): Use CVS_MKDIR instead of mkdir.
-
- * mkmodules.c (main): Call last_component instead of writing it out.
-
- * main.c (main): Call last_component instead of writing it out.
- Break up the long copyright string into several strings; Microsoft
- Visual C++ can't handle a line that long. Feh.
- Use fncmp instead of strcmp to compare filenames.
- Register signal handlers iff the signal name is #defined.
-
- * lock.c (readers_exist): Don't check return value of closedir.
- Most of the rest of the code doesn't, and some systems don't
- provide a return value anyway.
- (set_lock): Use CVS_MKDIR instead of mkdir.
-
- * import.c (import): Use the isabsolute function instead of
- checking the first character of the path.
- Try to delete the temporary file again after we close it, so it'll
- get deleted on systems that don't let you delete files that are
- open.
- (add_rev): Instead of making a hard link to the working file and
- checking in the revision with ci -r, use ci -u and restore the
- permission bits.
- (comtable): Include lines from SYSTEM_COMMENT_TABLE, if it is
- #defined.
- (add_rcs_file) [LINES_CRLF_TERMINATED]: Abort, because we have
- strong reason to believe this code is wrong.
- (import_descend_dir): Use CVS_MKDIR instead of mkdir.
-
- * history.c (read_hrecs): Open the file with OPEN_BINARY.
-
- * find_names.c (add_entries_proc, fsortcmp): Add prototypes.
- * entries.c (write_ent_proc): Add prototype.
- * hash.c (walklist): Add prototype for PROC argument.
- (sortlist): Add prototype for COMP argument.
- (printnode): Add a prototype, and make it static.
-
- * cvs.h (wrap_add_file, wrap_add): Add extern decls for these;
- they're used in import.c and update.c.
- * wrapper.c (wrap_add_file, wrap_add): Remove them from here.
-
- * cvs.h (RUN_NORMAL, RUN_COMBINED, RUN_REALLY, RUN_STDOUT_APPEND,
- RUN_STDERR_APPEND, RUN_SIGNIGNORE, RUN_TTY, run_arg, run_print,
- run_setup, run_args, run_exec, Popen, piped_child, close_on_exec,
- filter_stream_through_program, waitpid): Move all these
- declarations and definitions to the same section.
-
- * cvs.h (error_set_cleanup): Fix prototype.
-
- * cvs.h (isabsolute, last_component): New extern decls.
-
- * cvs.h (link_file): Function is deleted; remove extern decl.
-
- * cvs.h (DEATH_STATE, DEATH_SUPPORT): Move #definitions of these
- above the point where we #include rcs.h, since rcs.h tests them
- (or DEATH_SUPPORT, at least).
-
- * cvs.h (DEVNULL): #define this iff it isn't already #defined.
- config.h may want to override it.
-
- * cvs.h (SERVER_SUPPORT, CLIENT_SUPPORT): Don't #define these
- here; let config.h do that. On some systems, we don't have any
- server support.
-
- * cvs.h: Don't #include <io.h> or <direct.h>; we take care of
- those in lib/system.h.
-
- * commit.c (commit): Open logfile with the OPEN_BINARY flag.
- (precommit_proc): Use the isabsolute function, instead of
- comparing the first character with /.
- (remove_file, checkaddfile): Use CVS_MKDIR instead of mkdir.
-
- * client.c (send_repository): Use larger line buffers.
-
- * client.c [LINES_CRLF_TERMINATED] (update_entries): If we've just
- received a gzipped file, copy it over, converting LF to CRLF,
- instead of just renaming it into place.
- [LINES_CRLF_TERMINATED] (send_modified): Convert file to LF format
- before sending with gzip.
- (send_modified): Don't be disturbed if we get fewer than
- sb.st_size characters when we read. The read function may be
- collapsing CRLF to LF for us.
-
- * client.c: Add forward declarations for all the cvs command
- functions we call.
-
- * client.c: Add forward static declarations for all the
- handle_mumble functions.
-
- On some systems, RSH converts LF to CRLF; this screws us up.
- * client.c (rsh_pid): Declare this iff RSH_NOT_TRANSPARENT is not
- #defined.
- (get_responses_and_close): Use SHUTDOWN_SERVER if it is #defined.
- Only wait for rsh process to exit if RSH_NOT_TRANSPARENT is not
- #defined.
- (start_rsh_server): Declare and define only if
- RSH_NOT_TRANSPARENT is not #defined. Use piped_child, instead of
- writing all that out.
- (start_server): Only try to call start_rsh_server if
- RSH_NOT_TRANSPARENT is not #defined. Use START_SERVER if it is
- #defined. Convert file descriptors to stdio file pointers using
- the FOPEN_BINARY_WRITE and FOPEN_BINARY_READ strings.
-
- * client.h (rsh_pid): Don't declare this; it's never used elsewhere.
- (supported_request): Add external declaration for this;
- it's used in checkout.c.
-
- Move process-running functions to run.c; we need to totally
- replace these on other systems, like Windows NT.
- * client.c (close_on_exec, filter_stream_through_program): Moved
- to run.c.
- * run.c (close_on_exec, filter_stream_through_program): Here they
- are.
-
- * add.c (add_directory): Use CVS_MKDIR instead of straight mkdir.
- * checkout.c (checkout, build_dirs_and_chdir): Same.
- (checkout_proc): Use fncmp instead of strcmp.
- * client.c (call_in_directory): Use CVS_MKDIR instead of straight
- mkdir.
-
- * client.c (handle_checksum): Cast return value of strtol.
-
-Wed Aug 30 10:35:46 1995 Stefan Monnier <stefan.monnier@epfl.ch>
-
- * main.c (main): Allow -d to override CVSROOT_ENV.
-
-Thu Aug 24 18:57:49 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * cvs.h, rcscmds.c (RCS_unlock, RCS_deltag, RCS_lock): Add extra
- parameter for whether to direct stderr to DEVNULL.
- * checkin.c, tag.c, rtag.c, import.c, commit.c: Pass extra
- argument. 1 if stderr had been directed to DEVNULL before
- rcscmds.c was in use, 0 if it was RUN_TTY.
-
- * cvs.h: Add comment regarding attic.
-
-Tue Aug 22 10:09:29 1995 Alexander Dupuy <dupuy@smarts.com>
-
- * rcs.c (whitespace): Cast to unsigned char in case char is signed
- and value is negative.
-
-Tue Aug 22 10:09:29 1995 Kirby Koster <koster@sctc.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (join_file): If vers->vn_user is NULL, just return.
-
-Tue Aug 22 10:09:29 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c, client.c: Add comments about modes and umasks.
-
-Mon Aug 21 12:54:14 1995 Rick Sladkey <jrs@world.std.com>
-
- * update.c (update_filesdone_proc): If pipeout, don't try to
- create CVS/Root.
-
-Mon Aug 21 12:54:14 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (start_rsh_server): Don't pass -d to "cvs server"
- invocation via rsh.
-
- * server.c (serve_root): Report errors via pending_error_text.
- (serve_valid_requests): Check for pending errors.
-
-Sun Aug 20 00:59:46 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * options.h.in: Document usage of DIFF in update.c
- * update.c: Use DIFF -c, not DIFF -u. The small improvement in
- diff size is not worth the hassle in terms of everyone having to
- make sure that DIFF is GNU diff (IMHO).
-
-Sat Aug 19 22:05:46 1995 Jim Blandy <jimb@totoro.cyclic.com>
-
- * recurse.c (start_recursion): Doc fix.
-
- * server.c (do_cvs_command): Clear error_use_protocol in the
- child.
- (server): Set error_use_protocol.
-
-Sun Aug 13 15:33:37 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (do_cvs_command): Don't select on exceptions.
-
-Fri Aug 4 00:13:47 1995 Jim Meyering (meyering@comco.com)
-
- * Makefile.in (LDFLAGS): Set to @LDFLAGS@.
- (options.h): Depend on ../config.status and options.h.in.
- Add rule to build it from dependents.
-
- * add.c: Include save-cwd.h.
- (add_directory): Use save_cwd and restore_cwd instead of
- explicit getwd then chdir.
- * import.c (import_descend_dir): Likewise.
- * modules.c (do_module): Likewise.
-
- * recurse.c (save_cwd, restore_cwd, free_cwd): Remove functions.
- New versions have been broken out into save-cwd.c.
- (do_dir_proc): Adapt to handle status code returned by new versions
- of save_cwd and restore_cwd -- and one fewer argument to restore_cwd.
- (unroll_files_proc): Likewise.
-
- * wrapper.c (wrap_name_has): Add default: abort () to switch
- statement to avoid warning from gcc -Wall.
- (wrap_matching_entry): Remove dcl of unused TEMP.
- (wrap_tocvs_process_file): Remove dcl of unused ERR.
- (wrap_fromcvs_process_file): Likewise.
-
- * cvs.h: Remove prototype for error. Instead, include error.h.
- Also, remove trailing white space.
-
-Thu Aug 3 10:12:20 1995 Jim Meyering (meyering@comco.com)
-
- * import.c (import_descend_dir): Don't print probably-bogus CWD
- in error messages saying `cannot get working directory'.
-
-Sun Jul 30 20:52:04 1995 James Kingdon <kingdon@harvey.cyclic.com>
-
- * parseinfo.c (Parse_Info): Revise comments and indentation.
-
-Sun Jul 30 15:30:16 1995 Vince DeMarco <vdemarco@bou.shl.com>
-
- * history.c: put ifdef SERVER_SUPPORT around tracing code incase
- the client/server code is not compiled into the program.
-
-Sat Jul 29 16:59:49 1995 James Kingdon <kingdon@harvey.cyclic.com>
-
- * subr.c (deep_remove_dir): Use struct dirent, not struct direct.
-
-Sat Jul 29 18:32:06 1995 Vince DeMarco <vdemarco@bou.shl.com>
-
- * add.c: Check wrap_name_has.
-
- * diff.c, checkin.c, import.c: have code call unlink_file_dir in
- the appropriate places instead of just calling unlink_file.
-
- * checkin.c: Remove one unlink call.
-
- * import.c (comtable): Add .m .psw .pswm.
-
- * import.c (add_rcs_file): Remove tocvsPath before returning.
-
- * subr.c (unlink_file_dir): Add new function. unlinks the file if
- it is a file. or will do a recursive delete if the path is
- actually a directory.
- (deep_remove_dir): New function, helps unlink_file_dir.
-
- * mkmodules.c: Added CVSROOTADM_WRAPPER (cvswrappers file) to the
- checkout file list.
-
-Fri Jul 28 16:27:56 1995 James Kingdon <kingdon@harvey.cyclic.com>
-
- * checkout.c (safe_location): Use PATH_MAX not MAXPATHLEN.
-
-Fri Jul 28 19:37:03 1995 Paul Eggert <eggert@twinsun.com>
-
- * log.c (cvslog, log_fileproc): Pass all options (except -l)
- to rlog as-is, so that users can put spaces in options,
- can specify multiple -d options, etc.
- (ac, av): New variables.
- (log_option_with_arg, options): Remove.
-
- (log_fileproc): Don't prepend `/' to file name if update_dir is empty.
-
-Tue Jul 25 00:52:26 1995 James Kingdon <kingdon@harvey.cyclic.com>
-
- * checkout.c (safe_location): Don't use PROTO in function definition.
-
-Mon Jul 24 18:32:06 1995 Vince DeMarco <vdemarco@bou.shl.com>
-
- * checkout.c (safe_location): fix a compiler warning. (Declare
- safe_location). Changed code in safe_location to call getwd
- instead of getcwd. getwd is declared in the ../lib directory and
- used exclusively thoughout the code. (this helps portability on
- non POSIX systems).
-
- * wrapper.c: updated Andrew Athan's email address.
-
- * main.c: fix an ifdef so the code will compile. syntax error in
- the ifdef for CVS_NOADMIN.
-
-Mon Jul 24 13:25:00 1995 Del <del@babel.dialix.oz.au>
-
- * checkout.c: New procedure safe_location.
- Ensures that you don't check out into the repository
- itself.
-
- * tag.c, rtag.c, cvs.h, mkmodules.c: Added a "taginfo" file in
- CVSROOT to perform pre-tag checks.
-
- * main.c, options.h.in: Added a compile time option to
- disable the admin command.
-
-Fri Jul 21 17:07:42 1995 James Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c, status.c, patch.c, checkout.c, import.c, release.c,
- rtag.c, tag.c: Now -q and -Q options just print an error message
- telling you to use global -q and -Q options. The non-global
- options were a mess because some commands accepted them and some
- did not, and they were redundant with -q and -Q global options.
-
- * rcs.c, cvs.h, commit.c, log.c, find_names.c: Remove CVS.dea
- stuff. It is slower than the alternatives and I don't think
- anyone ever actually used it.
-
-Fri Jul 21 10:35:10 1995 Vince DeMarco <vdemarco@bou.shl.com>
-
- * Makefile.in (SOURCES, OBJECTS): Add wrapper.c, wrapper.o.
- * add.c, admin.c, checkout.c, commit.c, diff.c, import.c, log.c,
- remove.c, status.c: Call wrap_setup at start of commands.
- * add.c (add): Check for wrapper, as well as directory, in repository.
- * checkin.c: Add tocvsPath variable and associated handling.
- * cvs.h: Add wrapper declarations.
- * diff.c: Add tocvsPath variable and associated handling.
- * import.c: Add -W option, CVSDOTWRAPPER handling.
- (import_descend): check wrap_name_has.
- (update_rcs_file, add_rev, add_rcs_file): add tocvsPath
- variable and associated handling.
- * no_diff.c: Add tocvsPath variable and associated handling.
- * recurse.c (start_recursion): Check wrap_name_has.
- * update.c: Copy, don't merge, copy-by-merge files. Attempt to
- use -j on a copy-by-merge file generates a warning and no further
- action.
- * update.c: Add CVSDOTWRAPPER handling.
- * wrapper.c: Added.
-
-Fri Jul 21 00:20:52 1995 James Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c: Revert David Lamkin patch, except for the bits about
- removing temp_filename and the .rej file.
- * sanity.sh (errmsg1): Test for the underlying bug which Lamkin
- kludged around.
- * client.c (call_in_directory): Set short_pathname to include the
- filename, not just the directory. Improve comments regarding what
- is passed to FUNC.
-
-Thu Jul 20 17:51:54 1995 David Lamkin <drl@net-tel.co.uk>
-
- * client.c (short_pathname): Fixes the fetching of the whole file
- after a patch to bring it up to date has failed:
- - failed_patches[] now holds short path to file that failed
- - patch temp files are unlinked where the patch is done
-
-Thu Jul 20 12:37:10 1995 James Kingdon <kingdon@harvey.cyclic.com>
-
- * cvs.h: Declare error_set_cleanup
- * main.c: Call it.
- (error_cleanup): New function.
-
-Thu Jul 20 12:17:16 1995 Mark H. Wilkinson <mhw@minster.york.ac.uk>
-
- * add.c, admin.c, checkin.c, checkout.c, classify.c, client.c,
- client.h, commit.c, create_adm.c, cvs.h, diff.c, entries.c,
- history.c, import.c, log.c, main.c, modules.c, no_diff.c, patch.c,
- release.c, remove.c, repos.c, rtag.c, server.c, server.h,
- status.c, subr.c, tag.c, update.c, vers_ts.c, version.c: Put
- client code inside #ifdef CLIENT_SUPPORT, server code inside
- #ifdef SERVER_SUPPORT. When reporting version, report whether
- client and/or server are compiled in.
-
-Wed Jul 19 18:00:00 1995 Jim Blandy <jimb@cyclic.com>
-
- * subr.c (copy_file): Declare local var n to be an int,
- not a size_t. size_t is unsigned, and the return values
- of read and write are definitely not unsigned.
-
- * cvs.h [HAVE_IO_H]: #include <io.h>.
- [HAVE_DIRECT_H]: #include <direct.h>.
-
-Fri Jul 14 22:28:46 1995 Jim Blandy <jimb@totoro.cyclic.com>
-
- * server.c (dirswitch, serve_static_directory, serve_sticky,
- serve_lost, server_write_entries, serve_checkin_prog,
- serve_update_prog): Include more information in error messages.
- (Thanks, DJM.)
-
- * cvsbug.sh: Use /usr/sbin/sendmail, unless it doesn't
- exist, in which case use /usr/lib/sendmail. (Thanks, DJM.)
-
- * server.c (server, server_cleanup): Use "/tmp" instead of
- "/usr/tmp" when the TMPDIR environment variable isn't set. This
- is what the rest of the code uses.
-
-Thu Jul 13 11:03:17 1995 Jim Meyering (meyering@comco.com)
-
- * recurse.c (free_cwd): New function.
- (save_cwd, restore_cwd): Use it instead of simply freeing any
- string. The function also closes any open file descriptor.
-
- * import.c (comtable): Now static.
- (comtable): Put braces around each element of initializer.
-
- * cvs.h: Add prototype for xgetwd.
- * recurse.c (save_cwd, restore_cwd): New functions to encapsulate
- run-time solution to secure-SunOS vs. fchown problem.
- (do_dir_proc, unroll_files_proc): Use new functions instead of
- open-coded fchdir/chdir calls with cpp directives.
-
- * sanity.sh: Change out of TESTDIR before removing it.
- Some versions of rm fail when asked to delete the current directory.
-
-Wed Jul 12 22:35:04 1995 Jim Meyering (meyering@comco.com)
-
- * client.c (get_short_pathname): Add const qualifier to parameter dcl.
- (copy_a_file): Remove set-but-not-used variable, LEN.
- (handle_clear_static_directory): Likewise: SHORT_PATHNAME.
- (set_sticky): Likewise: LEN.
- (handle_set_sticky): Likewise: SHORT_PATHNAME.
- (handle_clear_sticky): Likewise: SHORT_PATHNAME.
- (start_rsh_server): Convert perl-style `cond || stmt' to more
- conventional C-style `if (cond) stmt.' Sheesh.
- Remove dcl of unused file-static, SEND_CONTENTS.
-
- * history.c: Remove dcls of set-but-not-used file-statics,
- HISTSIZE, HISTDATA.
- (read_hrecs): Don't set them.
-
- * import.c (add_rev): Remove dcl of set-but-not-used local, RETCODE.
-
- * repos.c (Name_Repository): Remove dcl of set-but-not-used local,
- HAS_CVSADM.
-
- * cvsrc.c (read_cvsrc): Parenthesize assignment used as truth value.
-
-Tue Jul 11 16:49:41 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * hash.h (struct entnode, Entnode): moved from here...
- * cvs.h: to here.
-
-Wed Jul 12 19:45:24 1995 Dominik Westner (dominik@gowest.ppp.informatik.uni-muenchen.de)
-
- * client.c (server_user): new var.
- (parse_cvsroot): set above if repo is "user@host:/dir".
- (start_rsh_server): if server_user set, then use it.
-
-Wed Jul 12 10:53:36 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * sanity.sh: remove the TESTDIR after done.
-
- * cvsbug.sh (GNATS_ADDR): now bug-cvs@prep.ai.mit.edu again.
-
-Tue Jul 11 15:53:08 1995 Greg A. Woods <woods@most.weird.com>
-
- * options.h.in: depend on configure for grep and diff, now that
- changes to configure.in are applied.
-
-Tue Jul 11 14:32:14 1995 Michael Shields <shields@tembel.org>
-
- * Makefile.in (LDFLAGS): Pick up from configure.
-
-Tue Jul 11 14:20:00 1995 Loren James Rittle <rittle@supra.comm.mot.com>
-
- * import.c (add_rev), commit.c (remove_file, ci_new_rev),
- checkin.c (Checkin), subr.c (make_message_rcslegal), cvs.h:
- Always perform sanity check and fix-up on messages to be passed
- directly to RCS via the '-m' switch. RCS 5.7 requires that a
- non-total-whitespace, non-null message be provided or it will
- abort with an error. CVS is not setup to handle any returned
- error from 'ci' gracefully and, thus, the repository entered a
- trashed state.
-
- * sanity.sh: Add regression tests for new code and interactions
- with RCS 5.7.
-
-Sun Jul 9 19:03:00 1995 Greg A. Woods <woods@most.weird.com>
-
- * .cvsignore: added new backup file
-
- * options.h.in: our new configure.in finds the right diff and
- grep paths now....
-
- * subr.c: quote the string in run_print() for visibility
- - indent a comment
- - Jun Hamano's xchmod() patch to prevent writable files
- (from previous local changes)
-
- * logmsg.c: fix a NULL pointer de-reference
- - clean up some string handling code...
- (from previous local changes)
-
- * parseinfo.c: add hack to expand $CVSROOT in an *info file.
- - document "ALL" and "DEFAULT" in opening comment for Parse_Info()
- - fix the code to match the comments w.r.t. callbacks for "ALL"
- - add a line of trace output...
- (from previous local changes)
-
- * mkmodules.c: add support for comments in CVSROOT/checkoutlist
- - add CVSroot used by something other .o, ala main.c
- (from previous local changes)
-
- * main.c, cvs.h: add support for $VISUAL as log msg editor
- (from previous local changes)
-
- * status.c: add support for -q and -Q (from previous local changes)
-
-
-Sun Jul 9 18:44:32 1995 Karl Fogel <kfogel@floss.cyclic.com>
-
- * log.c: trivial change to test ChangeLog stuff.
-
-Sat Jul 8 20:33:57 1995 Paul Eggert <eggert@twinsun.com>
-
- * history.c: (history_write): Don't assume that fopen(..., "a")
- lets one interleave writes to the history file from different processes
- without interlocking. Use open's O_APPEND option instead.
- Throw in an lseek to lessen the race bugs on non-Posix hosts.
- * cvs.h, subr.c (Fopen): Remove.
-
- * log.c (log_fileproc): Pass working file name to rlog, so that
- the name is reported correctly.
-
-Fri Jul 7 18:29:37 1995 Michael Hohmuth <hohmuth@inf.tu-dresden.de>
-
- * client.c, client.h (client_import_setup): New function.
- (client_import_done, client_process_import_file): Add comments
- regarding now-redundant code.
- * import.c (import): Call client_import_setup.
-
-Tue Jul 4 09:21:26 1995 Bernd Leibing <bernd.leibing@rz.uni-ulm.de>
-
- * rcs.c (RCS_parsercsfile_i): Rename error to l_error; SunOS4 /bin/cc
- doesn't like a label and function with the same name.
-
-Sun Jul 2 12:51:33 1995 Fred Appelman <Fred.Appelman@cv.ruu.nl>
-
- * logmsg.c: Rename strlist to str_list to avoid conflict with
- Unixware 2.01.
-
-Thu Jun 29 17:37:22 1995 Paul Eggert <eggert@twinsun.com>
-
- * rcs.c (RCS_check_kflag): Allow RCS 5.7's new -kb option.
-
-Wed Jun 28 09:53:14 1995 James Kingdon <kingdon@harvey.cyclic.com>
-
- * Makefile.in (HEADERS): Remove options.h.in.
- (DISTFILES): Add options.h.in.
- Depend on options.h in addition to HEADERS.
-
-Tue Jun 27 22:37:28 1995 Vince Demarco <vdemarco@bou.shl.com>
-
- * subr.c: Don't try to do fancy waitstatus stuff for NeXT,
- lib/wait.h is sufficient.
-
-Mon Jun 26 15:17:45 1995 James Kingdon <kingdon@harvey.cyclic.com>
-
- * Makefile.in (DISTFILES): Remove RCS-patches and convert.sh.
-
-Fri Jun 23 13:38:28 1995 J.T. Conklin (jtc@rtl.cygnus.com)
-
- * server.c (dirswitch, serve_co): Use CVSADM macro instead of
- literal "CVS".
-
-Fri Jun 23 00:00:51 1995 James Kingdon <kingdon@harvey.cyclic.com>
-
- * README-rm-add: Do not talk about patching RCS, that only
- confuses people.
- * RCS-patches, convert.sh: Removed (likewise).
-
-Thu Jun 22 10:41:41 1995 James Kingdon <kingdon@harvey.cyclic.com>
-
- * subr.c: Change -1 to (size_t)-1 when comparing against a size_t.
-
-Wed Jun 21 16:51:54 1995 nk@ipgate.col.sw-ley.de (Norbert Kiesel)
-
- * create_adm.c, entries.c, modules.c: Avoid coredumps if
- timestamps, tags, etc., are NULL.
-
-Tue Jun 20 15:52:53 1995 Jim Meyering (meyering@comco.com)
-
- * checkout.c (checkout): Remove dcl of unused variable.
- * client.c (call_in_directory, handle_clear_static_directory,
- handle_set_sticky, handle_clear_sticky, send_a_repository,
- send_modified, send_dirent_proc): Remove dcls of unused variables.
- * server.c (receive_file, serve_modified, server_cleanup):
- Remove dcls of unused variables.
- * subr.c (copy_file): Remove dcl of unused variable.
- * vers_ts.c (time_stamp_server): Remove dcl of unused variable.
-
-Mon Jun 19 13:49:35 1995 Jim Blandy <jimb@totoro.cyclic.com>
-
- * sanity.sh: Fix commencement message --- the test suite says
- "Ok." when it's done.
-
-Fri Jun 16 11:23:44 1995 Jim Meyering (meyering@comco.com)
-
- * entries.c (fgetentent): Parenthesize assignment in if-conditional.
-
-Thu Jun 15 17:33:28 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * server.c (get_buffer_data, buf_append_char, buf_append_data):
- Don't conditionalize use of "inline". Autoconf takes care of
- defining it away on systems that don't grok it.
-
-Thu Jun 15 13:43:38 1995 Jim Kingdon (kingdon@cyclic.com)
-
- * options.h.in (DIFF): Default to "diff" not "diff -a" since diff
- might not support the -a option.
-
-Wed Jun 14 11:29:42 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * import.c (import_descend): Initialize dirlist to NULL.
-
- * subr.c (copy_file): Fix infinite loop.
-
- * server.c (serve_directory): fix a memory leak.
-
- * checkout.c, commit.c, diff.c, history.c, import.c, log.c,
- patch.c, release.c, remove.c, rtag.c, status.c, tag.c, update.c:
- Use send_arg() to send command line arguments to server.
-
- * commit.c (fsortcmp), find_names (fsortcmp), hash.c (hashp,
- findnode), hash.h (findnode), rcs.c (RCS_addnode,
- RCS_check_kflag, RCS_check_tag, RCS_isdead, RCS_parse,
- RCS_parsercsfile_i), rcs.h (RCS_addnode, RCS_check_kflag,
- RCS_check_tag, RCS_parse): Added const qualifiers as
- appropriate.
- * rcs.h (RCS_isdead): Added prototype.
-
- * hash.h (walklist, sortlist): correct function prototypes.
-
- * ignore.c (ign_setup): don't bother checking to see if file
- exists before calling ign_add_file.
-
-Fri Jun 9 11:24:06 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * all source files (rcsid): Added const qualifer.
- * ignore.c (ign_default): Added const qualifier.
- * subr.c (numdots): Added const qualifier to function argument.
- * cvs.h (numdots): Added const qualifier to prototype argument.
-
- * client.c (change_mode): Tied consecutive if statements testing
- the same variable together with else if.
-
- * import.c (import_descend): Build list of subdirectories when
- reading directory, and then process the subdirectories in that
- list. This change avoids I/O overhead of rereading directory
- and reloading ignore list (.cvsignore) for each subdirectory.
-
-Thu Jun 8 11:54:24 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * import.c (import_descend): Use 4.4BSD d_type field if it is
- present.
-
- * lock.c (set_lockers_name): Use %lu in format and cast st_uid
- field to unsigned long.
-
- * import.c (import): Use RCS_check_kflag() to check -k options.
- (keyword_usage, str2expmode, strn2expmode, expand_names):
- Removed.
- * rcs.c (RCS_check_kflag): Added keyword_usage array from import.c
- for more descriptive error messages.
-
- * subr.c (run_setup, run_args): Changed variable argument
- processing to work on machines that use <varargs.h>.
-
- * subr.c (copy_file, xcmp): Changed to read the file(s) by blocks
- rather than by reading the whole file into a huge buffer. The
- claim that this was reasonable because source files tend to be
- small does not hold up in real world situations. CVS is used
- to manage non-source files, and mallocs of 400K+ buffers (x2
- for xcmp) can easily fail due to lack of available memory or
- even memory pool fragmentation.
- (block_read): New function, taken from GNU cmp and slightly
- modified.
-
- * subr.c (xcmp): Added const qualifier to function arguments.
- * cvs.h (xcmp): Added const qualifer to prototype arguments.
-
-Wed Jun 7 11:28:31 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * cvs.h (Popen): Added prototype.
- (Fopen, open_file, isreadable, iswritable, isdir, isfile,
- islink, make_directory, make_directories, rename_file,
- link_file, unlink_file, copy_file): Added const qualifer to
- prototype arguments.
- * subr.c (Fopen, Popen, open_file, isreadable, iswritable, isdir,
- isfile, islink, make_directory, make_directories, rename_file,
- link_file, unlink_file, copy_file): Added const qualifier to
- function arguments.
-
- * logmsg.c (logfile_write), recurse.c (do_recursion, addfile):
- Don't cast void functions to a void expression. There is at
- least one compiler (MPW) that balks at this.
-
- * rcs.c (keysize, valsize): Change type to size_t.
-
- * add.c (add_directory): Don't cast umask() argument to int.
-
- * import.c (add_rcs_file): Changed type of mode to mode_t.
-
- * rcscmds.c (RCS_merge): New function.
- * cvs.h (RCS_merge): Declare.
- * update.c (merge_file, join_file): Call RCS_merge instead of
- invoking rcsmerge directly.
-
- * cvs.h: Include <stdlib.h> if HAVE_STDC_HEADERS, otherwise
- declared getenv().
- * cvsrc.c, ignore.c, main.c: Removed getenv() declaration.
-
- * client.c (mode_to_string): Changed to take mode_t instead of
- struct statb argument. Simplified implementation, no longer
- overallocates storage for returned mode string.
- * client.h (mode_to_string): Updated declaration.
- * server.c (server_updated): Updated for new calling conventions,
- pass st_mode instead of pointer to struct statb.
-
- * cvs.h (CONST): Removed definition, use of const qualifier is
- determined by autoconf.
- * history.c, modules.c, parseinfo.c: Use const instead of CONST.
-
- * add.c, admin.c, checkout.c, commit.c, diff.c, import.c, log.c,
- main.c, mkmodules.c, patch.c, recurse.c, remove.c, rtag.c,
- server.c, status.c, subr.c, tag.c, update.c: Changed function
- arguments "char *argv[]" to "char **argv" to silence lint
- warnings about performing arithmetic on arrays.
-
-Tue Jun 6 18:57:21 1995 Jim Blandy <jimb@totoro.cyclic.com>
-
- * version.c: Fix up version string, to say that this is Cyclic
- CVS.
-
-Tue Jun 6 15:26:16 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * subr.c (run_setup, run_args, run_add_arg, xstrdup): Add const
- qualifier to format argument.
- * cvs.h (run_setup, run_args, xstrdup): Likewise.
-
- * Makefile.in (SOURCES): Added rcscmds.c.
- (OBJECTS): Added rcscmds.o.
-
- * rcscmds.c: New file, with new functions RCS_settag, RCS_deltag,
- RCS_setbranch, RCS_lock, RCS_unlock.
- * checkin.c, commit.c, import.c, rtag.c, tag.c: Call above
- functions instead of exec'ing rcs commands.
- * cvs.h: Declare new functions.
-
-Mon May 29 21:40:54 1995 J.T. Conklin (jtc@rtl.cygnus.com)
-
- * recurse.c (start_recursion, do_recursion): Set entries to NULL
- after calling Entries_Close().
-
-Sat May 27 08:08:18 1995 Jim Meyering (meyering@comco.com)
-
- * Makefile.in (check): Export RCSBIN only if there exists an
- `rcs' executable in ../../rcs/src. Before, tests would fail when
- the directory existed but contained no executables.
- (distclean): Remove options.h, now that it's generated.
- (Makefile): Regenerate only *this* file when Makefile.in is
- out of date. Depend on ../config.status.
-
-Fri May 26 14:34:28 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * entries.c (Entries_Open): Added missing fclose().
- (Entries_Close): Don't write Entries unless Entries.Log exists.
-
- * entries.c (Entries_Open): Renamed from ParseEntries; changed to
- process Entries Log files left over from previous crashes or
- aborted runs.
- (Entries_Close): New function, write out Entries file if
- neccessary and erase Log file.
- (Register): Append changed records to Log file instead of
- re-writing file.
- (fgetentent): New function, parse one Entry record from a file.
- (AddEntryNode): It's no longer an error for two records with the
- same name to be added to the list. New records replace older
- ones.
- * cvs.h (Entries_Open, Entries_Close): Add prototypes.
- (CVSADM_ENTLOG): New constant, name of Entries Log file.
- * add.c, checkout.c, client.c, find_names.c, recurse.c: Use
- Entries_Open()/Entries_Close() instead of ParseEntries()/dellist().
-
- * add.c, admin.c, checkout.c, client.c, commit.c, diff.c,
- history.c, import.c, log.c, patch.c, release.c, remove.c,
- rtag.c, server.c, status.c, tag.c, update.c: Changed
- conditionals so that return value of *printf is tested less than
- 0 instead of equal to EOF.
-
-Thu May 25 08:30:12 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * subr.c (xmalloc): Never try to malloc zero bytes; if the user
- asks for zero bytes, malloc one instead.
-
-Wed May 24 12:44:25 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
-
- * subr.c (xmalloc): Don't complain about NULL if zero bytes were
- requested.
-
-Tue May 16 21:49:05 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
-
- * subr.c (xmalloc): Never try to malloc zero bytes; if the user
- asks for zero bytes, malloc one instead.
-
-Mon May 15 14:35:11 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * lock.c (L_LOCK_OWNED): Removed.
-
- * add.c, checkout.c, client.c, create_adm.c, cvs.h, entries.c,
- find_names.c modules.c, recurse.c, release.c, repos.c, update.c:
- removed CVS 1.2 compatibility/upgrade code.
-
-Mon May 8 11:25:07 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * lock.c (write_lock): Missed one instance where rmdir(tmp) should
- have been changed to clear_lock().
-
-Wed May 3 11:08:32 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * create_adm.c, entries.c, import.c, root.c: Changed conditionals
- so that return value of *printf is tested less than 0 instead of
- equal to EOF --- That's all Standard C requires.
-
-Wed May 3 18:03:37 1995 Samuel Tardieu <tardieu@emma.enst.fr>
-
- * rcs.h: removed #ifdef CVS_PRIVATE and #endif because cvs didn't
- compile anymore.
-
-Mon May 1 13:58:53 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * rcs.c, rcs.h: Implemented lazy parsing of rcs files.
- RCS_parsercsfile_i modified to read only the first two records
- of rcs files, a new function RCS_reparsercsfile is called only
- when additional information (tags, revision numbers, dates,
- etc.) is required.
-
-Mon May 1 12:20:02 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * Makefile.in (INCLUDES): Include -I. for options.h.
-
-Fri Apr 28 16:16:33 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
-
- * Makefile.in (SOURCES, HEADERS, DISTFILES): Updated.
- (dist-dir): Renamed from dist; changed to work with DISTDIR
- variable passed from parent.
-
- We don't want to include a file the user has to edit in the
- distribution.
- * options.h: No longer distributed.
- * options.h.in: Distribute this instead.
- * ../INSTALL, ../README: Installation instructions updated.
-
- * client.c (start_rsh_server): Send the remote command to rsh as a
- single string.
-
-Fri Apr 28 00:29:49 1995 Noel Cragg <noel@vo.com>
-
- * commit.c: Added initializer for FORCE_CI
-
- * sanity.sh: Fix tests added 25 Apr -- they were expecting the
- server to make noise, but the CVS_SERVER variable had been
- accidentally set with the `-Q' flag. Ran all tests -- both
- locally and remotely -- to verify that the change didn't break
- anything.
-
-Thu Apr 27 12:41:52 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * Makefile.in: Revise comment regarding check vs. remotecheck.
-
-Thu Apr 27 12:52:28 1995 Bryan O'Sullivan <bos@cyclic.com>
-
- * client.c (start_rsh_server): If the CVS_RSH environment variable
- is set, use its contents as the name of the program to invoke
- instead of `rsh'.
-
-Thu Apr 27 12:18:38 1995 Noel Cragg <noel@vo.com>
-
- * checkout.c (checkout): To fix new bug created by Apr 23 change,
- re-enabled "expand-module" functionality, because it has the side
- effect of setting the checkin/update programs for a directory. To
- solve the local/remote checkout problem that prompted this change
- in the first place, I performed the next change.
- * server.c (expand_proc): Now returns expansions for aliases only.
-
-Wed Apr 26 12:07:42 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * rcs.c (getrcskey): Rewritten to process runs of whitespace chars
- and rcs @ strings instead of using state variables "white" and
- "funky".
-
-Fri Apr 7 15:49:25 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * lock.c (unlock): Only call stat if we need to.
-
-Wed Apr 26 10:48:44 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * server.c (new_entries_line): Don't prototype.
-
-Tue Apr 25 22:19:16 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
-
- * sanity.sh: Add new tests to catch bugs in Apr 23 change.
-
-Tue Apr 25 17:10:55 1995 Roland McGrath <roland@baalperazim.frob.com>
-
- * create_adm.c (Create_Admin): Use getwd instead of getcwd.
-
-Sun Apr 23 20:58:32 1995 Noel Cragg <noel@vo.com>
-
- * checkout.c (checkout): Disabled "expand-module" functionality on
- remote checkout, since it makes modules behave like aliases (see
- longer note there). This change necessitated the change below.
- Also merged the like parts of a conditional.
-
- * client.c (call_in_directory): Changed the algorithm that created
- nested and directories and the "CVS" administration directories
- therein. The algoithm wrongly assumed that the name of the
- directory that that was to be created and the repository name were
- the same, which breaks modules.
-
- * create_adm.c (Create_Admin), module.c (do_module), server.c
- (server_register), subr.c, entries.c: Added fprintfs for trace-mode
- debugging.
-
- * client.c (client_send_expansions): Argument to function didn't
- have a type -- added one.
-
- * server.c (new_entries_line): Arguments to this function are
- never used -- reoved them and fixed callers.
-
-Sat Apr 22 11:17:20 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * rcs.c (RCS_parse): If we can't open the file, give an error
- message (except for ENOENT in case callers rely on that).
-
-Wed Apr 19 08:52:37 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * client.c (send_repository): Check for CVSADM_ENTSTAT in `dir', not
- in `.'.
-
- * sanity.sh: Add TODO list. Revise some comments. Add tests of
- one working directory adding a file and other updating it.
-
-Sat Apr 8 14:52:55 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
-
- * Makefile.in (CFLAGS): Let configure set the default for CFLAGS.
- Under GCC, we want -g -O.
-
-Fri Apr 7 15:49:25 1995 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * root.c (Name_Root): merge identical adjacent conditionals.
-
- * create_admin.c (Create_Admin): Rearranged check for CVSADM and
- OCVSADM directories so that CVSADM pathname is only built once.
-
- * update.c (update_dirleave_proc): Removed code to remove CVS
- administration directory if command_name == "export" and to
- create CVS/Root file if it is not present. Identical code
- in update_filesdone_proc() will perform these same actions.
- Also removed code that read and verfied CVS/Root. This is
- expensive, and if it is necessary should happen in the
- general recursion processor rather than in the update
- callbacks.
-
- * lock.c (masterlock): New variable, pathname of master lockdir.
- (set_lock): removed lockdir argument, now constructs it itself
- and stores it in masterlock.
- (clear_lock): new function, removes master lockdir.
- (Reader_Lock, write_lock): call clear_lock instead of removing
- master lockdir.
- (Reader_Lock, write_lock): #ifdef'd out CVSTFL code.
-
- * main.c (main): register Lock_Cleanup signal handler.
- * lock.c (Reader_Lock, write_lock): no longer register
- Lock_Cleanup.
-
- * main.c (main): initialize new array hostname.
- * lock.c (Reader_Lock, write_lock): Use global hostname array.
- * logmsg.c (logfile_write): Likewise.
-
- * recurse.c (do_dir_proc, unroll_files_proc): Use open()/fchdir()
- instead of getwd()/chdir() on systems that support the fchdir()
- system call.
-
-Fri Apr 7 06:57:20 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * server.c: Include the word "server" in error message for memory
- exhausted, so the user knows which machine ran out of memory.
-
- * sanity.sh: For remote, set CVS_SERVER to test the right server,
- rather than a random one from the PATH.
-
- * commit.c [DEATH_STATE]: Pass -f to `ci'.
-
-Thu Apr 6 13:05:15 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
-
- * commit.c (checkaddfile): If we didn't manage to fopen the file,
- don't try to fclose it.
-
- * client.c (handle_m, handle_e): Use fwrite, rather than a loop of
- putc's. Sometimes these streams are unbuffered.
-
-Tue Apr 4 11:33:56 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
-
- * (DISTFILES): Include cvsbug.sh, ChangeLog, NOTES, RCS-patches,
- README-rm-add, ChangeLog.fsf, sanity.sh, sanity.el, and
- .cvsignore.
-
-Mon Mar 27 08:58:42 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * rcs.c (RCS_parsercsfile_i): Accept `dead' state regardless of
- DEATH_STATE define. Revise comments regarding DEATH_STATE versus
- CVSDEA versus the scheme which uses a patched RCS.
- * README-rm-add, RCS-patches: Explain what versions of CVS need
- RCS patches.
-
-Sat Mar 25 18:51:39 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * server.c (server_cleanup): Only do the abysmal kludge of waiting
- for command and draining the pipe #ifdef sun. The code makes
- assumptions not valid on all systems, and is only there to
- workaround a SunOS bug.
-
-Wed Mar 22 21:55:56 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * server.c (mkdir_p): Call stat only if we get the EACCES. Faster
- and more elegant.
-
-Tue Jan 31 20:59:19 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
-
- * server.c: Try to avoid starting the "rm -rf" at cleanup time
- until after subprocesses have finished.
- (command_fds_to_drain, max_command_fd): New variables.
- (do_cvs_command): Set them.
- (command_pid_is_dead): New variable.
- (wait_sig): New function.
- (server_cleanup): If command_pid is nonzero, wait for it to die,
- draining output from it in the meantime. If nonzero SIG was
- passed, send a signal to the subprocess, to encourage it to die
- soon.
-
- * main.c (usage): Argument is now `const char *const *'.
- * cvs.h (usage): Changed prototype.
- (USE): Make new variable `const'.
- * add.c (add_usage), admin.c (admin_usage), checkout.c
- (checkout_usage, export_usage, checkout), commit.c (commit_usage),
- diff.c (diff_usage), history.c (history_usg), import.c
- (import_usage, keyword_usage), log.c (log_usage), main.c (usg),
- patch.c (patch_usage), release.c (release_usage), remove.c
- (remove_usage), rtag.c (rtag_usage), server.c (server), status.c
- (status_usage), tag.c (tag_usage), update.c (update_usage): Usage
- messages are now const arrays of pointers to const char.
-
- * import.c (comtable): Now const.
- * main.c (rcsid): Now static.
- (cmd): Now const.
- (main): Local variable CM now points to const.
- * server.c (outbuf_memory_error): Local var MSG now const.
-
- * client.c (client_commit_usage): Deleted.
-
-Sat Dec 31 15:51:55 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * logmsg.c (do_editor): Allocate enough space for trailing '\0'.
-
-Fri Mar 3 11:59:49 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
-
- * cvsbug.sh: Call it "Cyclic CVS" now, not "Remote CVS". Call it
- version C1.4A, not 1.4A2-remote. Send bugs to cyclic-cvs, not
- remote-cvs.
-
- * classify.c (Classify_File): Put check for dead file inside
- "#ifdef DEATH_SUPPORT".
-
-Thu Feb 23 23:03:43 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
-
- * update.c (join_file): Don't pass the -E option to rcsmerge here,
- either (see Jan 22 change).
-
-Mon Feb 13 13:28:46 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
-
- * cvsbug.sh: Send bug reports to remote-cvs@cyclic.com, rather
- than to the ordinary CVS bug address. This does mean we'll have
- to wade through GNATS-style bug reports, sigh.
-
-Wed Feb 8 06:42:27 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * server.c: Don't include <sys/stat.h>; system.h already does, and
- 4.3BSD can't take it twice.
-
- * subr.c [! HAVE_VPRINTF] (run_setup, run_args): Don't use va_dcl
- in declaration. Declare the a1..a8 args which are used in the
- sprintf call.
- * cvs.h [! HAVE_VPRINTF] (run_setup, run_args): Don't prototype
- args, to avoid conflicting with the function definitions
- themselves.
-
-Tue Feb 7 20:10:00 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
-
- * client.c (update_entries): Pass the patch subprocess the switch
- "-b ~", not "-b~"; the latter form seems not to work with patch
- version 2.0 and earlier --- it takes the next argv element as the
- backup suffix, and thus doesn't notice that the patch file's name
- has been specified, thus doesn't find the patch, thus... *aargh*
-
-Fri Feb 3 20:28:21 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
-
- * log.c (log_option_with_arg): New function.
- (cvslog): Use it and send_arg to handle the rlog options that take
- arguments. The code used to use send_option_string for
- everything, which assumes that "-d1995/01/02" is equivalent to
- "-d -1 -9 -9 -5 ...".
-
-Tue Jan 31 15:02:01 1995 Jim Blandy <jimb@floss.life.uiuc.edu>
-
- * server.c: #include <sys/stat.h> for the new stat call in mkdir_p.
- (mkdir_p): Don't try to create the intermediate directory if it
- exists already. Some systems return EEXIST, but others return
- EACCES, which we can't otherwise distinguish from a real access
- problem.
-
-Sun Jan 22 15:25:45 1995 Jim Blandy <jimb@totoro.bio.indiana.edu>
-
- * update.c (merge_file): My rcsmerge doesn't accept a -E option,
- and it doesn't look too important, so don't pass it.
-
-Fri Jan 20 14:24:58 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
-
- * client.c (do_deferred_progs): Don't try to chdir to toplevel_wd
- if it has not been set.
- (process_prune_candidates): Likewise.
-
-Mon Nov 28 09:59:14 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * client.c (client_commit): Move guts of function from here...
- * commit.c (commit): ...to here.
-
-Mon Nov 28 15:14:36 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
-
- * server.c (buf_input_data, buf_send_output): Start cpp directives
- in column 1, otherwise Sun 4 pcc complains.
-
-Mon Nov 28 09:59:14 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * client.c (add_prune_candidate): Don't try to prune ".".
-
-Tue Nov 22 05:27:10 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * server.c, client.c: More formatting cleanups.
-
- * client.h, client.c: New variable client_prune_dirs.
- * update.c (update), checkout.c (checkout): Set it.
- * client.c (add_prune_candidate, process_prune_candidates): New
- functions.
- (send_repository, call_in_directory, get_responses_and_close):
- Call them.
-
-Wed Nov 23 01:17:32 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
-
- * server.c (do_cvs_command): Don't select on STDOUT_FILENO unless
- we have something to write.
-
-Tue Nov 22 05:27:10 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * remove.c (remove_fileproc): Only call server_checked_in if we
- actually are changing the entries file.
-
- * server.c (server_write_entries): New function.
- (dirswitch, do_cvs_command): Call it.
- (serve_entry, serve_updated): Just update in-memory data
- structures, don't mess with CVS/Entries file.
-
-Mon Nov 21 10:15:11 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * server.c (server_checked_in): Set scratched_file to NULL after
- using it.
-
- * checkin.c (Checkin): If the file was changed by the checkin,
- call server_updated not server_checked_in.
-
-Sun Nov 20 08:01:51 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * client.c (send_repository): Move check for update_dir NULL to
- before where we check last_update_dir. Check for "" here too.
-
- * client.c (send_repository): Use new argument dir.
-
- * client.c: Pass new argument dir to send_repository and
- send_a_repository.
-
- * server.c, server.h (server_prog): New function.
- * modules.c (do_modules): Call it if server_expanding.
- * client.c: Support Set-checkin-prog and Set-update-prog responses.
- * server.c, client.c: Add Checkin-prog and Update-prog requests.
-
-Fri Nov 18 14:04:38 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * client.c (get_short_pathname, is_cvsroot_level,
- call_in_directory): Base whether this is new-style or
- old-style based on whether we actually used the Directory request,
- not based on whether the pathname is absolute. Rename
- directory_supported to use_directory.
- * server.c: Rename use_relative_pathnames to use_dir_and_repos.
- * client.c (send_a_repository): If update_dir is absolute, don't
- use it to try to reconstruct how far we have recursed.
-
- * server.c, server.h, client.c, client.h, vers_ts.c, update.h:
- More cosmetic changes (identation, PARAMS vs. PROTO, eliminate
- alloca, etc.) to remote CVS to make it more like the rest of CVS.
-
- * server.c: Make server_temp_dir just the dir name, not the name
- with "%s" at the end.
- * server.c, client.c: Add "Max-dotdot" request, and use it to make
- extra directories in server_temp_dir if needed.
-
-Thu Nov 17 09:03:28 1994 Jim Kingdon <kingdon@cygnus.com>
-
- * client.c: Fix two cases where NULL was used and 0 was meant.
-
-Mon Nov 14 08:48:41 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * server.c (serve_unchanged): Set noexec to 0 when calling Register.
-
- * update.c (merge_file): Don't call xcmp if noexec.
-
-Fri Nov 11 13:58:22 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * client.c (call_in_directory): Deal with it if reposdirname is
- not a subdirectory of toplevel_repos.
-
-Mon Nov 7 09:12:01 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * patch.c: If file is removed and we don't have a tag or date,
- just print "current release".
-
- * classify.c (Classify_File): Treat dead files appropriately.
-
-Fri Nov 4 07:33:03 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * main.c (main) [SERVER_SUPPORT]: Move call to getwd past where we
- know whether we are the server or not. Set CurDir to "<remote>"
- if we are the server.
-
- * client.c: Remove #if 0'd function option_with_arg.
- Remove #if 0'd code pertaining to the old way of logging the
- session.
-
- * client.c (start_rsh_server): Don't invoke the server with the
- -d option.
- * server.c (serve_root): Test root for validity, just like main.c
- does for non-remote CVS.
- * main.c (main): If `cvs server' happens with a colon in the
- CVSroot, just handle it normally; don't make it an error.
-
-Wed Nov 2 11:09:38 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * client.c (send_dirent_proc): If dir does not exist, just return
- R_SKIP_ALL.
-
- * server.c, client.c: Add Directory request and support for
- local relative pathnames (along with the repository absolute
- pathnames).
- * update.c, add.c, checkout.c, checkin.c, cvs.h, create_adm.c,
- commit.c, modules.c, server.c, server.h, remove.c, client.h:
- Pass update_dir to server_* functions. Include update_dir in
- more error messages.
-
-Fri Oct 28 08:54:00 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * client.c: Reformat to bring closer to cvs standards for brace
- position, comment formatting, etc.
-
- * sanity.sh: Remove wrong "last mod" line. Convert more tests to
- put PASS or FAIL in log file. Change it so arguments to the
- script specify which tests to run.
-
- * client.c, client.h, server.c, checkout.c: Expand modules in
- separate step from the checkout itself.
-
-Sat Oct 22 20:33:35 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com)
-
- * update.c (join_file): When checking for null return from
- RCS_getversion, still do return even if quiet flag is set.
-
-Thu Oct 13 07:36:11 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * client.c (send_files): Call send_repository even if
- toplevel_repos was NULL.
-
- * server.c (server_updated): If joining, don't remove file.
-
- * update.c (join_file): If server and file is unmodified, check it
- out before joining. After joining, call server_updated. New
- argument repository.
-
- * server.c, server.h (server_copy_file): New function.
- * update.c (update_file_proc, join_file): Call it.
- * client.c (copy_file, handle_copy_file): New functions.
- * client.c (responses): Add "Copy-file".
-
- * client.c, client.h: Make toplevel_wd, failed_patches and
- failed_patches_count extern.
- * client.c (client_update): Move guts of function from here...
- * update.c (update): ...to here.
-
- * client.c, checkout.c: Likewise for checkout.
-
- * client.c (is_cvsroot_level): New function.
- (handle_set_sticky, handle_clear_sticky,
- handle_clear_static_directory): Call it, instead of checking
- short_pathname for a slash.
-
- * client.c, client.h (client_process_import_file,
- client_import_done): New functions.
- * import.c (import, import_descend): Use them.
- * import.c (import_descend): If server, don't mention ignored CVS
- directories.
- * import.c (import_descend_dir): If client, don't print warm
- fuzzies, or make directories in repository. If server, print warm
- fuzzies to stdout not stderr.
- * client.c (send_modified): New function, broken out from
- send_fileproc.
- (send_fileproc): Call it.
-
- * client.c (handle_clear_sticky, handle_set_sticky,
- handle_clear_static_directory, handle_set_static_directory): If
- command is export, just return.
- (call_in_directory, update_entries): If command is export, don't
- create CVS directories, CVS/Entries files, etc.
- * update.c (update_filesdone_proc): Don't remove CVS directories if
- client_active.
-
- * client.c (send_a_repository): Instead of insisting that
- repository end with update_dir, just strip as many pathname
- components from the end as there are in update_dir.
-
- * Makefile.in (remotecheck): New target, pass -r to sanity.sh.
- * sanity.sh: Accept -r argument which means to test remote cvs.
-
- * tag.c (tag), rtag.c (rtag), patch.c (patch), import.c (import),
- admin.c (admin), release.c (release): If client_active, connect to
- the server and send the right requests.
- * main.c (cmds): Add these commands.
- (main): Remove code which would strip hostname off cvsroot and try
- the command locally. There are no longer any commands which are
- not supported.
- * client.c, client.h (client_rdiff, client_tag, client_rtag,
- client_import, client_admin, client_export, client_history,
- client_release): New functions.
- * server.c (serve_rdiff, serve_tag, serve_rtag, serve_import,
- serve_admin, serve_export, serve_history, serve_release): New
- functions.
- (requests): List them.
- * server.c: Declare cvs commands (add, admin, etc.).
- * cvs.h, server.h: Don't declare any of them here.
- * main.c: Restore declarations of cvs commands which were
- previously removed.
-
- * cvs.h: New define DEATH_STATE, commented out for now.
- * rcs.c (RCS_parsercsfile_i), commit.c (remove_file, checkaddfile)
- [DEATH_STATE]: Use RCS state to record a dead file.
-
-Mon Oct 3 09:44:54 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * status.c (status_fileproc): Now that ts_rcs is just one time,
- don't try to print the second time from it. (Same as raeburn 20
- Aug change, it accidentally got lost in 1.4 Alpha-1 merge).
-
- * cvs.h (CVSDEA): Added (but commented out for now).
- * rcs.c (RCS_parsercsfile_i) [CVSDEA]: Also look in CVSDEA to see if
- something is dead.
- * commit.c (ci_new_rev, mark_file) [CVSDEA]: New functions.
- (remove_file, checkaddfile) [CVSDEA]: Use them instead of ci -K.
- * find_names.c (find_dirs) [CVSDEA]: Don't match CVSDEA directories.
- * update.c (checkout_file): Check RCS_isdead rather than relying
- on co to not create the file.
-
- * sanity.sh: Direct output to logfile, not /dev/null.
-
- * subr.c (run_exec): Print error message if we are unable to exec.
-
- * commit.c (remove_file): Call Scratch_Entry when removing tag
- from file. The DEATH_SUPPORT ifdef was erroneous.
-
-Sun Oct 2 20:33:27 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * commit.c (checkaddfile): Instead of calling isdir before
- attempting to create the directory, just ignore EEXIST errors from
- mkdir. (This removes some DEATH_SUPPORT ifdefs which actually had
- nothing to do with death support).
-
-Thu Sep 29 09:23:57 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * diff.c (diff): Search attic too if we have a second tag/date.
- (diff_fileproc): If we have a second tag/date, don't do all the
- checking regarding the user file.
-
-Mon Sep 26 12:02:15 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * checkin.c (Checkin): Check for error from unlink_file.
-
-Mon Sep 26 08:51:10 1994 Anthony J. Lill (ajlill@ajlc.waterloo.on.ca)
-
- * rcs.c (getrcskey): Allocate space for terminating '\0' if
- necessary.
-
-Sat Sep 24 09:07:37 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * commit.c (commit_fileproc): Set got_message = 1 when calling
- do_editor (accidentally omitted from last change).
-
-Fri Sep 23 11:59:25 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- Revert buggy parts of Rich's change of 1 Nov 1993 (keeping the
- dynamic buffer allocation, which was the point of that change).
- * logmsg.c (do_editor): Reinstate message arg, but make it char
- **messagep instead of char *message. Change occurances of message
- to *messagep. Char return type from char * back to void.
- * cvs.h: Change do_editor declaration.
- * commit.c: Reinstate got_message variable
- (commit_filesdoneproc, commit_fileproc, commit_direntproc): Use it.
- * import.c (import), commit.c (commit_fileproc,
- commit_direntproc): Pass &message to do_editor; don't expect it to
- return a value.
- * client.c (client_commit): Likewise.
- * import.c (import): Deal with it if message is NULL.
-
-Wed Sep 21 09:43:25 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * server.c (server_updated): If the file doesn't exist, skip it.
-
- * diff.c, client.h, client.c: Rename diff_client_senddate to
- client_senddate and move from diff.c to client.c.
- * client.c (client_update, client_checkout): Use it.
-
-Sat Sep 17 08:36:58 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * checkout.c (checkout_proc): Don't pass NULL to Register for
- version. (should fix "cvs co -r <nonexistent-tag> <file>"
- coredump on Solaris).
-
-Fri Sep 16 08:38:02 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * diff.c (diff_fileproc): Set top_rev from vn_user, not vn_rcs.
- Rename it to user_file_rev because it need not be the head of any
- branch.
- (diff_file_nodiff): After checking user_file_rev, if we have both
- use_rev1 and use_rev2, compare them instead of going on to code
- which assumes use_rev2 == NULL.
-
-Thu Sep 15 08:20:23 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * status.c (status): Return a value in client_active case.
-
-Thu Sep 15 15:02:12 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
-
- * server.c (serve_modified): Create the file even if the size is
- zero.
-
-Thu Sep 15 08:20:23 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * lock.c (readers_exist): Clear errno each time around the loop,
- not just the first time.
-
- * client.c (start_server): Don't send Global_option -q twice.
-
- * no_diff.c (No_Difference): Check for error from unlink.
-
- * no_diff.c, cvs.h (No_Difference): New args repository,
- update_dir. Call server_update_entries if needed. Use update_dir
- in error message.
- * classify.c (Classify_File): Pass new args to No_Difference.
-
- * server.c (server_update_entries, server_checked_in,
- server_updated): Don't do anything if noexec.
-
- * client.c (send_fileproc): Rather than guessing how big the gzip
- output may be, just realloc the buffer as needed.
-
-Tue Sep 13 13:22:03 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * lock.c: Check for errors from unlink, readdir, and closedir.
-
- * classify.c (Classify_File): Pass repository and update_dir to
- sticky_ck.
- (sticky_ck): New args repository and update_dir.
- * server.c, server.h (server_update_entries): New function.
- * classify.c (sticky_ck): Call it.
- * client.c: New response "New-entry".
- * client.c (send_fileproc): Send tag/date from vers->entdata, not
- from vers itself.
-
-Mon Sep 12 07:07:05 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * server.c: Clean up formatting ("= (errno)" -> "= errno").
-
- * cvs.h: Declare strerror.
-
- * client.c: Add code to deal with Set-sticky and Clear-sticky
- responses, and Sticky request.
- * server.c: Add code to deal with Sticky request.
- * server.c, server.h (server_set_sticky): New function.
- * create_adm.c (Create_Admin), update.c (update, update_dirent_proc),
- commit.c (commit_dirleaveproc): Call it.
- * client.c, client.h (send_files): Add parameter aflag.
- * add.c (add), diff.c (diff), log.c (cvslog), remove.c (cvsremove),
- status.c (status),
- client.c (client_commit, client_update, client_checkout): Pass it.
- * client.c (client_update): Add -A flag.
-
-Fri Sep 9 07:05:35 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * entries.c (WriteTag): Check for error from unlink_file.
-
- * server.c (server_updated): Initialize size to 0. Previously if
- the file was zero length, the variable size got used without being
- set.
-
-Thu Sep 8 14:23:05 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * server.c (serve_repository): Check for error from fopen on
- CVSADM_ENT.
-
- * update.c (update, update_dirent_proc): Check for errors when
- removing Entries.Static.
-
- * client.c: Add code to deal with Set-static-directory and
- Clear-static-directory responses, and Static-directory request.
- * server.c, server.h (server_clear_entstat, server_set_entstat):
- New functions.
- * update.c, checkout.c, modules.c: Call them.
- * server.c: Add code to deal with Static-directory request.
-
- * server.c, client.c: Use strchr and strrchr instead of index and
- rindex.
-
- * server.c (serve_unchanged, serve_lost): Change comments which
- referred to changing timestamp; we don't always change the
- timestamp in those cases anymore.
-
-Wed Sep 7 10:58:12 1994 J.T. Conklin (jtc@rtl.cygnus.com)
-
- * cvsrc.c (read_cvsrc): Don't call getenv() three times when one
- time will do.
-
- * subr.c (xmalloc, xrealloc): Change type of bytes argument from
- int to size_t and remove the test that checks if it is less than
- zero.
- * cvs.h (xmalloc, xrealloc): Update prototype.
-
-Thu Sep 1 12:22:20 1994 Jim Kingdon (kingdon@cygnus.com)
-
- * update.c (merge_file, join_file): Pass -E to rcsmerge.
- (merge_file): If rcsmerge doesn't change the file, say so.
-
- * recurse.c, cvs.h (start_recursion): New argument wd_is_repos.
- * recurse.c (start_recursion): Use it instead of checking whether
- command_name is rtag to find out if we are cd'd to the repository.
- * client.c, update.c, commit.c, status.c, diff.c, log.c, admin.c,
- remove.c, tag.c: Pass 0 for wd_is_repos.
- * rtag.c, patch.c: Pass 1 for wd_is_repos.
-
- * classify.c, cvs.h (Classify_File): New argument pipeout.
- * classify.c (Classify_File): If pipeout, don't complain if the
- file is already there.
- * update.c, commit.c, status.c: Change callers.
-
- * mkmodules.c (main): Don't print "reminders" if commitinfo,
- loginfo, rcsinfo, or editinfo files are missing.
-
-Mon Aug 22 23:22:59 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com)
-
- * server.c (strerror): Static definition replaced by extern
- declaration.
-
-Sun Aug 21 07:16:27 1994 Ken Raeburn (raeburn@kr-pc.cygnus.com)
-
- * client.c (update_entries): Run "patch" with input from
- /dev/null, so if it's the wrong version, it fails quickly rather
- than waiting for EOF from terminal before failing.
-
-Sat Aug 20 04:16:33 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
-
- * server.c (serve_unchanged): Instead of creating a file with a
- zero timestamp, rewrite the entries file to have "=" in the
- timestamp field.
- * vers_ts.c (mark_lost, mark_unchanged): New macros.
- (time_stamp_server): Use them, for clarity. Interpret "="
- timestamp as an unchanged file. A zero-timestamp file should
- never be encountered now in use_unchanged mode.
-
- * client.c (start_server): If CVS_CLIENT_PORT indicates a
- non-positive port number, skip straight to rsh connection.
-
- * status.c (status_fileproc): Fix ts_rcs reference when printing
- version info, to correspond to new Entries file format. Don't
- print it at all if server_active, because it won't have any useful
- data.
-
-Thu Aug 18 14:38:21 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
-
- * cvs.h (status): Declare.
- * client.c (client_status): New function.
-
- * client.h (client_status): Declare.
- * main.c (cmds): Include it.
- * server.c (serve_status): New function.
- (requests): Add it.
- * status.c (status): Do the remote thing if client_active.
-
- * client.c (supported_request): New function.
- (start_server): Use it.
-
- * server.c (receive_partial_file): New function, broken out from
- serve_modified. Operate with fixed-size local buffer, instead of
- growing stack frame by entire file size.
- (receive_file): New function, broken out from serve_modified.
- (serve_modified): Call it.
- (server): Print out name of unrecognized request.
-
- More generic stream-filtering support:
- * client.c (close_on_exec, filter_stream_through_program): New
- functions.
- (server_fd): New variable.
- (get_responses_and_close): Direct non-rsh connection is now
- indicated by server_fd being non-negative. File descriptors for
- to_server and from_server may now be different in case "tee"
- filtering is being done. Wait for rsh_pid specifically.
- (start_server): Use filter_stream_through_program for "tee"
- filter, and enable it for direct Kerberos-authenticated
- connections. Use dup to create new file descriptors for server
- connection if logging is enabled.
- (start_rsh_server): Disable code that deals with logging.
-
- Per-file compression support:
- * cvs.h (gzip_level): Declare.
- * main.c (usg): Describe new -z argument.
- (main): Recognize it and set gzip_level.
- * client.c (filter_through_gzip, filter_through_gunzip): New
- functions to handle compression.
- (update_entries): If size starts with "z", uncompress
- (start_server): If gzip_level is non-zero and server supports it,
- issue gzip-file-contents request.
- (send_fileproc): Optionally compress file contents. Use a
- slightly larger buffer, anticipating the worst case.
- * server.c (gzip_level): Define here.
- (receive_file): Uncompress file contents if needed.
- (serve_modified): Recognize "z" in file size and pass receive_file
- appropriate flag.
- (buf_read_file_to_eof, buf_chain_length): New functions.
- (server_updated): Call them when sending a compressed file.
- (serve_gzip_contents): New function; set gzip_level.
- (requests): Added gzip-file-contents request.
-
-Wed Aug 17 09:37:44 1994 J.T. Conklin (jtc@cygnus.com)
-
- * find_names.c (find_dirs): Use 4.4BSD filesystem feature (it
- contains the file type in the dirent structure) to avoid
- stat'ing each file.
-
- * commit.c (remove_file,checkaddfile): Change type of umask
- variables from int to mode_t.
- * subr.c (): Likewise.
-
-Tue Aug 16 19:56:34 1994 Mark Eichin (eichin@cygnus.com)
-
- * diff.c (diff_fileproc): Don't use diff_rev* because they're
- invariant across calls -- add new variable top_rev.
- (diff_file_nodiff): After checking possible use_rev* values, if
- top_rev is set drop it in as well (if we don't already have two
- versions) and then clear it for next time around.
-
-Wed Aug 10 20:50:47 1994 Mark Eichin (eichin@cygnus.com)
-
- * diff.c (diff_fileproc): if ts_user and ts_rcs match, then the
- file is at the top of the tree -- so we might not even have a
- copy. Put the revision into diff_rev1 or diff_rev2.
-
-Wed Aug 10 14:55:38 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
-
- * server.c (do_cvs_command): Use waitpid.
-
- * subr.c (run_exec): Always use waitpid.
-
- * Makefile.in (CC, LIBS): Define here, in case "make" is run in
- this directory instead of top level.
-
-Wed Aug 10 13:57:06 1994 Mark Eichin (eichin@cygnus.com)
-
- * client.c (krb_get_err_text): use HAVE_KRB_GET_ERR_TEXT to
- determine if we need to use the array or the function.
- * main.c: ditto.
-
-Tue Aug 9 16:43:30 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
-
- * entries.c (ParseEntries): If timestamp is in old format, rebuild
- it in the new format. Fudge an unmatchable entry that won't
- trigger this code next time around, if the file is modified.
-
- * vers_ts.c (time_stamp): Only put st_mtime field into timestamp,
- and use GMT time for it. With st_ctime or in local time, copying
- trees between machines in different time zones makes all the files
- look modified.
- (time_stamp_server): Likewise.
-
-Tue Aug 9 19:40:51 1994 Mark Eichin (eichin@cygnus.com)
-
- * main.c (main): use krb_get_err_text function instead of
- krb_err_txt array.
-
-Thu Aug 4 15:37:50 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
-
- * main.c (main): When invoked as kserver, set LOGNAME and USER
- environment variables to the remote user name.
-
-Thu Aug 4 07:44:37 1994 Mark Eichin (eichin@cygnus.com)
-
- * client.c: (handle_valid_requests): if we get an option that has
- rq_enableme set, then send that option. If it is UseUnchanged, set
- use_unchanged so that the rest of the client knows about
- it. (Could become a more general method for dealing with protocol
- upgrades.)
- (send_fileproc): if use_unchanged didn't get set, send an
- old-style "Lost" request, otherwise send an "Unchanged" request.
- * server.c (serve_unchanged): new function, same as serve_lost,
- but used in the opposite case.
- (requests): add new UseUnchanged and Unchanged requests, and make
- "Lost" optional (there isn't a good way to interlock these.)
- * server.h (request.status): rq_enableme, new value for detecting
- compatibility changes.
- * vers_ts.c (time_stamp_server): swap meaning of zero timestamp if
- use_unchanged is set.
-
-Tue Jul 26 10:19:30 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * sanity.sh: Separate CVSROOT_FILENAME, which must be the filename
- of the root, from CVSROOT, which can include a hostname for
- testing remote CVS. (but the tests aren't yet prepared to deal
- with the bugs in remote CVS).
-
- * import.c (update_rcs_file): Change temporary file name in TMPDIR
- from FILE_HOLDER to cvs-imp<process-id>.
-
- * sanity.sh: Add ">/dev/null" and "2>/dev/null" many places to
- suppress spurious output. Comment out tests which don't work (cvs
- add on top-level directory, cvs diff when non-committed adds or
- removes have been made, cvs release, test 53 (already commented as
- broken), retagging without deleting old tag, test 63). Now 'make
- check' runs without any failures.
-
-Fri Jul 15 12:58:29 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
-
- * Makefile.in (install): Do not depend upon installdirs.
-
-Thu Jul 14 15:49:42 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
-
- * client.c, server.c: Don't try to handle alloca here; it's
- handled by cvs.h.
-
-Tue Jul 12 13:32:40 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
-
- * client.c (update_entries): Reset stored_checksum_valid if we
- quit early because of a patch failure.
-
-Fri Jul 8 11:13:05 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
-
- * client.c (responses): Mark "Remove-entry" as optional.
-
-Thu Jul 7 14:07:58 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
-
- * server.c (server_updated): Add new checksum argument. If it is
- not NULL, and the client supports the "Checksum" response, send
- it.
- * server.h (server_updated): Update prototype.
- * update.c: Include md5.h.
- (update_file_proc): Pass new arguments to patch_file and
- server_updated.
- (patch_file): Add new checksum argument. Set it to the MD5
- checksum of the version of the file being checked out.
- (merge_file): Pass new argument to server_updated.
- * client.c: Include md5.h.
- (stored_checksum_valid, stored_checksum): New static variables.
- (handle_checksum): New static function.
- (update_entries): If a checksum was received, check it against the
- MD5 checksum of the final file.
- (responses): Add "Checksum".
- (start_server): Clear stored_checksum_valid.
- * commit.c (commit_fileproc): Pass new argument to server_updated.
-
- * client.h (struct response): Move definition in from client.c,
- add status field.
- (responses): Declare.
- * client.c (struct response): Remove definition; moved to
- client.h.
- (responses): Make non-static. Initialize status field.
- * server.c (serve_valid_responses): Check and record valid
- responses, just as in handle_valid_requests in client.c.
-
- * diff.c (diff_client_senddate): New function.
- (diff): Use it to send -D arguments to server.
-
-Wed Jul 6 12:52:37 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
-
- * rcs.c (RCS_parsercsfile_i): New function, parse RCS file
- referenced by file ptr argument.
- (RCS_parsercsfile): Open file and pass its file ptr to above function.
- (RCS_parse): Likewise.
-
-Wed Jul 6 01:25:38 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
-
- * client.c (update_entries): Print message indicating that an
- unpatchable file will be refetched.
- (client_update): Print message when refetching unpatchable files.
-
-Fri Jul 1 07:16:29 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * client.c (send_dirent_proc): Don't call send_a_repository if
- repository is "".
-
-Fri Jul 1 13:58:11 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
-
- * client.c (last_dirname, last_repos): Move out of function.
- (failed_patches, failed_patches_count): New static variables.
- (update_entries): If patch program fails, save short_pathname in
- failed_patches array, only exit program if retcode is -1, and
- return out of the function rather than update the Entries line.
- (start_server): Clear toplevel_repos, last_dirname, last_repos.
- (client_update): If failed_patches is not NULL after doing first
- update, do another update, but remove all the failed files first.
-
-Thu Jun 30 09:08:57 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * server.c (requests): Add request "Global_option".
- (serve_global_option): New function, to handle it.
- * client.c (start_server): Deal with global options. Check for
- errors from fprintf.
-
- * client.c (send_fileproc): Split out code which sends repository
- into new function send_a_repository. Also, deal with update_dir
- being ".".
- (send_dirent_proc): Call send_a_repository.
- * add.c (add): If client_active, do special processing for
- directories.
- (add_directory): If server_active, don't try to create CVSADM
- directory.
-
-Thu Jun 30 11:58:52 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
-
- * client.c (update_entries): If patch succeeds, remove the backup
- file.
- * server.c (server_updated): Add new argument file_info. If it is
- not NULL, use it rather than sb to get the file mode.
- * server.h (server_updated): Update prototype for new argument.
- * update.c (update_file_proc): Pass new arguments to patch_file
- and server_updated.
- (patch_file): Add new argument file_info. Don't use -p to check
- out new version, check it out into file and rename that to file2.
- If result is not readable, assume file is dead and set docheckout.
- Call xchmod on file2. Close the patch file after checking for a
- binary diff. Set file_info to the results of stat on file2.
- (merge_file): Pass new argument to server_updated.
- * commit.c (commit_fileproc): Pass new argument to server_updated.
-
-Wed Jun 29 13:00:41 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
-
- * client.c (krb_realmofhost): Declare, since it's not the current
- <krb.h>.
- (start_server): Save the name returned by gethostbyname. Call
- krb_realmofhost to get the realm. Pass the resulting realm to
- krb_sendauth. Pass the saved real name to krb_sendauth, rather
- than server_host.
-
- * update.c (update_file_proc): Pass &docheckout to patch_file. If
- it is set to 1, fall through to T_CHECKOUT case.
- (patch_file): Add docheckout argument. Set it to 1 if we can't
- make a patch. Check out the files and run diff rather than
- rcsdiff. If either file does not end in a newline, we can't make
- a patch. If the patch starts with the string "Binary", assume
- one or the other is a binary file, and that we can't make a patch.
-
-Tue Jun 28 11:57:29 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
-
- * client.c (update_entries): If the patch file is empty, don't run
- patch program; avoids error message.
-
- * classify.c (Classify_File): Return T_CHECKOUT, not T_PATCH, if
- the file is in the Attic.
-
- * cvs.h (enum classify_type): Add T_PATCH.
- * config.h (PATCH_PROGRAM): Define.
- * classify.c (Classify_File): If user file exists and is not
- modified, and using the same -k options, return T_PATCH instead of
- T_CHECKOUT.
- * update.c (patches): New static variable.
- (update): Add u to gnu_getopt argument. Handle it.
- (update_file_proc): Handle T_PATCH.
- (patch_file): New static function.
- * server.h (enum server_updated_arg4): Add SERVER_PATCHED.
- * server.c (server_updated): Handle SERVER_PATCHED by sending
- "Patched" command.
- (serve_ignore): New static function.
- (requests): Add "update-patches".
- (client_update): If the server supports "update-patches", send -u.
- * client.c (struct update_entries_data): Change contents field
- from int to an unnamed enum.
- (update_entries): Correponding change. If contents is
- UPDATE_ENTRIES_PATCH, pass the input to the patch program.
- (handle_checked_in): Initialize contents to enum value, not int.
- (handle_updated, handle_merged): Likewise.
- (handle_patched): New static function.
- (responses): Add "Patched".
- * commit.c (check_fileproc): Handle T_PATCH.
- * status.c (status_fileproc): Likewise.
-
- * client.c (start_server): If CVS_CLIENT_PORT is set in the
- environment, connect to that port, rather than looking up "cvs" in
- /etc/services. For debugging.
-
-Tue Jun 21 12:48:16 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
-
- * update.c (joining): Return result of comparing pointer with
- NULL, not result of casting (truncating, on Alpha) pointer to int.
-
- * main.c (main) [HAVE_KERBEROS]: Impose a umask if starting as
- Kerberos server, so temp directories won't be world-writeable.
-
- * update.c (update_filesdone_proc) [CVSADM_ROOT]: If environment
- variable CVS_IGNORE_REMOTE_ROOT is set and repository is remote,
- don't create CVS/Root file.
- * main.c (main): If env var CVS_IGNORE_REMOTE_ROOT is set, don't
- check CVS/Root.
-
-Fri Jun 10 18:48:32 1994 Mark Eichin (eichin@cygnus.com)
-
- * server.c (O_NDELAY): use POSIX O_NONBLOCK by default, unless it
- isn't available (in which case substitute O_NDELAY.)
-
-Thu Jun 9 19:17:44 1994 Mark Eichin (eichin@cygnus.com)
-
- * server.c (server_cleanup): chdir out of server_temp_dir before
- deleting it (so that it works on non-BSD systems.) Code for choice
- of directory cloned from server().
-
-Fri May 27 18:16:01 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
-
- * client.c (update_entries): Add return type of void.
- (get_responses_and_close): If using Kerberos and from_server and
- to_server are using the same file descriptor, use shutdown, not
- fclose. Close from_server.
- (start_server): New function; most of old version renamed to
- start_rsh_server.
- (start_rsh_server): Mostly renamed from old start_server.
- (send_fileproc): Use %lu and cast sb.st_size in fprintf call.
- (send_files): Remove unused variables repos and i.
- (option_no_arg): Comment out; unused.
- * main.c (main): Initialize cvs_update_env to 0. If command is
- "kserver", authenticate and change command to "server". If
- command is "server", don't call Name_Root, don't check access to
- history file, and don't assume that CVSroot is not NULL.
- * server.c (my_memmove): Removed.
- (strerror): Change check from STRERROR_MISSING to HAVE_STRERROR.
- (serve_root): Likewise for putenv.
- (serve_modified): Initialize buf to NULL.
- (struct output_buffer, buf_try_send): Remove old buffering code.
- (struct buffer, struct buffer_data, BUFFER_DATA_SIZE,
- allocate_buffer_datas, get_buffer_data, buf_empty_p,
- buf_append_char, buf_append_data, buf_read_file, buf_input_data,
- buf_copy_lines): New buffering code.
- (buf_output, buf_output0, buf_send_output, set_nonblock,
- set_block, buf_send_counted, buf_copy_counted): Rewrite for new
- buffering code.
- (protocol, protocol_memory_error, outbuf_memory_error,
- do_cvs_command, server_updated): Rewrite for new buffering code.
- (input_memory_error): New function.
- (server): Put Rcsbin at start of PATH in environment.
- * Makefile.in: Add @includeopt@ to DEFS.
-
-Fri May 20 08:13:10 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * cvs.h, classify.c (Classify_File): New argument update_dir.
- Include it in user messages.
- * commit.c (check_fileproc), status.c (status_fileproc), update.c
- (update_file_proc): Pass update_dir to Classify_File.
- * commit.c (check_fileproc), update.c (checkout_file):
- Include update_dir in user messages.
- * commit.c (check_fileproc) update.c (update_file_proc): Re-word
- "unknown status" message.
-
- * server.c (server_checked_in): Deal with the case where
- scratched_file is set rather than entries_line.
-
- * entries.c (Register): Write file even if server_active.
- * add.c (add): Add comment about how we depend on above behavior.
-
-Tue May 17 08:16:42 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * mkmodules.c: Add dummy server_active and server_cleanup, to go
- with the dummy Lock_Cleanup already there.
-
- * server.c (server_cleanup): No longer static.
-
-Sat May 7 10:17:17 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- Deal with add and remove:
- * commit.c (checkaddfile): If CVSEXT_OPT or CVSEXT_LOG file does
- not exist, just silently keep going.
- (remove_file): If server_active, remove file before creating
- temporary file with that name.
- * server.c (serve_remove, serve_add): New functions.
- (requests): Add them.
- * server.c (server_register): If options is NULL, it means there
- are no options.
- * server.c, server.h (server_scratch_entry_only): New function.
- New variable kill_scratched_file.
- (server_scratch, server_updated): Deal with kill_scratched_file.
- * commit.c (commit_fileproc): If server_active, call
- server_scratch_entry_only and server_updated.
- * add.c (add): Add client_active code.
- (add): If server_active, call server_checked_in for each file added.
- * remove.c (remove): Add client_active code.
- (remove_fileproc): If server_active, call server_checked_in.
- * main.c (cmds), client.c, client.h: New functions client_add and
- client_remove.
- * Move declarations of add, cvsremove, diff, and cvslog from
- main.c to cvs.h.
- * client.c (call_in_directory): Update comment regarding Root and
- Repository files.
- (send_fileproc): Only send Entries line if Version_TS really finds
- an entry. If it doesn't find one, send Modified.
- (update_entries): If version is empty or starts with 0 or -,
- create a dummy timestamp.
-
-Thu May 5 19:02:51 1994 Per Bothner (bothner@kalessin.cygnus.com)
-
- * recurse/c (start_recursion): If we're doing rtag, and thus
- have cd'd to the reporsitory, add ,v to a file name before stat'ing.
-
-Wed Apr 20 15:01:45 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
-
- * client.c (client_commit): Call ign_setup.
- (client_update, client_checkout): Likewise.
- * diff.c (diff): If client, call ign_setup.
- * log.c (cvslog): Likewise.
- * update.h (ignlist): Change definition to declaration to avoid
- depending upon common semantics (not required by ANSI C, and not
- the default on Irix 5).
- * update.c (ignlist): Define.
-
-Tue Apr 19 00:02:54 1994 John Gilmore (gnu@cygnus.com)
-
- Add support for remote `cvs log'; clean up `cvs diff' a bit.
-
- * client.c (send_arg): Make external.
- (send_option_string): New function.
- (client_diff_usage): Remove, unused.
- (client_diff): Just call diff, not do_diff.
- (client_log): Add.
- * client.h (client_log, send_arg, send_option_string): Declare.
- * cvs.h (cvslog): Declare.
- * diff.c (do_diff): Fold back into diff(), distinguish by checking
- client_active.
- (diff): Remove `-*' arg parsing crud; use send_option_string.
- * log.c (cvslog): If a client, start the server, pass options
- and files, and handle server responses.
- * main.c (cmds): Add client_log.
- (main): Remove obnoxious message every time CVS/Root is used.
- Now CVS will be quiet about it -- unless there is a conflict
- between $CVSROOT or -d value versus CVS/Root.
- * server.c (serve_log): Add.
- (requests): Add "log".
-
-Mon Apr 18 22:07:53 1994 John Gilmore (gnu@cygnus.com)
-
- Add support for remote `cvs diff'.
-
- * diff.c (diff): Break guts out into new fn do_diff.
- Add code to handle starting server, writing args,
- sending files, and retrieving responses.
- (includes): Use PARAMS for static function declarations.
- * client.c (to_server, from_server, rsh_pid,
- get_responses_and_close, start_server, send_files,
- option_with_arg): Make external.
- (send_file_names): New function.
- (client_diff): New function.
- * client.h (client_diff, to_server, from_server,
- rsh_pid, option_with_arg, get_responses_and_close, start_server,
- send_file_names, send_files): Declare.
- * cvs.h (diff): Declare.
- * main.c (cmds): Add client_diff to command table.
- * server.c (serve_diff): New function.
- (requests): Add serve_diff.
- (server): Bug fix: avoid free()ing incremented cmd pointer.
- * update.h (update_filesdone_proc): Declare with PARAMS.
-
-Sat Apr 16 04:20:09 1994 John Gilmore (gnu@cygnus.com)
-
- * root.c (Name_root): Fix tyop (CVSroot when root meant).
-
-Sat Apr 16 03:49:36 1994 John Gilmore (gnu@cygnus.com)
-
- Clean up remote `cvs update' to properly handle ignored
- files (and files that CVS can't identify), and to create
- CVS/Root entries on the client side, not the server side.
-
- * client.c (send_fileproc): Handle the ignore list.
- (send_dirent_proc): New function for handling ignores.
- (send_files): Use update_filesdone_proc and send_dirent_proc
- while recursing through the local filesystem.
- * update.h: New file.
- * update.c: Move a few things into update.h so that client.c
- can use them.
-
-Fri Mar 11 13:13:20 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
-
- * server.c: If O_NDELAY is not defined, but O_NONBLOCK is, define
- O_NDELAY to O_NONBLOCK.
-
-Wed Mar 9 21:08:30 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- Fix some spurious remote CVS errors caused by the CVS/Root patches:
- * update.c (update_filesdone_proc): If server_active, don't try to
- create CVS/Root.
- * root.c (Name_Root): Make error messages which happen if root is
- not an absolute pathname or if it doesn't exist a bit clearer.
- Skip them if root contains a colon.
-
-Mon Nov 1 15:54:51 1993 K. Richard Pixley (rich@sendai.cygnus.com)
-
- * client.c (client_commit): dynamically allocate message.
-
-Tue Jun 1 17:03:05 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
-
- * server.h: remove alloca cruft
-
- * server.c: replace with better alloca cruft
-
-Mon May 24 11:25:11 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * entries.c (Scratch_Entry): Update our local Entries file even if
- server_active.
-
- * server.c (server_scratch, server_register): If both Register
- and Scratch_Entry happen, use whichever one happened later.
- If neither happen, silently continue.
-
- * client.c (client_checkout): Initialize tag and date (eichin and
- I independently discovered this bug at the same time).
-
-Wed May 19 10:11:51 1993 Mark Eichin (eichin@cygnus.com)
-
- * client.c (update_entries): handle short reads over the net
- (SVR4 fread is known to be broken, specifically for short
- reads off of streams.)
-
-Tue May 18 15:53:44 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- * server.c (do_cvs_command): Fix fencepost error in setting
- num_to_check.
-
- * server.c (do_cvs_command): If terminated with a core dump, print
- message and set dont_delete_temp.
- (server_cleanup): If dont_delete_temp, don't delete it.
-
- * client.c (get_server_responses): Don't change cmd since we
- are going to "free (cmd)".
-
- * server.c: Rename memmove to my_memmove pending a real fix.
-
- * server.c (do_cvs_command): Set num_to_check to largest descriptor
- we try to use, rather than using (non-portable) getdtablesize.
-
-Wed May 12 15:31:40 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
-
- Add CVS client feature:
- * client.{c,h}: New files.
- * cvs.h: Include client.h.
- * main.c: If CVSROOT has a colon, use client commands instead.
- * vers_ts.c (Version_TS): If repository arg is NULL, don't worry
- about the repository.
- * logmsg.c (do_editor): If repository or changes is NULL, just don't
- use those features.
- * create_adm.c (Create_Admin), callers: Move the test for whether
- the repository exists from here to callers.
- * repos.c (Name_Repository): Don't test whether the repository exists
- if client_active set (might be better to move test to callers).
-
- Add CVS server feature:
- * server.{c,h}: New files.
- * cvs.h: Include server.h.
- * checkin.c (Checkin): Call server_checked_in.
- * update.c (update_file_proc, merge_files): Call server_updated.
- * entries.c (Register): Call server_register.
- (Scratch_Entry): Call server_scratch.
- * main.c: Add server to cmds.
- * vers_ts.c (Version_TS): If server_active, call new function
- time_stamp_server to set ts_user.
-
-
-For older changes, there might be some relevant stuff in the bottom of
-the NEWS file, but I'm afraid probably a lot of them are lost in the
-mists of time.
diff --git a/contrib/cvs/src/ChangeLog-96 b/contrib/cvs/src/ChangeLog-96
deleted file mode 100644
index 6c3a2a12d642..000000000000
--- a/contrib/cvs/src/ChangeLog-96
+++ /dev/null
@@ -1,4434 +0,0 @@
-Mon Dec 30 15:43:48 1996 Abe Feldman <feldman@harvey.cyclic.com>
-
- * checkout.c (build_dirs_and_chdir): Reproduced block containing
- Create_Admin, placing it before Subdir_Register.
- * sanity.sh (basicb): Added tests 1a and 9a to test above changes
- to the checkout command.
-
-Mon Dec 30 13:29:14 1996 uz@wuschel.ibb.schwaben.com (Ullrich von Bassewitz)
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * cvs.h (CVSEDITPREFIXLEN): New define.
- * logmsg.c (do_editor): Use CVSEDITPREFIXLEN when deciding whether
- to strip off CVSEDITPREFIX and when telling the user what we will
- strip off.
-
-Sun Dec 22 22:06:49 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * logmsg.c (do_verify): If noexec, skip the verification *without*
- printing a message. Use cvs_output not printf. Skip verification
- for client_active.
-
-Wed Dec 18 12:27:35 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * repos.c (Name_Repository): Add comment regarding wording of
- "*PANIC*" error message.
-
-1996-12-18 Jim Kingdon
-
- * client.c (call_in_directory): If the directory we are about
- to create is the same as CVSADM as seen by fncmp (for example,
- it is "cvs" and filenames are case-insensitive), then give a
- fatal error.
-
-Tue Dec 17 13:14:22 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * options.h.in: Add comments about SETXID security holes.
-
- * logmsg.c (do_verify): Reindent comments. Check errno if return
- code from run_exec is -1, not if it is 1.
- * sanity.sh (info): Move tests info-4 and info-8 to end and rename
- them. Add verifymsg tests. Instead of forcibly removing loginfo,
- remove it nicely (test info-11).
-
-Tue Dec 17 12:45:32 1996 Abe Feldman <feldman@cyclic.com>
-
- * commit.c, import.c: Call do_verify as well as do_editor.
- * cvs.h (CVSROOTADM_VERIFYMSG): Define.
- * logmsg.c, cvs.h (do_verify, verifymsg_proc): New functions.
- (verifymsg_script): New variable.
- * mkmodules.c (filelist): Add CVSROOTADM_VERIFYMSG.
-
-Mon Dec 16 13:24:47 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * lock.c (remove_locks): New static function, copied from part of
- Lock_Cleanup.
- (Lock_Cleanup): Call remove_locks.
- (Writer_Lock): Call remove_locks rather than Lock_Cleanup when
- waiting for a lock.
-
-Thu Dec 12 10:36:37 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * login.c (get_cvs_password): If CVS_PASSWORD is set, print a
- warning (and then proceed to ignore it). It was a documented
- feature, so we should point people who were using it to the
- replacement.
-
-Mon Dec 9 12:35:43 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * server.c (server_updated): Change comment to only worry about
- umask in the rsh case.
- (server): Create the temporary directory, and change the mode to
- S_IRWXU.
- (switch_to_user): Set the umask to 0, not 077.
-
-Mon Dec 9 10:58:28 1996 Jim Blandy <jimb@floss.cyclic.com>
-
- * login.c (get_cvs_password): Remove code to check for value of
- CVS_PASSWORD. Keeping cleartext passwords in environment
- variables is a really bad idea on Unix, since anyone can print
- out a processes' environment using 'ps' (on BSD variants
- anyway). Update help message.
-
-Fri Dec 6 15:59:40 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: When matching "use .cvs commit. to remove this file
- permanently" messages, change "cvs" to "${PROG}".
- (rdiff, binfiles): Likewise.
- This fixes testing a program named something other than "cvs", e.g.
- $ cp cvs cvs-test
- $ /bin/sh <srcdir>/sanity.sh `pwd`/cvs-test
-
-1996-12-02 Jim Kingdon
-
- * client.c: In comment saying that socket buffers don't
- implement the blocking routine, say they are blocking.
- * buffer.h (struct buffer): In description of input function,
- describe blocking, non-blocking, and NEED more fully. Say
- what happens if we read a nonzero amount less than NEED and
- then get end of file.
- * client.c (socket_buffer_input): If NEED == 0, still call
- recv (once). Handle the case where recv returns 0.
-
-Sat Nov 30 15:10:07 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * subr.c, cvs.h (file_has_markers): New function.
- * rcs.h (RCS_MERGE_PAT): Now a fixed string not a regexp.
- * options.h.in (GREP): Removed; no longer used.
- * update.c (update_fileproc), commit.c (check_fileproc): Call
- file_has_markers rather than GREP.
- * rcscmds.c (RCS_merge): Just give a fatal error in the case where
- we had been calling GREP. I suspect noone is using this code
- any more.
- * sanity.sh (conflicts): Rewrite tests 131, 132, and 133 to use
- dotest; tests that the above changes didn't break anything.
-
-Fri Nov 29 09:06:41 1996 fnf@ninemoons.com (Fred Fish)
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * checkout.c (safe_location): Only call readlink if HAVE_READLINK.
-
- * run.c (piped_child, filter_stream_through_program): If
- HAVE_VFORK, call vfork not fork.
- * run.c (run_exec): Add comment about why we use vfork.
-
-Mon Nov 25 12:48:31 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * release.c (release): Don't return after processing the first
- argument; that kind of defeats the purpose of having a loop, eh?
- For client, close the connection after we've processed them all.
- * sanity.sh: Remove workaround for modules2-8 test; tests for
- above fix. Adjust modules2-6 test to answer both questions.
-
- * login.c: Reindent (all of get_cvs_password, a handful of lines
- elsewhere).
-
- Cleanups to release, mostly cosmetic:
- * release.c (release_server): New function; breaks out server code
- from the release function.
- * release.c: Move delete_flag inside the release function.
- * release.c (release): Reindent. Rewrite comments about how the
- implementation could be improved. Don't declare variables as
- "register". Include errno in error message. Don't cast result of
- printf to void. Remove unused variable srepos.
- * release.c: Remove comments at top of file about what it does.
- They were not particularly coherent and they were also out of date
- (I think). Likewise for comment in release function about "if we
- are in a repository".
- * release.c: Change "module" to "directory" in a few messages
- since that is what is meant.
- * sanity.sh: In tests ignore-195 and ignore-193, change expected
- message accordingly.
-
-Sun Nov 24 11:30:55 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Clarify a few items in the todo list.
-
- * log.c (log_parse_date): Use the "end" of the epoch not "next
- week" as the time which means "no end time".
- * sanity.sh (rcs): New test, tests dates and importing RCS files.
-
-1996-11-19 Jim Kingdon
-
- Visual C++ lint:
- * hash.c: Declare qsort_comp.
- * update.c: Declare isremoved.
-
-1996-11-19 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * root.c, repos.c, modules.c, create_adm.c: Change all calls to
- strip_path to strip_trailing_slashes. Basically strip_path is
- just an unneeded complication (we should keep the pathname the way
- the user specifies it, and the system can worry about things like
- consecutive /'s if it wants to). Stripping trailing slashes is
- potentially dubious for the same reason, but it is a somewhat
- different case which I won't try to tackle now.
- * cvs.h (strip_path): Remove declaration.
-
-Tue Nov 19 15:18:13 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- There are a lot of details to this change, but the concept is
- relatively simple: make it so that for every CVSLCK lock that we
- might take out, there is a flag which is set iff we have created
- the CVSLCK directory.
- * lock.c (struct lock): New structure.
- * lock.c: Remove static variables repository and cleanup_lckdir.
- They are replaced by global_readlock.repository and
- global_readlock.have_lckdir, respectively (except insofar as the
- rest of these changes change the concept of cleanup_lckdir).
- New static variable global_readlock.
- (Reader_Lock, Lock_Cleanup): Use global_readlock in place of
- repository.
- (lock_simple_remove, set_lock, clear_lock, write_lock): Take a
- struct lock * instead of just a repository. Set/clear
- lock->have_lckdir instead of cleanup_lckdir.
- (set_writelock_proc, unlock_proc): Pass ->data, not ->key, to
- write_lock or lock_simple_remove.
- (lock_filesdoneproc,lock_dir_for_write): Allocate a struct lock,
- put it in the ->data field, and fill in its fields.
- (lock_simple_remove): Use lock->have_lckdir as the sole test for
- whether the CVSLCK directory needs to be removed. Add
- comments about why readlock and writelock variables don't tell us
- for sure whether locks exist.
- (lock_simple_remove, clear_lock): Use SIG_beginCrSect and
- SIG_endCrSect to ensure that ->have_lckdir is set to 0 iff the
- CVSLCK directory was really removed.
- (lock_simple_remove): Check for errors removing CVSLCK directory.
- (lock_simple_remove, Check_Owner, set_lock): Remove all code which
- checks userids (including all of Check_Owner and all the AFCVS
- code). It was bogus if several CVS processes with the same userid
- were running (common if several users share a userid; a common
- practice with remote CVS), and with the rest of the changes here
- should not be needed.
-
-1996-11-16 Paul Eggert <eggert@twinsun.com>
-
- * rcs.c (RCS_deltas): Fix unintended trigraphs.
-
-Fri Nov 15 13:06:03 1996 Tom Hageman <tom@basil.icce.rug.nl>
-
- * diff.c (diff_fileproc): In printing error messages, use the
- correct filename for which the error occurred.
-
-Sun Nov 10 21:13:38 1996 Paul Sanders <p.sanders@dial.pipex.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c: Use all the right cruft which goes along with
- including sys/time.h.
-
- * server.c: Include a "copyright" notice.
-
- * server.c: If HAVE_WINSOCK_H, include winsock.h.
-
- * server.c (server): Only set a handler for SIGHUP if it is
- defined. Likewise for all the other signals.
-
- * server.c (do_cvs_command): Use DEVNULL not /dev/null.
-
-Fri Nov 08 12:14:20 1996 Jim Kingdon
-
- IBM ICC (OS/2) lint:
- * add.c (add): Only declare begin_added_files if
- SERVER_SUPPORT.
- * client.c (init_sockaddr): Change port argument from
- unsigned short to unsigned int. Change hostname
- argument from const char * to char *.
-
-Sun Nov 3 18:24:28 1996 Noel Cragg <noel@gargle.rain.org>
-
- * sanity.sh (info): add new tests that check behavior of format
- string substitution in loginfo file.
-
-Sat Nov 2 09:39:09 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (do_deferred_progs): Don't access memory once it is
- freed (we already did it right for checkin_progs; do the same
- thing for update_progs).
-
- * update.c, client.c, classify.c, client.h, diff.c, commit.c,
- create_adm.c: Nuke more PATH_MAX.
-
-Fri Nov 1 18:22:32 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * error.h: Define PROTO if it is not defined.
-
-Wed Oct 30 08:53:20 1996 jalving@ibm.net
-
- * patch.c (patch_fileproc): Set line1 and line2 to NULL up-front
- (before the first "goto out") so we don't try to free them.
-
-Wed Oct 30 08:53:20 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c (remove_file, commit_filesdoneproc), run.c (run_print,
- run_exec), modules.c (open_module, cat_module, do_module), update.c
- (update_dirleave_proc), tag.c (tag_fileproc): Call cvs_out* rather
- than stdio.
- * server.c (serve_expand_modules): Remove comment about do_module
- writing to stdout/stderr; above changes should fix this.
-
-Tue Oct 29 17:23:59 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * status.c (tag_list_proc): When printing the tag name, don't
- truncate it to 25 characters.
-
-Tue Oct 29 12:49:07 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c, checkin.c, checkout.c, filesubr.c: Nuke arbitrary limit
- of PATH_MAX. Many more such limits surely remain.
-
- * fileattr.c (fileattr_set): Set attrs_modified *after* we might
- call fileattr_read, because fileattr_read clears it.
- * sanity.sh (devcom2): New tests, test for above fix and other
- behaviors I discovered in the process of looking into it.
-
-Mon Oct 28 08:55:57 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- The following changes are to ensure that SYSTEM_CLEANUP is always
- called.
- * error.c, cvs.h, main.c: Remove error_set_cleanup and related
- machinery. It was for a time when error.c was intended to be
- shared with other programs, but that is no longer true.
- * error.c, error.h (error_exit): New function; like error_cleanup
- from main.c but also calls SYSTEM_CLEANUP and exit (EXIT_FAILURE).
- * error.c (error, fperror): Call error_exit instead of doing it
- ourself.
- * server.c (server, serve_valid_responses, switch_to_user,
- check_password, pserver_authenticate_connection,
- kserver_authenticate_connection): Call SYSTEM_CLEANUP before exit.
- * add.c, client.c, import.c, main.c, mkmodules.c, modules.c,
- recurse.c, server.c, tag.c, update.c: Call error_exit ()
- instead of exit (EXIT_FAILURE).
-
-Sun Oct 27 08:34:16 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (conflicts): New test 128.5 tests "cvs co -p" in an empty
- directory (like 126.5), but when the file has nonempty contents.
- * rcs.c (RCS_checkout): If writing to stdout, use cvs_output
- rather than fwrite.
- * update.c (checkout_file): Call cvs_stderr not fprintf.
- These changes should fix some out-of-order bugs which show up in
- situations like conflicts-126.5 and conflicts-128.5.
-
- * mkmodules.c (checkout_file): Call RCS_checkout rather than
- run_exec on RCS_CO.
-
-Sat Oct 26 18:29:46 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (rdiff): cd out of testimport directory and remove it
- when done.
-
- * sanity.sh (info): Adjust tests to reflect fact that loginfo was
- created by cvs init.
-
- * sanity.sh (ignore): Change test 187a1 to allow any number of
- files in CVSROOT, not just modules.
-
- * sanity.sh (modules): In tests 148a0 and 148a1, don't expect a
- module which defines CVSROOT to itself, since we don't define one
- any more. Also change test to rewrite modules rather than append
- to it (in case any previous tests are changed to do something with
- modules). Change test 155b to allow any number of files in
- CVSROOT, not just modules.
-
- * add.c (add_directory): Set rev_old and rev_new fields of struct
- logfile_info to NULL (prevents us from trying to free them later).
- * commit.c (find_fileproc), import.c (import): Likewise.
-
- * sanity.sh (crerepos): New tests, to test alternate ways of
- creating a repository and related matters.
- * sanity.sh: Remove tests 1 through 3 and related cruft; replace
- them with a new test 1 which merely tests "cvs init". By doing
- the obscure stuff in crerepos we avoid having to do all this stuff
- any time we run any single test.
-
-Sat Oct 26 16:19:48 1996 Jim Blandy <jimb@totoro.cyclic.com>
-
- * main.c (main): If HAVE_TZSET is #defined, call tzset. This is
- harmless on all systems I know of, and required on some.
-
-Fri Oct 25 13:20:44 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * diff.c (diff_file_nodiff): When setting use_rev1, only return
- DIFF_SAME if empty_file is DIFF_DIFFERENT and ts_user is not
- NULL. Don't get confused by a vn_user field of "0" or one
- starting with '-'.
- * sanity.sh (death2): Add new death2-diff-{1,2,7,8} tests for
- above patch. Renumber existing death2-diff tests to make room.
-
-Fri Oct 25 12:38:29 1996 Jim Wilson <wilson@cygnus.com>
-
- * sanity.sh (death2): In tests death2-diff-{2,4,6,8,10}, allow "_"
- in temp file names. The system (tmpnam or whatever) generates
- these names so they vary from system to system.
-
-Fri Oct 25 07:52:44 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * logmsg.c (logfile_write): Give an error for several cases which
- should not be legal. Adjust comments accordingly.
- * mkmodules.c (loginfo_contents): Make description of loginfo much
- more concise. This should be a reminder, not full documentation.
-
-Tue Oct 22 10:37:37 1996 Noel Cragg <noel@gargle.rain.org>
-
- * commit.c (update_delproc): free structure members rev_old and
- rev_new if they have been allocated.
-
- * mkmodules.c: change loginfo_contents to include a description of
- the new format string.
-
- * logmsg.c (logfile_write): change syntax of format string.
-
-Sat Oct 19 16:09:55 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- For reference, this takes CVS's text segment from 348348 bytes to
- 347420 bytes.
- * server.c (requests): Change Directory to rq_essential
- per change in doc/cvsclient.texi.
- * client.c: Remove use_directory and all code which executed if
- it wasn't set. This includes the get_short_pathname function.
- * server.c: Likewise, for use_dir_and_repos.
- (serve_repository): Give a fatal error.
- * server.c (requests): Remove Lost. Change Unchanged to rq_essential.
- (serve_lost): Removed.
- * server.c, server.h, client.c, vers_ts.c: Remove use_unchanged,
- code to set it, and all code which executed if it wasn't set.
-
-Sat Oct 19 12:44:08 1996 J. Richard Sladkey <jrs@world.std.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * hash.c (sortlist, new function qsort_comp): Rewrite to use qsort
- instead of insert sort. Changes algorithm from n^2 to n log n
- (assuming qsort is implemented with quicksort or similar).
-
-Sat Oct 19 12:44:08 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basic2): In test basic2-64, use -x and specify types
- which exclude E; the test is not built to deal with E (or any
- other new types).
-
-Sat Oct 19 12:00:00 1996 Mark Mitchell <mmitchell@usa.net>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (isemptydir, new function isremoved): Avoid pruning
- directories that contain files marked for removal but not
- comitted.
- * update.c, update.h (isemptydir): Now extern, not static.
- * update.c (isemptydir): New parameter might_not_exist handles
- difference in functionality from old client_isemptydir. Bring
- over the improved error checking from client_isemptydir.
- * client.c (client_isemptydir): Removed; isemptydir now suffices.
- * update.c (update_dirleave_proc), client.c
- (process_prune_candidates): Update callers.
- * sanity.sh (deep): Add tests deep-rm* for above fix.
-
-Fri Oct 18 15:53:41 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (devcom): Add tests devcom-some* to test watching just
- a single file.
-
- * root.c (Name_Root): Use isabsolute to test whether a pathname is
- absolute instead of checking for the first character being '/'.
- (Reported by Antoine P. Brusseau <brusseau@jprc.com>).
-
- * commit.c (checkaddfile): Free rev only if it is non-NULL (thanks
- to cwong@world.std.com (Christopher Wong) for diagnosing this; the
- death2-15 test in sanity.sh hits it).
-
-Thu Oct 17 15:21:56 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Reenable rdiff tests. Delete rdiff-9 test to reflect
- the fact that the change to add a -K option has not been
- incorporated. Adjust rdiff-8 test to reflect the fact that the
- change to change the default keyword expansion for the first
- revision has not been incorporated.
- * patch.c (patch_fileproc): Pass the symbolic revision to
- RCS_checkout so that Name can be expanded correctly. Reinstates
- one of the 30 Sep 96 changes and fixes a bug which the sanity.sh
- rdiff test tests for.
-
- Reinstate change from 30 Sep 96:
- * patch.c (patch): CLIENT_SUPPORT: send '-f' if NOT force_tag_match
-
- * client.c (process_prune_candidates): Do not ignore errors from
- unlink_file_dir.
-
- * filesubr.c (deep_remove_dir): If rmdir returns an error other
- than ENOTEMPTY or EEXIST, return -1 not 0. Add workaround for AIX
- header bug.
-
-Tue Apr 30 08:21:27 1996 Mike Sutton <mike_sutton@dayton.saic.com>
-
- * checkout.c, history.c: added logging/reporting of cvs export
- command
-
-Wed Oct 16 10:16:57 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Remove tests 4, 4.5, and 4.75; this functionality is
- already tested by 45, 45.5 and other tests.
- (ignore): New tests ignore-192, ignore-193, ignore-194, and
- ignore-195 test output from "cvs release".
- (modules2): New tests modules2-6, modules2-7, and modules2-8 test
- ability of cvs release to handle multiple arguments. Since it
- currently doesn't, the tests are kludged.
-
- * server.c, cvs.h (cvs_flushout): New function.
- * recurse.c (do_file_proc): Call it.
- * server.c (cvs_outerr): Call fflush (stdout) in non-server case.
- * main.c (main): Don't call setvbuf. The code was incorrectly
- checking for "patch" (it really is "rdiff"); the concern about
- slowing down large amounts of output is not specific to rdiff
- (it applies to "log" for example); and the above changes should
- meet the need.
-
-Tue Oct 15 10:22:10 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- This is intended to facilitate some future cleanups to the
- locking, but by itself it is a simple, conversative rearrangement:
- * tag.c (locked_dir, locked_list): Move from here...
- * lock.c: ...to here.
- * lock.c (Lock_Cleanup): If locked_dir is set clean it up too.
- * tag.c (tag_unlockdir): Removed; with the above change
- Lock_Cleanup suffices.
- * tag.c (tag_lockdir): Move from here...
- * lock.c (lock_dir_for_write): ...to here.
- * tag.c (tag_fileproc), rtag.c (rtag_fileproc): Update callers.
- Move comments concerning why we are locking what we are from
- tag_lockdir to here.
- * tag.c (tag_filesdoneproc), rtag.c (rtag_filesdoneproc):
- Update callers.
- * lock.c (Writer_Lock): Made static.
- * cvs.h: Update declarations.
- * server.c (server_notify): Call lock_dir_for_write rather than
- calling Writer_Lock ourselves.
-
- This is intended to facilitate some future cleanups to the
- locking, but by itself it is a simple, conversative rearrangement:
- * lock.c (Lock_Cleanup): Also dellist (lock_tree_list).
- * lock.c, cvs.h (lock_tree_cleanup): Removed; with the above change
- Lock_Cleanup suffices.
- * commit.c, edit.c, watch.c: Change callers.
-
-Sat Oct 12 21:41:46 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (deep): Add comment about whether the deep-4b behavior
- is considered desirable.
-
-Sat Oct 12 20:36:36 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * client.c (client_send_expansions): Add build_dirs parameter.
- Change all callers.
- (send_dirent_proc): Get build_dirs from callerdat; if it is
- zero, don't send a nonexistent directory to the server.
- (send_files): Add build_dirs parameter. Change all callers.
- * client.h (send_files): Update prototype.
- (send_files_contents): Remove prototype for nonexistent function.
- (client_send_expansions): Update prototype.
- * sanity.sh (deep): Add deep-4b test for above patch.
-
-Fri Oct 11 14:07:12 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- gcc -Wall lint:
- * logmsg.c (title_proc): Remove unused variables title and comma.
-
- * sanity.sh (modules2): Don't be picky about whether we are
- checking in 1.3 or 1.2 of modules; it depends on whether we are
- running all the tests or just some.
-
-Thu Oct 10 14:52:06 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c, server.h (server_dir): New variable.
- (output_dir): If it is set, send it before the directory name.
- * modules.c (do_module): Set it, in the case of & modules, and
- restore it when done.
- * sanity.sh (modules): Don't clean up first-dir before starting;
- tests now clean up for themselves at the end.
- (modules2): New tests, for above fix.
-
-Wed Oct 9 15:52:34 1996 Jim Blandy <jimb@totoro.cyclic.com>
-
- * sanity.sh: Barf immediately if run as root.
-
- * rcs.c (RCS_getrevtime): When giving a date to get_date, use the full
- year, not the year - 1900, so that dates after 1999 are parsed
- correctly. (Change thanks to Paul Eggert.)
-
-Wed Oct 9 10:59:11 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- Clean up gcc -Wmissing-prototypes lint:
- * cvs.h (admin, add, checkout, commit, diff, history, import,
- cvslog, login, patch, release, cvsremove, rtag, status, tag):
- Declare.
- * server.c, main.c: Don't declare them here. Don't declare update
- either (which is already declared in cvs.h).
- * tag.c, cvs.h, main.c, server.c: Rename tag to cvstag to avoid
- name conflicts.
- * client.c (init_sockaddr, auth_server_port_number), entries.c
- (Entnode_Create, Entnode_Destroy), hash.c (nodetypestring),
- login.c (construct_cvspass_filename), server.c
- (supported_response), wrapper.c (wrap_matching_entry): Make static;
- prototype.
- * hash.c (printlist): Prototype.
- * myndbm.c (mydbm_load_file): Change declaration to prototype.
-
-Tue Oct 8 22:35:34 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (log2): Re-add these tests; they were deleted for 1.9
- (because they were thought to be destabilizing and/or due to
- confusion/accident), but they can be put back now.
-
- * sanity.sh (death2): In tests death2-diff-{2,4,6,8,10}, allow "-"
- or "%" in temp file names. The system (tmpnam or whatever)
- generates these names so they vary from system to system.
-
-Tue Oct 8 12:37:09 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * options.h.in (HAD_RCS4): Remove; no longer used.
-
-Sun Oct 6 15:58:11 1996 Noel Cragg <noel@gargle.rain.org>
-
- * The following changes address problem #56 in the GNATS database
- on harvey.cyclic.com:
-
- * logmsg.c (str_list_format): new global -- contains the format
- for items to be placed in str_list.
- (Update_Logfile): move code that creates the "title" string...
- (logfile_write): ...to here. Pull apart the filter program and
- look for a format string, extracting it if there is one.
- (title_proc): write a given filename/value based on the format
- string.
-
- * commit.c (classify_file_internal): new routine, old code (needed
- to use the code in more than one place). Determines the status
- and version information about a file.
- (check_fileproc): use classify_file_internal. Fill in the rev_old
- field for the struct logfile_info.
- (commit_fileproc): Fill in the rev_new field.
-
- * cvs.h (struct logfile_info): add two new fields -- rev_old and
- rev_new -- that keep track of revision numbers across commits.
-
-Fri Sep 27 15:21:47 1996 Peter Wemm <peter@spinner.dialix.com>
-
- * logmsg.c (do_editor): Do not use editinfo if running on the client.
-
-Fri Oct 4 15:11:46 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (server_cleanup): Temporarily clear noexec when calling
- unlink_file_dir. This is so we clean up the temp directory even
- when the -n global option is specified.
-
-Wed Oct 2 10:47:33 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * client.c (send_repository): initialize some variables before
- first usage
-
-Tue Oct 1 13:01:24 1996 Jim Blandy <jimb@floss.cyclic.com>
-
- Revert some of Greg's changes; they're welcome later, but we're
- trying to keep CVS stable for pre-release testing at the moment.
- * checkin.c, commit.c, cvs.h, diff.c, import.c, main.c, no_diff.c,
- options.h.in, patch.c, rcs.c, rcs.h, rcscmds.c, sanity.sh, update.c:
- Revert changes of Sep 29 and 30.
-
-Tue Oct 1 13:17:31 1996 Ian Lance Taylor <ian@cygnus.com>
-
- Make sure the server temporary directory is removed even if
- Max-dotdot is used.
- * server.c (orig_server_temp_dir): New static variable.
- (serve_max_dotdot): Don't free server_temp_dir if it is the same
- as orig_server_temp_dir.
- (do_cvs_command): Use orig_server_temp_dir in error message.
- (server_cleanup): Remove orig_server_temp_dir.
- (server): Set orig_server_temp_dir. Remove incorrect indentation
- of error message.
-
- * import.c (update_rcs_file): Restore new argument to
- RCS_checkout, removed in last patch.
-
-Tue Oct 1 00:32:55 1996 Jim Blandy <jimb@floss.cyclic.com>
-
- * import.c: Revert Greg Woods' changes of Sep 30. We may want
- them later, but not before 1.9.
-
-Mon Sep 30 23:31:01 1996 Jim Blandy <jimb@floss.cyclic.com>
-
- * log.c (log_fileproc): Now that we might actually find a "desc"
- node in rcsfile->other, thanks to Ian's change below, we had
- better deal correctly if we find a null pointer in it.
-
-Mon Sep 30 13:55:03 1996 Greg A. Woods <woods@most.weird.com>
-
- * main.c (main): don't set need_to_create_root for "cvs init"
- either, just in case it's run from within a valid working
- directory.
-
- * sanity.sh (testcvs): oops, forgot to comment out test version I
- was using...
-
- * diff.c (diff_fileproc): use Diffbin instead of DIFF (3).
- * patch.c (patch_fileproc): use Diffbin instead of DIFF.
- * commit.c (check_fileproc): use Grepbin instead of GREP.
- * rcscmds.c (RCS_merge): use Grepbin instead of GREP.
- * update.c (patch_file): use Diffbin instead of DIFF.
- (update_fileproc): use Grepbin instead of GREP.
- * cvs.h (Diffbin): new declaration.
- (Grepbin): new declaration.
- (DIFFBIN_ENV): new manifest to name DIFFBIN environ var.
- (GREPBIN_ENV): new manifest to name GREPBIN environ var.
- * option.h.in (DIFFBIN_DFLT): renamed from DIFF.
- (GREPBIN_DFLT): renamed from GREP.
- * main.c (main): new variables diffbin_update_env and
- grepbin_update_inv, ala rcsbin_update_env.
- (main): new options -D diffbin and -g grepbin
- (usg): describe new options -D diffbin and -g grepbin.
- (Diffbin): new global variable for DIFF path.
- (Grepfbin): new global variable for GREP path.
-
- * options.h.in (RCSBIN_DFLT): mention this needs to be set if
- your PATH isn't set properly by rshd.
-
- * sanity.sh (rdiff): re-do Jim's change, but with the original
- keywords I had intended (should be a bit more like real life), and
- Jim's better RCS date and user matching form.
- [I guess that's what I get for checking things in at 3am! ;-)]
-
-Mon Sep 30 17:00:20 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (RCS_reparsercsfile): Store desc field value in main RCS
- node data, not in version specific data.
- * sanity.sh: Enable log2 test (for local CVS only).
-
-Mon Sep 30 13:01:45 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (log2): New test, tests cvs add -m. Not yet enabled
- in "tests" because CVS currently flunks this test.
-
- * sanity.sh (rdiff, basic2): Allow "cvs server" as well as "cvs
- checkout" and friends in messages. In testing output of cvs
- status, don't require a tab which isn't there for remote. Skip
- test rdiff-9 for remote. In test basic2-64, add missing slash in
- the pattern which gets used for remote.
-
- * sanity.sh (rdiff): Fix strings we were matching against which
- got keyword-expanded in checking in sanity.sh.
-
-Mon Sep 30 03:21:37 1996 Greg A. Woods <woods@most.weird.com>
-
- * sanity.sh: change all regexpr literal '.' to '\.'
- (basic2): why are tests 34 & 42 commented out (because
- of 'diff -u'?)?
- add tests 56[abc], 57a, and 58a to test import to the main
- branch (i.e. branch '1').
- (rdiff): new test section for rdiff -K, etc.
- (dotest): remove dotest.ex? before running a new test.
- (dotest_fail): remove dotest.ex? before running a new test.
- (dotest_internal): write expected output to dotest.exp, or if $4
- also used, to dotest.ex1 and dotest.ex2.
- (patch): renamed this test to 'serverpatch'.
- (dotest_lit): rename dotest.res to dotest.exp ala dotest().
- remove dotest.ex? before running a new test.
- (DOTSTAR): mention the bug exists up to 1.12
- (ENDANCHOR): mention the bug exists up to 1.12
- (dotest_all_in_one): new function for debugging.
- (dotest_line_by_line): new function for debugging.
- (dotest_internal_debug): new function for debugging.
- (dotest_internal): stop emulating the ancient tests and don't spew
- the dotest.tmp contents onto $LOGFILE -- it's just too much
- meaningless noise. Only do this if the test fails. Many tests
- don't use dotest() yet, so this isn't quite so helpful as it might
- otherwise be.
- (TODO): mention CVS/* files, especially CVS/Root.
-
- * main.c (main): add a commented out piece of code to suggest that
- there should be a function lookup_command_attribute() that could
- tell us various things about internal commands, such as whether
- they use CVS/Root, or if they're repository-only, or if they need
- a working directory, etc....
- (main): don't set need_to_create_root if command doesn't use a
- local working directory.
-
- * patch.c (patch): CLIENT_SUPPORT: send '-f' if NOT force_tag_match
-
- * error.c (fperror): protect declaration for un-defined __STDC__
-
- * import.c (import): permit imports to a branch with zero dots,
- i.e. the trunk.
- (update_rcs_file): don't detect conflicts if importing to the
- trunk.
- (import): add hint that we should allow a module name, instead of
- just a pathname relative to $CVSROOT.
- (add_rcs_file): if importing to trunk, do it with ci(1).
-
- * import.c: XXX the following are all #if 0'ed out until a full
- implementation can be designed....
- (cbranch): new variable to support conflict detection on another
- branch set by -c.
- (import): truncate -b and -c optarg if to fit in static storage.
- (import_usage): describe -c
-
- * rcscmds.c (RCS_checkout): add new argument 'rcsver'. If rcsver
- is set, turn on 'keywords' to force call to RCS_exec_checkout.
- * rcs.c (RCS_exec_checkout): add new argument 'rcsver'. Pass
- 'rcsver' to "co" with run_arg().
- * cvs.h: (RCS_checkout): add new argument 'rcsver' to prototype.
- (RCS_exec_checkout): add new argument 'rcsver' to prototype.
- * commit.c (remove_file): supply new argument to RCS_checkout.
- * checkin.c (Checkin): supply new argument to RCS_checkout.
- * diff.c (diff_fileproc): supply new argument to RCS_checkout.
- (diff_file_nodiff): supply new argument to RCS_checkout.
- * no_diff.c (No_Difference): supply new argument to RCS_checkout.
- * update.c (checkout_file): supply new argument to RCS_checkout.
- (patch_file): supply new argument to RCS_checkout.
- (join_file): supply new argument to RCS_checkout.
-
- * patch.c: (o_options): new variable for -K
- (rcsver): new variable for -V.
- (patch): add -K flag which sets o_options, change -V to set
- rcsver, send o_options and rcsver if in client mode.
- (patch_fileproc): use RCS_checkout instead of RCS_fast_checkout in
- order to ensure $Name is expanded, use o_options if set, or
- options if set, or by default "-ko" when getting "old" file.
-
-Sun Sep 29 16:43:28 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcscmds.c: Replace comment at top of file concerning RCS library
- with a reworded version based on discussion between me, Ian, Paul
- Eggert, and JimB.
-
-Sun Sep 29 13:09:45 1996 Noel Cragg <noel@kiva.rain.org>
-
- * main.c (main): don't create/update CVS/Root when doing the "cvs
- login" command. Consider: if the user executes "cvs login" with
- the working directory inside an already checked out module, we'd
- incorrectly change the CVS/Root file to reflect the CVSROOT of the
- "cvs login" command.
-
- * login.c (login): if we're re-logging into a server for which a
- .cvspass entry already exists, copy the temporary file to its home
- location rather than renaming. Renaming doesn't work between
- filesystems. After copying, unlink the temporary file.
-
-Fri Sep 27 05:24:56 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * diff.c: Add comment about --brief option.
-
- * README-rm-add: Removed; the information which was here is now in
- cvs.texinfo.
- * Makefile.in (DISTFILES): Remove README-rm-add.
-
-Wed Sep 25 10:00:00 1996 Larry Jones <larry.jones@sdrc.com>
-
- * Makefile.in (cvsbug): Add dependency on version.c.
-
-Wed Sep 25 09:01:48 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * filesubr.c (get_homedir), update.c (update): Reindent.
-
-Wed Sep 25 04:44:54 1996 Jim Blandy <jimb@totoro.cyclic.com>
-
- * version.c (version_string): Bump to 1.8.86.
-
-Wed Sep 25 05:17:50 1996 Jim Blandy <jimb@floss.cyclic.com>
-
- * update.c (update): Don't neglect to pass the -kmumble options
- to the server.
- * sanity.sh (binfiles-sticky): New tests for above.
-
- * cvsrc.c (read_cvsrc): Deal correctly with lines that specify a
- command, but no options; don't corrupt argv.
-
- * sanity.sh: When testing rsh, use the program specified by
- the CVS_RSH environment variable, if it's set. Move test to top
- of file, so it runs before all other tests (it's really a
- meta-test).
-
- * filesubr.c (get_homedir): Use getpwuid to find the home
- directory, if the HOME environment variable isn't set.
- * ignore.c (ign_add_file): Call get_homedir to find the user's
- home directory; this is more portable than calling getpwuid.
-
-Tue Sep 24 09:08:17 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * log.c (log_tree): When walking through branches, follow the
- ->prev field rather than following ->next which insures that the
- loop only executes once and we only see the last branch.
- * sanity.sh (multibranch): Test "cvs log" too; tests for above fix.
-
-Mon Sep 23 09:55:22 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * options.h.in: Fixed some typos in the comments and reindented
- them.
-
-Sat Sep 21 02:33:26 1996 Jim Blandy <jimb@totoro.cyclic.com>
-
- * sanity.sh: If we're testing remote CVS, make sure rsh itself is
- working before running any tests. It's confusing when basica-1
- fails just because you don't have the local host in your .rhosts
- file.
-
- * version.c (version_string): Bump to 1.8.85.
-
-Thu Sep 19 09:15:41 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * options.h.in: Define SERVER_FLOWCONTROL, SERVER_HI_WATER,
- SERVER_LO_WATER. Several large sites (FreeBSD, Cygnus) have been
- pounding on this code without problems, and it doesn't seem to
- have any significant downsides.
-
-Tue Sep 17 01:13:41 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * status.c (status_fileproc): Instead of a default case, set sstat
- before the switch. This way gcc -Wall can detect a missed case.
- Add explicit T_TITLE case.
-
-Tue Sep 17 00:09:44 1996 Assar Westerlund <assar@pdc.kth.se>
-
- * login.c (login): Print usage if argc < 0.
-
-Tue Sep 17 00:09:44 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * lock.c: In comment, mention one more function of readlocks
- (fileattr not updated atomically). Note similarity between
- solutions #2 and #5.
-
- * checkout.c (safe_location): Do not reject a location merely
- because it textually starts with hardpath; insist that it be
- hardpath or a subdirectory thereof.
-
-Mon Sep 16 11:46:36 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (server_cleanup): Add comment about ignoring errors
- from unlink_file_dir.
-
-Mon Sep 16 10:31:48 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * main.c: Add support for -T <tmpdir> command line option. This
- is needed for servers started via inetd.
- (usg): Added line for -T. Improved -z documentation.
- (main): Read default for tmpdir from the environment. Test for 'T'
- in getopt loop. Use '/tmp' as ultimative fallback. Update
- environment if possible.
-
- * cvs.h (TMPDIR_ENV): Added for -T <tmpdir> command line option.
-
- * options.h.in: Add TMPDIR_DFLT
-
- * import.c (update_rcs_file): Use global variable Tmpdir instead
- of reading the environment.
-
- * server.c (server_cleanup): Use global variable Tmpdir instead of
- reading the environment. Also, replace system("rm -rf") with
- unlink_file_dir.
- (server): Use global variable Tmpdir instead of reading the
- environment.
-
-Thu Sep 12 1996 Jim Kingdon <kingdon@cyclic.com>
-
- * main.c (main): If ARGV0_NOT_PROGRAM_NAME, then just set
- program_name to "cvs" rather than argv[0].
-
-Thu Sep 12 12:06:56 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (update_entries): If we can't write the file, don't
- make it a fatal error.
-
-Wed Sep 11 12:46:23 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (start_server): Move START_SERVER_RETURNS_SOCKET code
- so that it is only run for server_method. It is wrong for
- pserver_method (in which connect_to_pserver sets server_sock).
-
- * login.c (construct_cvspass_filename): If NO_SLASH_AFTER_HOME,
- don't put a '/' between $HOME and .cvspass. Reindent function.
- * build_src.com: Add zlib.c, login.c, and scramble.c.
-
- * rcs.c (RCS_deltas): When looking for our branch in ->branches,
- check the branch number.
- * sanity.sh (multibranch): New tests test for above fix.
-
- * commit.c (precommit_list_proc): Fix typo in last change
- (->status to ->type).
-
-Tue Sep 10 23:05:41 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Makefile.in (DISTFILES): Add build_src.com.
- * build_src.com: Add buffer.c, buffer.obj, and zlib.olb.
-
-Tue Sep 10 20:35:23 1996 Juergen Renz <renz@conware.de>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c (precommit_list_proc): Update to reflect Jul 22 change
- in which p->data was changed from a Ctype to a struct
- logfile_info *. This means that commitinfo scripts again get
- passed the file list like they should.
-
-Tue Sep 10 20:35:23 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (auth_server_port_number): Change name of service from
- "cvs" to "cvspserver". The latter is what the manual has always
- recommended, and it is also officially registered with IANA.
-
-Tue Sep 10 11:12:42 1996 Mark A. Solinski <markso@mcs.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (socket_buffer_output): Change ifdef VMS to ifdef
- SEND_NEVER_PARTIAL.
- (start_server): Change ifdef VMS to ifdef START_SERVER_RETURNS_SOCKET.
-
-Tue Sep 10 17:15:21 1996 Jim Blandy <jimb@totoro.cyclic.com>
-
- * client.c (auth_server_port_number): Look up "cvs" in the
- services database, and use the value it returns; fall back to
- CVS_AUTH_PORT if no entry is present.
- (connect_to_pserver): Use the correct port number in any error
- messages.
-
-Tue Sep 10 11:12:42 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (newb): New test newb-123j0 tests for another "cvs
- status" case.
-
-Sun Sep 8 15:20:37 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (RCS_checkout): Clarify handling of options parameter.
-
- * rcs.c (RCS_checkout): Free buffer allocated by RCS_deltas.
-
-Sat Sep 7 21:28:27 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (struct cmd): Add comment concerning recognizing unique
- abbreviations.
-
-Fri Sep 6 22:31:52 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_checkout): Fix indentation.
-
-Fri Sep 6 11:48:08 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (RCS_checkout): Replace tag parameter with rev and nametag
- parameters. Change all callers.
- * rcs.h (RCS_checkout): Update declaration.
-
- * rcs.c (RCS_getversion): Replace return_both parameter with
- simple_tag. Change all callers.
- (RCS_gettag): Likewise.
- * rcs.h (RCS_getversion, RCS_gettag): Update declarations.
- * vers_ts.c (Version_TS): Simplify vn_tag initialization using new
- simple_tag rather than old return_both.
- * cvs.h (struct vers_ts): Clarify vn_tag comment a bit.
-
- * main.c (usg): Only mention -x if ENCRYPTION is defined.
- (main): Mention ENCRYPTION define in comment for -x.
- * client.h (krb_encrypt_buffer_initialize): Only declare if
- ENCRYPTION is defined.
- * client.c (start_server): Only encrypt if ENCRYPTION is defined.
- * server.c (serve_kerberos_encrypt): Only define if ENCRYPTION is
- defined.
- (requests): Only include Kerberos-encrypt is ENCRYPTION is
- defined.
- (krb_encrypt_*): Only define if ENCRYPTION is defined.
-
-Thu Sep 5 17:32:39 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * sanity.sh: When testing remote, use :ext: instead of :server: to
- match change made earlier today.
-
-Thu Sep 5 13:57:47 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (start_tcp_server): Don't allow :kserver: to mean
- "direct tcp" (root.c already takes care of this, but I want to
- make it clear what is intended, and not intended, here).
- (start_server): Handle ext_method (external rsh program) and
- server_method (internal rsh client) separately.
- * client.c: Take rsh_pid and start_rsh_server out of
- RSH_NOT_TRANSPARENT ifdefs. It is useful for things like SSH on NT.
- * cvs.h (CVSmethod), root.c (method_names): Add ext_method.
- * root.c (parse_cvsroot): Recognize "ext" access method.
- If access method is not specified and CVSROOT contains a colon,
- use either ext_method or server_method depending on
- RSH_NOT_TRANSPARENT.
-
-Thu Sep 5 00:09:49 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (RCS_checkout): Remove flags parameter, which was not
- serving any useful purpose. Change all callers.
- * rcscmds.c (RCS_exec_checkout): Likewise.
-
- * rcscmds.c (RCS_exec_checkout): Rename from RCS_checkout. Change
- all callers.
- * rcs.c (RCS_checkout): Rename from RCS_fast_checkout. Change all
- callers.
-
-Wed Sep 4 14:42:28 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (RCS_fast_checkout): If tracing, output a message. If
- noexec, and workfile is not NULL, just return immediately. Assert
- that sout is RUN_TTY or workfile is NULL, rather than using it as
- a conditional. Replace found variable with two variables--gothead
- and keywords--reflecting what it actually means.
-
- * rcs.c (RCS_fast_checkout): Don't handle the case of workfile set
- to "".
- * rcscmds.c (RCS_checkout): Likewise.
- * checkin.c (Checkin): Pass explicit file name, not "", to
- RCS_fast_checkout.
- * update.c (join_file): Likewise.
- * commit.c (remove_file): Pass explicit file name to
- RCS_fast_checkout and RCS_checkin.
-
- * rcs.c (RCS_reparsercsfile): Always continue after seeing
- RCSSYMBOLS, even if the value is NULL. Clear the NODELTA flag
- after setting delta_pos.
- (free_rcsnode_contents): New static function.
- (freercsnode): Call free_rcsnode_contents.
- (RCS_fast_checkout): If NODELTA is set, reparse the RCS file.
- (RCS_settag): New function. Change all callers to old function.
- (RCS_deltag, RCS_setbranch): Likewise.
- (RCS_lock, RCS_unlock): Likewise.
- (RCS_deltas): If NODELTA is set, reparse the RCS file.
- * rcs.h (NODELTA): Define.
- (RCS_settag, RCS_deltag, RCS_setbranch): Declare.
- (RCS_lock, RCS_unlock): Declare.
- * rcscmds.c (RCS_exec_settag): Rename from RCS_settag. Don't
- check tag against BASE or HEAD (now done in new RCS_settag).
- (RCS_exec_deltag): Rename from RCS_deltag.
- (RCS_exec_setbranch): Rename from RCS_setbranch.
- (RCS_exec_lock): Rename from RCS_lock.
- (RCS_exec_unlock): Rename from RCS_unlock.
- * cvs.h: Update declarations of renamed functions.
- * checkin.c (Checkin): Remove rcscopy variable (no longer needed
- because of change in RCS_unlock call).
- * commit.c: Include <assert.h>.
- (remove_file): Update RCSNode path if the file is renamed.
- (unblockrcs): Change rcs parameter to RCSNode. Change all
- callers.
- (fixbranch): Likewise.
- (lock_RCS): Likewise. Don't call RCS_parsercsfile.
- (checkaddfile): Update RCSNode path if the file is renamed. After
- creating a new file, call RCS_parse. When stubbing a branch, use
- the passed in RCSNode if there is one, rather than calling
- RCS_Parse. Don't call RCS_Parse again after calling RCS_settag.
- Free head and magicrev even if RCS_settag fails.
- * import.c (add_rev): Change rcs parameter to RCSNode. Change all
- callers.
- (add_tag): Likewise.
-
- * rcs.c (RCS_fast_checkout): Amend last patch: if workfile is
- NULL, but sout is not NULL, use sout in error message.
-
-Wed Sep 4 13:35:09 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Increment version number to 1.8.8.
-
- * Version 1.8.7.
-
-Wed Sep 4 1996 Jim Kingdon <kingdon@cyclic.com>
-
- * client.c (send_file_names): Look for the name to send in
- Entries even if the file doesn't exist; we should send the
- name as it appears in Entries in the "rm foo; cvs update FOO"
- case.
-
-Tue Sep 3 20:50:11 1996 William A. Hoffman <hoffman@albirio.crd.ge.com>
-
- * rcs.c (RCS_fast_checkout): If workfile is NULL, don't try to
- include it in error message.
-
-Mon Aug 26 12:27:38 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * mkmodules.c (mkdir_if_needed): Move from here ...
- * filesubr.c, cvs.h (mkdir_if_needed): ... to here. Have it
- return a value saying whether the directory was created.
- * client.c (call_in_directory), edit.c (edit_fileproc): Call it.
-
-Fri Aug 23 19:19:44 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * checkin.c (Checkin): Copy rcs parameter in case it is freed when
- finfo->rcs is freed.
-
-Fri Aug 23 14:55:41 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * remove.c (remove_fileproc): Revert change of 23 Aug to print
- getwd and finfo->file in message. The latter is redundant with
- fullname and the former is redundant with fullname and the working
- directory when CVS was invoked. The implementation was also
- lacking as the getwd call could overflow the buffer.
-
-Fri Aug 23 18:40:35 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * remove.c (cvsremove): fix remove -f for client/server
-
-Fri Aug 23 11:28:27 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * wrapper.c, cvs.h: Remove conflictHook field of WrapperEntry,
- WRAP_CONFLICT in WrapMergeHas, and 'c' option in wrap_add; they
- are never used.
-
-Fri Aug 23 11:41:46 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * server.c (switch_to_user): use #ifdef SETXID_SUPPORT instead of
- #if SETXID_SUPPORT
-
-Thu Aug 22 14:18:43 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * checkin.c (Checkin): Remove local variable xfinfo. Reparse the
- RCS file after the checkin. Call RCS_fast_checkout rather than
- RCS_checkout.
-
- * cvs.h (RCS_FLAGS_LOCK): Don't define.
- (RCS_FLAGS_*): Adjust values to fill in hole left by removal of
- RCS_FLAGS_LOCK.
- * rcs.c (RCS_fast_checkout): Don't check for RCS_FLAGS_LOCK.
- * rcscmds.c (RCS_checkout): Likewise.
- * commit.c (commit_fileproc): Remove rcs local variable. If
- status is T_MODIFIED, require that finfo->rcs be set, call
- Lock_RCS directly, and don't call locate_rcs. If adding to a tag,
- require that finfo->rcs be set, and don't call locate_rcs.
- (remove_file): Remove rcs local variable. Require that finfo->rcs
- be set. Don't call locate_rcs. Don't pass RCS_FLAGS_LOCK to
- RCS_checkout; use RCS_lock instead. Call RCS_fast_checkout rather
- than RCS_checkout.
- (unlockrcs): Use a single rcs parameter rather than two parameters
- for file and repository. Change all callers. Don't call
- locate_rcs.
- (fixbranch): Likewise.
- (lockrcsfile): Remove; no more callers.
-
-Tue Aug 20 10:13:59 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * buffer.c, rcs.c: Don't use inline. It wasn't being used in a
- loop or any such place where it would matter for performance, and
- it was a (minor) portability hassle.
-
- * server.c (server): Change "Dummy argument 0" to "cvs server" and
- add comment explaining why.
-
- * rcs.c (linevector_add): Add comment regarding changing \n to \0.
-
-Tue Aug 20 09:19:19 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * checkout.c (checkout_proc): Call RCS_parse to get the default
- options from the RCS file.
-
- * sanity.sh (binfiles): Add tests 5.5b0 and 5.5b1 for the above fix
-
-Mon Aug 19 18:13:32 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (linevector_init): Make inline. Set lines_alloced to 0,
- not 10. Set vector to NULL.
- (linevector_add): Remove assertion that lines_alloced is greater
- than zero. Initialize lines_alloced if necessary.
- (linevector_copy): Initialize lines_alloced if necessary.
- (linevector_free): Only free vector if it is not NULL.
- (RCS_deltas): Always call linevector_init and linevector_free on
- curlines, headlines, and trunklines.
- (RCS_fast_checkout): Remove #if 0 around code that calls
- RCS_deltas.
-
-Fri Aug 16 17:52:54 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (linevector_add): Handle zero length correctly.
- (RCS_deltas): In RCS_FETCH case, the data is in headlines, not
- curlines.
- (RCS_fast_checkout): Update comment about RCS_deltas: the
- testsuite now passes.
-
- * rcs.c (RCS_fully_parse): Use the length of the value, rather
- than assuming that there are no embedded zero bytes.
- (struct line): Add len field.
- (linevector_add): Add len parameter. Change all callers. Use
- len, rather than assuming that there are no embedded zero bytes.
- Set the len field in new lines.
- (RCS_deltas): Use the length of the value, rather than assuming
- that there are no embedded zero bytes. Use the line length when
- outputting it and when copying it.
- (RCS_fast_checkout): Update comment about RCS_deltas to remove
- note about supporting zero bytes correctly.
-
-Thu Aug 15 23:38:48 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c, import.c: Revise comments regarding the fact that we
- call start_server before do_editor.
-
-Thu Aug 15 11:30:55 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * server.c: Include <sys/socket.h> if AUTH_SERVER_SUPPORT.
- (pserver_authenticate_connection): Set SO_KEEPALIVE on
- STDIN_FILENO.
- (kserver_authenticate_connection): Likewise.
-
-Thu Aug 15 10:26:41 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * server.c (switch_to_user): Fix previous patch to compile it for
- both HAVE_KERBEROS and AUTH_SERVER_SUPPORT
-
-Wed Aug 14 14:02:00 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * server.c (check_password): if available use getspnam instead of
- getpwnam when reading system passwords. This allows cvs pserver
- to run on systems with shadow passwords.
- (switch_to_user): new static function. Contains the extracted
- common tail of kserver_authenticate_connection and
- pserver_authenticate_connection. If compiled with SETXID_SUPPORT,
- honor the setgid bit if it is set.
- (check_repository_password): turn into a static function
- (check_password): ditto
- (pserver_authenticate_connection): little code cleanup
-
-Wed Aug 14 01:07:10 1996 Greg A. Woods <woods@most.weird.com>
-
- * history.c (history): apply fix posted by Steven Meyer
- <steve@blacksmith.com> to info-cvs to correct handling of '-D'
- argument. Message-Id: <9608122335.AA01385@nijel.blacksmith.com>
-
-Tue Aug 13 13:42:36 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * log.c (cvslog): Remove comment about calling rlog.
- * rcs.c (translate_symtag): Correct typo in comment (l ist ->
- list).
- * server.c (server_write_entries): Add omitted word (lists) in
- comment.
-
-Tue Aug 13 14:01:49 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * wrapper.c (wrap_rcsoption): fix memory access error
-
- * rcs.c (RCS_fast_checkout): fix memory access error (triggered
- by an empty option string)
-
-Mon Aug 12 17:45:15 1996 Jim Kingdon (unknown@beezley)
-
- * buffer.c, zlib.c: If EIO is not defined, try to define it.
-
-Mon Aug 12 10:33:27 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * import.c (comtable): Add comment concerning applicability with
- RCS 5.7.
-
- * server.c (server): If TMPDIR is not an absolute pathname, give
- an error.
-
-Mon Aug 12 10:34:43 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * main.c: add synonym "ann" for "annotate" again
-
-Sun Aug 11 17:54:11 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.h (RCS_RLOG): Removed; no longer used.
-
-Fri Aug 9 20:16:20 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * server.c (dirswitch): Open the Entries file with mode "a" rather
- than "w+".
- (server_write_entries): Open the Entries file with mode "a" rather
- than "w".
- * sanity.sh (modules): Add topfiles module and 155cN tests for
- above patch.
-
-Fri Aug 9 12:11:25 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (cmd): Add comment regarding synonyms.
-
-Thu Aug 8 14:40:10 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c: Remove synonyms for "cvs annotate". Synonyms create
- user confusion.
-
-Thu Aug 8 10:24:04 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * main.c: Revert (undocumented) change to rename the cvs history
- alias "his" to "hist"
-
-Wed Aug 7 18:26:25 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * server.c (cvs_output): Change str parameter to const char *.
- Correct loop to print from p, not str.
- (cvs_outerr): Likewise.
- * cvs.h (cvs_output, cvs_outerr): Update declarations.
-
- * server.c (receive_partial_file): Read and discard remaining file
- data on a write error.
- (serve_modified): Discard data while size > 0, not >=.
-
-Wed Aug 7 15:11:40 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * main.c (cmds): Add some aliases for "annotate".
- (usg): Improve usage message text
- (cmd_synonyms): New function to print the command synonym list
- (main): Add new option --help-synonyms
-
-Wed Aug 7 00:07:31 1996 Ian Lance Taylor <ian@cygnus.com>
-
- Keep track of subdirectories in the Entries file.
- * cvs.h (enum ent_type): Define.
- (struct entnode): Add type field.
- (struct stickydirtag): Add subdirs field.
- (Subdirs_Known, Subdir_Register, Subdir_Deregister): Declare.
- (ignore_files): Update declaration for new parameter.
- (FILESDONEPROC): Add entries parameter.
- (DIRENTPROC, DIRLEAVEPROC): Likewise.
- * entries.c (Entnode_Create): Add type parameter. Change all
- callers.
- (write_ent_proc): If closure is not NULL, treat it as a pointer to
- an int, and set it to 1 if a node is seen which is not ENT_FILE.
- (write_entries): If subdirectory information is known, but no
- subdirectories were written, write an unadorned D to the file.
- (Scratch_Entry): Write an R command to Entries.Log. Don't rewrite
- the Entries file.
- (Register): Set entfilename. Write an A command rather than an
- unadorned entries line.
- (fgetentent): Add cmd and sawdir parameters. Change all callers.
- If CMD is not NULL, expect and return a single character command.
- Handle an initial D by setting the type to ENT_SUBDIR.
- (fputentent): Output an initial D for an ENT_SUBDIR entry.
- (Entries_Open): Handle removal commands in Entries.Log. Record
- whether subdirectory information is known in the list private
- data.
- (Subdirs_Known): New function.
- (subdir_record): New static function.
- (Subdir_Register, Subdir_Deregister): New functions.
- * find_names.c (add_entries_proc): Skip entries that are not
- ENT_FILE.
- (add_subdir_proc): New static function.
- (register_subdir_proc): New static function.
- (Find_Directories): If the Entries file has subdirectory
- information, get the directories out of it. Otherwise, call
- find_dirs, and add the information to the Entries file.
- * recurse.c (struct frame_and_entries): Define.
- (do_recursion): Don't call Entries_Close until after processing
- dirlist. Pass entries to filesdoneproc. Pass a frame_and_entries
- structure to do_dir_proc via walklist.
- (do_dir_proc): Expect a frame_and_entries structure in closure,
- not a recursion_frame. Pass entries to direntproc and
- dirleaveproc.
- * ignore.c (ignore_files): Add entries parameter. Change all
- callers. If we have subdirectory information, check for
- directories in entries.
- * add.c (add): If client_active, call Subdir_Register on each new
- directory.
- (add_directory): Add entries parameter. Change caller. Call
- Subdir_Register.
- * checkout.c (build_dirs_and_chdir): Call Subdir_Register.
- * client.c (call_in_directory): Call Subdir_Register for newly
- created directories. Call Subdirs_Known or Find_Directories after
- calling Entries_Open.
- (process_prune_candidates): Call Subdir_Deregister.
- * commit.c (findmaxrev): Skip entries that are not ENT_FILE.
- * server.c (dirswitch): Call Subdir_Register.
- * update.c (update_dirent_proc): Call Subdir_Register.
- (update_dirleave_proc): Call Subdir_Deregister.
- * Several files: Change direntproc, dirleaveproc, and
- filesdoneproc routines to expect an entries argument.
-
- * rcs.c (translate_symtag): New static function.
- (RCS_gettag): Use translate_symtag rather than RCS_symbols.
- (RCS_nodeisbranch, RCS_whatbranch): Likewise.
-
-Tue Aug 6 15:36:09 1996 Ian Lance Taylor <ian@cygnus.com>
-
- Finish the conversion of cvs log so that it never invokes rlog.
- * log.c (struct log_data): Remove dorlog field. Add nameonly,
- header, long_header, statelist, and authorlist fields.
- (log_usage): Remove rlog-options. Add -R, -h, -t, -b, -s, -w.
- (cvslog): Don't clear opterr. Handle -h, -R, -s, -t, -w. If an
- unrecognized option is seen, call usage.
- (log_parse_list): New static function.
- (log_fileproc): Remove code that called rlog. Check nameonly,
- header, and long_header fields in log_data.
- (log_version_requested): Check statelist and authorlist.
-
- * log.c (struct datelist): Define.
- (struct log_data): Add datelist and singledatelist fields.
- (log_usage): Add -d.
- (cvslog): Handle -d.
- (log_parse_date): New static function.
- (log_fileproc): Do special single date handling.
- (log_version_requested): Check datelist and singledatelist.
- (log_fix_singledate): New static function.
-
-Mon Aug 5 23:48:16 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * log.c (struct option_revlist): Define.
- (struct revlist): Define.
- (struct log_data): Add default_branch and revlist fields.
- (struct log_data_and_rcs): Define.
- (log_usage): Add -N and -r.
- (cvslog): Handle -N and -r.
- (log_parse_revlist): New static function.
- (log_fileproc): Call log_expand_revlist and log_free_revlist.
- Pass log_data_and_rcs structure to log_count_print via walklist.
- (log_expand_revlist, log_free_revlist): New static functions.
- (log_version_requested): New static function.
- (log_count_print): New static function.
- (log_tree): Add log_data and revlist parameter. Change all
- callers.
- (log_abranch): Likewise.
- (log_version): Likewise. Call log_version_requested.
- (version_compare): New static function.
- * sanity.sh (log): New tests for -r, -b, and -N options to log.
-
-Sun Aug 4 11:19:30 1996 Ian Lance Taylor <ian@cygnus.com>
-
- Handle simple cases of cvs log without invoking rlog.
- * log.c (struct log_data): Define.
- (cvslog): Use getopt to parse options. Set up a log_data
- structure, and pass it to start_recursion.
- (log_fileproc): Get arguments form callerdat rather than static
- variables. In simple cases, print the log information directly,
- rather than invoking rlog.
- (log_symbol, log_count, log_tree): New static functions.
- (log_abranch, log_version, log_branch): New static functions.
- * rcs.h (struct rcsnode): Add other field.
- (struct rcsversnode): Add other field.
- (RCS_fully_parse): Declare.
- * rcs.c (getrcsrev): Move declaration to start of file.
- (RCS_reparsercsfile): Add all parameter. Change all callers.
- (RCS_fully_parse): New function.
- (freercsnode): Free other list.
- (rcsvers_delproc): Free other list.
- * hash.h (enum ntype): Add RCSFIELD.
- * hash.c (nodetypestring): Handle RCSFIELD.
-
-Sat Aug 3 19:39:54 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * log.c (cvslog): Correct position of CLIENT_SUPPORT #endif.
-
-Thu Jul 25 12:06:45 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * update.c (join_file): If merging a branch, and the branch
- revision does not exist, just return without doing anything.
- * sanity.sh (join): Add cases file7 and file8 to test above
- patch.
-
- * server.c (cvsencrypt): Rename from encrypt, to avoid conflict
- with NetBSD unistd.h. Rename all uses.
-
- * server.c (krb_encrypt_buffer_output): Fix typo in comment (reply
- -> replay).
-
-Thu Jul 25 10:37:32 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (krb_encrypt_buffer_output): Fix typo in comment
- (krb_recv_auth -> krb_recvauth).
-
-Wed Jul 24 09:28:33 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * lock.c (set_lock): Adjust comment regarding why we call stat.
-
-Wed Jul 24 15:06:08 1996 Ian Lance Taylor <ian@cygnus.com>
-
- Add encryption support over a Kerberos connection.
- * main.c (usg): Mention -x if CLIENT_SUPPORT.
- (main): Handle -x.
- * client.h (encrypt): Declare.
- (krb_encrypt_buffer_initialize): Declare.
- * client.c (kblock, sched): New static variables if
- HAVE_KERBEROS.
- (start_tcp_server): Remove sched local variable. Copy
- cred.session into kblock.
- (start_server): Turn on encryption if requested.
- * server.c (kblock, sched): New static variables if
- HAVE_KERBEROS.
- (serve_kerberos_encrypt): New static function.
- (requests): Add "Kerberos-encrypt" if HAVE_KERBEROS.
- (kserver_authenticate_connection): Remove sched local variable.
- Copy auth.session into kblock.
- (encrypt): New global variable.
- (struct krb_encrypt_buffer): Define.
- (krb_encrypt_buffer_initialize): New function.
- (krb_encrypt_buffer_input): New static function.
- (krb_encrypt_buffer_output): New static function.
- (krb_encrypt_buffer_flush): New static function.
- (krb_encrypt_buffer_block): New static function.
- (krb_encrypt_buffer_shutdown): New static function.
-
-Wed Jul 24 09:28:33 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * recurse.c (do_recursion): Add comment about calling
- Name_Repository in !(which & W_LOCAL) case.
-
- * expand_path.c (expand_variable): Fix typo (varaible -> variable).
-
-Tue Jul 23 15:05:01 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * update.c (update_fileproc): In T_REMOVE_ENTRY case, only call
- server_scratch_entry_only if ts_user is NULL.
- * sanity.sh (death2): Add death2-20 test for above patch.
-
- * diff.c (diff_fileproc): If a file is not in the working
- directory, check that the tag is present before warning that no
- comparison is possible.
- * sanity.sh (death2): Add death2-diff-9 and death2-diff-10 tests
- for above patch.
-
-Tue Jul 23 12:05:42 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * tag.c (tag_check_valid): Fix indentation.
-
- * client.c (handle_e): Flush stdout before writing to stderr.
- (handle_m): Flush stderr before writing to stdout.
-
-Fri Jul 19 16:02:11 1996 Mike Ladwig <mike@twinpeaks.prc.com>
-
- * client.c: Added NO_CLIENT_GZIP_PROCESS to deal with the MacOS
- client where Gzip-stream is supported, but "gzip-file-contents" is
- not.
-
-Fri Jul 19 16:02:11 1996 Mike Ladwig <mike@twinpeaks.prc.com>
-
- * repos.c: Fixed recent patch which added plain fopen rather than
- CVS_FOPEN
-
-Mon Jul 22 22:25:53 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * logmsg.c (tag): New static variable.
- (setup_tmpfile): Don't print the prefix before calling fmt_proc.
- Free tag if it is set.
- (find_type): Get type from logfile_info struct.
- (fmt_proc): Likewise. Print tag information. Handle all prefix
- printing.
- (revision): Remove static variable.
- (Update_Logfile): Remove xrevision parameter. Change all
- callers.
- (title_proc): Get type from logfile_info struct.
- (logfile_write): Remove revision parameter. Change all callers.
- * cvs.h (struct logfile_info): Define.
- (Update_Logfile): Update prototype.
- * commit.c (find_fileproc): Set logfile_info information.
- (check_fileproc): Likewise.
- (commit_filesdoneproc): Don't call ParseTag.
- (update_delproc): Free logfile_info information.
- * add.c (add_directory): Set logfile_info information.
- * import.c (import): Likewise.
-
- * tag.c (tag_check_valid): The special BASE and HEAD tags are
- always valid.
- * sanity.sh (basica): Add basica-6.3 test for above patch.
-
-Mon Jul 22 14:41:20 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (merge_file): Pass 0 not NULL to checkout_file (20 Jul
- 96 change changed other calls to checkout_file but missed this one).
-
-Sat Jul 20 00:21:54 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * update.c (join_file): Check whether the target of the merge is
- the same as the working file revision before checking whether the
- file was added during the merge.
-
- * update.c (scratch_file): Remove existing parameters, and add a
- single parameter of type struct file_info. Change all callers.
- Warn if unlink_file fails.
- (checkout_file): Remove resurrecting_out parameter. Add adding
- parameter. Change all callers. Remove joining code.
- (join_file): Remove resurrecting parameter. Rewrite to handle
- joining dead or added revisions.
- * classify.c (Classify_File): If there is no user file, and the
- RCS file is dead, return T_UPTODATE rather than T_CHECKOUT.
- * checkout.c (checkout_proc): Set W_ATTIC if there is a join tag.
- * sanity.sh (join): New set of tests for above patches.
- (death): Adjust tests 86, 89, 89a, 92.1c, 95 for above patches.
- (import): Adjust test 113 for above patches.
-
-Thu Jul 18 19:24:08 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * lock.c: Add comment explaining what locks are for. Also discuss
- various changes to locking which get proposed from time to time.
-
- * sanity.sh (death2): Change a number of test names from death-*
- to death2-*.
-
- * wrapper.c (wrap_setup): Don't look in repository if client_active.
- * wrapper.c, cvs.h (wrap_send): New function.
- * update.c (update), import.c (import): Call it.
- * sanity.sh (binwrap): Do binwrap tests for remote as well as
- local; tests for above fixes.
-
- * wrapper.c: Add a few FIXME comments.
-
-Thu Jul 18 18:43:50 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * sanity.sh (patch): Fix names of a couple of tests to say patch
- rather than death2.
-
-Thu Jul 18 16:19:21 1996 Bill Bumgarner <bbum@friday.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c (add), import.c (add_rcs_file): Check for options from
- wrappers and use them if specified.
- * cvs.h (WrapMergeHas): Add WRAP_RCSOPTION.
- * wrapper.c (WrapperEntry): Add rcsOption field.
- (wrap_add): Allow a single character argument to an option.
- (wrap_add): Handle -k option.
- (wrap_add_entry): Handle rcsOption field.
- (wrap_name_has): Handle WRAP_RCSOPTION.
- * wrapper.c, cvs.h (wrap_rcsoption): New function.
- * add.c, import.c, wrapper.c: Minor beautification (mostly
- removing trailing spaces).
- * sanity.sh (binwrap): New tests test for this feature.
-
-Wed Jul 17 10:14:20 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * checkout.c (checkout): Remove extraneous else accidentally
- inserted in last checkin.
-
-Tue Jul 16 11:37:41 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * sanity.sh (import): Use quoting to avoid expansion of RCS ID
- strings.
-
- * sanity.sh (import): Use dotest to examine the output of test
- 113, and the actual contents of the file in test 116.
-
- * update.c (join_file): Always skip rcsmerge if the two revisions
- are the same (the old code always did the rcsmerge when two -j
- options were specified).
-
- * checkout.c (history_name): New static variable.
- (checkout): Permit both tag and date to be specified. Set
- history_name.
- (checkout_proc): Use history_name when calling history_write.
- * rcs.c (RCS_getversion): If both tag and date are set, use
- RCS_whatbranch to get the branch revision number of a symbolic
- tag.
- (RCS_getdatebranch): If the branch revision itself is early
- enough, then use it if the first branch is not early enough. Add
- comment for invalid RCS file. Don't bother to check for NULL
- before calling xstrdup, since xstrdup checks anyhow.
-
- * client.h (file_gzip_level): Declare.
- * client.c (file_gzip_level): Define.
- (start_server): Don't set gzip_level to zero after sending
- Gzip-stream command. Set file_gzip_level after sending
- gzip-file-contents command.
- (send_modified): Use file_gzip_level rather than gzip_level.
- * server.c (server_updated): Likewise.
- (serve_gzip_contents): Likewise.
-
- * sanity.sh (patch): New tests. Test remote CVS handling of
- unpatchable files.
-
- * sanity.sh (death2): Accept a '.' in the temporary file name
- printed by diff.
-
- * rcscmds.c (RCS_checkin): Remove noerr parameter. Change all
- callers.
- * cvs.h (RCS_checkin): Update declaration.
- * commit.c (remove_file): Pass RCS_FLAGS_QUIET to RCS_checkin.
-
- * history.c (history): Cast sizeof to int to use correct type in
- error printf string.
- (report_hrecs): Cast strlen result to int to use correct type in
- printf string.
-
- * server.c (cvs_flusherr): Correct typo in comment.
-
- * rcs.c (getrcskey): Hoist three constant strcmp calls out of the
- value reading loop.
-
- * fileattr.c (fileattr_get): Change parameter types from char * to
- const char *.
- (fileattr_get0, fileattr_modify, fileattr_set): Likewise.
- (fileattr_newfile): Likewise.
- * fileattr.h (fileattr_get): Update declaration.
- (fileattr_get0, fileattr_modify, fileattr_set): Likewise.
- (fileattr_newfile): Likewise.
-
-Thu May 16 11:12:18 1996 Mark P. Immel <immel@radix.net>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.h, client.c, checkout.c (client_send_expansions):
- Pass an additional parameter indicating where the checkout is
- to occur, to avoid passing the wrong information to send_files().
- * sanity.sh (basicb): New test basicb-cod-1 tests for above fix.
-
-Mon Jul 15 18:26:56 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * recurse.c (do_recursion): Require a repository before calling
- Find_Names.
- * repos.c (Name_Repository): Remove sanity checks which spend time
- examining the filesystem.
-
-Mon Jul 15 1996 Jim Kingdon <kingdon@cyclic.com>
-
- * client.c (send_file_names): Send file names as they appear
- in CVS/Entries, rather than as specified (in cases where they
- might differ in case).
- (send_fileproc): Use file name from CVS/Entries (vers->entdata->user)
- rather than file name as specified (finfo->file) when available.
-
-Sun Jul 14 15:39:44 1996 Mark Eichin <eichin@cygnus.com>
- and Ian Lance Taylor <ian@cygnus.com>
-
- Improve diff -N handling of nonexistent tags and removed files.
- * diff.c (enum diff_file): New definition for whole file, moving
- unnamed enum out of diff_fileproc, renaming DIFF_NEITHER to
- DIFF_DIFFERENT, and adding DIFF_SAME.
- (diff): Look through the repository even if only one revision is
- given.
- (diff_fileproc): Change empty_file to be enum diff_file. If there
- is no user revision, but there is a repository file, treat it as a
- removed file. Pass empty_file to diff_file_nodiff, and set it
- from the return value.
- (diff_file_nodiff): Change return type to enum diff_file. Replace
- just_set_rev parameter with enum diff_file empty_file parameter.
- Change handling of a missing tag to return an enum diff_file value
- if empty_files is set, rather than reporting an error. Free tmp
- if xcmp returns 0.
- * sanity.sh (death2): Add tests for above patches.
-
-Sat Jul 13 19:11:32 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (annotate): In sending options to server, reverse sense of
- test so that we send -f iff -f was specified, rather than iff -f was
- not specified.
-
-Fri Jul 12 20:23:54 1996 Greg A. Woods <woods@most.weird.com>
-
- * zlib.c (compress_buffer_input): add a couple of casts for
- uses of z_stream's next_in and next_out
-
-Fri Jul 12 18:55:26 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * zlib.c: New file.
- * client.c (log_buffer_block): Call set_block and set_nonblock,
- rather than lb->buf->block.
- (log_buffer_shutdown): New static function.
- (get_responses_and_close): Call buf_shutdown on to_server and
- from_server.
- (start_server): If "Gzip-stream" is supported, use it rather than
- "gzip-file-contents".
- * server.c (print_error): Call buf_flush rather than
- buf_send_output.
- (print_pending_error, serve_valid_responses): Likewise.
- (serve_expand_modules, serve_valid_requests): Likewise.
- (do_cvs_command): Call buf_flush rather than buf_send_output
- before the fork, and in the parent after the child has completed.
- In the child, set buf_to_net and buf_from_net to NULL.
- (serve_gzip_stream): New static function.
- (requests): Add "Gzip-stream".
- (server_cleanup): Don't do anything with buf_to_net if it is
- NULL. Call buf_flush rather than buf_send_output. Call
- buf_shutdown on buf_to_net and buf_from_net. Call error for an
- malloc failure rather than buf_output to buf_to_net.
- * buffer.h (struct buffer): Add shutdown field.
- (buf_initialize): Update declaration for new shutdown parameter.
- (compress_buffer_initialize): Declare.
- (buf_shutdown): Declare.
- * buffer.c (buf_initialize): Add shutdown parameter. Change all
- callers.
- (buf_shutdown): New function.
- * Makefile.in (SOURCES): Add zlib.c
- (OBJECTS): Add zlib.o.
- ($(PROGS)): Depend upon ../zlib/libz.a.
- (cvs): Link against ../zlib/libz.a.
- (zlib.o): New target.
-
-Fri Jul 12 1996 Jim Kingdon <kingdon@cyclic.com>
-
- * client.c (log_buffer_input, log_buffer_output): Use size_t
- to avoid Visual C++ signed/unsigned warnings.
-
-Thu Jul 11 22:01:37 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (handle_f): Reindent.
-
- * client.c (mode_to_string, handle_m, handle_e,
- auth_server_port_number, get_responses_and_close), server.c
- (pserver_authenticate_connection, serve_modified,
- serve_enable_unchanged, wait_sig, server_cleanup): Reindent.
- * server.c: Remove #if 0'd block of code above
- check_repository_password; it was yanked out of some unknown
- context and didn't seem to be very useful.
-
-Thu Jul 11 20:10:21 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * server.c (do_cvs_command): Pass new special parameter to
- buf_copy_counted. If it gets set to -1, send an 'F' response if
- the client supports it, and call cvs_flusherr.
- (cvs_flusherr): New function.
- * cvs.h (cvs_flusherr): Declare.
- * client.c (handle_f): New static function.
- (responses): Add "F".
- * buffer.c (buf_send_special_count): New function.
- (buf_copy_counted): Add special parameter. Handle negative counts
- specially.
- * buffer.h (buf_send_sepcial_count): Declare.
- (buf_copy_counted): Update declaration.
- * lock.c (lock_wait, lock_obtained): Call cvs_flusherr.
-
- Change the client to use the buffer data structure.
- * client.c: Include "buffer.h".
- (to_server): Change to be struct buffer *.
- (to_server_fp): New static variable.
- (from_server): Change to be struct buffer *.
- (from_server_fp): New static variable.
- (from_server_logfile, to_server_logfile): Remove.
- (buf_memory_error): New static function.
- (struct log_buffer): Define.
- (log_buffer_initialize, log_buffer_input): New static functions.
- (log_buffer_output, log_buffer_flush): New static functions.
- (log_buffer_block): New static function.
- (struct socket_buffer): Define if NO_SOCKET_TO_FD.
- (socket_buffer_initialize): New static function if
- NO_SOCKET_TO_FD.
- (socket_buffer_input, socket_buffer_output): Likewise.
- (socket_buffer_flush): Likewise.
- (read_line): Rewrite to use buf_read_line. Remove eof_ok
- parameter (it was always passed as 0); change all callers.
- (send_to_server): Rewrite to use buf_output.
- (try_read_from_server): Rewrite to use buf_read_data.
- (get_responses_and_close): Use from_server_fp and to_server_fp for
- the streams. Check buf_empty_p when checking for dying gasps.
- (start_server): Don't set from_server_logfile and
- to_server_logfile; instead, call log_buffer_initialize. If
- NO_SOCKET_TO_FD and use_socket_style, call
- socket_buffer_initialize; otherwise, call
- stdio_buffer_initialize.
- * buffer.c: Compile if CLIENT_SUPPORT is defined.
- (buf_flush): Fix comment to describe return value.
- (buf_read_line): Add lenp parameter. Change all callers. Look
- for a line terminated by \012 rather than \n.
- * buffer.h: Compile if CLIENT_SUPPORT is defined.
- (buf_read_line): Update declaration.
-
- * server.c (server): Initialize buf_to_net, buf_from_net,
- saved_output, and saved_outerr before setting error_use_protocol.
- (pserver_authenticate_connection): Don't set error_use_protocol.
- Errors before the authentication is complete aren't handled
- cleanly anyhow. Change error call after authentication to use
- printf.
-
-Thu Jul 11 1996 Jim Kingdon <kingdon@cyclic.com>
-
- * client.c (start_server): Open logfiles in binary, not text, mode.
-
-Wed Jul 10 19:24:22 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (print_pending_error, print_error): Remove comments
- about deadlocks; they don't apply here. Add comments saying
- that these functions must only be called when it is OK to
- send output (which is why the deadlock concern doesn't apply). The
- comments remain for server_cleanup and serve_valid_responses,
- where they are an example of the "print a message and exit"
- behavior which is noted in cvsclient.texi and which also exists
- places like kserver_authenticate_connection.
-
-Wed Jul 10 18:24:46 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * server.c (print_error): Add comment warning about potential
- deadlock.
- (print_pending_error, serve_valid_responses): Likewise.
- (server_cleanup): Likewise.
- (serve_directory): Don't call buf_send_output.
- (serve_modified, serve_notify, server, cvs_outerr): Likewise.
- (serve_expand_modules): Call buf_send_output.
- (serve_valid_requests): Likewise.
-
-Wed Jul 10 15:51:29 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (main): Print a warning for rlog command.
-
-Wed Jul 10 15:00:55 1996 Ian Lance Taylor <ian@cygnus.com>
-
- Abstract the buffer data structure away from the underlying
- communication medium.
- * buffer.h (struct buffer): Remove fd and output fields. Add
- input, output, flush, block, and closure fields.
- (buf_initialize, buf_nonio_initialize): Declare.
- (stdio_buffer_initialize, buf_flush): Declare.
- (buf_read_line, buf_read_data): Declare.
- * buffer.c: Include <assert.h>. Don't include <fcntl.h>.
- (O_NONBLOCK, blocking_error): Don't define.
- (buf_initialize, buf_nonio_initialize): New functions.
- (buf_send_output): Use output function, rather than write.
- (buf_flush): New function.
- (set_nonblock, set_block): Use block function, rather than calling
- fcntl.
- (buf_send_counted): Don't check output.
- (buf_input_data): Call input function, rather than read.
- (buf_read_line, buf_read_data): New functions.
- (buf_copy_lines, buf_copy_counted): Don't check output.
- (stdio_buffer_initialize): New function.
- (stdio_buffer_input, stdio_buffer_output): New static functions.
- (stdio_bufer_flush): New static function.
- * server.c: Include "getline.h".
- (buf_to_net): Change to be a pointer. Change all uses.
- (protocol, saved_output, saved_outerr): Likewise.
- (buf_from_net): New static variable.
- (no_mem_error, NO_MEM_ERROR, read_line): Remove.
- (struct fd_buffer): Define.
- (fd_buffer_initialize, fd_buffer_input): New static functions.
- (fd_buffer_output, fd_buffer_flush): New static functions.
- (fd_buffer_block): New static function.
- (serve_directory): Call buf_read_line rather than read_line.
- (serve_notify, server): Likewise.
- (receive_partial_file): Call buf_read_data rather than fread.
- (serve_modified): Call buf_read_line rather than read_line. Call
- buf_read_data rather than fread.
- (do_cvs_command): Initialize buffers with fd_buffer_initialize.
- Change stdoutbuf, stderrbuf, and protocol_inbuf to be pointers.
- (server): Initialize buffers using fd_buffer_initialize,
- stdio_buffer_initialize, and buf_nonio_initialize.
- (check_repository_password): Call getline rather than read_line.
-
-Wed Jul 10 15:51:29 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c (find_fileproc): Add comments describing a few cases
- that we aren't handling.
-
-Tue Jul 9 04:33:03 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_deltas): New function, created from guts of old
- annotate_fileproc.
- (annotate_fileproc): Call RCS_deltas.
- (RCS_fast_checkout): Call it (commented out for now; see comment
- for reasons).
-
- * cvs.h, recurse.c (start_recursion): Add callerdat argument.
- * cvs.h: Add callerdat argument to recursion processor callbacks.
- * recurse.c: add it to struct recursion_frame and pass it to all
- the callbacks.
- * admin.c, client.c, commit.c, diff.c, edit.c, lock.c, log.c,
- patch.c, rcs.c, remove.c, rtag.c, status.c, tag.c, update.c,
- watch.c: Update all the functions used as callbacks. Update calls
- to start_recursion.
- * commit.c (find_filesdoneproc, find_fileproc, find_dirent_proc,
- commit), tag.c (val_fileproc, tag_check_valid): Use callerdat
- instead of a static variable.
-
- * recurse.c (do_recursion): Make static and move declaration to here...
- * cvs.h: ...from here.
- * recurse.c (do_recursion): Replace plethora of arguments with
- single struct recursion_frame *. Change callers.
- * recurse.c: New structure frame_and_file. Use it and existing
- struct recursion_frame structures to pass info to do_file_proc and
- do_dir_proc. Remove globals fileproc, filesdoneproc, direntproc,
- dirleaveproc, which, flags, aflag, readlock, and dosrcs.
-
-Tue Jul 9 11:13:29 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * modules.c (do_module): Call cvs_outerr rather than fprintf.
-
-Mon Jul 8 1996 Jim Kingdon <kingdon@cyclic.com>
-
- * rcs.c (RCS_fast_checkout): If -kb is not in use, open the
- working file in text, not binary, mode.
-
-Sun Jul 7 10:36:16 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcscmds.c (RCS_settag): Add comment regarding moving check for
- reserved tag names to RCS_check_tag.
-
- * rcscmds.c: Add comment regarding librarifying RCS and related
- issues. This is a lightly edited version of a message I sent to
- the CVS developers and didn't get flamed for, so it would appear
- to be relatively uncontroversial.
-
- * rcs.c (annotate): Remove comment suggesting -r option and
- related functionality; it is done.
-
-Fri Jul 5 17:19:57 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * client.c (last_entries): Make file static, rather than function
- static within call_in_directory.
- (get_responses_and_close): If last_entries is not NULL, pass it to
- Entries_Close.
-
- * server.c (server_pause_check): Check for errors when reading
- from flowcontrol_pipe.
-
- * client.c (call_in_directory): If dir_name is ".", call
- Create_Admin if there is no CVS directory.
- (send_dirent_proc): If there is no CVS subdirectory, pretend that
- the directory does not exist (i.e., don't try to send any files in
- the directory).
- * server.c (dirswitch): If dir is "." in the top level repository,
- add "/." after the Repository entry.
- * sanity.sh (modules): Add test 155b for above patches.
-
-Thu Jul 4 15:57:34 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * server.c (buf_to_net): Move definition near top of file.
- (read_line): Call buf_send_output rather than fflush.
- (print_error): Output information to buf_to_net buffer rather than
- stdout.
- (print_pending_error, serve_valid_responses): Likewise.
- (server_notify, do_cvs_command, server_co): Likewise.
- (expand_proc, serve_expand_modules, server_prog): Likewise.
- (serve_valid_requests, server_cleanup, server): Likewise.
- (server_notify): Don't call fflush on stdout.
- (do_cvs_command): Flush saved_output and saved_outerr to
- buf_to_net before fork. Flush buf_to_net before fork. In child,
- just initialize memory_error field of saved_output and
- saved_outerr.
- (server_cleanup): Flush buf_to_net.
- (server): Initialize saved_output and saved_outerr.
- (cvs_output): Add support for error_use_protocol case.
- (cvs_outerr): Likewise.
- * error.c (error): In HAVE_VPRINTF case, just call cvs_outerr.
-
- * buffer.c: New file; buffer support functions taken from
- server.c.
- * buffer.h: New file; declarations for buffer.c.
- * server.c: Move buffer support functions into buffer.c and
- buffer.h. Include "buffer.h".
- * Makefile.in (SOURCES): Add buffer.c.
- (OBJECTS): Add buffer.o.
- (HEADERS): Add buffer.h.
-
-Thu Jul 4 00:12:45 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Increment version number to 1.8.6.
-
-Wed Jul 3 22:31:16 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Version 1.8.5.
-
-Wed Jul 3 21:51:23 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * server.c (blocking_error): Define macro.
- (buf_send_output, buf_input_data): Use blocking_error rather than
- #ifdef EWOULDBLOCK.
-
-Tue Jul 2 20:38:41 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c (add): Change message which said "version 1.2 of foo.c
- will be resurrected"; the message was confusing because it made
- people think that the old contents of the file would come back
- instead of the contents in the working directory.
-
-Mon Jul 1 01:38:57 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * find_names.c (find_dirs): Add comment explaining why we bother
- with the entries stuff.
-
-Sat Jun 29 20:23:50 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * find_names.c (Find_Directories): Add entries parameter, and pass
- it to find_dirs.
- (find_dirs): Add entries parameter, and skip all files it names.
- * cvs.h (Find_Directories): Update declaration.
- * recurse.c (start_recursion): Pass NULL to Find_Directories.
- (do_recursion): Pass entries to Find_Directories.
-
- * client.c (send_modified): Add trace output.
-
- * diff.c (diff_fileproc): Always call diff_file_nodiff. Handle
- dead versions correctly. Handle diffs between a specified
- revision to a dead file correctly.
- (diff_file_nodiff): Add just_set_rev parameter. Change caller.
- * patch.c (patch_fileproc): Check for dead versions.
- * sanity.sh (death2): Add tests for above patches.
-
-Fri Jun 28 20:30:48 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- For reference, this takes CVS's text segment from 271136 bytes to
- 270352 bytes, a saving of 784. Not as good as I had hoped (oh well,
- the source *seems* simpler at least).
- * checkin.c (Checkin), commit.c (finaladd, remove_file), update.c
- (join_file, checkout_file, patch_file), no_diff.c
- (No_Differences), server.c (server_updated), classify.c
- (Classify_File), vers_ts.c (Version_TS), diff.c (diff_file_nodiff):
- Use a single struct file_info * argument instead of a bunch of
- separate arguments for each of its fields. Remove local fullname
- emulations. Use fullname in error messages where file had
- erroneously been used.
- * cvs.h: Update declarations of above functions and move them to
- after the struct file_info declaration.
- * server.h: Update declarations.
- * add.c, admin.c, checkin.c, checkout.c, classify.c, client.c,
- commit.c, diff.c, history.c, import.c, update.c, status.c,
- remove.c, rtag.c, tag.c: Change callers.
-
- * diff.c (diff): Remove -q and -Q command options. This somehow
- slipped through the cracks of the general removal of -q and -Q
- command options on Jul 21 1995. Note that there is no need to
- accept and ignore these options in server mode, like there is for
- some of the commands, because the client has never sent -q and -Q
- command options for "cvs diff".
-
-Fri Jun 28 16:50:18 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * add.c (add): Pass force_tag_match as 1 when calling Version_TS.
- * sanity.sh (death2): Add test for above patch. Also add
- commented out test for adding a file on a nonbranch tag, which CVS
- currently, mistakenly, permits.
-
-Thu Jun 27 23:20:49 1996 Ian Lance Taylor <ian@cygnus.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * diff.c (longopts): New static array.
- (diff): Handle long options and new short options in diff 2.7.
- Fix arbitrary limit associated with the tmp variable.
- * client.c (send_option_string): Parse options as space separated,
- rather than requiring all options to be single characters.
- * diff.c, options.h.in: Remove CVS_DIFFDATE; the need for it is gone
- now that we have --ifdef (the new behavior is the behavior which
- was the default, which is that -D specifies a date).
-
-Wed Jun 26 22:36:29 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * commit.c (check_fileproc): If there is a tag, permit adding a
- file even if the RCS file already exists.
- (checkaddfile): If there is a tag, use the file in the regular
- repository, rather than the Attic, if it exists.
- * sanity.sh (death2): New set of tests for above patch.
-
-Tue Jun 25 23:34:13 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (checkout_file): Add comments about two cases which
- seem fishy.
-
- * sanity.sh (basic2, death): Add comments encouraging people to
- stop making these sections bigger and more complex. I'm not (yet
- at least) trying to figure out the ideal size for a section (my
- current best estimate is 10-20 tests), but surely these
- two sections are pushing the limit, whatever it is.
-
-Tue Jun 25 19:52:02 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * update.c (checkout_file): Rewrite handling of dead files when
- joining. Avoid space leaks. Avoid unnecessary file
- resurrections.
- (join_file): Add checks to skip merging a dead revision onto a
- dead revision, and to skip merging a common ancestor onto a dead
- revision. Move check for non-existent working file after new
- checks.
- * sanity.sh (death): Use dotest for tests 86 and 95, and add test
- death-file2-1, to test above changes.
-
-Mon Jun 24 11:27:37 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (merge_file): Replace file, repository, entries, and
- update_dir arguments with finfo argument. Use fullname field
- instead of locally emulating it.
- (update_fileproc): Update caller.
- (merge_file): If -kb is in effect, call it a conflict, leave
- the two versions in the file and the backup file, and tell the
- user to deal with it. The previous behavior was that the merge
- would fail and then there was no way to do a checkin even once you
- resolved the conflict (short of kludges like moving the file
- aside, updating, and then moving it back).
- * sanity.sh (binfiles): New tests binfiles-con* test for above
- behavior. Adjust remaining tests to reflect changes in revision
- numbers.
-
-Mon Jun 17 15:11:09 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * sanity.sh (import): Remove sleep. Requiring it was a bug, and
- it is fixed in the current sources.
-
-Mon Jun 17 1996 Ian Lance Taylor <ian@cygnus.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (TMPPWD): Set to real name of /tmp directory.
- (basic2-64, conflicts-126.5): Use ${TMPPWD}.
-
-Mon Jun 17 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * rcscmds.c (RCS_checkout): Remove noerr parameter. Change all
- callers.
- * rcs.c (RCS_fast_checkout): Likewise.
-
-Mon Jun 17 1996 Ian Lance Taylor <ian@cygnus.com>
-
- Cleaner implementation of tag locking code added Jun 13 1996:
- * cvs.h (tag_lockdir, tag_unlockdir): Declare.
- * rtag.c (locked_dir, locked_list): Remove.
- (rtag_fileproc): Don't lock here; just call tag_lockdir.
- (rtag_filesdoneproc): Don't unlock here; just call tag_unlockdir.
- * tag.c (locked_dir, locked_list): Move farther down in file.
- (tag_fileproc): Don't lock here; just call tag_lockdir.
- (tag_filesdoneproc): Don't unlock here; just call tag_unlockdir.
- (tag_lockdir, tag_unlockdir): New functions.
-
-Wed Jun 15 07:52:22 1996 Mike Ladwig <mike@twinpeaks.prc.com>
-
- * client.c (send_modified, update_entries): Fixed bug which didn't
- handle binary file transfers in BROKEN_READWRITE_CONVERSION.
-
-Thu Jun 13 1996 Ian Lance Taylor <ian@cygnus.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (checkout_file): Call server_scratch_entry_only when a
- non-pertinent file is found that does not exist.
- * sanity.sh (newb): Add test case for above patch.
-
-Thu Jun 13 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * update.c (update_fileproc): Call server_scratch_entry_only when
- handling T_REMOVE_ENTRY on the server.
- * sanity.sh (conflicts2): Remove special case for remote server
- bug fixed by above patch.
-
-Thu Jun 13 21:16:26 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basica-9): Update to reflect change to "sufficient
- access" message.
-
-Thu Jun 13 20:13:55 1996 Ian Lance Taylor <ian@cygnus.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * recurse.c, cvs.h (start_recursion): Remove wd_is_repos argument;
- add comment about meaning of which argument. Use !(which &
- W_LOCAL) instead of wd_is_repos.
- * admin.c, client.c, commit.c, diff.c, edit.c, lock.c, log.c,
- patch.c, rcs.c, remove.c, rtag.c, status.c, tag.c, update.c,
- watch.c: Change callers. This is a semantic change in only two
- cases: (1) tag_check_valid, where repository was not "", and (2)
- the pipeout case in checkout_proc. In both of those cases the
- previous setting of wd_is_repos did not reflect whether we
- actually were cd'd into the repository.
- * recurse.c (start_recursion): Only check for the CVS subdirectory
- if which & W_LOCAL.
- * sanity.sh (devcom): Add test case fixed by above patch.
-
-Thu Jun 13 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * ignore.c (ignore_files): Skip based on the file name before
- calling lstat.
-
- * client.c (last_register_time): New static variable.
- (update_entries): Set last_register_time when calling Register.
- (get_responses_and_close): If the current time is the same as
- last_register_time, sleep for a section to avoid timestamp races.
-
-Thu Jun 13 17:24:38 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (supported_request): Reindent.
-
-Thu Jun 13 1996 Mark H. Wilkinson <mhw@minster.york.ac.uk>
-
- * options.h.in, mkmodules.c: Corrections to allow compilation of
- non-client-server version.
-
-Thu Jun 13 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * tag.c (tag_check_valid_join): New function.
- * cvs.h (tag_check_valid_join): Declare.
- * checkout.c (join_tags_validated): New static variable.
- (checkout_proc): Check validity of join tags.
- * update.c (update): Likewise.
-
- * tag.c (tag_check_valid): Correct sizeof CVSROOTADM_HISTORY to
- use CVSROOTADM_VALTAGS.
-
- * lock.c (Writer_Lock): If we called lock_wait to wait for a lock,
- then call lock_obtained when we get it.
- (set_lock): Likewise.
- (lock_obtained): New static function.
-
-Thu Jun 13 13:55:38 1996 Ian Lance Taylor <ian@cygnus.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (main): If we can't read cvs root, don't say "you don't
- have sufficient access"; just print the message from errno. It
- might be "No such file or directory" or something else for which
- "you don't have sufficient access" doesn't make any sense.
-
-Thu Jun 13 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * commit.c (remove_file): Pass noerr as 0 to RCS_checkout.
-
-Thu Jun 13 12:55:56 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * patch.c: Initialize rev1_validated and rev2_validated to 0, not 1.
-
-Thu Jun 13 12:55:56 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rtag.c (locked_dir): Revise comments regarding locking; the rtag
- and tag situations are different (changing from readlocking one
- directory at a time to writelocking one directory at a time does
- not do everything we might want, but it does fix simultaneous tags
- and it doesn't make anything worse).
-
-Thu Jun 13 1996 Ian Lance Taylor <ian@cygnus.com>
-
- Prevent simultaneous tag operations from interfering with each
- other.
- * rtag.c (rtag_proc): Pass rtag_filesdoneproc to start_recursion,
- and pass readlock as 0.
- (locked_dir, locked_list): New static variables.
- (rtag_fileproc): Write lock the repository if it is not already
- locked.
- (rtag_filesdoneproc): New static function to unlock the
- repository.
- * tag.c (tag): Pass tag_filesdoneproc to start_recursion, and pass
- readlock as 0.
- (locked_dir, locked_list): New static variables.
- (tag_fileproc): Write lock the repository if it is not already
- locked.
- (tag_filesdoneproc): New static function.
-
-Thu Jun 13 11:42:25 1996 Mike Sutton <mws115@llcoolj.dayton.saic.com>
-
- * sanity.sh: Allow digits in usernames.
-
-Wed Jun 12 16:23:03 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (send_modified, update_entries): Reindent and add
- comments to BROKEN_READWRITE_CONVERSION code.
-
-Wed Jun 12 16:23:03 1996 Mike Ladwig <mike@twinpeaks.prc.com>
-
- * client.c (send_modified, update_entries): Add
- BROKEN_READWRITE_CONVERSION code.
-
-Mon Jun 10 20:03:16 1996 J.T. Conklin <jtc@cygnus.com>
-
- * rcs.c (RCS_gettag): No longer set p to NULL if rcs is also NULL.
- rcs will never be null, thanks to the assertion at top of function.
-
-Mon Jun 10 16:28:14 1996 Ian Lance Taylor <ian@cygnus.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (main): Ignore CVS/Root file when doing an import.
-
-Fri Jun 7 18:20:01 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * status.c (status_fileproc, tag_list_proc): Use cvs_output rather
- than writing to stdout directly.
-
-Wed Jun 5 13:54:57 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (force_tag_match, tag, date): New static variables.
- (annotate_fileproc): Redo the loop to look for the version
- specified by tag/date/force_tag_match, and handle branches
- correctly.
- (annotate_usage): Mention -f, -r, and -D.
- (annotate): Handle -f, -r, and -D.
-
-Tue Jun 4 13:38:17 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (annotate_fileproc): Skip unrelated branch deltas.
-
-Fri Jun 7 13:04:01 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (main): Change INITIALIZE_SOCKET_SUBSYSTEM to
- SYSTEM_INITIALIZE and pass it pointers to argc and argv. Rename
- CLEANUP_SOCKET_SUBSYSTEM to SYSTEM_CLEANUP.
-
-Wed Jun 05 10:07:29 1996 Mike Ladwig <mike@twinpeaks.prc.com>
-
- * import.c (add_rcs_file): make buf char[] not unsigned char[]
-
-Wed Jun 05 10:07:29 1996 Mike Ladwig <mike@twinpeaks.prc.com>
- and Jim Kingdon <kingdon@cyclic.com>
-
- * main.c (main): Add CLEANUP_SOCKET_SUBSYSTEM hook at end. Revise
- comments regarding INITIALIZE_SOCKET_SUBSYSTEM.
-
-Wed Jun 05 10:07:29 1996 Mike Ladwig <mike@twinpeaks.prc.com>
- and Jim Kingdon <kingdon@cyclic.com>
-
- * main.c (main): Don't mess with signals if DONT_USE_SIGNALS is
- defined.
-
-Thu Jun 6 15:32:41 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * modules.c (cat_module): Always format for 80 columns rather than
- trying to determine how wide the screen is. The code we had for
- the latter didn't cover all cases, was a portability headache, and
- didn't work client/server.
-
-Wed Jun 05 10:07:29 1996 Mike Ladwig <mike@twinpeaks.prc.com>
-
- * error.c: Don't declare strerror if it is #defined.
-
-Wed Jun 05 10:07:29 1996 Mike Ladwig <mike@twinpeaks.prc.com>
- and Jim Kingdon <kingdon@cyclic.com>
-
- * cvs.h: If ENUMS_CAN_BE_TROUBLE, typedef Dtype to int not an enum.
-
-Wed Jun 05 10:07:29 1996 Mike Ladwig <mike@twinpeaks.prc.com>
- and Jim Kingdon <kingdon@cyclic.com>
-
- * update.c (update): If DONT_USE_PATCH, don't request patches.
- Also call supported_request rather than reimplementing it.
-
-Wed Jun 05 10:07:29 1996 Mike Ladwig <mike@twinpeaks.prc.com>
-
- * client.c (read_line): Changed an occurence of '\n' to '\012'.
-
-Wed Jun 5 17:18:46 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c (add_directory): Don't create the directory if noexec.
- * sanity.sh (basica): New tests basica-1a10, basica-1a11 test for
- above fix.
- * sanity.sh (basicb): New tests basicb-2a10, basicb-2a11,
- basicb-3a1 test for analogous situation with files rather than
- directories.
-
-Tue Jun 4 13:38:17 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * sanity.sh: When doing a remote check, use :server: in CVSROOT.
-
-Wed Jun 5 13:32:40 1996 Larry Jones <larry.jones@sdrc.com>
- and Jim Kingdon <kingdon@cyclic.com>
-
- * ignore.c: Set ign_hold to -1 when not holding instead of 0 so
- that holding an empty list works correctly.
- * sanity.sh (ignore): New tests 190 & 191 for above fix.
-
-Wed Jun 5 1996 Jim Kingdon <kingdon@cyclic.com>
-
- Visual C++ lint:
- * client.c (update_entries): Copy the size to an unsigned variable
- before comparing it with unsigned variables.
- (handle_created, handle_update_existing): Prototype.
-
-Tue Jun 4 10:02:44 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (responses): Add Created and Update-existing responses.
- * server.c (server_updated): If they are supported, use them
- instead of Updated.
- * client.c (struct update_entries_data): Add existp field.
- (handle_checked_in, handle_updated, handle_new_entry,
- handle_merged, handle_patched): Set it.
- (handle_update_existing, handle_created): New functions,
- for new responses.
- (update_entries): Based on existp, check for
- existence/nonexistence of file.
- (try_read_from_server): Expand comment.
- * server.c, server.h (server_updated): New argument vers.
- * checkin.c (Checkin), commit.c (commit_fileproc), update.c
- (update_fileproc, merge_file, join_file): Pass it.
- * cvs.h: Move include of server.h after Vers_TS declaration.
- * sanity.sh (conflicts2): New tests conflicts2-142d* test for
- above fix.
-
- * sanity.sh (ignore): Fix typo in comment.
-
- * tag.c (tag_check_valid): Add comment clarifying when val-tags
- entries are created.
-
-Mon Jun 3 07:26:35 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Increment version number to 1.8.4.
-
-Mon Jun 3 02:20:30 1996 Noel Cragg <noel@gargle.rain.org>
-
- * version.c: version 1.8.3.
-
-Thu May 30 10:07:24 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (cmds): Fix typo ("bdif" -> "dif") which was accidentally
- introduced 24 May 96.
-
- * main.c (main_cleanup): Add comment stating default case will
- never be reached.
-
-Wed May 29 21:43:43 1996 noel <noel@BOAT_ANCHOR>
-
- * main.c (main_cleanup): check to see if SIGHUP, SIGINT, SIGQUIT,
- SIGPIPE, and SIGTERM are defined before using them. Also add a
- default case to print out those errors numerically which are not
- found.
-
-Wed May 29 18:43:45 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * expand_path.c (expand_path): Document LINE == 0 and allocation
- of return value.
- * modules.c (do_module): Pass 0, not -1, to indicate line number
- not known. Free value returned from expand_path. Deal with NULL
- return from expand_path.
-
-Wed May 29 15:56:47 1996 Greg A. Woods <woods@most.weird.com>
-
- * modules.c (do_module): call expand_path() on the program name
- specfied by one of '-o', '-t', or '-e' in the modules file before
- passing it to run_setup(). This makes it possible to use $CVSROOT
- (or indeed ~user or any other user-specified variable) to specify
- pathnames for programs not installed in the normal execution path.
-
-Sun May 26 21:57:09 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (start_server): Don't include %s in error message;
- there is no argument to go with it. Do include "internal error"
- in error message since that might not be clear to the user otherwise.
-
-Sun May 26 11:58:13 1996 Greg A. Woods <woods@most.weird.com>
-
- * root.c (set_local_cvsroot): enforce a wee bit of portability
- (parse_cvsroot): same....
- (DEBUG main): same, plus style guidelines
- (DEBUG error): deleted -- not necessary here (use fprintf instead)
-
- * mkmodules.c (modules_contents): updated notes about what must be
- done if you change any of the options for a module.
- (loginfo_contents): fixed grammar, re-pargraphed, and added 'echo
- %s;' to the example.
- (editinfo_contents): minor grammar fix.
-
-Sun May 26 17:51:18 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * vers_ts.c (Version_TS): Remove case where we get options from
- sdtp->options. Whatever case that was intended to handle is
- probably lost in the mists of time, but sdtp->options isn't set
- anywhere, and I think that has been true for a long time.
- * cvs.h (struct stickydirtag): remove options field.
- * entries.c (freesdt): Don't free ->options.
- * sanity.sh (binfiles): New tests binfiles-13a* test for above fix.
-
- * tag.c (check_fileproc): Use fullname not file in error message.
- Say "locally modified" not "up-to-date"; the file need not match
- the head revision it only need match some revision.
-
-Sun May 26 16:57:02 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * tag.c: added support for new option -c to make sure all tagged
- files are up-to-date
- (tag): check for option and set check_uptodate
- (check_fileproc): check status of file if check_uptodate is set
-
-Sat May 25 15:22:26 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (main): Revert change to look for a -H command option;
- command option parsing should be up to each subcommand and the -H
- global option works fine.
-
-Mon May 23 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * client.c (process_prune_candidates): Set prune_candidates to
- NULL at the end of the function.
-
-Mon May 23 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * checkout.c (checkout): In code to handle multiple arguments,
- pass preload_update_dir, not where, to Create_Admin.
- (checkout_proc): Pass preload_update_dir, not where, to
- Create_Admin.
-
-Thu May 23 19:14:35 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (server_set_sticky): Assert that update_dir != NULL.
- * sanity.sh (basicb): New test; tests for Ian's fix to checkout.c
- above.
-
-Thu May 23 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * patch.c (patch_fileproc): Don't ignore a file just because it is
- in the Attic directory.
-
-Thu May 23 10:40:24 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (death): New tests death-{72a,76a0,76a1} test for bug
- fixed by Ian's patch_fileproc change above.
-
- * sanity.sh (death): Remove "temporary hack" in test 89.
-
- * rcs.c (RCS_fast_checkout): If error closing file, and workfile
- is NULL, use sout in error message instead of workfile.
-
-Thu May 23 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (RCS_fast_checkout): Do a fast checkout in the case where
- workfile is NULL and sout is a file name.
-
-Wed May 22 19:06:23 1996 Mark Immel <immel@centerline.com>
-
- * update.c (checkout_file): New arg resurrecting_out, to provide
- resurrecting flag to caller.
- (join_file): New arg resurrecting. Register with "0" if we are
- the server and are resurrecting.
- (update_fileproc): Pass the flag from checkout_file to join_file.
-
-Wed May 22 19:06:23 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (death): Test for above fix, in test 89 and new test 89a.
-
-Tue May 21 09:49:04 1996 Greg A. Woods <woods@most.weird.com>
-
- * update.c (update_usage): oops -- fix my spelling typo.
-
-Mon May 20 10:53:14 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c (find_fileproc): Call freevers_ts.
-
- * commit.c (find_*): Keep an ignlist, like update.c and client.c do.
- * commit.c (commit): Process the files from the ignlists, once we
- are connected to the server.
- * sanity.sh (ignore): New tests 189e and 189f test for new
- commit.c behavior (and client.c behavior, which is unchanged).
- * sanity.sh (conflicts): Remove dir1 and sdir in parts of the test
- where we aren't prepared for "? dir1" and similar output.
-
-Mon May 20 13:23:36 1996 Greg A. Woods <woods@most.weird.com>
-
- * main.c (cmd_usage): minor corrections to descriptions of status,
- rtag, tag, and rdiff. Sort alphabetically by command name.
-
-Mon May 20 10:36:07 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * client.c (call_in_directory): Move the call to Entries_Close
- before the call to chdir, since Entries_Close examines files in
- the current directory.
-
-Fri May 17 12:13:09 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (start_tcp_server, start_server, start_rsh_server,
- read_line, filter_through_gzip, filter_through_gunzip,
- call_in_directory): Reindent as needed.
-
- * main.c (main): Add missing #endif. Use indentation to indicate
- nesting.
-
-Thu May 16 17:15:01 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (cmd_usage): Add "init" command.
-
-Thu May 16 16:45:51 1996 Noel Cragg <noel@gargle.rain.org>
-
- * client.c (start_tcp_server): Error message modified to tell the
- user to use ":server:" instead of setting CVS_CLIENT_PORT to a
- negative number.
-
- * main.c (main): Add #ifdefs for turning off buffering of
- stdio/stderr, so we don't get it by default.
-
-Thu May 16 01:29:47 1996 noel <noel@BOAT_ANCHOR>
-
- * commit.c (commit_filesdoneproc): Print the repository and root
- directories as part of the error message.
-
- * main.c (main): Don't buffer stdout or stderr. It's inefficient,
- but it then produces the right output for sanity.sh.
-
-Thu May 16 09:44:47 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * fileattr.c (fileattr_set): In the case where we are about to
- call delproc, don't free ->data; delproc does that.
- * sanity.sh (devcom): New tests devcom-b* test for this fix.
-
- * sanity.sh (conflicts): Remove redundant clean up from previous
- tests at the beginning of the test. Use dotest a few more places.
- (conflicts2): New test, tests for Ian's fix to Classify_File.
-
- * client.c (remove_entry_and_file): Add comment about
- existence_error's.
-
-Sat May 16 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * update.c (update_dirleave_proc): Don't try to chdir .. and check
- for an empty directory if there is a slash in the directory name.
-
-Thu May 16 09:02:59 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (deep): New tests deep-4a* test for Ian's fix to
- update_dirleave_proc.
-
-Sat May 16 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * main.c (main_cleanup): Report signal name before dying.
-
-Wed May 15 23:47:59 1996 Noel Cragg <noel@gargle.rain.org>
-
- * main.c (usg): revert usage strings for `-H' flag change.
-
-Sat May 15 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * server.c (serve_static_directory): Return immediately if there
- is a pending error.
- (serve_sticky): Likewise.
- (serve_modified): Read the file data even if there is a pending
- error.
-
-Wed May 15 14:26:32 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (main): If -d and CVS/Root both specified, after writing
- the value from -d into CVS/Root, use the value from -d, not the
- old value from CVS/Root. Don't write CVS/Root with value from -d
- until we have verified that it works.
- * sanity.sh: Reenable test basica-9 and adjust for new behavior.
-
-Tue May 14 1996 Jim Kingdon <kingdon@cyclic.com>
-
- * logmsg.c (do_editor): If user aborts the commit, still remove the
- temporary file.
-
-Tue May 14 11:45:41 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * filesubr.c, cvs.h (cvs_temp_name): New function. Move L_tmpnam
- define from cvs.h to filesubr.c.
- * client.c, diff.c, import.c, login.c, logmsg.c, no_diff.c,
- patch.c, wrapper.c: Call cvs_temp_name not tmpnam.
- * login.c (login): Reindent function.
-
-Tue May 14 10:56:56 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (RCS_fast_checkout): If workfile is NULL, don't call chmod.
-
-Mon May 13 10:52:10 1996 Greg A. Woods <woods@most.weird.com>
-
- * checkout.c (export_usage): note which options cause a sticky
- version to be set, and which option avoids this.
- * update.c (update_usage): likewise
-
-Sat May 11 18:57:07 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Comment out test basica-9 until I get around to
- actually fixing it (the -d vs. CVS/Root change broke it).
-
-Fri May 10 09:39:49 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (main): -d now overrides CVS/Root.
-
-Thu May 9 19:45:24 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c: Remove comment listing commands at beginning. It was
- out of date and redundant with the help.
-
-Thu May 9 09:33:55 1996 Greg A. Woods <woods@most.weird.com>
-
- * main.c: add 'init' to opening comment listing commands
-
- * mkmodules.c (init): fix to recognize argc==-1 as hint to call
- usage() [should make "cvs init -H" work as expected]
-
-Wed May 8 15:02:49 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Set EXPR in the case that the expr in the path is the
- one that we want.
-
-Wed May 8 14:06:24 1996 Greg A. Woods <woods@most.weird.com>
-
- * sanity.sh (test): - convert all '[' to test ala GCD
-
-Wed May 8 13:46:56 1996 Greg A. Woods <woods@most.weird.com>
-
- * sanity.sh (expr): - make a valiant attempt to find GNU expr
- - Patch from Larry Jones:
- sanity test deep-4 failed with "expr: arg list too long"
- sanity test 56 failed because the stderr and stdout output was not
- interleaved as expected.
- sanity test modules-155a4 failed with "ls: illegal option -- 1"
-
- * main.c (main): - Patch from Larry Jones for SysV setvbuf
-
-Tue May 7 16:41:16 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Increment version number to 1.8.2 to work around fact
- that CVS 1.8 (confusingly) calls itself 1.8.1 not 1.8.
-
-Tue May 7 10:44:20 MET DST 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * rcs.c (rcsvers_delproc): fix memory leak by freeing author
- field.
-
-Mon May 6 10:40:05 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (conflicts): New test conflicts-126.5 tests for bug
- which Ian fixed May 5 in update.c
-
-Mon May 6 06:00:10 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * Version 1.8.1
-
-Sun May 5 21:39:02 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * vers_ts.c (Version_TS): If sdtp is NULL, go ahead and check
- RCS_getexpand for options. Fixes binaries and non-unix clients.
- * sanity.sh: Fix binfiles-5.5 to test for the correct behavior
- rather than the buggy behavior which existed when the binfiles-5.5
- test was written.
- (binfiles-14c,binfiles-14f): Likewise.
-
-Sun May 5 17:38:21 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- Integrated changes submitted by Ian Taylor <ian@cygnus.com>
-
- * update.c (update_dirent_proc): cvs co -p doesn't print
- anything when run from an empty directory.
-
- * import.c (import_descend_dir): Check for a file in the
- repository which will be checked out to the same name as the
- directory.
-
-Sat May 4 12:33:02 1996 Ian Lance Taylor <ian@cygnus.com>
-
- Extract the head revision directly from the RCS file when
- possible, rather than execing co.
- * rcs.c (RCS_reparsercsfile): Set delta_pos field.
- (getrcskey): Add lenp parameter. Change all callers.
- (RCS_fast_checkout): New function.
- (annotate_fileproc): If PARTIAL is not set, just fseek to
- delta_pos.
- * rcs.h (struct rcsnode): Add delta_pos field.
- (RCS_fast_checkout): Declare.
- * diff.c (diff_file_nodiff): Call RCS_fast_checkout rather than
- RCS_checkout.
- * import.c (update_rcs_file): Likewise.
- * no_diff.c (No_Difference): Likewise.
- * patch.c (patch_fileproc): Likewise.
- * update.c (checkout_file): Likewise.
- (patch_file): Likewise.
- (join_file): Likewise.
-
-Sat May 4 12:33:02 1996 Ian Lance Taylor <ian@cygnus.com>
-
- * classify.c (Classify_File): Don't report a conflict for a
- pending remove if somebody else has already removed the file.
-
-Thu May 2 13:34:37 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * Version 1.7.88
-
-Thu May 2 01:40:55 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * server.c (HAVE_INITGROUPS): Use initgroups() only if
- located by configure, in the event a system has crypt(), but
- no initgroups()
-
-Wed May 01 21:08:21 1996 noel <noel@BOAT_ANCHOR>
-
- * client.c (filter_through_gunzip): use "gzip -d" instead of
- "gunzip," since there's no good reason (on NT at least) to have an
- extra copy of gzip.exe copied to gunzip.exe (Arrrrgh! No symbolic
- links!).
-
- * mkmodules.c (init): check to see that we have the correct number
- of arguments or print out the usage message (used to be argc > 1,
- should be argc != 1, because help forces argc == -1 as a special
- case).
-
-Wed May 1 18:05:02 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basica): When testing rejection of reserved tag name,
- use BASE instead of RESERVED.
-
-Wed May 1 15:15:11 1996 Tom Jarmolowski <tjj@booklink.com>
-
- * rcs.c (linevector_delete): Only copy up to vec->nlines - nlines,
- not to vec->nlines.
-
-Wed May 1 15:43:21 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcscmds.c (RCS_settag): Instead of reserving all tag names
- containing only uppercase letters, reserve only BASE and HEAD.
- * sanity.sh (mflag): Revert 26 Mar change; use all-uppercase tag
- name again.
-
-Wed May 1 15:15:11 1996 Tom Jarmolowski <tjj@booklink.com>
-
- * rcs.c (linevector_add): Move increment of i out of larger
- statement, to avoid assumptions about evaluation order.
-
-Tue Apr 30 15:46:03 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Version 1.7.87.
-
- * server.c (check_password): Don't use ANSI string concatenation.
- Reindent function.
-
-Mon Apr 29 10:48:38 1996 Noel Cragg <noel@gargle>
-
- * root.c (parse_cvsroot): removed "rsh" as an alias to "server" in
- the method section.
-
- * main.c (main): new variable help so we can support the `cvs -H
- cmd' convention. Reverts change of 26 Apr 96 which removed this
- feature.
-
-Sun Apr 28 14:57:38 1996 Noel Cragg <noel@gargle>
-
- * main.c (main): update error message if parse_cvsroot fails.
- * server.c (serve_root): same.
- (serve_init): same.
-
- * client.c (start_tcp_server): get rid of the "fall through"
- stuff, now that we have access methods.
- (start_server): switch off the access method to choose routine
- that starts the server.
- (start_tcp_server): tofd wasn't getting set to -1 early enough,
- because a call to error for bind or gethostbyname might fail and
- the subsequent error check to see if the connection had been made
- would fail.
-
- * root.c: new variable method_names for error reporting purposes.
-
-Sun Apr 28 17:22:15 1996 Noel Cragg <noel@occs.cs.oberlin.edu>
-
- * server.c: moved kerberos #includes from main.c for the
- kserver_authenticate_connection routine.
-
-Fri Apr 26 07:59:44 1996 Noel Cragg <noel@gargle>
-
- * server.c (serve_init): use the new return value from
- parse_cvsroot.
- (serve_root): same.
- * main.c (main): same.
-
- * root.c (parse_cvsroot): fix indentation, add a return value
- which tells whether the command succeeded or failed.
-
- * main.c (main): move the setting of the UMASK environment
- variable inside the stuff that gets done if the user is NOT asking
- for help, so we don't signal any errors prematurely (don't want to
- give an error because we can't parse an environment variable
- correctly if the user asks for help). Similar mods for the code
- that tries to get the working directory.
-
- Also make CVSADM_Root a local variable instead of a global, since
- its scope is only about 20 lines here!
-
- * server.c (kserver_authenticate_connection): moved code from
- main.c to clean up MAIN. Makes sense, since we already have a
- pserver_authenticate_connection.
- (pserver_authenticate_connection): rename from
- authenticate_connection.
-
- * main.c (main): reorganized the routine to eliminate variables
- help, help_commands, and version_flag. Now the routine is much
- clearer, since we don't have to be checking to see if these
- variables are set. One behavior that was a bug/feature which is
- now gone is an invocation like "cvs -H rtag" -- previously this
- would give usage for rtag, but now gives usage for cvs itself.
- The first behavior didn't make sense, especially since we say in
- the docs that command-line flags are position-specific. *Reverted
- Above*
-
-Thu Apr 25 20:05:10 1996 Noel Cragg <noel@gargle>
-
- * main.c (main): make sure we have a valid command name before we
- do anything else (moved the thing that looks for a command in CMDS
- to right after the GETOPT loop). Added `kserver' and `pserver' to
- the table so they will be recognized; set their functions to
- SERVER so that help will be given when asked for.
-
- * expand_path.c (expand_variable): return CVSroot_original rather
- than CVSroot_directory.
-
- * main.c (main): save CVSroot in the env rather than
- CVSroot_original, since we might not have called PARSE_CVSROOT
- (this can happen if we use the -H option to a command).
-
- * root.c (parse_cvsroot): the parsing method was bogus for
- guessing when we had hostnames vs. directories specified. Any
- ambiguity should be removed by having the user specify the access
- method. If the access method isn't specified, choose
- server_method if the string contains a colon or local_method
- otherwise.
-
- * Changed CVSroot_remote back to client_active since the code
- reads better.
-
-Wed Apr 24 17:27:53 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * vers_ts.c (Version_TS): xmalloc enough space (1 more
- byte). Thanks to purify!
-
-Mon Apr 22 00:38:08 1996 Noel Cragg <noel@gargle>
-
- * create_adm.c (Create_Admin): pass CVSroot_original instead of
- CVSroot_directory (oops!).
- * update.c (update_filesdone_proc): same.
-
- * server.c (serve_root): modify to use parse_cvsroot rather than
- goofing around with other variables. Will need to fix
- parse_cvsroot to have a return value so we can return an error and
- quit gracefully if in server mode.
- (serve_init): same.
-
- * main.c: modify command table to remove client_* routines, since
- they no longer exist.
- (main): don't try to switch off non-existent field in command
- table! ;-)
-
- * client.h (client_*): removed prototypes for now non-existent
- functions.
-
- * client.c: remove proto for get_cvs_password, since it is now in
- cvs.h. Modify routines to use new globals that describe CVSROOT
- rather than client_active, server_host, server_user, and
- server_cvsroot.
- (parse_cvsroot): removed function, since a more generic version
- now lives in root.c.
- (connect_to_pserver): remove call to parse_cvsroot, since main.c
- has already done it for us.
- (client_*): removed all of these routines, since they only call
- parse_cvsroot and then their respective operation functions.
- Since main.c has already called parse_cvsroot, we shouldn't bother
- with the extra function call, since client-server diffs are
- already handled in the core routines themselves.
-
- * main.c: remove CVSroot as a global variable. Remove
- use_authenticating_server variable since we have a new
- `CVSroot_method' variable instead.
- (main): add `CVSroot' as a local variable. Call parse_cvsroot
- after we're sure we have the right setting for `CVSroot.'
-
- * login.c (login): update to use new global variables. Instead of
- old behavior which let the user type in user@host when prompted,
- it makes them do it in CVSROOT proper. The routine still lets the
- user type the password, however.
- (get_cvs_password): make sure that CVSROOT is fully qualified
- before trying to find the entry in the .cvspass file.
- * cvs.h: add prototype for get_cvs_password.
-
- * add.c: use new globals that describe CVSROOT.
- * admin.c: same.
- * checkout.c: same.
- * commit.c: same.
- * create_adm.c: same.
- * diff.c: same.
- * edit.c: same.
- * expand_path.c: same.
- * history.c: same.
- * ignore.c: same.
- * import.c: same.
- * log.c: same.
- * mkmodules.c: same.
- * modules.c: same.
- * parseinfo.c: same.
- * patch.c: same.
- * rcs.c: same.
- * recurse.c: same.
- * release.c: same.
- * remove.c: same.
- * repos.c: same.
- * rtag.c: same.
- * status.c: same.
- * tag.c: same.
- * update.c: same.
- * watch.c: same.
- * wrapper.c: same.
-
- * root.c (Name_Root): remove error message that reports missing
- CVSROOT, since new code in main.c will catch it and also print out
- an error.
- (parse_cvsroot): new function -- takes a CVSROOT string and breaks
- it up into its component parts -- method, hostname, username, and
- repository directory. Sets new global variables that describe the
- repository location more precisely: CVSroot_original,
- CVSroot_remote, CVSroot_method, CVSroot_username,
- CVSroot_hostname, CVSroot_directory for use by all other
- functions. Checks for obvious errors in format of string.
- (main): a short routine to test parse_cvsroot from the command
- line.
- * cvs.h: add prototype for parse_cvsroot and extern definitions
- for new globals.
-
- * cvs.h: removed CVSroot variable, since we don't want other
- routines using the raw CVSROOT (also helped to find all of the
- refs to the variable!).
-
-Fri Apr 19 11:22:35 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * Version 1.7.86
-
-Thu Apr 18 1996 Jim Kingdon <kingdon@cyclic.com>
-
- * client.c (try_read_from_server): Compare return value from fwrite
- with a size_t not an int (Visual C++ lint).
-
-Wed Apr 17 11:56:32 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (try_read_from_server): New function.
- (read_from_server): Use it.
- (read_counted_file): New function.
- * client.c, server.c: Add Template response.
- * cvs.h (CVSADM_TEMPLATE): Added.
- * logmsg.c (do_editor): If repository is NULL, use CVSADM_TEMPLATE
- file in place of rcsinfo.
- * server.c, server.h (server_template): New function.
- * create_adm.c (Create_Admin): Call it.
-
-Tue Apr 16 13:56:06 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * repos.c (Name_Repository): Fix comments.
- * create_adm.c (Create_Admin): Fix indentation.
-
-Wed Apr 10 16:46:54 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * options.h.in: Include relevant information here rather than
- citing (former) FAQ.
-
- * ChangeLog-9395: Fix typo in introductory paragraph.
-
-Wed Apr 10 14:55:10 1996 code by Mike Spengler mks@msc.edu
- comments by Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * filesubr.c (unlink_file_dir,deep_remove_dir): Don't call unlink
- on something which might be a directory; check using isdir instead.
-
-Wed Apr 10 14:55:10 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * checkout.c (build_dirs_and_chdir): Pass path, not cp, to
- Create_Admin. The former is the correct update dir.
- * sanity.sh (modules): New tests modules-155* test, for above fix.
-
-Mon Apr 8 13:53:27 1996 Samuel Tardieu <sam@inf.enst.fr>
-
- * rcs.c (annotate_fileproc): If the file is not under CVS control,
- return instead of dumping a core. Don't bug on files with an empty
- first revision.
-
-Fri Mar 29 16:08:28 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (annotate_fileproc): If last line of add-chunk is not
- newline terminated, end the loop when we find that out.
-
-Fri Mar 29 16:59:34 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * rcs.c (annotate_fileproc): allow last line of add-chunk not to
- be newline terminated
-
-Thu Mar 28 10:56:36 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- Add more diff tests:
- * sanity.sh (basic2): Use dotest for test 61.
- (basica): Add test basica-6.2.
- (branches): Add tests branches-14.4 and branches-14.5.
- (basic1): Remove tests 19, 20, 25, and 26. The only thing this
- might miss out on is diff's interaction with added and removed
- files, but those tests didn't test that very well anyway.
-
- * rcs.c (RCS_getrevtime): Add comment regarding years after 1999.
-
- * rcs.c: Add "cvs annotate" command and related code.
- (getrcskey): Move special handling of RCSDESC from here to
- callers. Handle those keys (desc, log, text) which do not
- end in a semicolon.
- * rcs.h (RCSVers): Add author field.
- * rcs.c (RCS_reparsercsfile): Set it.
- * cvs.h (annotate), main.c (cmd_usage, cmds), client.h client.c
- (client_annotate), server.c (serve_annotate, requests): Usual
- machinery to add a new command.
- * sanity.sh (basica): Test cvs annotate.
-
- * sanity.sh (branches): More tests, of things like adding files on
- the trunk after a branch has been made.
-
-Tue Mar 26 09:48:49 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * expand_path.c: Don't declare free and xmalloc; cvs.h already
- takes care of that.
-
- * sanity.sh (mflag): Don't use tag name reserved to CVS.
-
- NT local changes plus miscellaneous things noticed in the process:
- * import.c (add_rcs_file): Use binary mode to write RCS file. Use
- \012 where linefeed is intended. Copy data a small block at a
- time, until we hit EOF, rather than trying to read the whole file
- into memory at once.
- * client.c (send_modified): Add comments regarding st_size.
- * commit.c (commit): Add comments regarding binary mode and read().
- * logmsg.c (do_editor): Add comments regarding st_size.
- * server.c (server_updated): Use binary mode to read file we are
- sending.
-
- * rcscmds.c (RCS_settag): Complain if user tries to add a tag name
- reserved to CVS.
- * sanity.sh (basica): Test for this behavior.
-
- * sanity.sh (binfiles): New tests test ability to change keyword
- expansion.
-
-Mon Mar 25 1996 Jim Kingdon <kingdon@cyclic.com>
-
- * cvs.h, filesubr.c (expand_wild): New function.
- * recurse.c (start_recursion): Call expand_wild at beginning and
- free its results at the end.
- * cvs.h, subr.c (xrealloc): Make argument and return value void *.
- * client.h, client.c (send_file_names): Add flags argument. If
- SEND_EXPAND_WILD flag is passed, call expand_wild at beginning and
- free its results at the end.
- * admin.c, add.c, log.c, tag.c, status.c, edit.c, watch.c,
- update.c, commit.c, remove.c, client.c, diff.c: Update callers.
-
-Fri Mar 22 10:09:55 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * error.c (error, fperror): Exit with status EXIT_FAILURE rather
- than STATUS. We had been neglecting to check for 256, and the
- value of providing a count of errors is probably minimal anyway.
- * add.c, modules.c, mkmodules.c, tag.c, server.c, main.c,
- import.c, client.c, scramble.c, recurse.c: Exit with status
- EXIT_FAILURE rather than 1. On VMS, 1 is success, not failure.
- * main.c (main): Return EXIT_FAILURE or 0. The value of providing
- a count of errors is minimal.
-
- * client.c (init_sockaddr): Exit with status 1 rather than
- EXIT_FAILURE. The latter apparently doesn't exist on SunOS4.
- Reindent function.
-
-Mon Mar 18 14:28:00 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * cvs.h, ignore.c: New variable ign_case.
- * ignore.c (ign_name): If it is set, match in a case-insensitive
- fashion.
- * server.c (serve_case): New function.
- (requests): Add Case request.
- * client.c (start_server): If FILENAMES_CASE_INSENSITIVE is
- defined, send Case request.
-
-Sat Mar 16 08:20:01 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- For reference, this change takes cvs's text segment from 315392
- bytes to 311296 bytes (one 4096 byte page).
- * cvs.h (struct file_info): Add fullname field.
- * recurse.c (do_file_proc): Set it.
- * commit.c (find_fileproc), client.c (send_fileproc), commit.c
- (check_fileproc), diff.c (diff_fileproc), edit.c
- (unedit_fileproc), patch.c (patch_fileproc), remove.c
- (remove_fileproc), rtag.c (rtag_fileproc), tag.c (tag_fileproc),
- update.c (update_fileproc), watch.c (watchers_fileproc): Use it
- instead of computing it each time.
- * diff.c (diff_fileproc), remove.c (remove_fileproc): Use fullname
- where we had been (bogusly) omitting the directory from user
- messages.
- * edit.c (unedit_fileproc, edit_fileproc): If we cannot close
- CVSADM_NOTIFY, mention CVSADM_NOTIFY rather than finfo->file in
- error message.
- * rtag.c (rtag_fileproc), tag.c (tag_fileproc): Reindent.
-
-Fri Mar 15 15:12:11 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * server.h: fix prototype of server_pause_check (was
- server_check_pause)
-
-Thu Mar 14 1996 Jim Kingdon <kingdon@cyclic.com>
-
- * vers_ts.c (Version_TS), entries.c (Scratch_Entry, AddEntryNode):
- Change findnode to findnode_fn.
-
- * main.c: Depending on HAVE_WINSOCK_H, include winsock.h or
- declare gethostname.
- * cvs.h: Don't declare it here.
-
-Thu Mar 14 07:06:59 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c (find_fileproc): If vn_user is NULL and ts_user is not,
- print an error rather than silently succeeding.
- * sanity.sh (basica-notadded): New test, for above fix.
- (dotest_internal): New function.
- (dotest,dotest_fail): Call it instead of duplicating code between
- these two functions.
-
- * sanity.sh: Skip tests binfiles-9 through binfiles-13 for remote.
-
- * options.h.in: Adjust comment to reflect kfogel change.
-
-Thu Mar 14 01:38:30 1996 Karl Fogel <kfogel@floss.red-bean.com>
-
- * options.h.in (AUTH_CLIENT_SUPPORT): turn on by default.
-
-Wed Mar 13 09:25:56 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * vers_ts.c (Version_TS): Don't try to override options from rcs
- file if there isn't an rcs file (e.g. called from send_fileproc).
- This fixes a bug detected by test 59 in "make remotecheck".
-
- * rcs.c (RCS_reparsercsfile, RCS_getexpand): Assert that argument
- is not NULL.
-
- Fix a gcc -Wall warning:
- * rcs.c, rcs.h (RCS_getexpand): New function.
- * vers_ts.c (Version_TS): Call it.
- * rcs.c (RCS_reparsercsfile): Make static.
-
- Add a "cvs init" command. This is needed because cvsinit.sh
- invoked mkmodules which doesn't exist any more.
- * mkmodules.c: Break filelist out of mkmodules function, rename
- struct _checkout_file to struct admin_file (for namespace
- correctness), and add contents field.
- (init,mkdir_if_needed): New functions.
- * cvs.h (init): Declare.
- * main.c (cmds): Add init.
- (main): If command is init, don't require cvsroot to exist.
- * client.c, client.h (client_init, send_init_command): New functions.
- * client.c (start_server): Don't send Root request if command is init.
- * server.c (serve_init): New function.
- (requests): Add "init".
-
-Wed Mar 13 09:51:03 MET 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * vers_ts.c (Version_TS): set options to default option if the
- file if no -k option but -A was given. This avoids the (wrong)
- update message for binary files which are up-to-date when
- running 'cvs -A'.
-
- * update.c (checkout_file): remove test of -k option stored in the
- file itself because it was moved to vers_ts.c
-
- * sanity.sh: added tests for the above fix.
-
-Tue Mar 12 13:47:09 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * hash.c (findnode): Adjust comment regarding errors.
-
- * hash.c (findnode, findnode_fn): Assert that key != NULL. This
- way the check still happens even if the function is later
- rewritten to not start out by calling hashp.
-
-Mon Mar 11 10:21:05 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: If expr accepts multi-line patterns but is too
- liberal in matching them, print a warning but keep going.
-
- * sanity.sh: Add QUESTION variable, analogous to PLUS. Use it
- instead of \? to match a question mark.
-
- * cvs.h (CVSMODULE_OPTS, CVSMODULE_SPEC): Move from here...
- * modules.c: ...to here. They are only used here and the code to
- handle the syntax of modules files should not be scattered all over.
- * modules.c (CVSMODULE_OPTS): Add "+" as first character.
- * sanity.sh (modules): New tests 148a0 and 148a1 test for
- above-fixed bug.
-
-Mon Mar 11 13:11:04 1996 Samuel Tardieu <sam@inf.enst.fr>
-
- * modules.c (cat_module): set optind to 0 to force getopt() to
- reinitialize its internal nextchar
-
-Mon Mar 11 00:09:14 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * hash.c (findnode, findnode_fn): Revert changes of 7-8 Mar 1996.
- The correct style is to assert() that key != NULL (see HACKING),
- which is already done in the hashp function.
- * fileattr.c (fileattr_delproc): Likewise, assert() that
- node->data != NULL rather than trying to deal with it being NULL.
-
-Fri Mar 8 01:31:04 1996 Greg A. Woods <woods@most.weird.com>
-
- * hash.c (findnode_fn): one more place to avoid calling hashp()
- with a NULL key
-
-Thu Mar 7 17:30:01 1996 Greg A. Woods <woods@most.weird.com>
-
- * hash.c (findnode): also return NULL if key is not set
- [[ reported by Chris_Eich@optilink.optilink.dsccc.com, and
- supposedly in a PR that should be marked "fixed"..... ]]
-
- * fileattr.c (fileattr_set): set node->data to NULL after freeing
- it to prevent subsequent accesses
- (fileattr_delproc): don't free node->data if it's NULL, and set it
- to NULL after freeing
- [[ reported by Chris_Eich@optilink.optilink.dsccc.com, and
- supposedly in a PR that should be marked "fixed"..... ]]
-
-Fri Mar 1 14:56:08 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basica): New test basica-4a tests for bug fixed by
- sam@inf.enst.fr on 1 Mar 96.
-
-Fri Mar 1 18:10:49 1996 Samuel Tardieu <sam@inf.enst.fr>
-
- * tag.c (check_fileproc): Check for file existence before trying
- to tag it.
-
-Fri Mar 1 07:51:29 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (update_entries): If command is export, set options to
- NULL.
-
-Thu Feb 29 16:54:14 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * lock.c (write_lock, Reader_Lock): Remove
- BOGUS_UNLESS_PROVEN_OTHERWISE code. It was pretty bogus, and has
- been ifdeffed out for a long time.
- * cvs.h (CVSTFL): Removed; no longer used.
-
- * cvsrc.c, cvs.h (read_cvsrc): Pass in command name rather than
- using global variable command_name.
- * main.c (command_name): Initialize to "", not "cvs" so that error
- messages don't say "cvs cvs". Update calls to read_cvsrc to pass
- in command_name or "cvs" as appropriate.
- * sanity.sh (basica): New test basica-9 tests for above-fixed bug.
-
- * lock.c: Rename unlock to lock_simple_remove to avoid conflict
- with builtin function on QNX.
-
-Thu Feb 29 17:02:22 1996 Samuel Tardieu <sam@inf.enst.fr>
-
- * fileattr.c (fileattr_get): Removed NULL pointer dereference
- which occurred in the absence of default attribute.
-
-Thu Feb 29 07:36:57 1996 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * rcs.c (RCS_isbranch, RCS_whatbranch): Remove no longer used file
- argument, swap order of remaining two arguments to be like other
- RCS_* functions.
- (RCS_nodeisbranch): swap order of arguments to be like other RCS_*
- functions.
- * rcs.h (RCS_isbranch, RCS_whatbranch, RCS_nodeisbranch): Update
- prototypes for above changes.
- * commit.c, rtag.c, status.c, tag.c: Update for above calling
- convention changes.
-
-Thu Feb 29 08:39:03 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (start_server): Revert changes which claimed to fall
- back to a different way of connecting. Add comments explaining
- why. (I don't think the changes did what they claimed, anyway).
- Use indentation rather than comments to line up #if, #else, and
- #endif.
-
- * patch.c (patch, patch_fileproc): Revert change to add optional
- arguments to -c and -u. Optional arguments are evil and in
- violation of the POSIX argument syntax guidelines. The correct
- way to do this is -C and -U. Also change DIFF back to "diff" in
- output (see comments).
-
- gcc -Wall lint:
- * client.c (copy_a_file): Declare p inside the #ifdef in which is
- it used.
- * commit.c (remove_file): Remove unused variable p.
- * commit.c (checkaddfile): Remove unused variables p.
- * rcs.c (RCS_isbranch): Remove unused variable p.
- * rcs.c: Remove unused declarations and definitions of
- parse_rcs_proc, rcsnode_delproc, rcslist, and repository.
- * rtag.c (rtag_fileproc): Remove unused variable p.
- * patch.c (patch_fileproc): Remove unused variable p.
- * tag.c (val_fileproc): Remove unused variable node.
- * client.c, import.c, lock.c, server.c: Cast pid_t to long before
- passing it to %ld.
-
- * cvs.h: Don't prototype gethostname; merely declare it (on linux,
- second argument is size_t not int).
-
-Thu Feb 29 10:29:25 MET 1996 Norbert Kiesel (nk) <nk@col.sw-ley.de>
-
- * sanity.sh: added "cat > /dev/null" to loginfo entry to avoid the
- SIGPIPE signal
-
-Thu Feb 29 10:28:25 MET 1996 Norbert Kiesel (nk) <nk@col.sw-ley.de>
-
- * patch.c: added new variable diff_opt
- (patch): allow optional parameter to -c and -u option, send it to
- server
- (patch_fileproc): cleaned up the code which prints the current
- filename. For "-s" option, print the pathname relative to CVSROOT
- instead of just the filename.
-
- * filesubr.c (xchmod): added cast to shut up gcc
-
- * cvs.h: added prototype for gethostname
-
-Thu Feb 29 10:27:25 MET 1996 Norbert Kiesel (nk) <nk@col.sw-ley.de>
-
- * lock.c (write_lock), (Reader_Lock), import.c (update_rcs_file),
- client.c (update_entries), (send_modified), server.c (server),
- (receive_file), (server_updated): use %ld for printing pid_t
- variables
-
-Thu Feb 29 02:22:12 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * run.c (run_exec): Added VMS return status support.
-
-Thu Feb 29 01:07:43 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * client.c (send_to_server): wrtn wasn't being declared under
- VMS for some reason.
-
-Wed Feb 28 23:27:04 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * client.c: Changed #ifdef VMS && NO_SOCKET_TO_FD to
- #if defined(VMS) && defined(NO_SOCKET_TO_FD)
-
-Wed Feb 28 22:28:43 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * build_src.com: Added DCL command procedure to build
- and link CVS client for VMS.
-
-Wed Feb 28 22:07:20 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * client.c: VMS CVS client specific changes.
-
- Added USE_DIRECT_TCP to allow CVS_PORT to be used to specify
- a TCP connection port (no Kerberos). Changed
- start_kerberos_server() to start_tcp_server().
-
- In copy_a_file(): transform a backup file to have a
- VMS-friendly name.
-
- Added HAVE_CONFIG_H to include "config.h".
-
- start_server() will starts the first successful of any
- mutually exclusive methods of starting the CVS server
- which might be enabled.
-
- Initialized use_socket_style and server_sock for VMS in
- start_server().
-
-Wed Feb 28 21:49:48 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * find_names.c, recurse.c, cvs.h: Changed Find_Dirs() to
- Find_Directories().
- * cvs.h: Added VMS filenames enabled through USE_VMS_FILENAMES
- VMS POSIX will require to use the regular CVS filenames
- while VMS is #define'd.
-
-Wed Feb 28 21:26:22 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * ignore.c: Added the patterns *.olb *.exe _$* *$ to default
- ignore list for VMS.
-
-Wed Feb 28 13:32:28 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * logmsg.c (do_editor): Fix indentation.
-
-Wed Feb 28 12:56:49 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * logmsg.c (do_editor): If no editor is defined, exit and print
- a message.
-
-Wed Feb 28 10:40:25 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * vers_ts.c (time_stamp, time_stamp_server): Reindent and revise
- comments.
-
-Tue Feb 27 23:57:55 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * vers_ts.c: gmtime() returns NULL on some systems (VMS)
- revert to local time via ctime() if GMT is not avaiable.
-
-Tue Feb 27 13:07:45 1996 J.T. Conklin <jtc@rtl.cygnus.com>
-
- The changes listed below cause cvs to parse each rcs file (and
- free the associated rcsnode after the file has been processed)
- sequentially. cvs used to parse all files in a directory, an
- approach that does not scale to huge repositories with lots
- of revisions/branches/tags/etc.
-
- * cvs.h (struct file_info): Removed srcfiles field. Added rcs
- (node) field.
- * recurse.c (do_recursion): Removed code that pre-parsed all
- rcs files in the directory.
- (do_file_proc): Parse current rcs file.
- * rcs.c (RCS_parsefiles, parse_rcs_proc, RCS_addnode): Removed.
- (RCS_isbranch, RCS_whatbranch): Changed srcfiles argument to
- rcs (node).
- * rcs.h (RCS_parsefiles, RCS_addnode): Removed prototypes.
- (RCS_isbranch, RCS_whatbranch): Updated prototypes.
- * add.c, admin.c, checkin.c, checkout.c, classify.c, client.c,
- commit.c, diff.c, history.c, import.c, log.c, patch.c, remove.c,
- rtag.c, status.c, tag.c, update.c, vers_ts: Updated for above
- calling convention / data structure changes.
-
-Mon Feb 26 16:07:56 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Version 1.7.3.
-
- * Version 1.7.2.
-
-Mon Feb 26 1996 Jim Kingdon <kingdon@cyclic.com>
-
- * recurse.c (start_recursion): Use last_component rather than
- checking for '/' directly.
- (do_dir_proc): Likewise.
-
- Visual C++ lint:
- * client.c (send_to_server): Change wrtn to size_t.
- (connect_to_pserver): Put tofd and fromfd declarations inside
- #ifndef NO_SOCKET_TO_FD.
- * scramble.c (shifts): Change from array of char to array of
- unsigned char.
-
-Mon Feb 26 13:31:25 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (check_repository_password): Remove unused variables
- linelen, ch.
-
- * client.c (send_file_names): Translate ISDIRSEP characters to '/'.
-
-Sat Feb 24 21:25:46 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * checkout.c (safe_location): Re-indent one line.
-
-Sat Feb 24 10:50:42 1996 Karl Fogel <kfogel@floss.red-bean.com>
-
- * checkout.c (safe_location): put assignment to hardpath[x] in an
- `else'-clause, so we don't do it when x == -1.
-
-Sat Feb 24 01:40:28 1996 Marcus Daniels <marcus@sayre.sysc.pdx.edu>
- via Karl Fogel <kfogel@floss.red-bean.com>
-
- * server.c (check_repository_password): Return by reference an
- optional username, the `host_user', from the passwd file. The
- host_user will be the user-id under which the cvs repository is
- run.
- (check_repository_password): Use `read_line' instead of fgets to
- allow for passwords larger than 32 characters, as well as the
- optional host user argument.
- (check_password): Modify to use host_user.
- (authenticate_connection): Modify to use host_user.
-
-Sat Feb 24 01:05:21 1996 Karl Fogel <kfogel@floss.red-bean.com>
-
- * scramble.c (descramble): just shift descrambled string to get
- rid of tag char, instead of allocating a whole new copy.
- (scramble): cast return value of xmalloc to avoid unsightly
- compiler warnings.
-
- * options.h.in (RCSBIN_DFLT): don't refer to AUTH_SERVER_SUPPORT
- in comment anymore, now that it's not defined in this file.
-
-Fri Feb 23 1996 Jim Kingdon <kingdon@cyclic.com>
-
- * client.c: Ifdef HAVE_WINSOCK_H, include winsock.h
- instead of sys/socket.h and friends.
- * login.c: Don't include sys/socket.h and friends.
- * login.c (login): Only fclose fp in the case where it was
- successfully fopen'd.
- * login.c: Declare getpass.
- * filesubr.c, cvs.h (get_homedir): New function.
- * cvsrc.c, expand_path.c, history.c, login.c: Call it instead
- of getenv ("HOME").
-
-Fri Feb 23 09:23:20 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (connect_to_pserver): Remove unused variable host.
- * login.c: Include getline.h.
- (login): Remove unused variables i and username.
- (get_cvs_password): Move free of linebuf to where it actually will
- be called. Add a "return NULL" at the end of the function to shut
- up gcc -Wall.
-
- * options.h.in: Remove AUTH_SERVER_SUPPORT.
- * client.h (authenticate_connection): Declare.
- * scramble.c (scramble): Cast char to unsigned char before using
- it to look up in table (char might be signed).
- * server.c [AUTH_SERVER_SUPPORT]: Include grp.h
- (authenticate_connection): Remove unused variables len and
- server_user.
-
- * sanity.sh (basica): Add comments regarding creating a top-level
- directory.
- (basic1): Don't try to remove first-dir and
- ${CVSROOT_DIRNAME}/first-dir at start of test; tests are now
- responsible for cleaning up at the end.
- (PLUS,DOTSTAR,ENDANCHOR): Add comments regarding fixed GNU expr.
-
-Thu Feb 22 22:34:11 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * cvs.h: Remove alloca cruft.
-
-Wed Feb 21 07:30:16 1996 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * modules.c (do_module): call free_cwd before exiting.
-
- * recurse.c: Removed entries global variable.
- (do_recursion): Declare entries. Moved call to Entries_Close so
- entries list is closed on all code paths.
- (start_recursion): Removed call to Entries_Close, entries list has
- been moved to do_recursion only.
-
-Tue Feb 20 22:10:05 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (update_dirent_proc): If dir lacks a CVS subdirectory,
- don't recurse into it.
- * sanity.sh (conflicts): Test for above-fixed bug.
-
- * update.c (merge_file): Use write_letter not printf.
-
-Tue Feb 20 12:34:07 EST 1996: Gary Oberbrunner <garyo@avs.com>
- and Jim Kingdon <kingdon@cyclic.com>
-
- * history.c (history_write): Change username to char * and call
- getcaller() to set it. Setting username accidentally got deleted
- 8 Feb 96.
- * sanity.sh: Revise test 64 to test for above-fixed bug.
- * sanity.sh (PLUS): New variable, work around yet another GNU expr
- bug.
-
-Tue Feb 20 14:07:50 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Merge test rtags into test basic2. They never were
- capable of running separately of each other.
-
- * sanity.sh (deep): New test, to test ability to operate in deeply
- nested directories (more quickly than basic2 test did).
- (basic2,rtags): Remove directories dir3 and dir4. Remove file8,
- file10, file12, file9, file11, file13, file15, file16, file17.
- These additional files slowed down the tests considerably without
- significantly increasing coverage.
-
- * sanity.sh (PROG): New variable. Use it instead of "cvs"
- to match the name cvs prints out for itself.
-
-Mon Feb 19 09:00:29 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- This fixes a bug whereby old default attributes would get
- clobbered instead of added to on "cvs watch add".
- * hash.c (findnode): Don't check for key == NULL; let the
- assertion in hashp take care of it.
- * fileattr.h, fileattr.c (fileattr_get): If filename is NULL,
- return default attributes.
-
- * client.c (send_repository): Fix indentation.
-
-Mon Feb 19 01:10:01 1996 Karl Fogel <kfogel@floss.red-bean.com>
-
- * login.c (login): print out full repos so user knows which server
- she's logging into.
-
- * client.c (send_repository): die if `repos' is NULL. This is a
- lame solution; see comments in code.
-
-Thu Feb 15 15:04:01 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * error.c (error): Free entire and mess when done with them.
-
- * sanity.sh (info): Correct syntax of .cvsrc file.
-
- * cvs.h, expand_path.c, edit.c, parseinfo.c, wrapper.c:
- expand_path now takes arguments containing file and line for error
- message, and it prints the error message itself.
- * sanity.sh (info-6a): Test printing of error message.
-
- * expand_path.c (expand_variable): Add USER internal variable.
- * sanity.sh (info): Test USER and CVSROOT internal variables too.
-
-Wed Feb 14 19:11:08 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (usg): Add -s option.
-
-Tue Feb 13 20:26:06 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- gcc -Wall lint:
- * mkmodules.c (mkmodules_usage): Remove declaration of
- non-existent function.
- * cvs.h (mkmodules): Declare.
-
-Mon Feb 12 12:20:04 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * mkmodules.c: Rename main to mkmodules and remove various pieces
- of scaffolding which it used to emulate non-existent parts of CVS.
- Change calling convention to just take a char * not argc,argv.
- Save and restore working directory.
- * commit.c (commit_filesdoneproc): Call it if checking files into
- CVSROOT.
- * Makefile.in (SOURCES): Add mkmodules.c.
- (OBJECTS): Add mkmodules.o.
- (MSOURCES,MOBJECTS): Removed.
- (COMMON_OBJECTS): Removed; move former contents into OBJECTS.
- Update other rules accordingly.
- * sanity.sh: Adjust to reflect nonexistence of mkmodules.
-
- These changes introduce functions cvs_output and cvs_outerr;
- eventually all server output will go through them rather than
- stdio directly.
- * server.c (saved_output, saved_outerr): New variables.
- (do_cvs_command): Initialize them.
- (buf_output): Don't require that buf->output be set; saved_* use
- this to shove some data in a buffer which buf_copy_lines will
- later want to get data from.
- * server.c, cvs.h (cvs_output, cvs_outerr): New functions.
- * mkmodules.c (cvs_outerr): New function, so error() works.
- * error.c: Reindent. Don't declare program_name and command_name;
- cvs.h declares them.
- (error): Use vasprintf and cvs_outerr (or fputs in the
- error_use_protocol case) rather than stdio directly.
- * import.c (import_descend_dir): Remove kludge which had prevented
- messages from error() from being out of order with respect to
- messages from printf; cvs_output and cvs_outerr are a cleaner
- solution to the problem.
- (add_log, import): Use cvs_output not printf.
- * update.c (write_letter): Use cvs_output not printf.
- (checkout_file): Use write_letter not printf.
- * sanity.sh: Use dotest for test 56 (test that output is actually
- correct). In theory should test that the import.c bug is fixed,
- but I was unable to reproduce the bug (it is timing dependent).
-
-Mon Feb 12 16:07:45 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * commit.c: define last_register_time
- (commit): make sure cvs doesn't exit in the same second it wrote
- the last timestamp
- (commit_fileproc): set last_register_time
- (finaladd): set last_register_time
-
- * run.c, cvs.h: Changed more Popen() to run_popen()
-
-Mon Feb 12 03:06:50 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * release.c, rtag.c, tag.c: changed 'delete' to 'delete_flag'
- to avoid symbol collision with DEC C RTL function delete()
-
-Mon Feb 12 03:01:48 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * mkmodules.c: changed 'void Lock_Cleanup()' to 'void static
- Lock_Cleanup() to avoid conflict with more substantial
- Lock_Cleanup() in lock.c
-
-Mon Feb 12 02:50:19 1996 Benjamin J. Lee <benjamin@cyclic.com>
-
- * edit.c, logmsg.c, release.c, run.c: Changed Popen() to
- run_popen(). VMS' linker is not case sensitive and considered
- popen() and Popen() to be identical symbols.
-
-Sun Feb 11 10:51:14 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (main) [!CLIENT_SUPPORT]: Silently ignore gzip level
- rather than printing usage message.
-
- * cvs.h, expand_path.c (variable_list): New variable.
- (variable_set): New function.
- * hash.h (enum ntype), hash.c (nodetypestring): Add VARIABLE.
- * expand_path.c (expand_path, expand_variable): Reindent.
- (expand_variable): Use user variables not environment variables
- for ${=VAR} syntax. The environment variables didn't work
- client/server.
- * main.c (main): Process new -s global option.
- * client.c (send_variable_proc): New function.
- (start_server): Call it, to send user variables.
- * server.c (serve_set): New function.
- (requests): Add Set request.
- * sanity.sh: Revise info test to use user variables rather than
- environment variables.
-
-Sat Feb 10 16:55:37 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- By itself this is only a small cleanup, but in the long run it
- will be way cool (for reference, it takes CVS's text segment from
- 290816 bytes to 294912, which I expect will be made up by future
- changes which this enables):
- * cvs.h (struct file_info): Added.
- (FILEPROC): Replace 5 args with single struct file_info *.
- * recurse.c (do_file_proc): Adjust args to fileproc; passed in
- instead of from globals.
- (do_recursion): Call do_file_proc accordingly. Remove srcfiles
- global variable.
- * update.c (update_fileproc): Renamed from update_file_proc.
- * admin.c, client.c, commit.c, diff.c, edit.c, log.c, patch.c,
- remove.c, rtag.c, status.c, tag.c, update.c, watch.c: Update
- fileprocs to new calling convention.
-
-Fri Feb 9 15:30:32 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * expand_path.c (expand_variable): Accept a variable name starting
- with '=' as a way to specify an environment variable.
- * sanity.sh (info): New tests, for above behavior.
-
- * Makefile.in (clean): Also remove check.log check.plog.
-
- * import.c (comtable): Remove SYSTEM_COMMENT_TABLE; the table
- should *not* depend on what kind of machine the server happens to
- be. Add "mak", "rc", "dlg", "frm", and "bas" types which were
- formerly included via SYSTEM_COMMENT_TABLE.
-
- * cvs.h, rcs.h, add.c, checkin.c, classify.c, commit.c, diff.c,
- import.c, patch.c, rcs.c, update.c, vers_ts.c: Remove
- DEATH_SUPPORT ifdefs. They were introduced to facilitate merging
- between Cygnus and Berliner variants of CVS, not because it was
- intended to subset CVS this way. And they clutter up the code
- quite a bit.
- * cvs.h, create_adm.c, main.c, update.c: Likewise, remove
- CVSADM_ROOT ifdefs (it is still a #define, of course). I believe
- they had a more-or-less similar motivation.
-
- * sanity.sh: Move setting of HOME from ignore test to the start of
- the tests so it applies to all tests.
- (CVS): Remove -f; the above change takes care of it.
-
- * rcs.h (RCS_MERGE): Removed; unused.
-
- * commit.c (checkaddfile): Fix memory leak.
-
- * admin.c, commit.c, diff.c, log.c, mkmodules.c: Pass -x,v/ to RCS
- commands.
-
- * rcscmds.c, cvs.h (RCS_checkin): New function.
- * checkin.c, commit.c, import.c: Call it, rather than run_*.
- * cvs.h, commit.c: Remove DEATH_STATE define; the behavior
- which used to be the default (DEATH_STATE) is now the only one.
- Failing to define DEATH_STATE has been commented as obsolete at
- least since CVS 1.5. We still can read repositories created with
- such a CVS, however.
- * rcs.h, rcs.c: Adjust comments regarding DEATH_STATE.
- * subr.c (make_message_rcslegal): Add comment, describing
- allocation of returned value.
-
-Fri Feb 9 09:53:44 MET 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * sanity.sh: use "${testcvs}" instead of "cvs" in devcom tests
-
- * hash.c: fix "dereferencing a NULL pointer" bug triggered with
- "cvs watch add"
- (findnode): return NULL if key == NULL
- (hashp): assert (key != NULL)
-
-Fri Feb 9 00:46:47 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_reparsercsfile): Remove unused variable date.
-
- * myndbm.c (mydbm_load_file): Fix typo ('015' -> '\015').
-
-Thu Feb 8 13:00:00 1996 Jim Kingdon <kingdon@peary.cyclic.com>
-
- * rcs.c (RCS_parse, RCS_parsercsfile, RCS_reparsercsfile),
- fileattr.c (fileattr_read), myndbm.c (myndbm_open):
- Use FOPEN_BINARY_READ.
- * fileattr.c (fileattr_write), myndbm.c (myndbm_close):
- Use FOPEN_BINARY_WRITE.
- * history.c (history_write, read_hrecs): Specify OPEN_BINARY.
- * rcs.c: Remove calls to abort.
- * myndbm.c (myndbm_load_file): Ignore CRs from ends of lines
- if present.
- * myndbm.c, fileattr.c: While I am at it, change \n to \012
- a few places where LF is intended.
- * history.c (history_write): Use getenv ("HOME"), not getpwnam,
- to find home directory. If it isn't set, just keep going; don't
- print a message.
- * rcscmds.c, cvs.h (RCS_checkout): New function.
- * update.c, checkin.c, commit.c, diff.c, import.c, no_diff.c,
- patch.c: Call it instead of run_*.
- * patch.c (patch_fileproc): Clean up inconsistent handling of
- noexec flag.
- * rcscmds.c (RCS_*): Pass -x,v/ to RCS commands; elsewhere in
- CVS it is assumed that ,v is a suffix.
-
-Fri Feb 2 14:07:32 1996 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * rcs.h (struct rcsnode): Remove dates field (list of rcsversnodes
- indexed by date). CVS maintained this list for each RCS file even
- though it was never used. This resulted in higher then necessary
- memory requirements (and run time too). Even if revision info was
- needed, CVS' List data structure is inappropriate because can't
- handle duplicate keys. The above was discovered by tracking down
- a memory leak.
- * rcs.c (RCS_reparsercsfile): Don't build dates list.
- (freercsnode): Don't delete dates list.
- (rcsvers_delproc): Free date field.
- (null_delproc): Removed.
-
-Thu Feb 1 12:28:33 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * remove.c (cvsremove): Don't tell user the name of the program
- which they use to remove files; we don't have any way of knowing
- that, and besides which they might use a GUI or emacs 'dired' anyway.
- * update.c (update_filesdone_proc, update_dirleave_proc): Call
- unlink_file_dir instead of rm -rf.
- * options.h.in: Remove RM; no longer used.
-
- * sanity.sh: New tests devcom-a* test "cvs watch add",
- "cvs watch remove", and "cvs watchers".
-
- * sanity.sh: New test 171a0 tests for watch.c bug just fixed by kfogel.
-
- * Most .c files: Remove rcsids.
- * cvs.h: Remove USE macro.
-
-Thu Feb 1 13:07:15 1996 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * tag.c, rtag.c: Update various comments to reflect function name
- changes.
-
-Thu Feb 1 14:14:31 1996 Karl Fogel <kfogel@floss.red-bean.com>
-
- * recurse.c (do_recursion): comment #endif.
-
- * edit.c (notify_check): surround with #ifdef CLIENT_SUPPORT; else
- CVS won't compile if CLIENT_SUPPORT is undefined.
-
- * edit.h (notify_check): surround declaration with #ifdef
- CLIENT_SUPPORT.
-
- * watch.c (watch): if argc <= 1, then just give usage (previously
- was "argc == -1").
-
-Thu Feb 1 12:28:33 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * README-rm-add: Remove information which is now in cvs.texinfo.
-
- * sanity.sh: Remove basic0 tests. Move a few to new tests
- basica-1a* (but there is no need to test that *every* command
- gracefully does nothing on an empty directory; exhaustive testing
- is impractical and the generic recursion processor handles this
- anyway).
-
- * sanity.sh: New tests 69a* test use of update -p to restore old
- version of dead file.
-
-Wed Jan 31 18:32:34 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * ChangeLog-9395: Remove duplicate entries from 1996 which
- accidentally got into this file.
-
- * client.c (read_line, read_from_server): Change "premature end of
- file from server" message to "end of file from server (consult
- above messages if any)" because 99% of the time it means rsh has
- printed an error message and exited.
-
-Wed Jan 31 15:09:51 1996 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * edit.c (ncheck_fileproc): Fix memory leak; free line before
- returning.
-
-Tue Jan 30 18:06:12 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * recurse.c (do_recursion): Add comment about the fact that we
- don't have locks in place at certain points.
-
-Tue Jan 30 09:43:34 1996 Vince Demarco <vdemarco@bou.shl.com>
-
- * edit.c (notify_proc): have notify_proc call expand_path with
- the name of the filter program. The user may have used a
- cvs environmental variable. (Popen will expand it, but it may not
- use the correct value)
-
-Tue Jan 30 09:43:34 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * ChangeLog: take the pre-1996 changes and put them in a new file
- ChangeLog-9395.
- * ChangeLog-9194: Renamed from ChangeLog.fsf.
- * ChangeLog-9194, ChangeLog-9395, ChangeLog: Add additional text
- explaining the difference between all these logs and pointing to
- older logs.
- * Makefile.in (DISTFILES): Add ChangeLog-9194 and ChangeLog-9395;
- remove ChangeLog.fsf.
-
- * modules.c (do_module): Don't fall through from 'l' to 'o' case
- of option processing switch statement.
-
-Tue Jan 30 06:50:19 1996 J.T. Conklin <jtc@rtl.cygnus.com>
-
- * client.c (send_repository): Fix memory leak; free adm_name
- before returning.
- * diff.c (diff_file_nodiff): Fix memory leak; free xvers before
- returning.
- * rtag.c (rtag_fileproc): Fix memory leak; if branch_mode is set,
- free rev before returning.
- * status.c (status_fileproc, tag_list_proc): Fix memory leak; free
- return value of RCS_whatbranch.
- * tag.c (tag_fileproc): Fix memory leak; free vers before
- returning.
- (val_fileproc): Fix memory leak; free return value of RCS_gettag.
- * watch.c (watch_modify_watchers): Fix memory leak; free mynewattr
- before returning.
-
-Tue Jan 30 09:43:34 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * lock.c (readers_exist): If stat gave an error, print an error
- message saying it was from stat, rather than from "reading
- directory". Skip the message completely if it was an
- existence_error.
-
- * sanity.sh (branches): New tests (branches off of branches, etc.).
-
-Tue Jan 30 11:55:34 MET 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * main.c (main): Add change to run getopt_long twice again.
-
-Mon Jan 29 15:59:31 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- gcc -Wall lint:
- * client.c: Include edit.h
-
-Sun Jan 28 09:45:53 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * edit.c, edit.h (mark_up_to_date): New function, to remove file
- in CVS/Base.
- * client.c (update_entries): Call it if file is up to date.
- * checkin.c (Checkin): Call it in non-server (local) case.
- * sanity.sh: New test 182.5, tests for above-fixed bug.
-
-Sun Jan 28 01:07:22 1996 Jim Kingdon (kingdon@beezley)
-
- * client.c (change_mode): Separate out CHMOD_BROKEN code to parse
- mode_string, rather than going through a mode_t. Cleaner than
- the previous CHMOD_BROKEN code (which also had a typo of && not &).
-
-Sat Jan 27 23:29:46 1996 Jim Kingdon (kingdon@beezley)
-
- * edit.c (edit_fileproc): Check for EACCESS as well as EEXIST.
-
-Sat Jan 27 16:26:30 1996 Karl Fogel (kfogel@floss.cyclic.com)
-
- * client.c (notified_a_file): use rename_file() instead of
- rename() (but temporarily set `noexec' to 0 so it runs
- unconditionally).
- (change_mode): deal with CHMOD_BROKEN.
-
-Fri Jan 26 00:14:00 1996 Karl Fogel <kfogel@floss.red-bean.com>
-
- * server.c: renamed `dirname' to `dir_name', to avoid conflicts
- with system headers.
-
- * client.c: renamed `dirname' and `last_dirname' to `dir_name' and
- last_dir_name' (see above). Not strictly necessary, but
- consistency is nice -- as long as you do it all the time.
-
-Thu Jan 25 00:41:59 1996 Karl Fogel <kfogel@floss.red-bean.com>
-
- * options.h.in (AUTH_SERVER_SUPPORT, AUTH_CLIENT_SUPPORT): change
- comment now that no longer under construction.
-
-Wed Jan 24 15:25:22 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Version 1.7.1.
-
- * Version 1.7.
-
-Sat Jan 20 00:05:08 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Version 1.6.87.
-
-Mon Jan 15 18:14:55 1996 Gary Oberbrunner <garyo@avs.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * tag.c (val_direntproc): New function to ignore
- nonexistent dirs when recursing to check tag validity.
- (tag_check_valid): Pass it to start_recursion.
- * sanity.sh (death): New tests 65a0-65a6 cause test 74 to test for
- above-fixed bug.
-
-Mon Jan 15 12:55:37 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c: Revert change to run getopt_long twice. This can go in
- after 1.7.
-
-Mon Jan 15 13:03:28 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * filesubr.c (deep_remove_dir): added test of EEXIST for nonempty
- directory (Posix states that both ENOTEMPTY (BSD) and EEXIST
- (SYSV) are valid)
-
- * main.c (main): run getopt_long twice to allow command-line
- suppression of reading the cvsrc file
-
-Fri Jan 12 10:02:43 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Version 1.6.86.
-
-Thu Jan 11 23:28:05 1996 J.T. Conklin <jtc@rtl.cygnus.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * fileattr.h (fileattr_startdir): Add comment about REPOS == NULL.
- * fileattr.c (fileattr_read, fileattr_write): Assert that
- fileattr_stored_repos != NULL.
- (fileattr_free): If fileattr_stored_repos is NULL, don't free it.
-
-Thu Jan 11 18:03:21 1996 Karl Fogel <kfogel@floss.red-bean.com>
-
- * scramble.c (descramble): deal with DIAGNOSTIC better.
-
-Thu Jan 11 12:04:42 1996 Norbert Kiesel <nk@col.sw-ley.de>
-
- * main.c: remove CVS_NOADMIN.
-
- * options.h.in: remove CVS_NOADMIN
-
-Thu Jan 11 10:28:44 1996 Karl Fogel <kfogel@floss.red-bean.com>
-
- * scramble.c (descramble): make sure the string returned is safe
- to free().
-
-Wed Jan 10 01:11:23 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (serve_notify): Cast return value from malloc.
-
- * edit.c (notify_do): Use struct assignment, not struct
- initialization (which SunOS4 /bin/cc doesn't have).
-
-Tue Jan 9 09:41:29 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Version 1.6.85.
-
- We use version numbers instead of patchlevels. But there was some
- confusing patchlevel stuff lying around. Nuke it:
- * Makefile.in (HEADERS): Remove patchlevel.h
- * patchlevel.h: Removed.
- * main.c: Don't include patchlevel.h.
- (main): Don't print patch level.
-
- * server.c (check_repository_password): Check for errors from
- system calls; reindent function.
-
-Tue Jan 9 23:15:30 1996 Karl Fogel <kfogel@floss.red-bean.com>
-
- * expand_path.c: fix comments (explain expand_path()'s behavior
- correctly).
-
-Tue Jan 9 09:41:29 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * edit.c (notify_proc): After copying in string following %s,
- don't clobber it. Instead set up q to end of string.
-
- * watch.c (watch_modify_watchers), edit.c (editor_set): Fix sense
- of test in trying to decide whether attributes are changed.
-
- * cvs.h (CVSROOTADM_USERS): New macro.
- * edit.c (notify_do): Look up notifyee in CVSROOTADM_USERS if it
- exists.
-
-Tue Jan 9 21:39:45 1996 Karl Fogel <kfogel@floss.red-bean.com>
-
- * expand_path.c: don't redundantly #include things that cvs.h
- already #includes (i.e., stdio.h, ctype.h, string[s].h).
-
-Tue Jan 9 09:41:29 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * ignore.c (ign_default): Add *.obj.
-
- * server.c: Put /* */ around #endif comment.
-
-Mon Jan 8 20:37:17 1996 Karl Fogel <kfogel@floss.red-bean.com>
-
- * client.c (connect_to_pserver): check return value of recv().
-
-Mon Jan 8 11:37:57 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (connect_to_pserver): Check for error from connect;
- reindent function.
-
- * sanity.sh (4.75): Use dotest, so we get a PASS if test passes.
-
- * sanity.sh (dotest): New argument OUTPUT2.
- (188a): Use it instead of \|.
-
- * sanity.sh (import): Avoid using string $ followed by Id followed
- by $ in sanity.sh source, in case sanity.sh itself is under CVS.
- I hate keyword expansion.
-
- * sanity.sh: If expr cannot handle multiline expressions, fail and
- tell the user to get one which can.
-
- * release.c (release_delete): Remove unused variable retcode.
-
-Fri Jan 5 13:30:00 1996 Jim Kingdon <kingdon@peary.cyclic.com>
-
- * release.c (release_delete): Call unlink_file_dir rather
- than "rm -rf".
-
-Thu Jan 4 09:58:30 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c (find_fileproc): Print "nothing known about foo" and
- return 1 if the file doesn't exist and isn't in CVS/Entries.
- (commit): If the recursion over find_fileproc returns an error,
- print "correct above errors first!" just like local CVS.
- * sanity.sh (basica): Test for above-fixed bug.
-
- * release.c (release): If we are the client, only unedit if the
- server supports it.
-
- * sanity.sh: Remove STARTANCHOR stuff; expr patterns are
- automatically anchored to the start. ENDANCHOR remains.
-
- * commit.c (commit): Don't start the server until we have
- determined that there is something to commit.
-
-Thu Jan 4 09:48:33 1996 Ben Laurie <ben@gonzo.ben.algroup.co.uk>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (start_server): dup the file descriptor before
- fdopening it.
-
-Wed Jan 3 18:25:25 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Remove tests 5, 5.5, and 5.75. All that stuff is
- tested elsewhere.
-
- * ignore.c (ign_default): Change CVS* to CVS CVS.adm. CVS* is too
- broad, especially in a case-insensitive filesystem.
-
- * Makefile.in (cvsbug): version.c is in srcdir.
-
-Wed Jan 3 17:30:45 1996 Phi-Long Tran <ptran@autodesk.com>
-
- * modules.c (do_module): Honor error_use_protocol in printing trace.
- * server.c (server_register): Move check for options NULL to above
- printing of the trace.
-
-Wed Jan 3 01:19:53 1996 Mark Immel <immel@centerline.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (checkout_file): Do not resurrect file on join if it
- doesn't contain the revisions we are joining. Probably not a
- perfect test, but should be an improvement.
- * sanity.sh (death): New death-file4-* tests, for bug fixed above.
-
-Wed Jan 3 01:19:53 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c, admin.c, checkout.c, client.c, commit.c, diff.c, edit.c,
- history.c, import.c, log.c, patch.c, release.c, remove.c, rtag.c,
- status.c, tag.c, update.c, watch.c: In calling send_to_server,
- pass \012 not \n. On the Mac \n is CR, not LF, and we want to
- send LF. I didn't try to deal with whether files in CVSADM should
- contain CR or LF--in fact there is some code in client.c which
- reads \n from CVSADM files and passes it to send_to_server; it
- needs to be cleaned up one way or the other.
-
- * entries.c (Entries_Open): Don't try to close fpin twice.
-
- * client.c (update_entries): Fix typo ("strlen (filename + 10)"
- -> "strlen (filename) + 10").
-
- * commit.c (checkaddfile): Remove arbitrary limit.
-
-Tue Jan 2 11:25:22 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c (commit): Only pass files which were modified, added,
- or removed to send_file_names. This has as a side effect a
- semantic change--the up-to-date check is now skipped for other
- files--but probably a good one, or at least not a bad one.
- * sanity.sh (basica): New test; tests for bug fixed above.
- * sanity.sh (187a3): Adjust for new 'cvs commit' output. Set up
- DOTSTAR to match arbitrary text (another GNU expr bug/misfeature,
- sigh).
-
- * sanity.sh: Test that the commit in test 43 actually worked.
- Merge tests basic2 and basic3 and make them independent of basic1.
- (pass,fail): Don't insert spurious space.
- (45.5): Fix typo in directory name.
-
-Tue Jan 2 13:00:00 1996 Jim Kingdon <kingdon@peary.cyclic.com>
-
- Visual C++ lint:
- * myndbm.c: Prototype write_item.
-
-Tue Jan 2 11:25:22 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- gcc -Wall lint:
- * client.c (client_expand_modules): Pass error message not "" to error.
- * client.c (supported_request), server.c (supported_response):
- Return a value (gcc -Wall can't know that error doesn't return).
- * commit.c (copy_ulist): Return a value.
- * history.c (fill_hrec): Don't make assumptions about whether
- time_t is "int" or "long" or what.
- * cvs.h: Declare link_file.
- * server.c: Include fileattr.h.
- * server.c (server_notify): Remove unused variable val.
- * tag.c (val_fileproc): Remove unused variable foundtag.
-
-Mon Jan 1 09:49:16 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Version 1.6.5.
-
- * Version 1.6.4.
-
- * filesubr.c (link_file): Add comment about link vs. copy semantics.
-
- * cvs.h (struct vers_ts): Fix comments.
- * commit.c (commit): Before we ask for a log message, figure out
- what is modified and what is not and pass the information to
- do_editor.
- (copy_ulist,find_fileproc): New helper functions for above code.
-
- * client.c (read_line): When writing to from_server_logfile, write
- the \n too.
-
- * client.c (send_files): No longer call send_file_names.
- * client.h: Update comment.
- * add.c, admin.c, commit.c, diff.c, edit.c, log.c, remove.c,
- status.c, tag.c, update.c, watch.c: Call send_file_names before
- send_files.
- * client.c: New variables module_argc, module_argv.
- (client_expand_modules): Set them, to arguments.
- (client_send_expansions): Use them instead of modules_vector to
- send arguments.
- * sanity.sh (modules): Add test of modules -d flag.
-
-
-For older changes see ChangeLog-9395.
diff --git a/contrib/cvs/src/ChangeLog-97 b/contrib/cvs/src/ChangeLog-97
deleted file mode 100644
index ce7180b39d36..000000000000
--- a/contrib/cvs/src/ChangeLog-97
+++ /dev/null
@@ -1,3249 +0,0 @@
-1997-12-30 enami tsugutomo <enami@but-b.or.jp>
-
- * rcs.c (RCS_checkin): Use gmtime() instead of localtime()
- (restores behavior from RCS 5.x which was broken with RCS library
- -kingdon).
-
-Mon Dec 29 12:53:00 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * modules.c (do_module): Check for a request for a file within a
- module which is not a directory.
- * sanity.sh (modules): Add test 149b1 for above patch.
-
- * client.c (start_tcp_server): Remove useless assignment, left
- behind by Dec 15 patch.
-
-Sat Dec 27 17:41:11 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c, options.h.in, history.c, import.c, main.c, rcs.c,
- update.c: Remove !HAVE_RCS5 code. It had bit-rotted a while ago,
- and more to the point is obsolete with the RCS library.
-
-27 Dec 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * zlib.c, server.h (gunzip_and_write): New function.
- * client.c (update_entries): Call it instead of a gunzip subprocess.
- * zlib.c, server.h (read_and_gzip): New function.
- * client.c (send_modified): Call it instead of a gzip subprocess.
-
-Sat Dec 27 13:07:38 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- Decrease RCS_deltas memory usage to what we need (approximately
- the size of the file we are patching plus the size of the largest
- patch). Previously memory usage had been approximately the size
- of the RCS file because we never freed lines until the end.
- * rcs.c (linevector_free, linevector_copy, linevector_add,
- linevector_delete):
- Instead of having all the lines and struct line's in the alloc_*
- space, have each line and its struct line in its own malloc'd
- space. Use a refcount to deal with curlines vs. headlines
- vs. trunklines in RCS_deltas.
- (struct allocblock, blocks, block_alloc, block_free): Remove; no
- longer used.
- (apply_rcs_changes, RCS_deltas): Don't copy lines into allocated
- space; linevector_add now does that for us.
- (rcs_change_text, RCS_deltas): Don't call block_free.
-
-Tue Dec 23 08:28:44 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * cvsbug.sh: Change bug-cvs address from prep.ai.mit.edu to gnu.org
- per email from Martin Hamilton.
-
-Sun Dec 21 21:49:50 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_checkin): Disable keyword expansion when generating
- the change text.
- * sanity.sh: Move tests keyword-24 through keyword-27 into
- new section keywordlog and expand greatly. Note that CVS 1.9.18
- passes the new tests both local and remote but the current
- version failed them both local and remote before this fix.
-
-Sat Dec 20 19:56:00 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_delete_revs): Clean up temporary files even if noexec.
- Without this fix, basica-o5a in sanity.sh would leave files around.
-
-Thu Dec 18 13:05:00 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * run.c: Fix typo in declaration (evecvp -> execvp) (credit to
- Erik Walthinsen for reporting this). Only declare it if not
- HAVE_UNISTD_H. Move declaration to before the first use.
-
-Tue Dec 16 12:59:00 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c: Collapse two identical declarations for join_file.
-
-Mon Dec 15 16:01:49 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * client.c (start_tcp_server): Remove calls to htons and add one
- call to ntohs (init_sockaddr calls htons on the port argument).
-
-Mon Dec 15 00:07:02 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (failure_exit): New variable.
- (get_server_responses): If it is set, then return
- failure.
- (updated_seen, updated_fname): New variables.
- (update_entries): Use updated_fname if set. In the "move away
- foo.c; it is in the way" case print "C" not "U", and set
- failure_exit.
- (handle_mt): If we get +updated tagged text, stash it away in
- updated_fname rather than printing it immediately.
- (handle_mt, get_server_responses): If we stashed a filename and
- didn't get around to printing it, go ahead and print it.
- * sanity.sh (conflicts2-142d2): Adjust to test for fix. Remote is
- now like local was in terms of exit status and "C aa.c" message.
-
-Sun Dec 14 00:27:26 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- Implement tagged text feature:
- * update.c (write_letter): Take a single finfo argument rather
- than file and update_dir. While we are at it change it to return
- void (since the returned value always had been 0).
- * update.c: Update callers.
- * server.c, cvs.h (cvs_output_tagged): New function.
- * client.c (responses): Add "MT" response.
- (handle_mt): New function.
- * update.c (write_letter): Output via cvs_output_tagged.
-
-Sun Dec 14 14:13:05 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * recurse.c (do_dir_proc): Only check for CVS/Repository if
- W_LOCAL.
- * sanity.sh (devcom-t2, devcom-t3): New tests for above patch.
-
-Sun Dec 14 00:27:26 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * root.c (parse_cvsroot): Initialize check_hostname (fixes thinko
- in GSSAPI changes).
-
-Sat Dec 13 13:15:35 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c: Use indentation to indicate nesting of #ifdef's.
-
- * client.c (connect_to_gserver): Reindent (in one place).
-
-Fri Dec 12 17:38:15 1997 Chris Provenzano <proven@cygnus.com>
- and Ian Lance Taylor <ian@cygnus.com>
-
- * cvs.h (CVSmethod): Add gserver_method.
- * root.c (method_names): Add gserver.
- (parse_cvsroot): Handle :gserver:.
- * client.h (cvsauthenticate): Declare.
- (cvs_gssapi_encrypt): Declare if HAVE_GSSAPI and ENCRYPTION.
- (cvs_gssapi_wrap_buffer_initialize): Declare if HAVE_GSSAPI.
- (connect_to_pserver): Update declaration.
- (pserver_authenticate_connection): Declare when HAVE_GSSAPI and
- SERVER_SUPPORT is defined in addition to other case.
- * client.c: If HAVE_GSSAPI, include GSSAPI header files.
- (gcontext): New static variable if HAVE_GSSAPI.
- (connect_to_pserver): Add do_gssapi parameter. Change all
- callers. Move rejection handling to bottom of function.
- (recv_bytes): New static function if HAVE_GSSAPI.
- (connect_to_gserver): Likewise.
- (start_server): Handle gserver_method. Handle GSSAPI encryption
- and authentication.
- * server.c: Include <sys/socket.h> if HAVE_GSSAPI, in addition to
- existing cases. If HAVE_GSSAPI, include GSSAPI header files.
- Include <grp.h> even if AUTH_SERVER_SUPPORT is not defined.
- (gcontext, cvs_gssapi_wrapping): New static variables if
- HAVE_GSSAPI.
- (cvs_gssapi_encrypt): New global variable if HAVE_GSSAPI and
- ENCRYPTION.
- (serve_gssapi_encrypt): New static function if HAVE_GSSAPI and
- ENCRYPTION.
- (serve_gssapi_authenticate): New static function if HAVE_GSSAPI.
- (requests): Add Gssapi-encrypt if HAVE_GSSAPI and ENCRYPTION. Add
- Gssapi-authenticate if HAVE_GSSAPI.
- (switch_to_user): Compile if HAVE_GSSAPI, in addition to existing
- cases.
- (pserver_authenticate_connection): Likewise. Ifdef out part of
- the code for AUTH_SERVER_SUPPORT. Handle a GSSAPI request.
- (gserver_authenticate_connection): New static function if
- HAVE_GSSAPI.
- (cvsauthenticate): New global variable.
- (struct cvs_gssapi_wrap_data): Define if HAVE_GSSAPI.
- (cvs_gssapi_wrap_buffer_initialize): New function if HAVE_GSSAPI.
- (cvs_gssapi_wrap_input): New static function if HAVE_GSSAPI.
- (cvs_gssapi_wrap_output): Likewise.
- * main.c (opt_usage): Mention -a.
- (main): Handle -a. Handle pserver if HAVE_GSSAPI, in addition to
- existing cases.
- * login.c (login): Pass new argument to connect_to_pserver.
-
-Fri Dec 12 15:33:19 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * buffer.c (PACKET_SLOP): Define.
- (packetizing_buffer_initialize): Use PACKET_SLOP when allocating
- holdbuf.
- (packetizing_buffer_input): Allow up to PACKET_SLOP bytes in
- stackoutbuf.
- (packetizing_buffer_output): Use just BUFFER_DATA_SIZE + 2 for
- inbuf. Allow PACKET_SLOP + 4 extra bytes in stack_outbuf.
- Correct >= to > in test of incoming number of bytes. Use
- PACKET_SLOP in other tests.
-
-Fri Dec 12 10:27:08 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (start_tcp_server): Revise comment to reflect
- SOCK_STRERROR and SOCK_ERRNO now being in use.
-
-Thu Dec 11 15:32:31 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * client.c (init_sockaddr): Compile if HAVE_KERBEROS, as well as
- if AUTH_CLIENT_SUPPORT. Return a pointer to a struct hostent.
- (start_tcp_server): Clean up. Use init_sockaddr. Use
- SOCK_STRERROR and SOCK_ERRNO. Don't bind the socket.
-
- Generalize buffering code used by Kerberos encryption routines
- into a generic packetizing buffer. The new code in buffer.c is a
- modified version of the code removed from server.c.
- * buffer.c (struct packetizing_buffer): Define.
- (packetizing_buffer_initialize): New function.
- (packetizing_buffer_input): New static function.
- (packetizing_buffer_output): New static function.
- (packetizing_buffer_flush): New static function.
- (packetizing_buffer_block): New static function.
- (packetizing_buffer_shutdown): New static function.
- * buffer.h (packetizing_buffer_initialize): Declare.
- * server.c (struct krb_encrypt_data): Rename from
- krb_encrypt_buffer, and remove all fields not related to
- encryption.
- (krb_encrypt_buffer_initialize): Just call
- packetizing_buffer_initialize.
- (krb_encrypt_input): New static function.
- (krb_encrypt_output): New static function.
- (krb_encrypt_buffer_input): Remove.
- (krb_encrypt_buffer_output): Remove.
- (krb_encrypt_buffer_flush): Remove.
- (krb_encrypt_buffer_block): Remove.
- (krb_encrypt_buffer_shutdown): Remove.
-
-Wed Dec 10 15:39:44 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * buffer.c (stdio_buffer_initialize): Correct formatting.
-
-Sun Dec 7 09:37:19 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basicb-0d0): New test, for checkout on existing
- directory.
-
-Sat Dec 6 00:25:11 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (binwrap3): Clean up repository too. Clean up working
- directory with "rm -r" not "rm -rf".
-
-Thu Dec 4 17:11:18 1997 Larry Jones <larry.jones@sdrc.com>
-
- * subr.c (check_numeric): Don't reference argv[1] when argc is 1
- (should be argv[0]).
-
- * sanity.sh: Fix lines that look like conflict markers but aren't
- to prevent problems checking in.
- (binwrap3): Remove local CVSROOT when done so that later
- tests that expect to create it don't fail.
-
-Thu Dec 4 18:19:21 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * cvs.h: Remove mempcpy definition. I think the polite way to
- describe my feelings about mempcpy is something like "we don't
- have agreement that it is a good idea".
- * rcs.c (truncate_revnum): Don't call it.
- * sanity.sh: Run multibranch2 test by default.
- (multibranch2): Use ${TESTDIR} a few places.
- (multibranch2-9): Accept "P file1" as well as "U file1".
-
- * sanity.sh: Don't add 1997 to the copyright notice. Add GPL
- terms. Add discussion of copyright issues.
- * rcs.c (truncate_revnum, truncate_revnum_in_place,
- compare_truncated_revnums): Reindent.
-
-1997-12-04 Jim Meyering <meyering@na-net.ornl.gov>
-
- * subr.c (xstrdup): Use memcpy rather than strcpy.
- (compare_revnums): Declare parameters to be `const'.
- Remove unnecessary uses of xstrdup and corresponding frees.
- (increment_revnum): Declare parameter to be `const'.
- Use memcpy rather than strcpy.
- (gca): Declare parameters to be `const'.
- (check_numeric): Declare REV parameter to be `const'.
- (file_has_markers): Declare parameter to be `const'.
- (get_file): Declare `char*' parameters to be `const'.
- * run.c (run_exec): Declare `char*' parameters to be `const'.
- * cvs.h (mempcpy) [! HAVE_MEMPCPY]: Define it.
- Add `const' to types in several prototypes.
-
- * rcs.c (truncate_revnum): New function.
- (truncate_revnum_in_place): New function.
- (compare_truncated_revnums): New function.
- (max_rev): New function.
- (RCS_addbranch): Make BRANCH parameter `const'.
- Use the above functions rather than open-coding them.
- When BRANCH is a revision number, insert it *in order*
- in the sorted list of branch numbers, not at the end.
- Add assertion that insertion succeeds.
- * sanity.sh (multibranch2): Test for this.
- (Copyright): Add 1997.
-
-Dec 1997 Karl Fogel <kfogel@floss.red-bean.com>
-
- * wrapper.c (wrap_name_has): loop as far as wrap_count +
- wrap_temp_count, not wrap_count + wrap_saved_count, otherwise
- some wrappers get skipped.
- (wrap_matching_entry): same.
- * sanity.sh (binwrap3): new test, for import with
- CVSROOT/cvswrappers and .cvswrappers specifying -k 'b' options.
-
-1997-11-30 Jim Meyering <meyering@na-net.ornl.gov>
-
- * client.c (send_a_repository): Strip trailing slashes from the name
- of the update directory. Otherwise, running `cvs update dir/' provokes
- this failure `protocol error: illegal directory syntax in dir/' when
- running in client/server mode.
-
- * hash.c (insert_before): New function derived from addnode.
- (addnode): Simply return insert_before.
- (addnode_at_front): Simply return insert_before.
- * hash.h (insert_before): Add prototype.
-
- * server.c (dirswitch): Compute `strlen(dir)' once and save it,
- rather than computing it four times. Also do s/illegal/invalid/ to
- this diagnostic: "E protocol error: illegal directory syntax in %s".
-
-Sun Nov 30 18:03:02 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * admin.c: Fix comment (no longer a front-end to "rcs").
-
- * error.c, error.h (rcserror): Remove.
- * admin.c, rcs.c: Call error instead of rcserror. This changes
- the format of these messages from "rcs: <path>: error" to "cvs
- <command>: <path>: error". The former format wasn't quite what
- RCS printed anyway (because RCS would sometimes print "ci", "co",
- &c, not "rcs"), and preserving RCS's exact output probably is not
- a good idea anyway (because it will make people think that the
- error was caused by an external program). In two cases, I tidied
- up the message in a more drastic fashion ("cannot stat" in
- RCS_checkin and "could not diff" in RCS_delete_revs).
-
- * sanity.sh (basica-o2b, binfiles2-o1, admin-18, admin-22-o10,
- admin-22-o17): Look for "cvs <command>" not "rcs".
-
- * run.c, cvs.h (run_setup): Replace varargs nonsense with a single
- argument which gets parsed as the result of the vasprintf
- used to.
- * client.c, commit.c, logmsg.c, modules.c, rtag.c, tag.c, update.c,
- wrapper.c: Update callers, either to do the sprintf themself or to
- just call run_arg if it will do the job.
- * rcscmds.c: Likewise for call_diff_setup and callers.
-
- * run.c, cvs.h (run_args): Remove; nowhere used.
-
-Sat Nov 29 22:15:06 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * options.h.in: Remove declaration of getwd; see lib/ChangeLog for
- rationale.
-
-1997-11-29 Jim Meyering <meyering@na-net.ornl.gov>
-
- * update.c (checkout_file): Initialize `backup'.
-
- * diff.c (diff_fileproc): Initialize `tmp' and `fname'.
-
- * modules.c (do_module): Initialize `server_dir_to_restore'.
- (do_module): Initialize `value' in an else clause.
-
- * rcs.c (RCS_checkin): Initialize `commitpt'.
- (RCS_delete_revs): Initialize `revp'.
- (RCS_copydeltas): Always initialize `insertbefore'.
-
- * run.c (run_print): Define `outfn' even in error case.
-
-Mon Nov 24 17:28:50 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_findlock_or_tip): Prototype.
- (RCS_checkin): Fix call to pass correct number of arguments.
-
-Sun Nov 23 10:34:03 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * recurse.c (do_dir_proc): Move check for CVS/Repository and
- CVS/Entries to before where we call the direntproc.
- * client.c (send_dirent_proc): Remove code to check for
- CVS/Repository, now that recurse.c does it.
- * sanity.sh (conflicts3-18 through conflicts3-19): New tests, for this.
-
-Sat Nov 22 10:54:16 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * recurse.c (do_dir_proc): Check that CVS/Repository and
- CVS/Entries exist.
- * sanity.sh (conflicts3-14 through conflicts3-17): New tests, for this.
-
- * client.c (send_fileproc): Send options field from
- vers->entdata->options not vers->options.
- * cvs.h (struct entnode): Add comment (options and timestamp must
- not be NULL).
- * sanity.sh (binfiles-9 through binfiles-13, binfiles-sticky5,
- keyword-17): Remove kludges for remote; tests for fix.
-
- * update.c (update_fileproc): Fix comment; direct checkout is
- still faster than patches for local but not for quite the
- same reasons.
-
- * add.c (add): Pass SEND_NO_CONTENTS to send_files.
-
-Wed Nov 19 18:25:03 1997 Mike Glendinning <mikeg@sequent.com>
-
- * update.c (patch_file_write): Missing cast provided.
-
-Wed Nov 19 15:57:59 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_deltas): Solve trigraph problem (once and for all, I
- hope) with 3 calls to cvs_output.
-
-Wed Nov 19 01:52:57 1997 Andy Piper <andyp@parallax.co.uk>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * classify.c (Classify_File), cvs.h (struct vers_ts), vers_ts.c
- (Version_TS): Clarify NULL versus "" for options in comments.
- * vers_ts.c (Version_TS): Treat "" the same way as NULL in options
- and vers_ts->options.
- * sanity.sh: New tests binfiles-sticky5 through binfiles-17 test
- for this.
-
-1997-11-16 Karl Fogel <kfogel@floss.red-bean.com>
-
- * client.c (update_entries): parse server-sent entries line even
- in the case of "cvs export", because we need to know if -kb option
- is set.
- Init `options' to NULL like anything else.
-
-Tue Nov 18 09:20:29 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Change version number to 1.9.21.
-
- * Version 1.9.20.
-
-Mon Nov 17 14:35:31 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (server_updated): If scratched_file and noexec are set,
- clean up so we don't get a "duplicate Scratch_Entry" warning
- later.
- * sanity.sh: New tests conflicts3-10 to conflicts3-13, for this.
-
- * sanity.sh (conflicts3): Don't allow "file1 was lost" messages
- here; I don't think CVS actually produced them, and they don't
- belong.
-
-Sun Nov 16 23:19:41 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Accept either "U file1" or "P file1".
-
-Fri Nov 14 12:32:05 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c: Add comment about cleaning up ,foo, file on ^C.
-
-Fri Nov 14 11:56:29 1997 Andy Piper <andyp@parallax.co.uk>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * filesubr.c (unlink_file_dir): Don't print trace message in the
- server.
-
-Fri Nov 14 11:28:55 1997 Jim Meyering and Jim Kingdon
-
- * rcs.c (RCS_getdatebranch): If the branch we are looking for
- doesn't exist, return a revision which matches the date, not
- just NULL.
- * sanity.sh (tagdate): New test, for this.
-
-Thu Nov 13 10:11:48 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basicb-21): Fix comment which described a behavior
- which no longer exists.
-
-Wed Nov 12 16:24:45 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- Clean up infrastructure made unnecessary by RCS library:
- * rcscmds.c (diff_exec, diff_execv): Use literal "diff" not DIFF.
- * options.h.in (DIFF), rcs.h (RCS, RCS_CI, RCS_DIFF,
- RCS_RCSMERGE): Removed; no longer used.
- * commit.c (commit), patch.c (patch_fileproc),
- rcscmds.c (RCS_exec_rcsdiff), start of rcscmds.c: Update comments
- to reflect librarification of RCS.
- * options.h.in (RCSBIN_DFLT): Removed.
- * main.c, cvs.h (Rcsbin, free_Rcsbin): Removed.
- * main.c (main): Don't check RCSBIN environment variable. -b
- global option is now a noop.
- * cvs.h (RCSBIN_ENV): Removed.
- * expand_path.c (expand_variable): $RCSBIN is now an error.
- * mkmodules.c (config_contents): Remove RCSBIN.
- * parseinfo.c (parse_config): RCSBIN now a noop.
- * server.c (server): Don't put Rcsbin in PATH.
-
-Mon, 10 Nov 1997 Jim Kingdon
-
- * rcs.c (RCS_checkin): Actually, when we get a change text
- for a text file using get_file, we want text mode, although
- the reasons are kind of subtle (see comment).
-
- * rcs.c (RCS_checkin): Pass correct mode to get_file for
- binary files.
-
- * rcscmds.c: Declare vasprintf.
-
-Mon Nov 10 11:11:17 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- This fixes problems with windows-NT/run.c improperly quoting, and
- is cleaner anyway.
- * rcscmds.c (call_diff_setup, call_diff_arg, call_diff_add_arg,
- call_diff_argv, call_diff_argc, call_diff_argc_allocated): New
- functions/variables, lightly adapted from src/run.c.
- * cvs.h, run.c (call_diff, call_diff3): Move from here...
- * rcscmds.c: ...to here.
-
-Sun, 9 Nov 1997 Jim Kingdon
-
- * rcs.c (rcs_internal_unlockfile): Call rename_file not rename.
- This makes it work on NT again.
-
-Sun Nov 9 16:54:28 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (diffmerge2): Protect keywords against unwanted
- expansion. They got clobbered and the testcase stopped working
- when I checked it in.
-
-Fri Nov 7 13:23:38 1997 Karl Fogel <kfogel@floss.red-bean.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (diffmerge1, diffmerge2): new tests, for bugs, or
- potential bugs, in ../diff/analyze.c which were fixed by Paul
- Eggert's patch.
-
-Sun Nov 9 10:28:43 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_settag): Reindent.
-
- * rcs.c (rcs_internal_lockfile): Fix typo (thow -> throw).
-
-Sat Nov 8 15:58:53 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (cvsadm): Remove most of the tests which tested
- CVS/Root. This takes the run time for the cvsadm tests from
- about 5 minutes 15 seconds to about 4 minutes 10 seconds with no
- significant loss in coverage.
-
- * rcs.c (rcs_internal_lockfile): Check for errors from system
- calls. If open() gives an error, don't muck with stat and errno
- (I don't know what the RCS code that this comes from was trying to
- do, but it clearly isn't accomplishing anything here).
- (RCS_rewrite, RCS_delete_revs): Check for errors from system calls.
-
-Sat Nov 1 14:21:29 1997 Michael L.H. Brouwer <michael@thi.nl>
-
- * rcs.c (RCS_checkin): Change type of bufsize from int to size_t.
- (RCS_delete_revs): Change type of bufsize and len from int to size_t.
- (RCS_getdeltatext): Change type of textlen from int to size_t.
- * rcs.h (struct deltatext): Change len from int to size_t to keep
- the compiler happy on systems where size_t is unsigned int.
- [This goes well beyond keeping the compiler happy; if sizeof
- (size_t) != sizeof (int), the old code was quite broken -kingdon]
-
-Sat Nov 1 14:21:29 1997 Michael L.H. Brouwer <michael@thi.nl>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_checkin): When checking if we were holding the lock
- use delta->author instead of user since the latter might have been
- clobbered by a call to getcaller. This resulted in the failure of
- test basica-7.
- [I don't completely follow the scenario where it gets clobbered,
- it but sounds vaguely plausible and the replacement seems
- cleaner, precisely because it avoids allocation issues -kingdon]
-
-Wed Nov 5 20:16:12 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * checkin.c, checkout.c, commit.c, cvs.h, import.c, login.c,
- main.c, update.c: Change FALSE to 0 and TRUE to 1 and replace
- monstrosities like "cvswrite == TRUE" with just "cvswrite". FALSE
- and TRUE sometimes conflicted with system headers (NextStep3.3?),
- but more to the point, good old 1 and 0 are fine and were used by
- most of CVS already.
-
-Tue Nov 4 12:19:28 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_checkin, RCS_lock, RCS_unlock): Rename local variable
- quiet to checkin_quiet or some such, to avoid confusion with
- global variable quiet.
-
- * lock.c: Update comment to refer to add_rcs_file rather than "rcs
- -i".
-
- * rcs.h (struct rcsnode): Add comments for all fields.
- * rcs.c (RCS_delete_revs): Refuse to delete revisions which have
- symbolic names. Fix fencepost bug which caused us to sometimes
- check one more revision than we should for locks, branches, and
- this.
- (findtag): New function, to help above code.
-
- * admin.c (admin): Take out writelocks not readlocks. This has
- been a bug "forever", but may become more noticeable with
- rcs_internal_lockfile relying on the writelocks.
-
-Mon Nov 3 10:17:19 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_rewrite): Don't write the file if noexec.
- * sanity.sh (basica, branches): Test for this.
-
-Sat Nov 1 10:01:56 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.h (struct deltatext): Comment text and log fields.
-
- * admin.c (admin_fileproc): Call RCS_reparsercsfile not
- RCS_fully_parse. Don't muck with ->other field in RCSVers (it
- doesn't need to be set).
- * rcs.h, rcs.c (RCS_reparsercsfile): No longer static. No point
- in having this static when RCS_rewrite and RCS_fully_parse are not.
- * rcs.c (getdelta): Remove obsolete comment about not storing the
- newphrases from the deltas, since we now do.
-
-Sat Nov 1 10:01:56 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
- and Paul Eggert
-
- * rcs.c (rcs_internal_lockfile): Clarify the comments about O_EXCL
- and such matters.
-
-Sat Nov 1 10:01:56 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_delete_revs): Pass force_tag_match to RCS_settag.
- * sanity.sh (basica-o2a, basica-o2b): Test for this.
-
-1997-11-01 Peter Brandstrom <d91-pbr@nada.kth.se>
-
- * sanity.sh: Use ${username} more places.
-
-Sat Nov 1 00:14:00 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (rcs_internal_lockfile): Add comments about what we are
- trying to accomplish here (versus what RCS tries to accomplish).
-
- * rcs.c (RCS_parsercsfile_i): Clarify/expand comment about
- the purpose of having both this and RCS_reparsercsfile.
- (RCS_rewrite): Add comment about how this works.
-
- * admin.c (admin_fileproc): Add comment about call to
- RCS_fully_parse not RCS_reparsercsfile.
- * rcs.h: Comment on what delta_pos field of struct rcsnode is.
-
-Fri Oct 31 16:38:39 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
- and Abe Feldman
-
- * client.c (update_entries): If UTIME_EXPECTS_WRITABLE, if
- necessary change the file to be writable temporarily to set its
- modification time.
-
-Thu Oct 30 17:42:59 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * admin.c (admin): Deal with new :: syntax for ranges.
- * rcs.c, rcs.h (RCS_delete_revs): New arg inclusive (set for the old
- behavior, clear to enable new code).
- * admin.c (admin_fileproc): Set it if :, clear it if ::.
- * sanity.sh (basica, head, branches, log): Add tests for this feature.
-
- * admin.c (admin_fileproc): Clean up the error message which
- happens if one of the RCS_* functions returns an error status; it
- is confusing to say that "rcs" failed now that this is implemented
- internally.
- * sanity.sh (admin): Update accordingly.
-
-Wed Oct 29 07:07:36 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (admin-22-o24): New test, tests that admin -o
- correctly munged the deltatexts on a branch too.
-
- * rcs.c (RCS_delete_revs): If we are deleting an entire branch,
- delete the node in ->branches rather than setting the ->key to the
- bogus value NULL.
- * rcs.c (RCS_delete_revs): If "rev1" equals "branchpoint", then set
- "before" to the revision on the trunk that we branch from.
- * rcs.c (RCS_delete_revs): Don't set rev2 to revp->version (the
- code is missing an xstrdup, but it doesn't matter because rev2
- isn't used after this point).
- * sanity.sh (binfiles2-o2 to binfiles2-o4): New tests, for this.
-
-Tue Oct 28 19:30:05 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_delete_revs): Restore code which passes rev2 to
- RCS_getbranchpoint if rev1 is NULL; it still makes sense for the
- non-trunk case. Fixes admin-22-o22 in testsuite.
-
- * sanity.sh (admin-18): Adjust to reflect "rcs failed" no longer
- being suppressed by global -q option.
-
- * rcs.c (RCS_delete_revs): If rev1 == NULL and rev2 is on the
- trunk, handle it the same way we do everything else--by swapping
- the two. This replaces the code which tried to kludge what we
- passed to RCS_getbranchpoint (which didn't work).
- * sanity.sh (binfiles2-o1 to binfiles2-o4): New tests, for this fix.
- * admin.c (admin_fileproc): Don't have -q global option suppress
- "rcs failed" message.
-
-1997-10-28 Jim Kingdon
-
- * log.c (printlock_proc), rcs.c (putlock_proc): Prototype.
- * rcs.c (rcs_internal_lockfile): Only try to call fchmod if
- HAVE_FCHMOD is defined.
-
-Tue Oct 28 10:27:03 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (RCS_deltas): Don't use \? in string if __STDC__ is not
- defined.
-
- * rcs.c (make_file_label): Remove extraneous `+'.
-
-Mon Oct 27 14:40:15 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * status.c (status): Don't pass SEND_NO_CONTENTS to send_files.
-
-Sat Oct 25 00:33:57 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_delete_revs): Use : not - for range in error message.
-
- * rcs.h: Add comment about '\0' in RCS fields.
-
- * rcs.c (getdelta): Add comment about branches and next field
- being mandatory.
-
- * rcs.c (RCS_reparsercsfile, RCS_deltas), sanity.sh (reserved):
- Reindent sections which were misindented as a result of recent
- changes.
-
-Fri Oct 24 10:22:15 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_findlock_or_tip): Don't worry about file ownership
- and nonstrict locking when returning the default branch or head.
- The most conspicuous problem with the old code is that in the
- error case it would examine rstat.st_uid when it had not been
- set. For a discussion of more fundamental reasons, see comment.
-
- * admin.c (admin_fileproc): In handling -A, don't handle relative
- pathnames differently from absolute pathnames. See comment for
- rationale. If problem opening the file, give a nice error not a
- coredump.
- * sanity.sh (admin-19a-admin, admin-19a-log, admin-19a-fix):
- New tests, test for traditional "cvs admin -A" behavior with
- relative pathnames.
- * sanity.sh (admin-19a-nonexist): Test for the core dump fix.
- * sanity.sh (admin-22-o1): Look for ${PROG} not cvs.
-
- * sanity.sh (reserved-16): Remove commitinfo change with "cvs
- commit" not "cvs admin -o". In addition to commit being The Right
- Thing on general principles, cvs admin -o doesn't work because it
- doesn't rebuild the administrative file database.
-
- * update.c (patch_file): If the first revision does not exist in
- the RCS file, fall back to sending entire file. Fixes
- admin-22-o15 in make remotecheck.
-
-1997-10-23 enami tsugutomo <enami@but-b.or.jp>
-
- * rcs.c (RCS_checkin): Unlink temporary files stored in variable
- `tmpfile' and `changefile'.
-
-Wed Oct 22 12:16:10 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (rcs_lockfilename): Allocate enough memory for terminating
- '\0'.
-
- * admin.c (admin_fileproc): Don't support '-' for ranges in "cvs
- admin -o".
- (admin): Adjust comment.
-
- * rcs.h (RCSVers): New field other_delta.
- * rcs.c (free_rcsvers_contents): Also free other_delta.
- (getdelta): Read newphrases from deltas into other_delta field.
- (putdelta): Write those newphrases.
- * sanity.sh (rcs-8a): New test, for this fix.
- * admin.c (admin_fileproc): If "-b" without argument, then set
- branch to NULL, not "" (uncovered by rcs-8a test).
- * rcs.c (putrcsfield_proc): Add comment about how we (mis)handle
- values in newphrases.
-
- * sanity.sh (reserved): Instead of looking for rcslock.pl in CVS
- distribution, just use our own equivalent.
-
- * rcs.c (RCS_rewrite): Call ferror before fclose to avoid "Invalid
- argument" warnings.
-
-Mon Oct 20 00:30:16 1997 Tim Pierce <twp@twp.tezcat.com>
-
- [I removed a ChangeLog entry for a change to sanity.sh (editor),
- because the actual change was not made. With this change, CVS no
- longer runs RCS. I'll be checking in my cleanups shortly. -kingdon]
-
- Librarify `ci'.
- * rcscmds.c, cvs.h (RCS_checkin): Removed.
- * rcs.c, rcs.h (RCS_checkin, RCS_getbranchpoint, RCS_addbranch,
- RCS_findlock_or_tip): New functions. RCS_checkin completely
- rewritten to eliminate RCS 5.7; change `rcs' parameter from string
- to RCSNode, so we can update RCSNode without re-reading from
- disk.
- * checkin.c (Checkin): Updated RCS_checkin caller, moved RCS_parse
- call to before RCS_checkin.
- * import.c (add_rev): Updated caller.
- * commit.c (remove_file): Updated caller.
- (checkaddfile): Updated caller. Parse `rcsfile' after
- calling add_rcs_file. Free `rcsfile' instead of asserting it to
- be NULL.
-
- Librarify `rcs'.
- * rcscmds.c, cvs.h (RCS_exec_settag, RCS_exec_deltag,
- RCS_exec_setbranch, RCS_exec_lock, RCS_exec_unlock): Removed.
-
- * rcs.c (RCS_settag): Rewritten to eliminate RCS 5.7.
- * commit.c (checkaddfile): Call RCS_rewrite after calling RCS_settag.
- * import.c (add_tags): Same.
- * rtag.c (rtag_fileproc): Same.
- * tag.c (tag_fileproc): Same.
-
- * rcs.c (RCS_deltag): Rewritten to eliminate RCS 5.7. Remove
- `quiet' parameter, since this function no longer prints any output.
- * commit.c (remove_file): Update caller. Also call RCS_rewrite
- after RCS_deltag.
- * rtag.c (rtag_delete): Same.
- * tag.c (tag_fileproc): Same.
-
- * rcs.c (RCS_setbranch): Rewritten to eliminate RCS 5.7.
- * commit.c (remove_file): Call RCS_rewrite after calling RCS_setbranch.
- (fixbranch): Same.
- (lock_RCS): Same.
-
- * rcs.c (RCS_lock): Rewritten to eliminate RCS 5.7. Change third
- arg to mean `quiet' and not `noerr', permitting admin_fileproc to
- run RCS_lock verbosely.
- * commit.c (lock_RCS): Update callers; call
- RCS_rewrite after RCS_lock.
- (remove_file): Same. Call RCS_lock quietly.
- * import.c (add_rev): Same. Do not print `fork failed' error
- message, since we're no longer forking.
-
- * rcs.c (RCS_unlock): Rewritten to eliminate RCS 5.7. Change
- `noerr' arg to mean `quiet', permitting admin_fileproc to run
- RCS_unlock verbosely. Use notify_do when breaking another user's
- lock. Include "edit.h" for notify_do prototype.
- * checkin.c (Checkin): Update caller; use RCS_rewrite after RCS_unlock.
- * commit.c (unlockrcs): Same.
- * import.c (add_rev): Same.
-
- * rcs.c, rcs.h (RCS_getlocks, RCS_addaccess, RCS_delaccess,
- RCS_getaccess, RCS_delete_revs): New functions.
- (expand_keywords, RCS_lock, RCS_unlock): Use RCS_getlocks.
- * log.c (log_fileproc, log_version): Call RCS_getlocks. Don't add
- bogus ";locker" nodes to RCSVers nodes -- walk lock list with
- printlock_proc.
- (printlock_proc): New function.
-
- * admin.c (admin_fileproc): Largely rewritten: call internal RCS
- library functions instead of forking RCS processes.
- (admin, admin_fileproc): Obsolete -V option.
- (struct admin_data): Remove `version' member.
- * sanity.sh (admin-24): Remove -V test case.
-
- New functions for reading and writing RCS files.
- * rcs.h (struct deltatext, Deltatext): New types.
- (struct rcsversnode): New members `text' and `outdated'.
- (struct rcsnode): New members `access', `locks', `strict_locks',
- `comment', and `desc'.
- * rcs.c (RCS_reparsercsfile, expand_keywords): Use new RCSNode members.
- (free_rcsnode_contents): Free them.
- * log.c (log_fileproc): Use new RCSNode members instead of ->other.
-
- * rcs.c (getdelta, RCS_getdeltatext, freedeltatext, do_locks,
- RCS_putadmin, RCS_putdtree, RCS_putdesc, putdelta,
- putrcsfield_proc, putsymbol_proc, RCS_copydeltas, putdeltatext,
- RCS_rewrite, getrevnum, rcs_internal_lockfile,
- rcs_internal_unlockfile, rcs_lockfilename): New functions.
-
- (RCS_reparsercsfile): Use getdelta, making sure fp is positioned
- correctly before calling it. Skip `head' and `branch' nodes: we
- have already parsed them, and they were being added incorrectly to
- rcs->other. Do not signal error if the RCS file has an empty
- delta tree; this made it impossible for RCS_checkin to perform an
- initial checkin. Remove `all' parameter; always store all RCS
- fields.
- (RCS_fully_parse, RCS_gettag, RCS_getbranch, RCS_getdate,
- RCS_getdatebranch, RCS_getrevtime, RCS_symbols, translate_symtag,
- RCS_isdead, RCS_getexpand, RCS_checkout, annotate_fileproc):
- Update all callers to remove `all' parameter.
-
- (getrcskey): Do not append trailing whitespace to a value. This
- corrupted some log fields and wrecked some sanity.sh test cases.
-
- (free_rcsvers_contents): New function.
- (rcsvers_delproc): Call it.
-
- * rcs.h (NODELTA): Removed symbol; now obsolete (since RCSNodes
- do not go stale).
- * import.c (add_rev): Removed NODELTA reference.
- * rcs.c (RCS_reparsercsfile, RCS_checkout, RCS_settag, RCS_deltag,
- RCS_setbranch, RCS_lock, RCS_unlock, RCS_deltas): Removed NODELTA
- references.
-
- Miscellaneous changes to support RCS librarification and fix some bugs.
- * subr.c, cvs.h (line2argv): Add `sepchars' argument.
- * modules.c (cat_module, admin_fileproc): Update all callers.
-
- * subr.c, cvs.h (compare_revnums, increment_revnum): New functions.
- (make_message_rcslegal): Strip whitespace from end of
- lines and end of string, a la `cleanlogmsg' in RCS 5.7.
- (get_file): Terminate buf with \0, extending it if
- necessary. Read from stdin if `name' arg is NULL.
- * admin.c (admin_fileproc): Call get_file to read -t arg from stdin.
-
- * error.c, error.h (rcserror): New function, used everywhere.
-
- * hash.c, hash.h (addnode_at_front): New function.
- * rcs.c (RCS_settag, RCS_lock): Call it.
-
- * import.c, cvs.h (expand_at_signs): Make extern.
- * rcs.c (putrcsfield_proc, RCS_putadmin, RCS_putdesc,
- putdeltatext): Call it.
-
- * rcs.c (make_file_label): Use last_component to get file's basename.
-
- * sanity.sh (srcdir): New variable.
- (rcs-7): Remove newphrase warning, no longer produced by CVS.
- (rcs-8): Permit random whitespace around newphrase fields.
- (admin-22): New test cases for -o options: admin-22-o{1..23}.
- (reserved): New test cases for rcslock.pl: reserved-{8..16}.
-
-Tue Oct 21 16:48:32 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * tag.c (tag_check_valid): Add comment about locking or lack
- thereof.
-
-1997-10-20 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Change version number to 1.9.19.
-
-1997-10-19 Jim Kingdon
-
- * Version 1.9.18.
-
-Wed Oct 15 15:21:43 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (username): Add '-' to characters allowed in user name.
-
- * rcscmds.c (diff_exec): Remove item about external diff
- programs. It doesn't really belong here now that diff is
- librarified and TODO #191 now mentions this.
-
- * checkout.c (checkout_proc): Add comment about assuming '/' is
- the only path separator.
- * options.h.in: Fix thinko (CVS/Repository -> CVS/Root).
-
-Mon Oct 13 22:46:03 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c (commit): Add comment about CVS_BADROOT and command
- other than "commit".
-
-1997-10-11 Noel Cragg <noel@swish.red-bean.com>
-
- * options.h.in: RELATIVE_REPOS has been checked for bitrot -- it
- now works again. Change the comment before the #define to say
- that we'll be switching to it soon.
-
- * sanity.sh (basicb-1, basicb-1a): update dotest strings to match
- no matter if we're running with RELATIVE_REPOS defined or not.
- (basicb-9b, basicb-9c): same.
-
- * sanity.sh (basicb-9b, basicb-9c): modified tests, since the
- checkout.c fix changes the way this test module is checked out.
- (basicb-9d, basicb-9e, basicb-9f): new tests, same.
- (basicb-18): modify test, same.
- (cvsadm): new set of exhaustive tests to check the contents of
- CVS/Root and CVS/Repository files under various conditions. As a
- side effect, it tests the behavior of the "-d" flags (command line
- and modules file).
- (modules3-7e through modules3-7h): removed, since these tests were
- a small subset of what is tested in the new cvsadm section.
- (modules-1b, modules-1c): same.
- (modules-2b, modules-2c): same.
- (modules-3b, modules-3c, modules-3e, modules-3f): same.
-
- * create_adm.c (Create_Admin): be a bit more verbose when using
- trace mode.
-
- * checkout.c (checkout_proc): rewrote the code that sets the where
- variable and the code that matches directory names with repository
- directories. This fixes a long-standing bug in CVS. (It used to
- be the case that "cvs co -d foo <mod1> <mod2>" would not properly,
- where <mod1> and <mod2> where defined in the modules file. While
- the first module would be checked out correctly, the second would
- be checked out under the name of the directory to which the module
- referred rather than the module name!). This fix also allows us
- to check out things into directories that are more than one deep
- (e.g. "cvs -d foo/bar/baz co blah" will now work).
- (checkout): remove code that performed a CHDIR if the
- number of arguments specified was greater than one, since it's no
- longer necessary. Also remove the code that prevented us from
- doing "cvs co -d <dir1>/<dir2>" without <dir1> existing, since
- checkout_proc handles things correctly now.
-
- * cvs.h: fix typo.
-
- * rtag.c (rtag): reformat so that we don't run over 80 characters
- per line.
- (rtag_dirproc): same.
-
- * sanity.sh: change all old test cases to use pass and fail
- functions rather than doing some combination of echo and exit
- themselves.
-
- * commit.c (commit_direntproc): remove the "warm fuzzy" -- this
- code never gets called when running in client/server mode, and we
- should have CVS' output match as much as possible between the two
- modes. Moreover, there is no analogous place to put this same
- message when we're running in c/s mode.
- (find_direntproc): print the same "fuzzy" as in check_direntproc
- so that local and c/s mode have the same messages.
- * sanity.sh (187a3): update test case to reflect the above.
-
-Thu Oct 9 10:57:02 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * parseinfo.c (parse_config): Add comment about compatibility
- issues with adding keywords.
-
-Wed Oct 8 16:40:37 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * recurse.c (do_dir_proc), commit.c (check_direntproc,
- commit_direntproc, find_dirent_proc): If this
- directory doesn't exist, skip it.
- * diff.c (diff_dirproc): Reindent.
- * sanity.sh (deep-4b0a, deep-4b0b): Check for this fix.
-
-Thu Sep 26 16:30:00 1997 Larry Jones <larry.jones@sdrc.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (checkout_file): Don't set timestamp in noexec mode.
- * vers_ts.c (Version_TS): Add comment about ignoring errors from
- utime.
- * sanity.sh (conflicts3): New tests, for this fix.
-
-Fri Oct 3 09:47:04 1997 Noel Cragg <noel@swish.red-bean.com>
-
- * sanity.sh (168): use PROG instead of CVSBASE, since they are
- equal.
- (importb-2): refer to PROG instead of "cvs" in error message.
-
- * add.c (add): use PROGRAM_NAME in the error message rather than
- "cvs".
- * classify.c (Classify_File): same.
- * commit.c (find_fileproc): same.
- * sanity.sh: change all add notification messages to refer to PROG
- rather than "cvs". Fixed nasty quoting in several places at the
- same time, replacing older "'command'" forms with newer
- ".command." for simplicity.
-
-Sat Sep 27 01:37:10 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (rcslib-merge-8): Accept "P file1" as well as "U file1".
-
-Fri Sep 26 22:24:10 1997 Noel Cragg <noel@swish.red-bean.com>
-
- * create_adm.c (Create_Admin): assign our duplicate pointer `cp'
- after the xrealloc of `reposcopy' because the latter might have
- changed addresses.
-
-Fri Sep 26 14:25:59 1997 Tim Pierce <twp@twp.tezcat.com>
-
- * run.c (call_diff): Don't reset optind; this is done by diff_run now.
-
- Librarify rcsmerge/diff3.
- * rcscmds.c, cvs.h (RCS_merge): Rewritten from scratch: check out
- selected files and diff3 them. Take new `rcs' and `workfile'
- arguments, so we can resolve symbolic tags and manipulate the
- working file.
- * update.c (merge_file, join_file): Update RCS_merge calls.
- * run.c, cvs.h (call_diff3): New function.
-
- * sanity.sh (rcslib): New tests, rcslib-merge-{1..13}.
-
-Fri Sep 26 22:59:56 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * create_adm.c (Create_Admin): Fix thinko in Noel's change: keep
- track of the originally allocated "cp" and free it, rather than
- calling free on a pointer which may point halfway into the allocation.
- * repos.c (Sanitize_Repository_Name): Per HACKING, assert that
- repository != NULL, rather than just silently returning if NULL.
- Reindent a line.
-
-Fri Sep 26 15:40:00 1997 Noel Cragg <noel@swish.red-bean.com>
-
- * sanity.sh (modules): add tests modules-[123]* that make sure the
- administrative files get rebuilt in various cases.
-
- * add.c (combine_dir): removed function, since we no longer need
- to worry about stripping the "." path element out. Changed the
- two callers to simply concatenate their two arguments.
-
- * recurse.c (do_dir_proc): don't bother trying to strip off "." in
- the repository name since the below changes fix that behavior --
- simply concatenate the repository and directory names together.
-
- * checkout.c (checkout_proc): sanitize the repository name after
- constructing it (we may create "/path/to/repos/.", but we don't
- want that to be passed around). Remove the code that tacks on
- "/." when constructing top_repository, since the below changes fix
- that behavior. Added comments to the part of this function that
- builds administrative files.
-
- * sanity.sh (basicb): now that the below weirdness is fixed, the
- extra "." path element in test basicb-0c doesn't appear when a
- top-level file is checked out. Remove it from the expect string.
-
- * create_adm.c (Create_Admin): now that the repository name isn't
- floating around with "." as the last path element, make creation
- of the top-level administrative files a special case -- save the
- repository name as "/path/to/repos/." Why? I considered not
- including the "." but didn't know how it would affect the remote
- protocol when RELATIVE_REPOS was defined (do we have a way of
- sending "" via the protocol?). After I make sure that the
- RELATIVE_REPOS patches still work, I'll check the "" possibility
- so we don't have to have a this special case.
-
- * repos.c (Sanitize_Repository_Name): new function that removes
- (if present) the trailing slash and "." component from the
- repository name. Many routines break if we don't guarantee this.
- See the comment before the function for complete information.
- (Name_Repository): call Sanitize_Repository_Name before returning
- the value.
- * cvs.h: add prototype for Sanitize_Repository_Name.
-
-Fri Sep 26 14:19:25 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * cvs.h (CVS_CMD_USES_WORK_DIR): Fix comment (the sense of the
- flag is not reversed from what it would seem; when I thought so it
- was because I was misreading the lookup_command_attribute code).
-
-Thu Sep 25 23:14:47 1997 Noel Cragg <noel@swish.red-bean.com>
-
- * parseinfo.c (Parse_Info): fix typo in the trace message.
-
-Thu Sep 25 14:22:54 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * build_src.com: Also link with diff.olb.
-
- * main.c (Make_Date): If gmtime returns NULL, try localtime.
-
-Wed Sep 24 19:18:40 1997 Noel Cragg <noel@swish.red-bean.com>
-
- * checkout.c (checkout): fix typo in comment.
-
-Wed Sep 24 08:31:46 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (patch_file): Revise comments about diff -a now that
- diff is librarified.
-
-Sun Sep 21 21:28:26 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * run.c (call_diff): Sleep for a second, in hopes of helping with
- out of order bugs.
-
-Sat Sep 20 07:19:18 1997 Tim Pierce <twp@twp.tezcat.com>
-
- Integrate diff library into CVS.
- * run.c, cvs.h (call_diff): New function.
- * rcscmds.c (diff_exec, diff_execv): Get diffs from call_diff
- instead of running diff as a subprocess.
- * Makefile.in (cvs): Add ../diff/libdiff.a.
-
- * diff.c (longopts, diff): Use 131 for --ifdef, fixing Jim's thinko
- (using 147 for both --side-by-side and --ifdef).
-
- * sanity.sh (rcslib): Added tests rcslib-diffrgx-*, to test
- handling of regex diff options.
-
-1997-09-21 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- (Note that this requires that DIFF support -L. I'll be checking
- in a fix to that in a moment, but I wanted separate checkins in
- case that helps with clarity).
- Tweaks to rcsdiff librarification:
- * sanity.sh (rcslib): Change "cvs" to "${PROG}" and subcommand
- names (e.g. "add") to "[a-z]*". Former should deal with ${testcvs}
- being "cvs.old" or something; latter fixes make remotecheck.
- * rcs.c (make_file_label): Take into account strlen (rev) when
- allocating space. Removes a FIXME and probably fixes a buffer
- overrun security hole.
- * rcscmds.c (RCS_exec_rcsdiff): Remove #if 0'd code to call
- rcsdiff. Tim says he has compared the new code with rcsdiff code
- and is confident that the behavior is preserved, so we need to
- nuke the comment which says this has not been done. #if 0 isn't
- really a very good way to document the way it used to work anyway;
- the old code is still in CVS.
- * diff.c: Add comment about rcsdiff options that we don't support,
- which Tim had sent in email. Remove -T and -y, as the
- previous meaning had been very confused.
-
-1997-09-21 Tim Pierce <twp@xochi.tezcat.com>
-
- Librarify rcsdiff.
-
- * diff.c (have_rev1_label, have_rev2_label): New variables.
- (diff): Generate file labels with make_file_label if necessary;
- pass labels, revisions and working file name to RCS_exec_rcsdiff.
- * rcscmds.c, cvs.h (RCS_exec_rcsdiff): Completely revised function
- to eliminate rcsdiff dependency, based on patch from JimK.
- (diff_execv): New function, to exec diff with explicit -L args.
- * rcs.c, rcs.h (make_file_label): New function.
- (RCS_output_diff_options): New function.
- * sanity.sh (rcslib): New test.
-
-Fri Sep 19 15:08:08 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_nodeisbranch): Assert that RCS is non-NULL.
- * commit.c (remove_file), rcs.c (RCS_getversion), rtag.c
- (rtag_fileproc), status.c (status_fileproc, tag_list_proc), tag.c
- (tag_fileproc): Call RCS_nodeisbranch not RCS_isbranch
- in contexts where we know the RCS argument is non-NULL.
-
- * commit.c (find_fileproc): Pass tag not NULL to Version_TS for
- the tag.
- * vers_ts.c (Version_TS): Improve (somewhat) the introductory
- comment.
- * sanity.sh (editor): New test editor-9 tests for above fix.
- Renumber/tweak surrounding tests to fit.
-
- * log.c (log_version): If p->data is NULL, it is an empty log
- message.
- * sanity.sh (rcs-14): New test, tests for above fix (previously
- this was a coredump).
-
-Thu Sep 18 08:45:05 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (rcs-7): Fix stupid ${TESTDIR} omission.
-
-Wed Sep 17 16:27:41 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (rcs): New tests rcs-5 through rcs-13 test for
- getdate.y fix (rcs-12 and rcs-13 both failed with the buggy
- getdate.y).
-
-Tue Sep 16 00:07:17 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (editor): Clean up first-dir at end of test.
-
- * sanity.sh (editor): New tests test do_editor.
-
- * commit.c (commit): For the client, if we got the log message
- from do_editor and there was an error, don't toss the message.
-
-Mon Sep 15 14:27:54 1997 martin.sjoelin@ubs.com
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (RCS_checkout): fwrite in bite-size pieces, not the whole
- file in one fwrite.
-
-Sun Sep 14 12:23:15 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c (check_fileproc): If the file has "conflict
- indicators", spit a warning and proceed with the checkin.
- * sanity.sh (conflicts): Adjust tests conflicts-132,
- conflicts-status-3, conflicts-133, and conflicts-status-4
- for new behavior.
-
-Fri Sep 12 11:12:34 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c, admin.c, checkin.c, checkout.c, classify.c, commit.c,
- create_adm.c, cvsrc.c, diff.c, entries.c, find_names.c, hash.c,
- import.c, lock.c, log.c, logmsg.c, main.c, modules.c, myndbm.c,
- no_diff.c, parseinfo.c, patch.c, rcs.c, rcscmds.c, recurse.c,
- remove.c, repos.c, root.c, rtag.c, status.c, subr.c, tag.c,
- update.c, vers_ts.c, hash.h, rcs.h, options.h.in: Change "CVS 1.4
- kit" to "CVS source distribution".
-
- * sanity.sh: Comment out call to "whoami".
-
-Thu Sep 11 10:09:04 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c (classify_file_internal): Add comment about saving
- quiet vs. saving really_quiet.
-
- * sanity.sh (newb-123j0): Use two regexps instead of assuming that
- expr has "\(", "\|", and "\)". If we want to require the latter,
- we should check for it up front, rather than let people get
- halfway through and wonder why the test failed.
-
-Tue Sep 9 19:22:44 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * expand_path.c (expand_path): If GETPWNAM_MISSING is defined,
- just give an error instead of calling getpwnam.
-
- * subr.c (getcaller): If SYSTEM_GETCALLER is defined, call it
- instead of all the getlogin/getpwuid/etc.
- * wrapper.c (wrap_setup): Call get_homedir not getpwuid.
-
-Mon Sep 8 17:54:14 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basicc): Change ls -1 to echo *; according to
- larry.jones@sdrc.com, ls -1 isn't portable.
-
-Sun Sep 7 07:45:35 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basic2): In test basic2-64, match usernames with
- ${username}.
-
- * root.c: Reindent a few things.
- * root.c, cvs.h (same_directories): Remove. Never used,
- portability hassle.
-
- * add.c (add_directory): When checking for CVSADM, call fncmp not
- strcmp. I actually suspect this code doesn't do much these days,
- but fncmp clearly will make more sense than strcmp.
-
- * rtag.c (rtag_usage), tag.c (tag_usage): Reword to hopefully be
- clearer that -r takes either numeric or symbolic revision.
-
- * ignore.c (ign_dir_add, ignore_directory): Reindent. Tweaks to
- comments.
-
- * update.c (checkout_file): Only ignore existence_error from
- unlink_file_dir, not all errors.
-
- * checkout.c (safe_location): Check for errors from xgetwd.
- * create_adm.c (Create_Admin): Remove call to xgetwd; it is just
- debugging code anyway and it wasn't checking for errors.
-
- * sanity.sh: Add comment about default value for TESTDIR.
-
- * server.c (serve_log): Change "cvslog" to "log". This
- (accidental, I presume) error had made it impossible for anonymous
- users to run "cvs log".
-
- * classify.c (sticky_ck): Change to take an finfo argument rather
- than several arguments taken from there. Cleans up the way the
- calling convention had depended on SERVER_SUPPORT.
- (Classify_File): Change callers.
-
- * version.c: Change version number to 1.9.17.
-
- * Version 1.9.16.
-
- * recurse.c (do_dir_proc): In combining repository and dir, omit
- trailing "/." from repository.
- * sanity.sh (modules3): Adjust test modules3-4 so we test for
- this fix (this is not just cosmetic; the bug prevented the
- "Rebuilding administrative file database" from happening).
- modules2 already tests the "co CVSROOT/modules" usage.
-
- * checkout.c (checkout_proc): When building top-level CVSADM
- directory, continue the process of walking up the repository one
- more level, rather than putting in the same repository as for the
- first-level directory.
- * sanity.sh: Adjust tests basicb-1b, basicb-9b, modules3-7f,
- toplevel-9, and toplevel-11 to test for this fix.
-
- (For reference, this takes CVS's text segment from 344460 to
- 344140 bytes. I know, this may seem unimportant, but it is so
- unusual for programs to shrink and I think it is so cool when they
- do without losing functionality/clarity/etc).
- * checkout.c, cvs.h (emptydir_name): New function.
- * checkout.c (checkout, checkout_proc), modules.c (do_module):
- Call it instead of duplicating the code to do that.
-
- * sanity.sh (basicc): Clean up first-dir at end of test.
-
-Sat Sep 6 09:48:39 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (join): Fix cut and paste error in join-28
- (/home/kingdon/... -> ${TESTDIR}).
-
- * recurse.c (start_recursion): If there is no CVSADM and no
- subdirectories, give an error.
- * sanity.sh (basicc): New tests, test for this fix.
-
- * sanity.sh (join): New tests join-25 through join-29 test merging
- from one branch to a different branch.
-
- * release.c: In comment about CVSROOTADM_IGNORE, also mention
- comment just added to entries.c.
- * entries.c: Expand this comment, especially the part about
- CVS/Template.
-
- Keep track of what revisions CVS/Base correspond to:
- * cvs.h (CVSADM_BASEREV, CVSADM_BASEREVTMP): Added.
- * entries.c, cvs.h (base_register, base_deregister, base_get,
- base_walk): New functions.
- * edit.c (edit_fileproc): Call base_register when setting up CVS/Base.
- (unedit_fileproc): When taking a file out of CVS/Base, put its
- revision back into entries, and base_deregister it.
- * sanity.sh (watch4): New tests watch4-10 through watch4-18 test
- for above fix.
-
-Fri Sep 5 09:14:10 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c: Only declare start_rsh_server if we are going to
- define it (!NO_EXT_METHOD).
-
- * subr.c, cvs.h (check_numeric): New function.
- * admin.c (admin): Call it.
- * sanity.sh (admin): New tests admin-10a and admin-10b test for fix.
-
-Thu Sep 4 15:55:39 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (binwrap2): New tests, test for the ability to specify
- all files are binary except certain patterns.
-
- * sanity.sh (modules3): New tests modules3-16 and modules3-17 test
- for another behavior involving '/' in a module name.
-
-Sun Aug 31 12:03:15 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c (add): Remove checks for '/' in pathnames.
- (add): Move code which handles entries and repository inside loop,
- since these now might be different for each argument. Add code to
- set finfo.update_dir, finfo.file, and finfo.fullname appropriately
- even if pathname contains '/'. Replace user variable with
- finfo.file or finfo.fullname, depending on which is meant. chdir
- into update_dir for each argument. Likewise for the client code
- which creates directories.
- (add_directory): Replace arguments with a single finfo argument.
- Replace dir with finfo->fullname as needed.
- (add): Update call to add_directory.
- * client.c, client.h (send_a_repository): No longer static.
- * sanity.sh (errmsg2): Adjust tests to test for '/' in pathname.
-
- * sanity.sh (errmsg2): New tests errmsg2-13 through errmsg2-16
- test the status quo with respect to '/' in cvs add argument.
-
-Sat Aug 30 17:37:29 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * run.c (run_popen): Add comment on return value.
- * release.c (release): Check for NULL return from popen.
-
-Fri Aug 29 17:49:20 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (get_server_responses): Add comment about "ok^M".
-
-Thu Aug 28 13:35:12 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * edit.c (edit_fileproc): If file doesn't exist, give an error.
- * sanity.sh (devcom2): Tests devcom2-12 through devcom2-17 test
- for above fix.
-
-Tue Aug 26 16:42:28 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * subr.c (xmalloc): Reword error message to clarify that memory,
- not disk space or some other resource, is in question.
-
-Tue Aug 26 01:04:48 1997 Steve Ralston <sralston@ppdpost.ks.symbios.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c (add_directory): In allocating message, also allocate
- enough for tag and date related text.
-
-Tue Aug 26 01:04:48 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (update_dirent_proc): Use update_dir not dir in "new
- directory" message.
- * find_names.c (find_dirs): Skip CVSNULLREPOS.
- (Find_Directories): Add comment about find_dirs skipping CVSATTIC
- and CVSLCK in working directories.
- * sanity.sh (basicb): New tests basicb-edir-* test for find_dirs
- fix. Change other tests to test that Emptydir is not special in
- non-CVSNULLREPOS contexts.
-
-Sun Aug 17 14:44:57 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * import.c (add_rcs_file): Add comment about -k overriding wrappers.
-
-Sat Aug 16 18:09:05 1997 Martin Sjoelin <martin.sjoelin@ubs.ch>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * import.c (add_rcs_file): Before opening the input file
- when importing, if options is binary, open the file in
- binary mode.
-
-1997-08-16 enami tsugutomo <enami@ba2.so-net.or.jp>
-
- * sanity.sh (mcopy): Unset CVSWRAPPERS last of all.
-
-Fri Aug 15 11:11:44 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c (add_directory): Copy default file attributes from the
- parent directory to the directory we are creating.
- * fileattr.h, fileattr.c (fileattr_getall, fileattr_setall):
- New functions, in support of above.
- * fileattr.c (fileattr_free): Add comment about fileattr_write
- maybe not clearing attrs_modified.
- * sanity.sh (watch4): New test, tests for above fix.
-
-Thu Aug 14 11:08:40 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (merge_file, join_file): If wrap_merge_is_copy, treat
- files as nonmergeable (as we had been treating binary files).
- (join_file, update_fileproc): Remove previous wrap_merge_is_copy
- cruft.
- * sanity.sh (mcopy): New tests, test for above fix.
- (binfiles2): New tests binfiles2-9a-* correct an oversight.
- (binfiles, binfiles2): Adjust to reflect wording change from
- "binary file" to "nonmergeable file".
- (mwrap): Adjust tests mwrap-8 through mwrap-10 for new behavior.
-
- * main.c (main): Reword copyright notices to include the latest
- year, to refer to "other authors" in addition to the ones listed,
- and to be more concisely formatted.
-
-Wed Aug 13 13:50:00 1997 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh: Replace hard-coded directory with ${TESTDIR}, add
- join3 to default tests
-
-Wed Aug 13 11:42:24 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcscmds.c: Adjust comment to reflect progress on removing RCS
- execs outside this file.
-
-Mon Aug 11 10:14:47 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * vers_ts.c (Version_TS): If vers_ts->vn_rcs == NULL, skip setting
- modification time in server case as well as local case.
- * server.c (server_modtime): Add assertion to clarify that caller
- must assure that vers_ts->vn_rcs != NULL.
- * sanity.sh (join3): Add file "file2" to test for above fix.
-
- * modules.c (save_d): When parsing -s option, don't assume that
- we will hit a space before we hit the '\0'.
- (struct sortrec): Document allocation policies (status quo except
- status field is now malloc'd).
- (cat_module): No longer need to set the '\0' at the end of the
- status field back to ' ', as it no longer shares storage with the
- rest field.
- * sanity.sh (modules): Add "statusmod" to test for above fix.
-
-Sun Aug 10 12:18:31 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Remove TODO item about more keyword expansion tests.
- The keyword test and others cover it pretty well, and such an item
- isn't useful unless it is specific.
-
- * sanity.sh (importb): New tests test "cvs import -b".
-
- * mkmodules.c: Update comment with more reasons why having
- CVSROOT/passwd be a regular administrative file would be a Bad
- Idea.
-
- * server.c (switch_to_user): Add comment about checking for errors
- from setuid and friends.
-
-Wed Aug 6 13:48:29 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (main): Add comment about errors writing CVS/Root in
- need_to_create_root code.
-
-Tue Aug 5 22:05:20 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * entries.c (write_entries): If trouble writing Entries.Backup,
- make it a warning not an error.
-
-Wed Jul 30 08:42:04 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * parseinfo.c (parse_config): If AUTH_SERVER_SUPPORT is not
- defined, don't set system_auth.
-
- * version.c: Change version number to 1.9.15.
-
- * Version 1.9.14.
-
- * create_adm.c, cvs.h (Create_Admin): If new argument WARN is set,
- then make creating the CVS directory itself a warning not a fatal
- error. New return value indicates whether we did this.
- * checkout.c (build_one_dir), client.c (call_in_directory):
- Pass WARN as one.
- * add.c, client.c, checkout.c, modules.c, update.c: Pass WARN as
- zero for all other Create_Admin callers.
- * sanity.sh (toplevel): New test toplevel-12 tests for this fix.
- * filesubr.c (mkdir_if_needed): Also check EACCES/isdir. Needed
- to make toplevel-12 test work.
-
- * sanity.sh (toplevel): New test toplevel-11 and friends test for
- another variation of the toplevel-9 bug.
-
-Tue Jul 29 12:11:16 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * login.c (construct_cvspass_filename): Revert this change. The
- main reason is procedural; Karl is not a current CVS developer.
- The other thing is that the new text doesn't say anything about
- HOMEDRIVE and HOMEPATH.
-
-Tue Jul 29 11:36:22 1997 Karl Fogel <kfogel@harvey.cyclic.com>
-
- * login.c (construct_cvspass_filename): error message informs user
- she may need to set HOME environment variable by hand.
-
-Sun Jul 27 15:36:44 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * admin.c (admin): Remove comment "XXX send -ko too with i = 0".
- It turns out to be a description of a bugfix which was applied on
- 8 Oct 1995, and never should have been in a comment in the first
- place.
-
- * admin.c (admin, admin_fileproc): Parse options ourself rather
- than blindly passing them to RCS.
- Accordingly, add struct admin_data and function arg_add, and delete
- global variables ac and av.
- * sanity.sh (admin): Change admin-3 test to reflect cvs admin -i
- now being an error.
- (basicb): Change basicb-21 test to relect the improved error
- message here.
-
-Sat Jul 26 11:34:51 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (join3): New tests, test a new branch topology and
- greatest common ancestor.
-
-Fri Jul 25 09:51:49 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (serve_directory): Repository must start with
- CVSroot_directory rather than some random pathname.
-
- * remove.c (remove_fileproc): If there is a numeric sticky tag,
- don't allow the remove.
- * commit.c (check_fileproc): Add comment about this case.
- * sanity.sh (sticky): New tests sticky-15 through sticky-23
- test for this behavior and the analogous behavior with
- non-branch sticky tags (which is unchanged).
-
- * client.c (update_entries): Clear the stored mode, modtime, and
- checksum even on an error.
- * sanity.sh (contents2-142d*): Also test cvs status. Also test
- the case in which the contents of the file are unchanged. Also
- test running diff to see the conflict, and resolving the conflict.
- Without the fix above, the new contents2-142d2 test would get a
- "duplicate Mod-time" warning.
-
-Thu Jul 24 13:29:15 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (pserver_authenticate_connection): Call parse_config
- here too.
- * parseinfo.c (parse_config): If we are called several times, the
- times beyond the first do nothing.
- * cvs.h, parseinfo.c (parse_config): New argument cvsroot.
- * server.c, main.c: Update callers.
- * server.c, server.h (system_auth): New variable.
- * parseinfo.c (parse_config): Parse new keyword SystemAuth.
- * mkmodules.c (config_contents): Add comments for SystemAuth.
- * server.c (check_password): If !system_auth, then skip the check
- for a system username/password.
-
- * main.c (main): No fatal error if parse_config returned an error.
- * server.c (serve_root): Likewise.
- * error.c (error): Add comment about calling from the server.
- * parseinfo.c, cvs.h (parse_config): Remove NOERR crock.
- Closer reading of server.c makes it seem like calling error
- here is OK after all.
- * sanity.sh (config): New test, tests for above fix.
-
- * server.c (serve_root): Fix typo ("doign" -> "doing").
-
-Wed Jul 23 13:55:09 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * vers_ts.c (Version_TS): If entdata is for a directory, don't set
- vn_user and friends.
- * server.c (dirswitch): Add comment about why Subdir_Register is
- sometimes a noop here.
- * cvs.h (struct vers_ts): Fix comments about NULL vs. "" in vn_user.
- * sanity.sh (errmsg2): New tests errmsg2-10 through errmsg2-12 test
- for above fix.
- * add.c (add_directory): Call cvs_output not printf. This fixes
- an out-of-order bug which was showing up in the testcase.
-
-21 Jul 1997 Jim Kingdon
-
- * subr.c (get_file): Put st_size into an unsigned variable to
- avoid signed/unsigned warnings.
-
-Mon Jul 21 00:19:30 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Change version number to 1.9.13.
-
- * Version 1.9.12.
-
- * sanity.sh (toplevel, head): Delete our files from the repository
- when done with them.
-
-Sun Jul 20 15:53:08 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (admin, reserved): New tests, test most cvs admin
- behaviors.
- (log2): New tests log2-5 through log2-10 test setting the
- description via cvs admin.
-
-Thu Jul 17 12:39:27 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (socket_buffer_input, socket_buffer_output): Add
- comment regarding size of of buffer we pass to send and recv.
-
-Sat Jul 12 15:21:24 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * import.c, rcs.h (add_rcs_file): New argument key_opt replaces
- access to global variable keyword_opt. New arguments desctext and
- desclen allow one to set the description. If add_vhead is NULL,
- then omit a revision, like rcs -i.
- * import.c (process_import_file), mkmodules.c (init): Change
- callers.
- * subr.c, cvs.h (get_file): New function, adapted from code in
- update_entries.
- * client.c (update_entries): Call it.
- * commit.c (checkaddfile): Create new RCS files with add_rcs_file
- rather than rcs -i.
-
-Fri Jul 11 12:14:54 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (join_file): Handle binary files ourself rather than
- passing them to RCS_merge (which sort of tries to handle binary
- files, but does so badly).
- * sanity.sh (binfile2): New "brmod", "brmod-trmod", and
- "brmod-wdmod" tests test for this fix.
-
- * add.c (add): Exit status is now nonzero if any of the arguments
- failed (already was mostly true, make it true for the new sanity
- check). Move check for '/' (now ISDIRSEP) up to sanity check, so
- the client does it too.
- * sanity.sh (errmsg2): Test for this fix.
-
-Thu Jul 10 00:02:54 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c (add): Check for CVSADM, ".", and "..", and skip any
- attempt to add them.
- * sanity.sh (errmsg2): New tests, tests for above fix.
-
- * main.c (main): In text printed upon --version, also refer
- people to --help.
-
- * rcscmds.c (RCS_exec_rcsdiff): Add comment about timezones.
-
- * server.c, cvs.h (cvs_output_binary): New function.
- * rcs.c (RCS_checkout): For a binary file, call cvs_output_binary
- rather than cvs_output.
- * client.c (handle_mbinary): New function.
- (responses): Add "Mbinary".
-
-Tue Jul 8 12:18:16 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * filesubr.c (get_homedir): Add comment about root vs. user
- directory in pserver server.
-
-Mon Jul 7 14:39:33 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (big): Also test Rcs-diff case.
-
- * client.c (update_entries): Reindent a line.
-
- * sanity.sh (death2): Add comment about Sun diff. Thanks to
- Warren Jones <wjones@TC.FLUKE.COM> for reporting this.
-
- * client.c (update_entries): If DONT_USE_PATCH, then just treat a
- Patched response as an indication to try again with complete files.
- * update.c (update): Remove DONT_USE_PATCH ifdefs, since a CVS
- with DONT_USE_PATCH defined can still handle Rcs-diff.
- * sanity.sh (serverpatch): Add comment about this coming up in
- real life if the user modifies the file while CVS is running.
-
- * client.c (start_server): Add comment about logfiles if there are
- several connections to the server.
- (log_buffer_shutdown): Close the logfile after shutting down the
- underlying buffer. This way at least we get the last set of
- logfiles rather than a bizarre mishmash.
-
-1997-07-06 enami tsugutomo <enami@but-b.or.jp>
-
- * logmsg.c (do_verify): Unlink temporary file before call error().
- Remove unneeded `return' statement. Fix comment.
-
-Sun Jul 6 13:36:32 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * diff.c (diff_fileproc): Change message from "during rcsdiff of"
- to "while diffing". For a while now, that message might be
- printed after a call to DIFF instead of rcsdiff.
-
- * diff.c (diff_fileproc): Call cvs_output not printf. Remove
- calls to fflush (should be handled now by call to cvs_outflush in
- recurse.c).
- * patch.c (patch_fileproc): Likewise.
-
- * rcscmds.c, cvs.h (diff_exec): New function.
- * diff.c (diff_fileproc), patch.c (patch_fileproc),
- update.c (patch_file): Call it.
-
- * rcscmds.c: Adjust comments concerning diff library to point to
- new, expanded comments at diff_exec. Remove comments concerning
- patch library; Rcs-diff should be adequate.
-
- * client.c (update_entries): Add comment about GNU patch usage (-b
- option and so on).
-
-Sat Jul 5 04:13:28 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcscmds.c, cvs.h (RCS_exec_rcsdiff): New function.
- * diff.c (diff_fileproc): Call it.
-
-Thu Jul 3 09:50:07 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (main): Add comment about how long we should keep the
- deprecated "cvs rlog" alias.
-
- * server.c (cvs_output): Add comment about whether to fflush.
-
-Wed Jul 2 18:57:29 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (join2): New tests join2-19 and friends test for a
- case that we can't readily get right (see comments).
-
-Tue Jul 1 09:52:09 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (cmd_usage): Say "specify" --help rather than the vague
- "use".
- (opt_usage, cmd_synonyms): Mention --help here too.
- * add.c, admin.c, checkout.c, commit.c, diff.c, edit.c, import.c,
- log.c, login.c, mkmodules.c, patch.c, rcs.c, release.c, remove.c,
- rtag.c, status.c, tag.c, update.c, watch.c: Likewise, for all the
- other help messages.
-
- * sanity.sh (join2): New tests.
-
- * repos.c (Name_Repository): Check for errors from fclose.
-
-Fri Jun 27 10:27:48 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * scramble.c, login.c: Reindent.
-
- * client.c (connect_to_pserver): Check for errors from send().
- If socket() fails, include SOCK_STRERROR (SOCK_ERRNO) in message.
-
-Wed Jun 25 11:21:52 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c: New option --help-options, with much of the text
- from --help. Fix a few capitalization and punctuation problems.
- Rewrite text for --help to be an intro to all the --help-*
- options.
-
- * sanity.sh (head): New tests, concerning meaning of HEAD.
-
-Tue Jun 24 10:14:18 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (recv_line): New function.
- (connect_to_pserver): Call it, and rewrite accordingly. Also
- accept new "E" and "error" responses. Change \n to \012.
- * server.c (pserver_authenticate_connection): Adjust comment
- accordingly, concerning sending I HATE YOU not "error".
-
-Sun, 22 Jun 1997 Jim Kingdon
-
- * main.c (main): Move setting of server_active inside #ifdef
- SERVER_SUPPORT; otherwise the variable doesn't exist.
- * main.c (main): Call return after exit to shut up warning.
-
-Fri Jun 20 22:56:34 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (connect_to_pserver): On "I HATE YOU", give
- "authorization failed" fatal error regardless of verify_only.
- * login.c (login): Don't print that "incorrect password" message;
- it now is possible with an --allow-root failure as well as an
- incorrect password. cvsclient.texi doesn't really specify what I
- HATE YOU means in any detail, and it seems a little silly for
- login to give different messages than the other commands.
- * client.c, client.h (connect_to_pserver): Return type now void.
-
-Thu Jun 19 12:16:10 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (serve_root): Give error on duplicate Root request.
- Call parse_config.
- * parseinfo.c, cvs.h (parse_config): New function.
- * cvs.h (CVSROOTADM_CONFIG): Added.
- * main.c (main): Set server_active here...
- * server.c (server): ...not here. That seems cleaner than
- strcmp's between command_name and "server" in main.c.
- * main.c (main): Call parse_config.
- * main.c, cvs.h (free_Rcsbin): Make global.
- * mkmodules.c (filelist): Add CVSROOTADM_CONFIG.
-
-Wed Jun 18 11:24:31 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Change version number to 1.9.11.
-
- * Version 1.9.10.
-
-Tue Jun 17 22:48:00 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (main): Add --allow-root=ROOT argument; call
- root_allow_add for each time it is specified. Call
- root_allow_free before exiting.
- * root.c, cvs.h (root_allow_add, root_allow_free, root_allow_ok):
- New function.
- * server.c (pserver_authenticate_connection): If root_allow_ok
- doesn't like the CVSROOT directory, don't allow access.
-
-Tue Jun 17 14:30:14 1997 Jim Kingdon (unknown@beezley)
-
- * client.c: Add "copyright" notice. If NO_EXT_METHOD, omit
- start_rsh_method.
- * client.c (update_entries): Cast argument to MD5Update from
- char * to unsigned char *.
-
-Mon Jun 16 16:46:28 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * run.c (piped_child, filter_stream_through_program):
- If USE_SETMODE_BINARY, then put the pipes into binary mode.
- * find_names.c, ignore.c, lock.c, wrapper.c: Change fnmatch to
- CVS_FNMATCH.
- * client.c (start_server): If NO_EXT_METHOD, then give a fatal
- error on any use of :ext:.
-
-Sun Jun 15 22:30:27 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (toplevel): Match U CVSROOT/* lines with DOTSTAR in
- test toplevel-9.
-
-Thu Jun 12 10:27:51 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (toplevel): Remove Emptydir before starting.
-
- * sanity.sh: Change "rm -rf" to "rm -r" when deleting working
- directories (except a few watches cases). Helps detect cases
- where the testsuite has cd'd to somewhere other than where we
- think it has.
- (basic2): Remove "rm -r first-dir" between tests 49 and 50. The
- directory was already deleted in test 45.5.
- (rcs): Add "cd .." at end of tests.
- (stamps): No longer cd to TESTDIR; shouldn't be necessary with
- fix to "rcs" test.
-
-Wed Jun 11 22:28:38 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basicb): Also remove CVSROOT/Emptydir at end of
- test. Otherwise it affects the toplevel-9 test for remote.
-
-Tue Jun 10 14:03:32 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (toplevel): Change "update" and "checkout" to "[a-z]*"
- as these read "server" instead for "make remotecheck". Change
- expect strings for toplevel-9 to accept the behavior of remote CVS
- (see comments for more discussion).
-
- * sanity.sh: New tests stamps-9 through stamps-11 test timestamp
- behavior on cvs update.
-
-Mon Jun 9 22:42:50 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Remove "#! /bin/zsh" line at end. I assume it was
- added accidentally.
-
-Tue Jun 10 03:08:46 1997 Norbert Kiesel <nk@psycho.de>
-
- * sanity.sh: new tests "toplevel" for the new toplevel CVS
- directory creation (including one test which shows an error in
- this area).
-
-Sun Jun 8 20:52:00 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.c (getrcsrev): Before printing error, check whether it was
- feof or ferror.
-
- * rcs.h, import.c (add_rcs_file): No longer static. New arguments
- add_vbranch, add_vhead, and add_logfp replace access to static
- variables vbranch, vhead, and logfp.
- * mkmodules.c: Call it instead of RCS_CI.
- * import.c (process_import_file): Adjust call to add_rcs_file.
-
-Tue Jun 3 10:18:33 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basicb): Match "." with "\." not ".".
-
-Tue Jun 3 13:02:37 1997 Norbert Kiesel <nk@cosa.de>
-
- * checkout.c (checkout): Removed restriction of not sending -k in
- remote export (I think this was introduced while the -k handling
- was still broken in remote mode). Give better error texts
- regarding -c and -s options. Use error() instead of usage() for
- reporting errors in all places. Reindented some lines. Free
- xmalloc'd space of options.
-
-Thu May 29 16:32:47 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcscmds.c (RCS_checkin), mkmodules.c (init): Pass -w option to
- "ci", specifying getcaller ().
- * server.h, server.c (CVS_Username): Now extern.
- * subr.c (getcaller): Return CVS_Username if it is set.
-
-Wed May 28 22:31:38 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (update_fileproc): If wrap_merge_is_copy and we would
- like to do a merge, give a fatal error. See comment for why.
- * sanity.sh (mwrap): New tests, tests for above fix.
-
-Tue May 27 21:59:32 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (stamps): cd to ${TESTDIR} before starting.
-
-Mon May 26 15:31:30 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (handle_mod_time): New function.
- (responses): Add "Mod-time".
- (stored_modtime_valid, stored_modtime): New variables.
- (update_entries): If it is set, change the file's modtime.
- * server.c, server.h (server_modtime): New function.
- * vers_ts.c (Version_TS): Call it.
- * patch.c (patch_fileproc): Add comment about why we don't.
- * sanity.sh (stamps): Added, tests for above fix.
-
-Fri May 16 13:14:30 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * subr.c (free_names): Update documentation to reflect fact that
- free_names is now called to free vectors allocated by expand_wild
- as well as by line2argv.
-
- * main.c (main): Use "xstrdup (foo)" not "xstrdup(foo)" as
- specified in HACKING.
-
-Fri May 16 15:10:37 1997 Norbert Kiesel <nk@cosa.de>
-
- * modules.c (do_module): initialize optind to 0. use local copies
- of optarg's (because they might me freed within free_names).
-
-Thu May 15 11:50:15 1997 Norbert Kiesel <nk@cosa.de>
-
- * main.c (main): initialize optind to 0. use local copies of
- optarg's (because they might me freed within read_cvsrc).
-
- * cvsrc.c (read_cvsrc): free old argv after constructing a new
- one. This fixes a memory leak.
-
- * recurse.c (start_recursion): use free_names() instead of
- reimplementing it
-
- * rcs.c (RCS_deltas): free branchversion (memory leak).
-
- * parseinfo.c (Parse_Info): free some vars (3 memory leaks).
-
- * logmsg.c (logfile_write): free str_list_format (memory leak).
-
- * watch.c (watch_addremove), (watchers), update.c (update), tag.c
- (cvstag), status.c (status), rtag.c (rtag), remove.c (cvsremove),
- release.c (release), patch.c (patch), log.c (cvslog), import.c
- (import), history.c (history), edit.c (watch_onoff), (edit),
- (unedit), (editors), diff.c (diff), commit.c (commit), checkout.c
- (checkout), add.c (add): initialize optind to 0
-
- * diff.c (diff_fileproc): cosmetic change (whitespace added).
-
- * checkout.c (checkout): move local variable definition into the
- block where the variable is used.
-
- * client.c (update_entries): initialize some local variables to shut up
- gcc -O -Wall.
-
- * buffer.c (buf_read_line): initialize a local variable to shut up
- gcc -O -Wall.
-
-
-Wed May 14 16:29:50 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * admin.c (admin): When sending options to server, don't try to
- send av[ac]. It may contain one of the names that we'll send in
- send_file_names (which caused tests like keyword-6 to work,
- sort of accidentally), or it may contain NULL (which would tend to
- cause a coredump).
- * sanity.sh (basicb): New test basicb-21 tests for above fix.
-
-Mon May 12 16:22:00 1997 Larry Jones <larry.jones@sdrc.com>
-
- * add.c (add): Free message and repository in client code.
- * checkout.c (checkout): Don't free repository unless allocated.
- * client.c (start_rsh_server): Free command.
-
-Sun May 11 11:43:54 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c: Remove all references to USE_DIRECT_TCP; see
- ../ChangeLog for rationale.
-
-Fri May 9 22:19:36 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (main): Add comment explaining why we call exit. Pass 0
- not EXIT_SUCCESS, because lib/system.h has portability cruft for
- EXIT_FAILURE but not EXIT_SUCCESS.
-
-Fri May 9 17:25:00 1997 Larry Jones <larry.jones@sdrc.com>
-
- Fix miscellaneous memory allocation problems:
- * add.c (add): Free repository.
- * client.c (notified_a_file): Free getline buffer.
- * edit.c (notify_check): Free getline buffer.
- * hash.c (dellist): Free header node when not caching.
- * login.c (login): Don't continually free & allocate getline
- buffer, use xstrdup instead of xmalloc/strcpy, free getline
- buffer before returning.
- * main.c (main): Call exit instead of returning so tools like
- Purify won't consider permanently allocated memory as leaks.
- * mkmodules.c (mkmodules): Free getline buffer.
- * modules.c (cat_module): Call close_module.
- * rcs.c (rcsvers_delproc): Free state.
- * recurse.c (start_recursion): Free files_by_dir.
- (unroll_files_proc): NULL out p->data after using it to set
- filelist to avoid multiple frees.
- * server.c (check_command_legal_p): Don't continually free &
- allocate getline buffer, free getline buffer before returning.
- (check_repository_password): Ditto, use xstrdup instead of
- xmalloc/strcpy.
- * wrapper.c (wrap_add_file): Free getline buffer.
-
-Thu May 8 14:21:00 1997 Larry Jones <larry.jones@sdrc.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * checkout.c (checkout_proc): Free finfo.rcs (memory leak).
-
-8 May 1997 Larry Jones <larry.jones@sdrc.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * hash.c: Add #ifdef's to disable caching. This makes it easier
- to track down memory allocation problems.
-
-Thu May 8 11:40:39 1997 Larry Jones <larry.jones@sdrc.com>
-
- * sanity.sh: In setting "tests" use a number of statements rather
- than one very long line.
-
-Thu May 8 11:40:39 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * cvsbug.sh: Remove $Id; we decided to get rid of these some time
- ago.
-
-Thu May 8 11:34:02 1997 Larry Jones <larry.jones@sdrc.com>
-
- * cvsbug.sh: Put separate statements on separate lines, so it
- works if awk is AT&T nawk.
-
-Tue May 6 16:56:00 1997 Larry Jones <larry.jones@sdrc.com>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * cvsrc.c (read_cvsrc): Fix various memory allocation problems:
- rearrange code to avoid leaks, use xrealloc instead of xmalloc/
- copy/free, make sure there's room for the remaining args before
- appending them.
-
-Tue May 6 14:20:00 1997 Larry Jones <larry.jones@sdrc.com>
-
- * edit.c (watch_onoff, edit, unedit, editors): Add -R like
- other things with -l.
- * watch.c (watch_addremove, watchers): Ditto.
-
-Mon May 5 18:10:37 1997 larry.jones@sdrc.com
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Change all /tmp/cvs-sanity to TESTDIR. If TESTDIR
- environment variable is set, use it instead of /tmp/cvs-sanity.
- * sanity.sh: Make TMPPWD the pwd equivalent of TESTDIR, not of /tmp.
-
-4 May 1997 Larry jones <larry.jones@sdrc.com>
- and Jim Kingdon
-
- * checkout.c, diff.c, patch.c, rcs.c: Update usage messages.
- * rcs.c (annotate): Add -R like other things with -l.
-
-Sat May 3 14:57:40 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basic1): Rewrite test (use dotest, unroll the loops
- which IMHO makes the test a zillion times more understandable, and
- only do the variant which tests for 4 files at a time--we test one
- file at a time lots of places).
-
-2 May 1997 Ziv Gigus <ziv@rest.home.net>
- and Jim Kingdon
-
- * client.c, client.h (client_process_import_file): New argument
- all_files_binary means treat all files as binary.
- * import.c (import_descend): Pass it if -kb is specified.
- * client.c (client_process_import_file): In the
- non-all_files_binary case, call wrap_rcsoption to determine
- whether the file is binary.
-
-Thu May 1 13:44:51 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (binfiles2): New tests, for update -j and binary files.
-
-Wed Apr 30 11:18:36 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * recurse.c (start_recursion): Also free reposfile.
- Don't look in repository if client_active (latter bug reported by Paul
- Sanders <p.sanders@dial.pipex.com>).
-
-Mon Apr 28 22:36:39 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * diff.c (diff_file_nodiff): Remove SERVER_SUPPORT ifdefs. They
- were not based on server_active, which doesn't really make any
- sense (it meant that compiling --disable-server could affect the
- behavior of the non-client/server CVS). This affected the output
- in tests death2-diff-11 and death2-diff-12 in the testsuite.
- * sanity.sh (newb-123j0): Also accept "Needs Checkout", for a
- --disable-server CVS.
-
- * main.c (cmd_usage): Change "run diffs" to "show differences";
- the former is jargon.
- * edit.c (edit_usage): Fix typo ("." -> ",").
- * edit.c (editors_usage), watch.c (watchers_usage): Mention -l.
- * checkout.c (export_usage): Say what -P does.
- * history.c (history_usg): Add comment about message wording.
-
-Mon Apr 28 14:47:45 1997 Norbert Kiesel <nk@cosa.de>
-
- * checkin.c (Checkin): use filename without path when calling
- wrapper (bug found by Michal Schmitz <ms@cosa.de>).
-
-Fri Apr 25 13:28:55 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * client.c (update_entries): In UPDATE_ENTRIES_RCS_DIFF case,
- write to a temporary file and then rename it.
-
-Thu Apr 24 11:35:40 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * subr.c, cvs.h (pathname_levels): New function, from a piece of
- send_file_names.
- * client.c (send_file_names): Call pathname_levels in place of the
- code which was moved there.
- * server.c, server.h (server_pathname_check): New function.
- * recurse.c (start_recursion): Call it.
- * sanity.sh (modules3): New test modules3-11b tests for above fix.
-
- * filesubr.c: Do not define L_tmpnam. It is in ANSI and SunOS4,
- so I don't think there will be a problem with it being missing.
- Defining it too small can cause memory corruption.
- (cvs_temp_name): Do not use L_tmpnam in the mktemp code; this
- could cause a buffer overflow if the -T global option was in use.
-
-Thu Apr 24 13:21:15 1997 Norbert Kiesel <nk@cosa.de>
-
- * filesubr.c (cvs_temp_name): Use tempnam if available, else
- mktemp, else tmpnam. See the comment for rationale.
-
- * sanity.sh: use "tar cf - ." instead of "tar cf - *" for
- directory copies.
-
-Wed Apr 23 23:41:47 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (serve_update_prog): If in readonly mode, give an error.
-
-Wed Apr 23 19:07:41 1997 Norbert Kiesel <nk@cosa.de>
-
- * subr.c (line2argv): Allocate at least 4 slots for argv.
-
- * checkout.c (checkout_proc): Add a comment which says why the
- above change was necessary to avoid writing to unallocated memory.
-
-Wed Apr 23 11:20:40 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * entries.c (ParseTag): Always set *NONBRANCHP.
-
-21 Apr 1997 Jim Kingdon
-
- * client.c (update_entries), rcs.c (expand_keywords): Rewrite
- test to avoid signed/unsigned warning.
-
-Mon Apr 21 09:02:22 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (patch_file): Add comment about whether auto-detecting
- features of the DIFF program is a good idea.
-
-Mon Apr 21 00:03:34 1997 Ian Lance Taylor <ian@cygnus.com>
-
- Don't require the patch program:
- * client.c (struct update_entries_data): Add
- UPDATE_ENTRIES_RCS_DIFF to contents enum.
- (update_entries): Handle UPDATE_ENTRIES_RCS_DIFF.
- (handle_rcs_diff): New static function.
- (responses): Add "Rcs-diff".
- * server.c (server_updated): Handle SERVER_RCS_DIFF.
- (server_use_rcs_diff): New function.
- * server.h (enum server_updated_arg4): Add SERVER_RCS_DIFF.
- (server_use_rcs_diff): Declare.
- * update.c (rcs_diff_patches): New static variable.
- (update): Set rcs_diff_patches.
- (update_fileproc): If rcs_diff_patches, pass SERVER_RCS_DIFF
- rather than SERVER_PATCHED to server_updated.
- (patch_file): Correct initial comment to say diff rather than
- rcsdiff. If rcs_diff_options, pass -n to diff rather than -c.
- * rcs.c (rcs_change_text): New function.
- * rcs.h (rcs_change_text): Declare.
-
-Mon Apr 21 00:08:59 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * diff.c (diff_fileproc): Add comment concerning updating the
- client timestamp.
-
-Sun Apr 20 23:20:37 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * commit.c (commit): Add comment regarding SEND_FORCE rationale.
-
-Sat Apr 19 17:10:36 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (dirswitch): If directory ends in '/', complain.
-
-Fri Apr 18 18:09:57 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (apply_rcs_changes): New static function, broken out of
- RCS_deltas.
- (RCS_deltas): Call it.
- (linevector_add): Change return type to int. Return an indication
- of an error for an invalid add, rather than calling error.
-
-Fri Apr 18 11:24:26 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Change version number to 1.9.9.
-
- * version.c: Version 1.9.8.
-
- * commit.c (struct find_data): Add field force.
- (find_fileproc, commit): Use it instead of force_ci to decide
- whether to send files to server.
- (commit): Set it if either -f or -r is specified.
- * sanity.sh (basica): Add tests basica-8a0, basica-8a1, and
- basica-8a2; tests for above fix.
-
-Wed Apr 16 11:50:59 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * zlib.c: Remove paragraph with Free Software Foundation address.
- See 2 Jan 1997 entry in ../ChangeLog for rationale.
-
-Tue Apr 15 00:36:23 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (patch_file_write): Always assign to final_nl, so that
- it ends up reflecting whether the data from the last call had a
- newline, not whether the data from any of the calls ended in a
- newline. Doesn't matter with the current RCS_checkout
- implementation, but it will if RCS_checkout is changed to pass
- less than the entire file.
-
- * rcs.c (RCS_cmp_file): Change NULL to RUN_TTY in passing sout to
- RCS_checkout, for clarity.
-
- * import.c (update_rcs_file): Remove unused variable ierrno.
-
- * add.c, checkout.c, commit.c, diff.c, edit.c, import.c,
- history.c, log.c, main.c, patch.c, release.c, remove.c, rtag.c,
- status.c, tag.c, update.c, watch.c: Pass "+" to all calls to
- getopt. This ensures that we maintain existing behavior even with
- glibc2.
-
- * filesubr.c (fopen_case): Don't set *PATHP if we return an
- error. Since the 9 Apr 1997 change, the behavior has been to
- sometimes set it and sometimes not.
- * rcs.c (RCS_parse): Adjust callers to not free it. Without this
- change, they could call free() on an uninitialized variable.
-
- * checkout.c (checkout): Add comment about export -k.
-
- * root.c (check_root_consistent): Add comment about wording of
- message.
-
-Mon Apr 14 11:51:49 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (call_in_directory): If rdirp reaches the end of
- reposdirname, then just set it to NULL. If server does not create
- directories one at a time, give a warning.
- * sanity.sh (modules3): Enable tests modules3-8 through
- modules3-11 for remote; tests for above fix.
-
- * client.c (call_in_directory): Don't set short_pathname to
- pathname for a while; just use pathname itself (cleans up a relic
- of the old "Repository" (not "Directory") code). Add comment
- explaining short_pathname.
-
-Sun Apr 13 18:07:50 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * rcs.c (RCS_checkout): Add pfn and callerdat parameters. Change
- all callers. Move setting of expand after retrieval of file
- data.
- (struct cmp_file_data): Define.
- (RCS_cmp_file): New function.
- (cmp_file_buffer): New static function.
- * rcs.h (RCSCHECKOUTPROC): Define type.
- (RCS_checkout): Update declaration.
- (RCS_cmp_file): Define.
- * diff.c (diff_file_nodiff): Call RCS_cmp_file rather than
- RCS_checkout and xcmp.
- * import.c (update_rcs_file): Likewise.
- * no_diff.c (No_Difference): Likewise.
- * update.c (struct patch_file_data): Define.
- (patch_file): Just return if noexec, or if binary file. Pass
- patch_file_write to RCS_checkout. Don't check for newlines or
- compute checksums here. Stat RCS file to set modes.
- (patch_file_write): New static function.
-
- * update.c (patch_file): Checkout directly to file2, rather than
- to finfo->file followed by rename. Remove check for whether
- result of checkout is readable; that was for an old, obsolete,
- form of death support.
-
-Sun Apr 13 13:16:40 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * checkout.c (build_one_dir): New function.
- (struct dir_to_build): New structure.
- (build_dirs_and_chir): Rewritten to accept a linked list of struct
- dir_to_build rather than the silly string processing we had been
- doing before.
- (checkout_proc): Rewrite code that calls build_dirs_and_chdir
- accordingly.
- * sanity.sh: Enable tests modules3-10 and modules3-11 for local CVS;
- tests for above fix.
-
- * rcs.h (RCS_CO): Removed; no longer used.
-
-Sun Apr 13 00:04:34 1997 Ian Lance Taylor <ian@cygnus.com>
-
- Expand RCS keywords internally; never call co:
- * rcs.h (struct rcsversnode): Add state field.
- * rcs.c (kflags): Move out of RCS_check_kflag, and make file
- static.
- (enum kflag): Define.
- (RCS_reparsercsfile): Always save lock information. Save state in
- new state field, rather than other field.
- (struct rcs_keyword): Define.
- (keywords): New static variable.
- (enum keyword): Define.
- (printable_date, escape_keyword_value): New static functions.
- (expand_keywords): New static function.
- (RCS_checkout): Call expand_keywords. Don't call
- RCS_exec_checkout.
- (RCS_deltas): Add log and loglen parameters. Change all callers.
- * log.c (log_version_requested): Use new state field.
- (log_version): Likewise.
- * cvs.h (RCS_exec_checkout): Don't declare.
- * rcscmds.c (RCS_exec_checkout): Remove.
-
-Sat Apr 12 17:32:59 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * sanity.sh (modules3): Remove second-dir at end of tests.
- (sticky): Correct removal of directories at end of tests.
-
- * sanity.sh (keyword): New tests for RCS keyword expansion.
-
-Sat Apr 12 16:47:13 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basicb): New tests basicb-1b, basicb-1c, basicb-9b,
- basic-9c test current build_dirs_and_chdir behavior.
-
-Fri Apr 11 23:54:56 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (modules3): New tests modules3-7* test for ability to
- supply a path in -d in modules. Similar to modules3-8 through
- modules3-11 except because the nesting is different, these ones
- work.
-
-Thu Apr 10 00:14:47 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (modules3): New tests modules3-12 through modules3-15
- test use of a module name which contains a slash.
-
- * sanity.sh (basicb): New tests basicb-14 to basicb-20 test use of
- co -d with two or more arguments.
-
- * rcscmds.c: Refer to doc/RCSFILES in comment.
-
-Wed Apr 9 09:49:17 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basicb): New tests basicb-11 through basicb-13 test
- ability to specify several directory levels in co -d (commented
- out).
-
- * filesubr.c (fopen_case): If CVS_OPENDIR gives an
- existence_error, return it to the caller instead of giving a fatal
- error.
-
- * client.c (update_entries): Fix typo in call to error (1 -> errno).
-
-Tue Apr 8 23:02:22 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * error.h, error.c: Test for #ifdef __STDC__, not #if __STDC__.
- This is consistent with other parts of CVS; it means that the
- declaration for fperror will match the definition even if __STDC__
- is defined to 0 as the SunPro 4.0 compiler does. Reported by
- Richard Smith <rjsmith@cisco.com>.
-
-2 Apr 1997 Jim Kingdon
-
- * entries.c (ParseTag): Add "break;" after "default:" to avoid
- error from Visual C++.
-
-Wed Apr 2 12:06:44 1997 Vince Del Vecchio <vdelvecc@spd.analog.com>
- and Jim Kingdon
-
- * client.c: In reporting errors from socket calls, use
- SOCK_STRERROR and SOCK_ERRNO since strerror(errno) doesn't work
- for Win32.
-
-Tue Apr 8 10:45:32 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (modules3): Add tests modules3-8 to modules3-11, to
- test for ability to supply a path to -d in modules. Mostly
- commented out as CVS is buggy in this area.
-
-Mon Apr 7 12:41:44 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c (add): Add comment about SEND_NO_CONTENTS.
-
-Sun Apr 6 21:46:32 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (update): Add comment about noexec and SEND_NO_CONTENTS.
-
-Sun Apr 6 17:34:08 1997 Robert Bihlmeyer <robbe@orcus.priv.at>
-
- * Pass +f not f to getopt_long to prevent options from being
- permuted with glibc 2.0.1.
-
-Sun Mar 30 00:07:05 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * cvs.h (struct vers_ts): Adjust comment regarding ts_user.
- * server.c (serve_is_modified): New function. Set entries to show
- that the file is modified but we don't know the contents.
- * server.c (requests): Add "Is-modified" request.
- * vers_ts.c (time_stamp_server): If the timestamp in entdata is
- "M" or "D", just copy that over into ts_user.
- * vers_ts.c (Version_TS): If timestamp is "D", use the entries
- line for the sole purpose of passing it to time_stamp_server.
- * no_diff.c (No_Difference): If ts_user is "M", conclude the files
- are different.
- * client.h, client.c (send_files): Replace arguments build_dirs
- and force with argument flags. Add flag SEND_NO_CONTENTS and add
- to struct send_data.
- (send_fileproc): If no_contents, then send Is-modified instead of
- Modified.
- * add.c, admin.c, client.c, commit.c, diff.c, edit.c, log.c,
- rcs.c, remove.c, status.c, tag.c, update.c, watch.c: Change all
- send_files callers.
-
-Fri Mar 28 22:32:25 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (requests): Change "Repository" to rq_optional. I'm
- not sure whether I overlooked this when I removed support for
- Repository, or whether I was thinking that servers would need to
- support it anyway, for CVS 1.5 to 1.9 clients, but making it
- optional doesn't prevent the server from supporting it and it
- seems silly for the client to complain about absence of a request
- that it never will use.
-
-Fri Mar 28 10:06:59 1997 Steven Miller <Miller@wingra.com>
-
- * entries.c (Subdirs_Known): Don't create Entries.Log if noexec.
-
-Thu Mar 27 18:14:12 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * sanity.sh (death2): Remove commented out test death2-21. It
- would now pass, but it duplicates the new test sticky-11.
-
-Thu Mar 27 10:21:19 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (dotest_internal): Write test output to logfile even
- if test succeeds. This was the behavior prior to 30 Sep 1996.
- See the comment for rationale.
-
-Tue Mar 25 13:26:52 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * cvs.h, entries.c (WriteTag): Add arguments nonbranch,
- update_dir, and repository. Move the server_set_sticky call from
- callers to here.
- * cvs.h, create_adm.c (Create_Admin): New argument nonbranch.
- * cvs.h, entries.c (ParseTag): Add argument nonbranchp.
- * cvs.h (struct stickydirtag): Add field nonbranch.
- * entries.c (Entries_Open): Set it.
- * cvs.h (Vers_TS): Add field nonbranch.
- * vers_ts.c (Version_TS): Copy it from struct stickydirtag.
- * server.c, server.h (server_set_sticky): Add argument nonbranch.
- * add.c, client.c, checkout.c, modules.c, update.c, create_adm.c,
- commit.c: Update callers.
- * add.c (add): If nonbranch, don't add the file on that "branch".
- * commit.c (write_dirnonbranch): New variable.
- (commit_fileproc, commit): Set it.
- (commit_dirleaveproc): Pass it to WriteTag.
- * update.c (rewrite_tag, nonbranch): New variables.
- (update, update_dirent_proc, update_fileproc): Set them.
- (update_filesdoneproc): If rewrite_tag, call WriteTag.
- * sanity.sh (sticky): New tests, test for above fix.
-
- * version.c: Change version number to 1.9.7.
-
- * version.c: Version 1.9.6.
-
-Mon Mar 24 13:02:04 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * entries.c (ParseTag): Add comment about unrecognized characters
- in CVS/Tag file.
-
- * classify.c (Classify_File): Add comment about how specifying a
- tag (bogusly?) suppresses certain messages.
-
-Fri Mar 21 13:37:46 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * rcs.h (struct rcsnode): Add comment about case of PATH.
- * rcs.c (RCS_parse): If ign_case, then try opening the file with
- fopen_case.
- * ignore.c (ign_case): Adjust comment.
- * cvs.h, filesubr.c (cvs_casecmp, fopen_case): New functions.
-
-20 Mar 1997 Jim Kingdon
-
- * client.c (send_repository): When sending Directory request,
- send any ISDIRSEP character as '/'. Fixes
- "cvs log foo\bar\baz.c" on NT & friends.
-
- * client.c (send_file_names): Don't try to read Entries file if
- CVSADM directory does not exist. Fixes fairly serious regression
- (warning on all fresh checkouts) introduced by 1997-01-08 change.
-
-Tue Mar 18 13:03:33 1997 Jim Meyering <meyering@totoro.cyclic.com>
-
- * sanity.sh (RCSINIT): Define to be empty and export, to hide any
- existing value that might cause spurious failures.
-
- * Makefile.in: (install): Depend on installdirs.
- Remove `CYGNUS LOCAL' comment saying not to.
-
-Tue Mar 18 09:36:26 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * recurse.c (struct recursion_frame): Reindent.
- (do_dir_proc): Print message if we try to recurse into a CVSADM
- directory.
- * sanity.sh (basicb): New test basicb-4a tests for above fix.
-
-Sun Mar 16 10:18:28 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (death2): Replace regexp matching temporary file name
- with new variable ${tempname}. For most of the tests this is a
- cosmetic change, but death2-diff-6 had been missing _ which caused
- it to fail on Solaris (at least sometimes).
-
- * sanity.sh (modes): Don't use export -n; it doesn't seem
- to be sufficiently portable.
-
- * version.c: Change version number to 1.9.5.
-
- * version.c: Version 1.9.4.
-
- * rcscmds.c (RCS_checkin): Preserve the mode of the rcsfile.
- RCS_CI usually, but not always, does this for us.
- * commit.c (fix_rcs_modes): Replace algorithm with a more
- CVSUMASK-friendly one.
- * sanity.sh (modes): Update tests modes-5, modes-7, modes-10, and
- modes-15 so they test that CVSUMASK is honored.
-
-Sun Mar 16 10:18:28 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (modes): New tests modes-7a and modes-7b test behavior
- if one manually changes the modes in the repository.
-
- * server.c (server): Revise code which checks for errors creating
- temporary directory. This won't solve the intermittent
- can't create temporary directory
- Unknown error -1
- but it will mean (a) the right message based on errno gets
- printed, instead of "unknown error -1", and (b) the message says
- that it happened in chmod instead of mkdir_p.
-
-Sat Mar 15 16:47:12 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (modes): New tests. Note that (for now) these are
- just testing how CVS already behaves; I want to record that before
- I move on to changing CVS's behavior with modes of RCS files.
-
-13 Mar 1997 Jim Kingdon
-
- * subr.c (line2argv): Change argv_allocated from size_t to int.
-
-Wed Mar 12 22:16:44 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c (add_directory): If repository has an extraneous "."
- directory at the end, strip it off. This fixes a bug which was
- introduced when strip_path was nuked (this fix is much more
- limited in scope than strip_path was; I _think_ that is a good
- thing).
- (add): Likewise, for client.
- (combine_dir): New function, helps with above.
- * sanity.sh (modules3): Reenable tests for this behavior.
- (basica-0b, basicb-0e): Adjust test to reflect "foo/bar" instead
- of "foo/./bar" in message. As with the rest of this, I believe
- this is just restoring the behavior prior to the strip_path nuking
- (I tried it with CVS 1.9).
-
-Sun Mar 9 10:06:29 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * root.c (parse_cvsroot), server.c (serve_root, serve_init):
- If CVSroot_directory is not an absolute pathname, give a fatal error.
- * sanity.sh (crerepos): New tests crerepos-6* test for above fixes.
-
-Sat Mar 8 22:06:17 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- This cleans up the last known code which can overflow its buffers
- (except the Mac client). I've skimmed through much of CVS looking
- for other such places; but I didn't read everything. If I missed
- any please report it to bug-cvs.
- * logmsg.c (logfile_write, title_proc): Realloc str_list as
- needed; don't assume MAXLISTLEN is enough.
- * cvs.h (MAXLISTLEN, MAXFILEPERDIR): Removed; no longer used.
- * add.c, myndbm.c, parseinfo.c, update.c: Nuke MAXLINELEN limit.
- * parseinfo.c, update.c, mkmodules.c: Check for errors reading file.
- * cvs.h (MAXLINELEN): Removed; no longer used.
- * logmsg (MAXHOSTNAMELEN): Removed; not used.
- * main.c (cmd_synonyms): Allocate based on fullname, nick1, and
- nick2, just in case someone makes those big enough so that 100
- bytes is not enough.
- (Make_Date): Use MAXDATELEN rather than our own fixed size.
- * mkmodules.c (mkmodules): Nuke arbitrary limit on line length.
- * rcs.c (ALLOCINCR): Remove; not used.
- (RCS_check_kflag): Add comment concerning karg size.
- * run.c: Allocate run_prog to the needed size, rather than
- allocating a fixed size buffer.
-
-Fri Mar 7 22:39:08 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * logmsg.c (logfile_write): Allocate prog to needed length rather
- than assuming MAXPROGLEN is enough.
- * cvs.h (MAXPROGLEN): Removed; no longer used.
- * subr.c (MIN_INCR): Update comment to reflect MAXPROGLEN's demise.
-
- * subr.c (free_names): Fix comment: this function is not used to
- free memory allocated by Find_Names (at least it hasn't for a long
- time).
- * subr.c, cvs.h (line2argv): Change calling convention so that we
- allocate argv array rather than the caller. The previous one had
- no way of checking whether we overflowed the passed-in buffer.
- * subr.c (free_names): Free the argv array too.
- * modules.c (do_module, cat_module): Update callers.
-
-Thu Mar 6 12:44:42 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * import.c: Allocate vhead and vbranch dynamically; removes
- arbitrary limit.
- * history.c: Likewise (since_rev, since_tag, backto, rec_types).
- * ignore.c: Likewise (line). Also check for errors from getline
- and add 'copyright' notice to top of file.
- * wrapper.c (wrap_add_file): Likewise (line). Also check for
- errors from various calls and add 'copyright' notice to top of file.
-
-Tue Mar 4 17:39:15 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (update_entries): Add comment about "move away <file>"
- message.
-
-Mon Mar 3 21:51:40 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basicb): Clean up topfile,v at end of test. Fixes
- failure in modules-155b.
-
-Sun Mar 2 18:11:09 1997 Dan Wilder <dan@gasboy.com>
- and Jim Kingdon
-
- * admin.c (admin): Arrange to perform recursion if "cvs admin"
- is passed only options.
-
-Sun Mar 2 18:11:09 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (basicb): New tests basicb-0* test for files at top
- level.
-
- * error.c (error): Add newline to "out of memory" message. I think
- that its omission probably could cause the message to be lost in
- the bowels of server.c and never passed to the user.
-
- * client.c (start_rsh_server): Add comment about "remsh" vs. "rsh".
-
- * cvs.h: Move copyright notice to top of file.
-
-Sun Mar 2 13:44:36 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * sanity.sh: Use -n when testing whether rsh works.
-
- * server.c (serve_root): Free path.
-
-Sun Mar 2 13:12:46 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- The following are things that I noticed in the process of trying
- to track down:
- can't create temporary directory
- Unknown error -1
- FAIL: test 28
- from nightly testing. I'm not sure that either item explains that
- message however.
- * server.c (server): Allocate pending_error_text;
- print_pending_error will try to free it so
- pending_error_text = "foo"
- won't work.
- (mkdir_p): Don't assume that isdir will leave errno unmolested.
-
-Thu Feb 27 15:29:58 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * remove.c (cvsremove): When forcing removal in client mode, use
- start_recursion rather than calling CVS_UNLINK on each argument.
- (remove_force_fileproc): New static function.
- * sanity.sh (deep): Add tests deep-rm7 through deep-rm10 for above
- patch.
-
- * sanity.sh (death): Enable death-76a0 and death-76a1 tests for
- remote, since they now work.
-
-Wed Feb 26 16:13:26 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * client.c (add_prune_candidate): Skip adding this directory if
- it is the same as the first directory already on the list.
-
-Mon Feb 24 21:36:43 1997 Noel Cragg <noel@gargle.rain.org>
-
- * main.c (lookup_command_attribute): Add the "init" command to the
- list of commands that don't use the current working directory.
-
-Sun Feb 23 09:54:49 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (devcom3): Clean up at end of test.
-
- * sanity.sh (basicb): Add commented out test basicb-8a0, for
- whether CVS can print an error on bad numeric revision to diff.
- Commented out until we get around to fixing CVS.
- * diff.c (diff_file_nodiff): Add comment about this case.
-
- * fileattr.c (fileattr_read): If a filename is duplicated,
- continue to ignore subsequent lines but free the node so that we
- don't leak memory.
- * sanity.sh (devcom3): New tests devcom3-8 and devcom3-9 test for
- behavior on duplicated filenames.
-
- * fileattr.h: Add comment about unrecognized ENT-TYPE and order of
- lines in fileattr file.
- * fileattr.c (struct unrecog, unrecog_head): New variables, to
- record unrecognized lines.
- (fileattr_startdir): Assert that unrecog_head == NULL.
- (fileattr_read): Record unrecognized lines in unrecog_head linked
- list rather than ignoring them.
- (fileattr_write): Also write out unrecognized lines, if any.
- * sanity.sh (devcom3): New tests, test for above fix.
-
- * fileattr.h (fileattr_modify): Fix example in comment.
-
-Sat Feb 22 08:30:27 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Add variable username.
- (basica rdiff multibranch log log2): Use it instead of our own
- (inconsistent) ways of matching an author name.
-
- * filesubr.c, root.c, rtag.c, server.c, subr.c, update.c,
- wrapper.c: Nuke PATH_MAX.
- * cvs.h, wrapper.c (wrap_fromcvs_process_file): Now returns void
- (return value had been unused).
- * cvs.h: Adjust comment to reflect the fact that PATH_MAX is
- gone, at least from src/*.c (except safe_location, as noted).
-
-22 Feb 1997 patch by Tom Hageman <tom@basil.icce.rug.nl> (4 Jun 1996)
- updated and commented by Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * update.c (checkout_file): Call unlink_file_dir on backup, not
- unlink_file.
-
-Fri Feb 21 16:40:03 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Makefile.in (DISTFILES): Remove NOTES.
-
- * NOTES: Removed. bcopy->memcpy is done. "static buffers" I
- assume refers to what is covered by reentrancy text in HACKING.
- Obstack idea moved to comment in hash.c (at nodecache). Checking
- system calls for error returns largely done, and isn't a very
- helpful suggestion unless you know where the bogus calls are
- anyway. Sizing limits--we're in the progress of removing them
- (assuming it meant things like PATH_MAX and earlier, already
- nuked, limits). Removed various items about changes which were
- done a long time ago (I realize that the ChangeLog's probably
- aren't reliable that far back, but I'm not convinced anyone cares
- anymore). CONFIRM_DIRECTORY_ADDS: I assume this is a
- reference to the #if 0'd code in add_directory which asks for
- confirmation--a better way of making it harder to accidentally add
- directories would be to have to add and commit directories like
- for files. I don't know what FORCE_MESSAGE_ON_ADD meant.
-
- * rcs.c (RCS_getrevtime): Fix documentation (in particular, the
- size of the array that DATE must point to, but many other things
- too).
- * patch.c, recurse.c, release.c, remove.c, repos.c: Nuke PATH_MAX.
- (patch_fileproc): Use MAXDATELEN not hardcoded 50.
-
-Sun Feb 16 12:00:44 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (client_process_import_file): New variable fullname;
- pass it to send_modified. This finishes the job of untangling the
- old short_pathname variable into update_dir vs. fullname.
-
- * client.c (client_process_import_file): Nuke first_time. If
- toplevel_repos were ever NULL here, the code would dump core in
- strncmp a few lines down. And client_import_setup ensures
- toplevel_repos is not NULL.
-
-Sun Feb 16 08:16:48 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * client.c (client_process_import_file): Rename short_pathname to
- update_dir (to reflect its function) and make sure that it doesn't
- point to uninitialized memory if repository and toplevel_repos
- contain the same string.
-
-Sun Feb 16 08:16:48 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (start_rsh_server): Nuke comment about weirdnesses with
- pre-1.5 versions of CVS and .bashrc/.cshrc. The remote protocol
- is interoperable only back to 1.5, and people who need to know are
- unlikely to see this comment anyway.
-
-Sun Dec 15 13:12:30 1996 Michael Douglass <mikedoug@texas.net>
- and Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * main.c (cmds): Added an entry for new logout command.
- (cmd_usage): Added an entry for new logout command.
- (lookup_command_attribute): Added 'logout' to list of commands
- that set need_to_crate_root to 1.
- * login.c, cvs.h (logout): New command for removing entries from
- the .cvspass file.
- (logout_usage): Usage information on the logout command.
-
-Wed Feb 12 11:19:42 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (struct send_data): Fix indentation.
-
-Wed Feb 12 08:48:04 1997 Greg A. Woods <woods@most.weird.com>
-
- * mkmodules.c (loginfo_contents): add missing comma in
- initializer statement (caused syntax error on SunOS-4).
-
-Tue Feb 11 21:14:28 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * commit.c (find_fileproc): If force_ci is set, set the status to
- T_MODIFIED even if the file hasn't changed.
- (commit): Pass force_ci to send_files as new force argument.
- * client.c (struct send_data): Define.
- (send_fileproc): The callerdat parameter now points to a send_data
- struct. If force is set, always call send_modified.
- (send_dirent_proc): The callerdat parameter now points to a
- send_data struct.
- (send_files): Add force parameter. Change all callers. Set up a
- send_data struct and pass it to start_recursion as callerdat.
- * client.h (send_files): Update declaration.
- * sanity.sh (basica): Add a simple test for the above patch.
-
-Sun Feb 9 12:58:59 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * tag.c (cvstag), rtag.c (rtag): Pass -f to server if specified in
- the client. I haven't tried to come up with a test case because
- the fix seems obvious.
-
- * import.c (add_rcs_file): Change size of altdate1 and altdate2 to
- MAXDATELEN.
- * cvs.h (MAXDATELEN): Fix comments; describe what this is for.
-
- * diff.c (diff_usage): Document --ifdef and try to briefly say
- what "rcsdiff-options" means.
-
- * update.c (update): If update had a nonzero status and we haven't
- yet tried to fetch unpatchable files, go ahead and try it again.
- The previous behavior was to quit, which meant that updates would
- keep failing until you hacked around the problem. Patch and bug
- report by Ian; comment, ChangeLog entry, and willingness to take
- the flak if checking it is premature by Jim.
-
- * server.c (alloc_pending): New function.
- * server.c: Call it. Fixes places where we had neglected to
- check for NULL return from malloc.
-
- * sanity.sh (binwrap): Add test binwrap-0, tests for import.c fix
- below.
-
-Sun, 9 Feb 1997 (submitted 19 Jul 1996) John Polstra <jdp@polstra.com>
-
- * import.c (import): Give error if the same tag is specified more
- than once. The previous behavior was to write an RCS file which
- had the same tag listed twice, once pointing to each revision,
- which is not legal.
-
-Sun Feb 9 12:37:09 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * checkin.c (Checkin): Use cvs_output to print message (should
- make out of order bugs no worse, as it merely substitues a
- protocol_pipe vs. stderr_pipe race instead of a stdout_pipe
- vs. stderr_pipe race). Add comment about stdout vs. stderr.
-
-Fri Feb 7 08:29:52 1997 Josef Nelissen <josef.nelissen@munich.ixos.de>
-
- * server.c (check_command_legal_p): Don't use ANSI-style definition.
-
-Thu Feb 6 10:55:37 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * patch.c (patch): Give a fatal error for -V option (see comment
- for rationale).
-
- * diff.c (diff): Also send "options" to server. Pretty much the
- patch submitted independently by josef.nelissen@munich.ixos.de and
- Ronald Khoo <ronald@demon.net>.
-
-Wed Feb 5 18:57:14 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * modules.c (do_module): Fix typo in 30 Jan 97 PATH_MAX nuking
- (free -> free_cwd). Testsuite test 151 gets credit for catching
- this one.
-
-Mon Feb 3 16:14:54 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * main.c (lookup_command_attribute): Don't use an ANSI prototype
- when defining the function.
-
-Fri Jan 31 12:49:02 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * modules.c (do_module): Actually goto found if is_found is set
- (fixes thinko in PATH_MAX nuking of 30 Jan 97).
-
-Fri Jan 31 12:49:02 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh: Add modules3 and big to list of tests to run
- by default; they were omitted by accident.
-
-Thu Jan 30 11:46:33 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * logmsg.c, main.c, mkmodules.c, modules.c, parseinfo.c, patch.c:
- Nuke more PATH_MAX.
-
- * server.c (server_updated): After we send Created or
- Update-existing for a file, mark it as unchanged, in case we
- process it again.
- * sanity.sh (modules3): New tests, test for above fix.
-
- * logmsg.c (do_verify): Error return from fopen is NULL, not -1.
- Pass errno to error().
-
- * login.c [_CRAY]: Don't declare getpass.
-
-Mon Jan 27 17:25:27 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * import.c (process_import_file): Fix freeing of rcs (Don't free
- it before we are done using it, and don't free it twice).
-
- * modules.c (cat_module): Allocate line right before we use
- it. The previous code was wrong because the length of the
- s_h->rest changes between the time we allocate line and the time we
- sprintf s_h->rest into it.
-
-Sun Jan 26 21:58:16 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * expand_path.c (expand_path): Revise to call expand_string as
- needed. Nuke PATH_MAX.
- * find_names.c (find_dirs): Likewise.
- * import.c, lock.c: Nuke more PATH_MAX.
-
- * server.c (mkdir_p): Set retval to 0 at start of function.
- Previously it had been uninitialized for some cases. Thanks are
- due to nightly testing for catching this one.
-
-Sat Jan 25 21:34:19 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * subr.c, cvs.h (expand_string): New function.
- * rcs.c (getrcskey, getrcsrev): Call it. This greatly reduces the
- number of calls to realloc if there is a very large file in the
- RCS file. Credit goes to Mike Heath <mike@pswtech.com> for
- pointing out the problem and the basic solution (MIN_INCR,
- MAX_INCR); I adapted it into the separate function expand_string.
- * sanity.sh (big): New test helps insure this hasn't broken
- anything obvious.
-
-Wed Jan 22 10:06:13 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * status.c (status_fileproc): Change message which is printed for
- T_MODIFIED and ts_conflict set, so that it doesn't say "unresolved
- confict". This message occurs whether the conflict is resolved or
- not.
- * sanity.sh (conflicts): Add tests conflicts-status-* to test
- output of "cvs status" in the context of conflicts. Tests for
- above fix.
-
- * rtag.c (rtag): Send -n if run_module_prog is NOT true.
-
-Thu Jan 16 00:06:00 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * version.c: Change version number to 1.9.3.
-
- * version.c: Version 1.9.2.
-
-Wed Jan 15 09:14:38 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * client.c (call_in_directory): Take code that creates CVSADM at
- top level, move it before the CVS_CHDIR (dir_name) call, and do it
- regardless of whether dir_name is ".". Pass "." not dir_name to
- Create_Admin (when the code was written they were always the
- same). Don't add reposdirname to the repository we pass to
- Create_Admin (when the code was written, I think reposdirname
- probably would always be "."). Don't create CVSADM if
- reposdirname_absolute.
- * sanity.sh (basicb): Enable tests basicb-1a and basicb-9a for
- remote; tests for above fix.
- (basic1): Do entire test within a "1" directory to deal with
- creation of CVS directories at top level. Support --keep.
- (conflicts): In test conflicts-136, only update first-dir.
- (basica): Uncomment the part that tests "cvs co -l .". That tests
- the existing functionality which I might have (but hopefully did not)
- perturbed with the call_in_directory changes.
-
-Mon Jan 13 11:04:32 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * server.c (check_command_legal_p): Do not call error (1, ...)
- here; that will always cause a protocol violation by shutting down
- the connection prematurely. Remove croak_on_illegal arg.
- (do_cvs_command): Move call to check_command_legal_p until after
- the call to print_pending_error. Print the error message ourself.
-
- * mkmodules.c (filelist): Add readers and writers. Add comment
- about why passwd is not included. Add comment about meaning of
- NULL contents field.
-
-Fri Jan 10 13:23:09 1997 Norbert Kiesel <nk@col.sw-ley.de>
-
- * release.c (release): Initialize delete_flag before reading it
- (found by running purify)
-
- * logmsg.c (do_verify): Fix reading unallocated memory (found by
- running purify)
-
-Thu Jan 9 16:32:47 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * checkout.c (build_dirs_and_chdir): Partially revert 3 Jan
- change--move call to Subdir_Register back above the CVS_CHDIR call
- (we need to register in the old, not the new, directory). Instead
- of calling CVS_MKDIR and ignoring errors, call mkdir_if_needed;
- this is an effort to catch errors there rather than catching them
- in the CVS_CHDIR. This makes test 27-add-add in sanity.sh work
- again.
-
- * find_names.c (Find_Directories): Remove code inside
- #ifdef ATTIC_DIR_SUPPORT and replace it with a comment explaining
- why we don't look in the attic. ATTIC_DIR_SUPPORT was never defined.
-
- * find_names.c (find_dirs): Add comment about tmp being unset.
-
- * commit.c (checkaddfile): Report errors with errno and specific
- error messages.
-
- * rcs.c, commit.c, create_adm.c, entries.c, find_names.c,
- ignore.c, history.c: Nuke PATH_MAX arbitrary limits.
-
-Wed Jan 8 23:07:41 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * add.c (add): Reindent a portion which needed it.
-
-1997-01-08 Jim Kingdon
-
- * client.c (send_file_names): When looking name up in Entries,
- call Entries_Open and Entries_Close. This has two effects:
- (1) we look at Entries.Log, and (2) we don't skip 'D' entries,
- both of which are needed to make us get the right (command
- line) name for a directory we are adding.
-
-Wed Jan 8 14:50:47 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Makefile.in, cvs.h, hash.h, myndbm.h, rcs.h: Remove CVSid; we
- decided to get rid of these some time ago.
-
-Tue Jan 7 12:56:10 1997 Karl Fogel <kfogel@ynu38.ynu.edu.cn>
-
- * root.c (check_root_consistent): new func, compares below new
- global var with CVSroot_directory, assuming both set.
- (set_local_cvsroot): use above new func for security check.
- (parse_cvsroot): same.
- But do all of above only #ifdef AUTH_SERVER_SUPPORT.
-
- * server.c: (Pserver_Repos): new global var, init to NULL.
- (pserver_authenticate_connection): set above new global.
- (check_repository_password): be a good scout and use
- CVSROOTADM and CVSROOTADM_PASSWD, now that they are the standard.
- Make sure all of above is in #ifdef AUTH_SERVER_SUPPORT.
- (check_command_legal_p): wrap most of body in #ifdef
- AUTH_SERVER_SUPPORT.
- Everywhere: wrap all references to CVS_Username in #ifdef
- AUTH_SERVER_SUPPORT.
-
- * cvs.h (Pserver_Repos): new var, used in consistency [security]
- check. Defined only #ifdef AUTH_SERVER_SUPPORT.
- (CVSROOTADM_PASSWD): new #define, trying to get with the program.
-
-Fri Jan 3 18:10:39 1997 Ian Lance Taylor <ian@cygnus.com>
-
- * checkout.c (build_dirs_and_chdir): Move call to Subdir_Register
- until after we know that the directory exists.
-
-Thu Jan 2 13:30:56 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Makefile.in, cvsbug.sh, edit.c, edit.h, error.c, error.h,
- fileattr.c, fileattr.h, filesubr.c, run.c, update.h, watch.c,
- watch.h: Remove "675" paragraph; see ../ChangeLog for rationale.
-
-Thu Jan 2 12:27:46 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * sanity.sh (info): New test info-cleanup-verifymsg gets rid of
- verifymsg when we are done with it.
-
- * sanity.sh (basicb): Skip tests basicb-1a and basicb-9a for remote.
- * sanity.sh (modules-155a4): It is OK if a CVS directory exists.
- * sanity.sh (ignore): Do everything inside a "1" directory. The
- change to create CVS directories at top-level causes messages such as
- "? home" otherwise. In test 191, specify -I CVS so that new CVS
- directory is ignored.
- * sanity.sh (crerepos): Manually remove CVS directory which had not
- existed before.
-
-Thu Jan 2 09:06:20 1997 Karl Fogel <kfogel@ynu38.ynu.edu.cn>
-
- * server.c: Changes for pserver read-only repository access:
- (check_command_legal_p): new func. Right now, just checks if
- repository modification is permitted, and that only if pserver is
- active.
- (do_cvs_command): take new parameter `cmd_name', a string. All
- callers changed. Pass it on to new func check_command_legal_p()
- before executing the command.
- (CVS_Username): new global, init to NULL. Used by
- check_command_legal_p(), set in check_password().
- (check_password): set above new global CVS_Username; reorganized a
- bit to facilitate this.
- (check_repository_password): give *host_user_ptr permanent
- storage iff success.
-
- * main.c: Changes for pserver read-only repository access:
- (lookup_command_attribute): new func.
- (main): use new func lookup_command_attribute() to establish if
- CVS_CMD_IGNORE_ADMROOT and CVS_CMD_USES_WORK_DIR.
-
- * cvs.h: Changes for pserver read-only repository access:
- (CVSROOTADM_READERS, CVSROOTADM_WRITERS): new #defines.
- Prototype lookup_command_attribute().
- (CVS_CMD_IGNORE_ADMROOT, CVS_CMD_USES_WORK_DIR,
- CVS_CMD_MODIFIES_REPOSITORY): new #defines for
- lookup_command_attribute() and its callers.
-
-Wed Jan 1 19:50:38 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * options.h.in: Reword comment for TMPDIR_DFLT to make it clear
- that this isn't specific to the pserver server.
-
- * modules.c (do_module): Give an error message if one tries to
- specify -a together with another option.
- * sanity.sh (modules2): New tests modules2-a* test for above fix.
-
- * sanity.sh (devcom): Add tests devcom-a-nonexist and
- devcom-t-nonexist for "cvs watchers" on nonexistent argument.
-
-1997-01-01 Fred Fish <fnf@ninemoons.com>
-
- * run.c (piped_child, filter_stream_through_program): Actually
- install these HAVE_VFORK patches that got missed.
- (There was a log entry for these changes for 29 Nov 1996 but it
- seems I accidentally forgot to actually check them in -kingdon).
-
-Wed Jan 1 18:32:44 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
-
- * Makefile.in: Add ChangeLog-96.
- * ChangeLog-96: New file, contains former contents of ChangeLog.
- * ChangeLog: Now just contains 1997 changes.
-
-
-For older changes see ChangeLog-96.
diff --git a/contrib/cvs/src/Makefile.am b/contrib/cvs/src/Makefile.am
deleted file mode 100644
index 63e6b18407a8..000000000000
--- a/contrib/cvs/src/Makefile.am
+++ /dev/null
@@ -1,138 +0,0 @@
-## Process this file with automake to produce Makefile.in
-# Makefile for GNU CVS program.
-#
-# Copyright (C) 1986-2005 The Free Software Foundation, Inc.
-#
-# Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
-# and others.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-SHELL = /bin/sh
-
-# $(includeopt) is CVS specific and set by configure
-# FIXME - This includes line is dependant on its order. This means there is
-# some namespace hackery going on that maybe shouldn't be. Long term fix is to
-# try and remove naming ocnflicts and fix Automake to allow particular includes
-# to be attached only to particular object files. Short term fix is either or.
-##INCLUDES = -I. -I.. -I$(srcdir) -I$(top_srcdir)/lib
-INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/diff -I$(top_srcdir)/zlib $(includeopt)
-
-bin_PROGRAMS = cvs
-bin_SCRIPTS = cvsbug
-
-# The cvs executable
-cvs_SOURCES = \
- add.c \
- admin.c \
- annotate.c \
- buffer.c \
- checkin.c \
- checkout.c \
- classify.c \
- client.c \
- commit.c \
- create_adm.c \
- cvsrc.c diff.c \
- edit.c \
- entries.c \
- error.c \
- expand_path.c \
- fileattr.c \
- filesubr.c \
- find_names.c \
- hardlink.c \
- hash.c \
- history.c \
- ignore.c \
- import.c \
- lock.c \
- log.c \
- login.c \
- logmsg.c \
- main.c \
- mkmodules.c \
- modules.c \
- myndbm.c \
- no_diff.c \
- parseinfo.c \
- patch.c \
- rcs.c \
- rcscmds.c \
- recurse.c \
- release.c \
- remove.c \
- repos.c \
- root.c \
- run.c \
- scramble.c \
- server.c \
- stack.c \
- status.c \
- subr.c \
- tag.c \
- update.c \
- version.c \
- vers_ts.c \
- watch.c \
- wrapper.c \
- zlib.c \
- buffer.h \
- client.h \
- cvs.h \
- edit.h \
- error.h \
- fileattr.h \
- hardlink.h \
- hash.h \
- history.h \
- myndbm.h \
- rcs.h \
- root.h \
- server.h \
- stack.h \
- update.h \
- watch.h
-
-cvs_LDADD = \
- ../diff/libdiff.a \
- ../lib/libcvs.a \
- ../zlib/libz.a
-
-# extra clean targets
-# wish this could be distclean-hdr-local but it's not part of automake
-DISTCLEANFILES = check.log check.plog
-
-# General
-EXTRA_DIST = \
- .cvsignore \
- ChangeLog-9194 \
- ChangeLog-9395 \
- ChangeLog-96 \
- ChangeLog-97 \
- build_src.com \
- sanity.sh
-
-check-local: localcheck remotecheck
-
-.PHONY: localcheck
-localcheck:
- $(SHELL) $(srcdir)/sanity.sh `pwd`/cvs$(EXEEXT)
-
-.PHONY: remotecheck
-remotecheck: all
- $(SHELL) $(srcdir)/sanity.sh -r `pwd`/cvs$(EXEEXT)
-
-## MAINTAINER Targets
-
-# for backwards compatibility with the old makefiles
-.PHONY: realclean
-realclean: maintainer-clean
diff --git a/contrib/cvs/src/Makefile.in b/contrib/cvs/src/Makefile.in
deleted file mode 100644
index d88773c3efd0..000000000000
--- a/contrib/cvs/src/Makefile.in
+++ /dev/null
@@ -1,658 +0,0 @@
-# Makefile.in generated by automake 1.10 from Makefile.am.
-# @configure_input@
-
-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-# This Makefile.in is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-@SET_MAKE@
-
-# Makefile for GNU CVS program.
-#
-# Copyright (C) 1986-2005 The Free Software Foundation, Inc.
-#
-# Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
-# and others.
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-
-VPATH = @srcdir@
-pkgdatadir = $(datadir)/@PACKAGE@
-pkglibdir = $(libdir)/@PACKAGE@
-pkgincludedir = $(includedir)/@PACKAGE@
-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
-install_sh_DATA = $(install_sh) -c -m 644
-install_sh_PROGRAM = $(install_sh) -c
-install_sh_SCRIPT = $(install_sh) -c
-INSTALL_HEADER = $(INSTALL_DATA)
-transform = $(program_transform_name)
-NORMAL_INSTALL = :
-PRE_INSTALL = :
-POST_INSTALL = :
-NORMAL_UNINSTALL = :
-PRE_UNINSTALL = :
-POST_UNINSTALL = :
-bin_PROGRAMS = cvs$(EXEEXT)
-subdir = src
-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
- $(srcdir)/cvsbug.in ChangeLog
-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
- $(top_srcdir)/configure.in
-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
- $(ACLOCAL_M4)
-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
-CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES = cvsbug
-am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)"
-binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
-PROGRAMS = $(bin_PROGRAMS)
-am_cvs_OBJECTS = add.$(OBJEXT) admin.$(OBJEXT) annotate.$(OBJEXT) \
- buffer.$(OBJEXT) checkin.$(OBJEXT) checkout.$(OBJEXT) \
- classify.$(OBJEXT) client.$(OBJEXT) commit.$(OBJEXT) \
- create_adm.$(OBJEXT) cvsrc.$(OBJEXT) diff.$(OBJEXT) \
- edit.$(OBJEXT) entries.$(OBJEXT) error.$(OBJEXT) \
- expand_path.$(OBJEXT) fileattr.$(OBJEXT) filesubr.$(OBJEXT) \
- find_names.$(OBJEXT) hardlink.$(OBJEXT) hash.$(OBJEXT) \
- history.$(OBJEXT) ignore.$(OBJEXT) import.$(OBJEXT) \
- lock.$(OBJEXT) log.$(OBJEXT) login.$(OBJEXT) logmsg.$(OBJEXT) \
- main.$(OBJEXT) mkmodules.$(OBJEXT) modules.$(OBJEXT) \
- myndbm.$(OBJEXT) no_diff.$(OBJEXT) parseinfo.$(OBJEXT) \
- patch.$(OBJEXT) rcs.$(OBJEXT) rcscmds.$(OBJEXT) \
- recurse.$(OBJEXT) release.$(OBJEXT) remove.$(OBJEXT) \
- repos.$(OBJEXT) root.$(OBJEXT) run.$(OBJEXT) \
- scramble.$(OBJEXT) server.$(OBJEXT) stack.$(OBJEXT) \
- status.$(OBJEXT) subr.$(OBJEXT) tag.$(OBJEXT) update.$(OBJEXT) \
- version.$(OBJEXT) vers_ts.$(OBJEXT) watch.$(OBJEXT) \
- wrapper.$(OBJEXT) zlib.$(OBJEXT)
-cvs_OBJECTS = $(am_cvs_OBJECTS)
-cvs_DEPENDENCIES = ../diff/libdiff.a ../lib/libcvs.a ../zlib/libz.a
-binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
-SCRIPTS = $(bin_SCRIPTS)
-DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
-depcomp = $(SHELL) $(top_srcdir)/depcomp
-am__depfiles_maybe = depfiles
-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-CCLD = $(CC)
-LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-SOURCES = $(cvs_SOURCES)
-DIST_SOURCES = $(cvs_SOURCES)
-ETAGS = etags
-CTAGS = ctags
-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
-ACLOCAL = @ACLOCAL@
-AMTAR = @AMTAR@
-AUTOCONF = @AUTOCONF@
-AUTOHEADER = @AUTOHEADER@
-AUTOMAKE = @AUTOMAKE@
-AWK = @AWK@
-CC = @CC@
-CCDEPMODE = @CCDEPMODE@
-CFLAGS = @CFLAGS@
-CPP = @CPP@
-CPPFLAGS = @CPPFLAGS@
-CSH = @CSH@
-CYGPATH_W = @CYGPATH_W@
-DEFS = @DEFS@
-DEPDIR = @DEPDIR@
-ECHO_C = @ECHO_C@
-ECHO_N = @ECHO_N@
-ECHO_T = @ECHO_T@
-EDITOR = @EDITOR@
-EGREP = @EGREP@
-EXEEXT = @EXEEXT@
-GREP = @GREP@
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_SCRIPT = @INSTALL_SCRIPT@
-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
-KRB4 = @KRB4@
-LDFLAGS = @LDFLAGS@
-LIBOBJS = @LIBOBJS@
-LIBS = @LIBS@
-LN_S = @LN_S@
-LTLIBOBJS = @LTLIBOBJS@
-MAINT = @MAINT@
-MAKEINFO = @MAKEINFO@
-MKDIR_P = @MKDIR_P@
-MKTEMP = @MKTEMP@
-OBJEXT = @OBJEXT@
-PACKAGE = @PACKAGE@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_TARNAME = @PACKAGE_TARNAME@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-PATH_SEPARATOR = @PATH_SEPARATOR@
-PERL = @PERL@
-PR = @PR@
-PS2PDF = @PS2PDF@
-RANLIB = @RANLIB@
-ROFF = @ROFF@
-SENDMAIL = @SENDMAIL@
-SET_MAKE = @SET_MAKE@
-SHELL = /bin/sh
-STRIP = @STRIP@
-TEXI2DVI = @TEXI2DVI@
-VERSION = @VERSION@
-YACC = @YACC@
-YFLAGS = @YFLAGS@
-abs_builddir = @abs_builddir@
-abs_srcdir = @abs_srcdir@
-abs_top_builddir = @abs_top_builddir@
-abs_top_srcdir = @abs_top_srcdir@
-ac_ct_CC = @ac_ct_CC@
-ac_prefix_program = @ac_prefix_program@
-am__include = @am__include@
-am__leading_dot = @am__leading_dot@
-am__quote = @am__quote@
-am__tar = @am__tar@
-am__untar = @am__untar@
-bindir = @bindir@
-build_alias = @build_alias@
-builddir = @builddir@
-datadir = @datadir@
-datarootdir = @datarootdir@
-docdir = @docdir@
-dvidir = @dvidir@
-exec_prefix = @exec_prefix@
-host_alias = @host_alias@
-htmldir = @htmldir@
-includedir = @includedir@
-includeopt = @includeopt@
-infodir = @infodir@
-install_sh = @install_sh@
-libdir = @libdir@
-libexecdir = @libexecdir@
-localedir = @localedir@
-localstatedir = @localstatedir@
-mandir = @mandir@
-mkdir_p = @mkdir_p@
-oldincludedir = @oldincludedir@
-pdfdir = @pdfdir@
-prefix = @prefix@
-program_transform_name = @program_transform_name@
-psdir = @psdir@
-sbindir = @sbindir@
-sharedstatedir = @sharedstatedir@
-srcdir = @srcdir@
-sysconfdir = @sysconfdir@
-target_alias = @target_alias@
-top_builddir = @top_builddir@
-top_srcdir = @top_srcdir@
-with_default_rsh = @with_default_rsh@
-with_default_ssh = @with_default_ssh@
-
-# $(includeopt) is CVS specific and set by configure
-# FIXME - This includes line is dependant on its order. This means there is
-# some namespace hackery going on that maybe shouldn't be. Long term fix is to
-# try and remove naming ocnflicts and fix Automake to allow particular includes
-# to be attached only to particular object files. Short term fix is either or.
-INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/diff -I$(top_srcdir)/zlib $(includeopt)
-bin_SCRIPTS = cvsbug
-
-# The cvs executable
-cvs_SOURCES = \
- add.c \
- admin.c \
- annotate.c \
- buffer.c \
- checkin.c \
- checkout.c \
- classify.c \
- client.c \
- commit.c \
- create_adm.c \
- cvsrc.c diff.c \
- edit.c \
- entries.c \
- error.c \
- expand_path.c \
- fileattr.c \
- filesubr.c \
- find_names.c \
- hardlink.c \
- hash.c \
- history.c \
- ignore.c \
- import.c \
- lock.c \
- log.c \
- login.c \
- logmsg.c \
- main.c \
- mkmodules.c \
- modules.c \
- myndbm.c \
- no_diff.c \
- parseinfo.c \
- patch.c \
- rcs.c \
- rcscmds.c \
- recurse.c \
- release.c \
- remove.c \
- repos.c \
- root.c \
- run.c \
- scramble.c \
- server.c \
- stack.c \
- status.c \
- subr.c \
- tag.c \
- update.c \
- version.c \
- vers_ts.c \
- watch.c \
- wrapper.c \
- zlib.c \
- buffer.h \
- client.h \
- cvs.h \
- edit.h \
- error.h \
- fileattr.h \
- hardlink.h \
- hash.h \
- history.h \
- myndbm.h \
- rcs.h \
- root.h \
- server.h \
- stack.h \
- update.h \
- watch.h
-
-cvs_LDADD = \
- ../diff/libdiff.a \
- ../lib/libcvs.a \
- ../zlib/libz.a
-
-
-# extra clean targets
-# wish this could be distclean-hdr-local but it's not part of automake
-DISTCLEANFILES = check.log check.plog
-
-# General
-EXTRA_DIST = \
- .cvsignore \
- ChangeLog-9194 \
- ChangeLog-9395 \
- ChangeLog-96 \
- ChangeLog-97 \
- build_src.com \
- sanity.sh
-
-all: all-am
-
-.SUFFIXES:
-.SUFFIXES: .c .o .obj
-$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
- @for dep in $?; do \
- case '$(am__configure_deps)' in \
- *$$dep*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
- && exit 0; \
- exit 1;; \
- esac; \
- done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
- cd $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/Makefile
-.PRECIOUS: Makefile
-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
- @case '$?' in \
- *config.status*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
- *) \
- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
- esac;
-
-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-
-$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
-cvsbug: $(top_builddir)/config.status $(srcdir)/cvsbug.in
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
-install-binPROGRAMS: $(bin_PROGRAMS)
- @$(NORMAL_INSTALL)
- test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
- @list='$(bin_PROGRAMS)'; for p in $$list; do \
- p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
- if test -f $$p \
- ; then \
- f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \
- $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \
- else :; fi; \
- done
-
-uninstall-binPROGRAMS:
- @$(NORMAL_UNINSTALL)
- @list='$(bin_PROGRAMS)'; for p in $$list; do \
- f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
- echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
- rm -f "$(DESTDIR)$(bindir)/$$f"; \
- done
-
-clean-binPROGRAMS:
- -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
-cvs$(EXEEXT): $(cvs_OBJECTS) $(cvs_DEPENDENCIES)
- @rm -f cvs$(EXEEXT)
- $(LINK) $(cvs_OBJECTS) $(cvs_LDADD) $(LIBS)
-install-binSCRIPTS: $(bin_SCRIPTS)
- @$(NORMAL_INSTALL)
- test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
- @list='$(bin_SCRIPTS)'; for p in $$list; do \
- if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
- if test -f $$d$$p; then \
- f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
- echo " $(binSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(bindir)/$$f'"; \
- $(binSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(bindir)/$$f"; \
- else :; fi; \
- done
-
-uninstall-binSCRIPTS:
- @$(NORMAL_UNINSTALL)
- @list='$(bin_SCRIPTS)'; for p in $$list; do \
- f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \
- echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \
- rm -f "$(DESTDIR)$(bindir)/$$f"; \
- done
-
-mostlyclean-compile:
- -rm -f *.$(OBJEXT)
-
-distclean-compile:
- -rm -f *.tab.c
-
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/add.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/admin.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/annotate.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/buffer.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checkin.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checkout.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/classify.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/commit.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/create_adm.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cvsrc.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/diff.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edit.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entries.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/expand_path.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fileattr.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filesubr.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/find_names.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hardlink.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/history.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ignore.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/import.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/login.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logmsg.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkmodules.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modules.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/myndbm.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/no_diff.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parseinfo.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/patch.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rcs.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rcscmds.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recurse.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/release.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remove.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/repos.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/root.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scramble.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stack.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/status.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subr.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tag.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/update.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vers_ts.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/watch.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wrapper.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zlib.Po@am__quote@
-
-.c.o:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
-
-.c.obj:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
-
-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- mkid -fID $$unique
-tags: TAGS
-
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- tags=; \
- here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
- test -n "$$unique" || unique=$$empty_fix; \
- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
- $$tags $$unique; \
- fi
-ctags: CTAGS
-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
- $(TAGS_FILES) $(LISP)
- tags=; \
- here=`pwd`; \
- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
- unique=`for i in $$list; do \
- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
- done | \
- $(AWK) ' { files[$$0] = 1; } \
- END { for (i in files) print i; }'`; \
- test -z "$(CTAGS_ARGS)$$tags$$unique" \
- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
- $$tags $$unique
-
-GTAGS:
- here=`$(am__cd) $(top_builddir) && pwd` \
- && cd $(top_srcdir) \
- && gtags -i $(GTAGS_ARGS) $$here
-
-distclean-tags:
- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
-
-distdir: $(DISTFILES)
- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
- list='$(DISTFILES)'; \
- dist_files=`for file in $$list; do echo $$file; done | \
- sed -e "s|^$$srcdirstrip/||;t" \
- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
- case $$dist_files in \
- */*) $(MKDIR_P) `echo "$$dist_files" | \
- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
- sort -u` ;; \
- esac; \
- for file in $$dist_files; do \
- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
- if test -d $$d/$$file; then \
- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
- cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
- fi; \
- cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
- else \
- test -f $(distdir)/$$file \
- || cp -p $$d/$$file $(distdir)/$$file \
- || exit 1; \
- fi; \
- done
-check-am: all-am
- $(MAKE) $(AM_MAKEFLAGS) check-local
-check: check-am
-all-am: Makefile $(PROGRAMS) $(SCRIPTS)
-installdirs:
- for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)"; do \
- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
- done
-install: install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
-
-install-am: all-am
- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-
-installcheck: installcheck-am
-install-strip:
- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
- `test -z '$(STRIP)' || \
- echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
-mostlyclean-generic:
-
-clean-generic:
-
-distclean-generic:
- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
- -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
-
-maintainer-clean-generic:
- @echo "This command is intended for maintainers to use"
- @echo "it deletes files that may require special tools to rebuild."
-clean: clean-am
-
-clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
-
-distclean: distclean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-distclean-am: clean-am distclean-compile distclean-generic \
- distclean-tags
-
-dvi: dvi-am
-
-dvi-am:
-
-html: html-am
-
-info: info-am
-
-info-am:
-
-install-data-am:
-
-install-dvi: install-dvi-am
-
-install-exec-am: install-binPROGRAMS install-binSCRIPTS
-
-install-html: install-html-am
-
-install-info: install-info-am
-
-install-man:
-
-install-pdf: install-pdf-am
-
-install-ps: install-ps-am
-
-installcheck-am:
-
-maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR)
- -rm -f Makefile
-maintainer-clean-am: distclean-am maintainer-clean-generic
-
-mostlyclean: mostlyclean-am
-
-mostlyclean-am: mostlyclean-compile mostlyclean-generic
-
-pdf: pdf-am
-
-pdf-am:
-
-ps: ps-am
-
-ps-am:
-
-uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS
-
-.MAKE: install-am install-strip
-
-.PHONY: CTAGS GTAGS all all-am check check-am check-local clean \
- clean-binPROGRAMS clean-generic ctags distclean \
- distclean-compile distclean-generic distclean-tags distdir dvi \
- dvi-am html html-am info info-am install install-am \
- install-binPROGRAMS install-binSCRIPTS install-data \
- install-data-am install-dvi install-dvi-am install-exec \
- install-exec-am install-html install-html-am install-info \
- install-info-am install-man install-pdf install-pdf-am \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
- uninstall-am uninstall-binPROGRAMS uninstall-binSCRIPTS
-
-
-check-local: localcheck remotecheck
-
-.PHONY: localcheck
-localcheck:
- $(SHELL) $(srcdir)/sanity.sh `pwd`/cvs$(EXEEXT)
-
-.PHONY: remotecheck
-remotecheck: all
- $(SHELL) $(srcdir)/sanity.sh -r `pwd`/cvs$(EXEEXT)
-
-# for backwards compatibility with the old makefiles
-.PHONY: realclean
-realclean: maintainer-clean
-# Tell versions [3.59,3.63) of GNU make to not export all variables.
-# Otherwise a system limit (for SysV at least) may be exceeded.
-.NOEXPORT:
diff --git a/contrib/cvs/src/add.c b/contrib/cvs/src/add.c
deleted file mode 100644
index 228ae69cfc18..000000000000
--- a/contrib/cvs/src/add.c
+++ /dev/null
@@ -1,951 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (c) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (c) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Add
- *
- * Adds a file or directory to the RCS source repository. For a file,
- * the entry is marked as "needing to be added" in the user's own CVS
- * directory, and really added to the repository when it is committed.
- * For a directory, it is added at the appropriate place in the source
- * repository and a CVS directory is generated within the directory.
- *
- * The -m option is currently the only supported option. Some may wish to
- * supply standard "rcs" options here, but I've found that this causes more
- * trouble than anything else.
- *
- * The user files or directories must already exist. For a directory, it must
- * not already have a CVS file in it.
- *
- * An "add" on a file that has been "remove"d but not committed will cause the
- * file to be resurrected.
- */
-
-#include <assert.h>
-#include "cvs.h"
-#include "savecwd.h"
-#include "fileattr.h"
-
-static int add_directory PROTO ((struct file_info *finfo));
-static int build_entry PROTO((const char *repository, const char *user,
- const char *options, const char *message,
- List * entries, const char *tag));
-
-static const char *const add_usage[] =
-{
- "Usage: %s %s [-k rcs-kflag] [-m message] files...\n",
- "\t-k rcs-kflag\tUse \"rcs-kflag\" to add the file with the specified\n",
- "\t\t\tkflag.\n",
- "\t-m message\tUse \"message\" for the creation log.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-int
-add (argc, argv)
- int argc;
- char **argv;
-{
- char *message = NULL;
- int i;
- char *repository;
- int c;
- int err = 0;
- int added_files = 0;
- char *options = NULL;
- List *entries;
- Vers_TS *vers;
- struct saved_cwd cwd;
- /* Nonzero if we found a slash, and are thus adding files in a
- subdirectory. */
- int found_slash = 0;
- size_t cvsroot_len;
-
- if (argc == 1 || argc == -1)
- usage (add_usage);
-
- wrap_setup ();
-
- /* parse args */
- optind = 0;
- while ((c = getopt (argc, argv, "+k:m:")) != -1)
- {
- switch (c)
- {
- case 'k':
- if (options) free (options);
- options = RCS_check_kflag (optarg);
- break;
-
- case 'm':
- if (message) free (message);
- message = xstrdup (optarg);
- break;
- case '?':
- default:
- usage (add_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- if (argc <= 0)
- usage (add_usage);
-
- cvsroot_len = strlen (current_parsed_root->directory);
-
- /* First some sanity checks. I know that the CVS case is (sort of)
- also handled by add_directory, but we need to check here so the
- client won't get all confused in send_file_names. */
- for (i = 0; i < argc; i++)
- {
- int skip_file = 0;
-
- /* If it were up to me I'd probably make this a fatal error.
- But some people are really fond of their "cvs add *", and
- don't seem to object to the warnings.
- Whatever. */
- strip_trailing_slashes (argv[i]);
- if (strcmp (argv[i], ".") == 0
- || strcmp (argv[i], "..") == 0
- || fncmp (last_component(argv[i]), CVSADM) == 0)
- {
- if (!quiet)
- error (0, 0, "cannot add special file `%s'; skipping", argv[i]);
- skip_file = 1;
- }
- else
- {
- char *p;
- p = argv[i];
- while (*p != '\0')
- {
- if (ISDIRSEP (*p))
- {
- found_slash = 1;
- break;
- }
- ++p;
- }
- }
-
- if (skip_file)
- {
- int j;
-
- /* FIXME: We don't do anything about free'ing argv[i]. But
- the problem is that it is only sometimes allocated (see
- cvsrc.c). */
-
- for (j = i; j < argc - 1; ++j)
- argv[j] = argv[j + 1];
- --argc;
- /* Check the new argv[i] again. */
- --i;
- ++err;
- }
- }
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- int j;
-
- if (argc == 0)
- {
- /* We snipped out all the arguments in the above sanity
- check. We can just forget the whole thing (and we
- better, because if we fired up the server and passed it
- nothing, it would spit back a usage message). */
- if (options)
- free (options);
- if (message)
- free (message);
- return err;
- }
-
- start_server ();
- ign_setup ();
- if (options)
- {
- send_arg (options);
- free (options);
- }
- option_with_arg ("-m", message);
- send_arg ("--");
-
- /* If !found_slash, refrain from sending "Directory", for
- CVS 1.9 compatibility. If we only tried to deal with servers
- which are at least CVS 1.9.26 or so, we wouldn't have to
- special-case this. */
- if (found_slash)
- {
- repository = Name_Repository (NULL, NULL);
- send_a_repository ("", repository, "");
- free (repository);
- }
-
- for (j = 0; j < argc; ++j)
- {
- /* FIXME: Does this erroneously call Create_Admin in error
- conditions which are only detected once the server gets its
- hands on things? */
- if (isdir (argv[j]))
- {
- char *tag;
- char *date;
- int nonbranch;
- char *rcsdir;
- char *p;
- char *update_dir;
- /* This is some mungeable storage into which we can point
- with p and/or update_dir. */
- char *filedir;
-
- if (save_cwd (&cwd))
- error_exit ();
-
- filedir = xstrdup (argv[j]);
- /* Deliberately discard the const below since we know we just
- * allocated filedir and can do what we like with it.
- */
- p = (char *)last_component (filedir);
- if (p == filedir)
- {
- update_dir = "";
- }
- else
- {
- p[-1] = '\0';
- update_dir = filedir;
- if (CVS_CHDIR (update_dir) < 0)
- error (1, errno,
- "could not chdir to %s", update_dir);
- }
-
- /* find the repository associated with our current dir */
- repository = Name_Repository (NULL, update_dir);
-
- /* don't add stuff to Emptydir */
- if (strncmp (repository, current_parsed_root->directory, cvsroot_len) == 0
- && ISDIRSEP (repository[cvsroot_len])
- && strncmp (repository + cvsroot_len + 1,
- CVSROOTADM,
- sizeof CVSROOTADM - 1) == 0
- && ISDIRSEP (repository[cvsroot_len + sizeof CVSROOTADM])
- && strcmp (repository + cvsroot_len + sizeof CVSROOTADM + 1,
- CVSNULLREPOS) == 0)
- error (1, 0, "cannot add to %s", repository);
-
- /* before we do anything else, see if we have any
- per-directory tags */
- ParseTag (&tag, &date, &nonbranch);
-
- rcsdir = xmalloc (strlen (repository) + strlen (p) + 5);
- sprintf (rcsdir, "%s/%s", repository, p);
-
- Create_Admin (p, argv[j], rcsdir, tag, date,
- nonbranch, 0, 1);
-
- if (found_slash)
- send_a_repository ("", repository, update_dir);
-
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- free_cwd (&cwd);
-
- if (tag)
- free (tag);
- if (date)
- free (date);
- free (rcsdir);
-
- if (p == filedir)
- Subdir_Register ((List *) NULL, (char *) NULL, argv[j]);
- else
- {
- Subdir_Register ((List *) NULL, update_dir, p);
- }
- free (repository);
- free (filedir);
- }
- }
- 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);
- return err + get_responses_and_close ();
- }
-#endif
-
- /* walk the arg list adding files/dirs */
- for (i = 0; i < argc; i++)
- {
- int begin_err = err;
-#ifdef SERVER_SUPPORT
- int begin_added_files = added_files;
-#endif
- struct file_info finfo;
- char *filename, *p;
-
- memset (&finfo, 0, sizeof finfo);
-
- if (save_cwd (&cwd))
- error_exit ();
-
- finfo.fullname = xstrdup (argv[i]);
- filename = xstrdup (argv[i]);
- /* We know we can discard the const below since we just allocated
- * filename and can do as we like with it.
- */
- p = (char *)last_component (filename);
- if (p == filename)
- {
- finfo.update_dir = "";
- finfo.file = p;
- }
- else
- {
- p[-1] = '\0';
- finfo.update_dir = filename;
- finfo.file = p;
- if (CVS_CHDIR (finfo.update_dir) < 0)
- error (1, errno, "could not chdir to %s", finfo.update_dir);
- }
-
- /* Add wrappers for this directory. They exist only until
- the next call to wrap_add_file. */
- wrap_add_file (CVSDOTWRAPPER, 1);
-
- finfo.rcs = NULL;
-
- /* Find the repository associated with our current dir. */
- repository = Name_Repository (NULL, finfo.update_dir);
-
- /* don't add stuff to Emptydir */
- if (strncmp (repository, current_parsed_root->directory,
- cvsroot_len) == 0
- && ISDIRSEP (repository[cvsroot_len])
- && strncmp (repository + cvsroot_len + 1,
- CVSROOTADM,
- sizeof CVSROOTADM - 1) == 0
- && ISDIRSEP (repository[cvsroot_len + sizeof CVSROOTADM])
- && strcmp (repository + cvsroot_len + sizeof CVSROOTADM + 1,
- CVSNULLREPOS) == 0)
- error (1, 0, "cannot add to %s", repository);
-
- entries = Entries_Open (0, NULL);
-
- finfo.repository = repository;
- finfo.entries = entries;
-
- /* 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
- meaningless to us. */
- vers = Version_TS (&finfo, options, NULL, NULL, 1, 0);
-
- if (vers->vn_user == NULL)
- {
- /* No entry available, ts_rcs is invalid */
- if (vers->vn_rcs == NULL)
- {
- /* There is no RCS file either */
- if (vers->ts_user == NULL)
- {
- /* There is no user file either */
- error (0, 0, "nothing known about %s", finfo.fullname);
- err++;
- }
- else if (!isdir (finfo.file)
- || wrap_name_has (finfo.file, WRAP_TOCVS))
- {
- /*
- * See if a directory exists in the repository with
- * the same name. If so, blow this request off.
- */
- char *dname = xmalloc (strlen (repository)
- + strlen (finfo.file)
- + 10);
- (void) sprintf (dname, "%s/%s", repository, finfo.file);
- if (isdir (dname))
- {
- error (0, 0,
- "cannot add file `%s' since the directory",
- finfo.fullname);
- error (0, 0, "`%s' already exists in the repository",
- dname);
- error (1, 0, "illegal filename overlap");
- }
- free (dname);
-
- if (vers->options == NULL || *vers->options == '\0')
- {
- /* No options specified on command line (or in
- rcs file if it existed, e.g. the file exists
- on another branch). Check for a value from
- the wrapper stuff. */
- if (wrap_name_has (finfo.file, WRAP_RCSOPTION))
- {
- if (vers->options)
- free (vers->options);
- vers->options = wrap_rcsoption (finfo.file, 1);
- }
- }
-
- if (vers->nonbranch)
- {
- error (0, 0,
- "cannot add file on non-branch tag %s",
- vers->tag);
- ++err;
- }
- else
- {
- /* There is a user file, so build the entry for it */
- if (build_entry (repository, finfo.file, vers->options,
- message, entries, vers->tag) != 0)
- err++;
- else
- {
- added_files++;
- if (!quiet)
- {
- if (vers->tag)
- error (0, 0, "\
-scheduling %s `%s' for addition on branch `%s'",
- (wrap_name_has (finfo.file,
- WRAP_TOCVS)
- ? "wrapper"
- : "file"),
- finfo.fullname, vers->tag);
- else
- error (0, 0,
- "scheduling %s `%s' for addition",
- (wrap_name_has (finfo.file,
- WRAP_TOCVS)
- ? "wrapper"
- : "file"),
- finfo.fullname);
- }
- }
- }
- }
- }
- else if (RCS_isdead (vers->srcfile, vers->vn_rcs))
- {
- if (isdir (finfo.file)
- && !wrap_name_has (finfo.file, WRAP_TOCVS))
- {
- error (0, 0, "\
-the directory `%s' cannot be added because a file of the", finfo.fullname);
- error (1, 0, "\
-same name already exists in the repository.");
- }
- else
- {
- if (vers->nonbranch)
- {
- error (0, 0,
- "cannot add file on non-branch tag %s",
- vers->tag);
- ++err;
- }
- else
- {
- char *timestamp = NULL;
- if (vers->ts_user == NULL)
- {
- /* If this file does not exist locally, assume that
- * the last version on the branch is being
- * resurrected.
- *
- * Compute previous revision. We assume that it
- * exists and that it is not a revision on the
- * trunk of the form X.1 (1.1, 2.1, 3.1, ...). We
- * also assume that it is not dead, which seems
- * fair since we know vers->vn_rcs is dead
- * and we shouldn't see two dead revisions in a
- * row.
- */
- char *prev = previous_rev (vers->srcfile,
- vers->vn_rcs);
- int status;
- if (prev == NULL)
- {
- /* There is no previous revision. Either:
- *
- * * Revision 1.1 was dead, as when a file was
- * inititially added on a branch,
- *
- * or
- *
- * * All previous revisions have been deleted.
- * For instance, via `admin -o'.
- */
- if (!really_quiet)
- error (0, 0,
-"File `%s' has no previous revision to resurrect.",
- finfo.fullname);
- free (prev);
- goto skip_this_file;
- }
- if (!quiet)
- error (0, 0,
-"Resurrecting file `%s' from revision %s.",
- finfo.fullname, prev);
- status = RCS_checkout (vers->srcfile, finfo.file,
- prev, vers->tag,
- vers->options, RUN_TTY,
- NULL, NULL);
- xchmod (finfo.file, 1);
- if (status != 0)
- {
- error (0, 0, "Failed to resurrect revision %s",
- prev);
- err++;
- }
- else
- {
- /* I don't actually set vers->ts_user here
- * because it would confuse server_update().
- */
- timestamp = time_stamp (finfo.file);
- if (!really_quiet)
- write_letter (&finfo, 'U');
- }
- free (prev);
- }
- if (!quiet)
- {
- if (vers->tag)
- error (0, 0,
-"file `%s' will be added on branch `%s' from version %s",
- finfo.fullname, vers->tag,
- vers->vn_rcs);
- else
- /* I'm not sure that mentioning
- vers->vn_rcs makes any sense here; I
- can't think of a way to word the
- message which is not confusing. */
- error (0, 0,
-"Re-adding file `%s' (in place of dead revision %s).",
- finfo.fullname, vers->vn_rcs);
- }
- Register (entries, finfo.file, "0",
- timestamp ? timestamp : vers->ts_user,
- vers->options, vers->tag, vers->date, NULL);
- if (timestamp) free (timestamp);
-#ifdef SERVER_SUPPORT
- if (server_active && vers->ts_user == NULL)
- {
- /* If we resurrected the file from the archive, we
- * need to tell the client about it.
- */
- server_updated (&finfo, vers,
- SERVER_UPDATED,
- (mode_t) -1, NULL, NULL);
- /* This is kinda hacky or, at least, it renders the
- * name "begin_added_files" obsolete, but we want
- * the added_files to be counted without triggering
- * the check that causes server_checked_in() to be
- * called below since we have already called
- * server_updated() to complete the resurrection.
- */
- ++begin_added_files;
- }
-#endif
- ++added_files;
- }
- }
- }
- else
- {
- /*
- * There is an RCS file already, so somebody else must've
- * added it
- */
- error (0, 0, "%s added independently by second party",
- finfo.fullname);
- err++;
- }
- }
- else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
- {
-
- /*
- * An entry for a new-born file, ts_rcs is dummy, but that is
- * inappropriate here
- */
- if (!quiet)
- error (0, 0, "%s has already been entered", finfo.fullname);
- err++;
- }
- else if (vers->vn_user[0] == '-')
- {
- /* An entry for a removed file, ts_rcs is invalid */
- if (vers->ts_user == NULL)
- {
- /* There is no user file (as it should be) */
- if (vers->vn_rcs == NULL)
- {
-
- /*
- * There is no RCS file, so somebody else must've removed
- * it from under us
- */
- error (0, 0, "\
-cannot resurrect %s; RCS file removed by second party", finfo.fullname);
- err++;
- }
- else
- {
- int status;
- /*
- * There is an RCS file, so remove the "-" from the
- * version number and restore the file
- */
- char *tmp = xmalloc (strlen (vers->vn_user));
- (void) strcpy (tmp, vers->vn_user + 1);
- (void) strcpy (vers->vn_user, tmp);
- free(tmp);
- status = RCS_checkout (vers->srcfile, finfo.file,
- vers->vn_user, vers->tag,
- vers->options, RUN_TTY,
- NULL, NULL);
- xchmod (finfo.file, 1);
- if (status != 0)
- {
- error (0, 0, "Failed to resurrect revision %s",
- vers->vn_user);
- err++;
- tmp = NULL;
- }
- else
- {
- /* I don't actually set vers->ts_user here because it
- * would confuse server_update().
- */
- tmp = time_stamp (finfo.file);
- write_letter (&finfo, 'U');
- if (!quiet)
- error (0, 0, "%s, version %s, resurrected",
- finfo.fullname, vers->vn_user);
- }
- Register (entries, finfo.file, vers->vn_user,
- tmp, vers->options,
- vers->tag, vers->date, NULL);
- if (tmp) free (tmp);
-#ifdef SERVER_SUPPORT
- if (server_active)
- {
- /* If we resurrected the file from the archive, we
- * need to tell the client about it.
- */
- server_updated (&finfo, vers,
- SERVER_UPDATED,
- (mode_t) -1, NULL, NULL);
- }
- /* We don't increment added_files here because this isn't
- * a change that needs to be committed.
- */
-#endif
- }
- }
- else
- {
- /* The user file shouldn't be there */
- error (0, 0, "\
-%s should be removed and is still there (or is back again)", finfo.fullname);
- err++;
- }
- }
- else
- {
- /* A normal entry, ts_rcs is valid, so it must already be there */
- if (!quiet)
- error (0, 0, "%s already exists, with version number %s",
- finfo.fullname,
- vers->vn_user);
- err++;
- }
- freevers_ts (&vers);
-
- /* passed all the checks. Go ahead and add it if its a directory */
- if (begin_err == err
- && isdir (finfo.file)
- && !wrap_name_has (finfo.file, WRAP_TOCVS))
- {
- err += add_directory (&finfo);
- }
- else
- {
-#ifdef SERVER_SUPPORT
- if (server_active && begin_added_files != added_files)
- server_checked_in (finfo.file, finfo.update_dir, repository);
-#endif
- }
-
-skip_this_file:
- free (repository);
- Entries_Close (entries);
-
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- free_cwd (&cwd);
-
- /* It's okay to discard the const to free this - we allocated this
- * above. The const is for everybody else.
- */
- free ((char *) finfo.fullname);
- free ((char *) filename);
- }
- if (added_files && !really_quiet)
- error (0, 0, "use '%s commit' to add %s permanently",
- program_name,
- (added_files == 1) ? "this file" : "these files");
-
- if (message)
- free (message);
- if (options)
- free (options);
-
- return err;
-}
-
-
-
-/*
- * The specified user file is really a directory. So, let's make sure that
- * it is created in the RCS source repository, and that the user's directory
- * is updated to include a CVS directory.
- *
- * Returns 1 on failure, 0 on success.
- */
-static int
-add_directory (finfo)
- struct file_info *finfo;
-{
- const char *repository = finfo->repository;
- List *entries = finfo->entries;
- const char *dir = finfo->file;
-
- char *rcsdir = NULL;
- struct saved_cwd cwd;
- char *message = NULL;
- char *tag, *date;
- int nonbranch;
- char *attrs;
-
- if (strchr (dir, '/') != NULL)
- {
- /* "Can't happen". */
- error (0, 0,
- "directory %s not added; must be a direct sub-directory", dir);
- return 1;
- }
- if (fncmp (dir, CVSADM) == 0)
- {
- error (0, 0, "cannot add a `%s' directory", CVSADM);
- return 1;
- }
-
- /* before we do anything else, see if we have any per-directory tags */
- ParseTag (&tag, &date, &nonbranch);
-
- /* Remember the default attributes from this directory, so we can apply
- them to the new directory. */
- fileattr_startdir (repository);
- attrs = fileattr_getall (NULL);
- fileattr_free ();
-
- /* now, remember where we were, so we can get back */
- if (save_cwd (&cwd))
- return 1;
- if (CVS_CHDIR (dir) < 0)
- {
- error (0, errno, "cannot chdir to %s", finfo->fullname);
- return 1;
- }
- if (!server_active && isfile (CVSADM))
- {
- error (0, 0, "%s/%s already exists", finfo->fullname, CVSADM);
- goto out;
- }
-
- rcsdir = xmalloc (strlen (repository) + strlen (dir) + 5);
- sprintf (rcsdir, "%s/%s", repository, dir);
- if (isfile (rcsdir) && !isdir (rcsdir))
- {
- error (0, 0, "%s is not a directory; %s not added", rcsdir,
- finfo->fullname);
- goto out;
- }
-
- /* setup the log message */
- message = xmalloc (strlen (rcsdir)
- + 80
- + (tag == NULL ? 0 : strlen (tag) + 80)
- + (date == NULL ? 0 : strlen (date) + 80));
- (void) sprintf (message, "Directory %s added to the repository\n",
- rcsdir);
- if (tag)
- {
- (void) strcat (message, "--> Using per-directory sticky tag `");
- (void) strcat (message, tag);
- (void) strcat (message, "'\n");
- }
- if (date)
- {
- (void) strcat (message, "--> Using per-directory sticky date `");
- (void) strcat (message, date);
- (void) strcat (message, "'\n");
- }
-
- if (!isdir (rcsdir))
- {
- mode_t omask;
- Node *p;
- List *ulist;
- struct logfile_info *li;
-
- /* There used to be some code here which would prompt for
- whether to add the directory. The details of that code had
- bitrotted, but more to the point it can't work
- client/server, doesn't ask in the right way for GUIs, etc.
- A better way of making it harder to accidentally add
- directories would be to have to add and commit directories
- like for files. The code was #if 0'd at least since CVS 1.5. */
-
- if (!noexec)
- {
- omask = umask (cvsumask);
- if (CVS_MKDIR (rcsdir, 0777) < 0)
- {
- error (0, errno, "cannot mkdir %s", rcsdir);
- (void) umask (omask);
- goto out;
- }
- (void) umask (omask);
- }
-
- /* Now set the default file attributes to the ones we inherited
- from the parent directory. */
- fileattr_startdir (rcsdir);
- fileattr_setall (NULL, attrs);
- fileattr_write ();
- fileattr_free ();
- if (attrs != NULL)
- {
- free (attrs);
- attrs = NULL;
- }
-
- /*
- * Set up an update list with a single title node for Update_Logfile
- */
- ulist = getlist ();
- p = getnode ();
- p->type = UPDATE;
- p->delproc = update_delproc;
- p->key = xstrdup ("- New directory");
- li = (struct logfile_info *) xmalloc (sizeof (struct logfile_info));
- li->type = T_TITLE;
- li->tag = xstrdup (tag);
- li->rev_old = li->rev_new = NULL;
- p->data = li;
- (void) addnode (ulist, p);
- Update_Logfile (rcsdir, message, (FILE *) NULL, ulist);
- dellist (&ulist);
- }
-
- if (!server_active)
- Create_Admin (".", finfo->fullname, rcsdir, tag, date, nonbranch, 0, 1);
- if (tag)
- free (tag);
- if (date)
- free (date);
-
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- free_cwd (&cwd);
-
- Subdir_Register (entries, (char *) NULL, dir);
-
- if (!really_quiet)
- cvs_output (message, 0);
-
- free (rcsdir);
- free (message);
- if (attrs != NULL)
- free (attrs);
-
- return 0;
-
-out:
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- free_cwd (&cwd);
- if (message) free (message);
- if (rcsdir != NULL)
- free (rcsdir);
- return 0;
-}
-
-
-
-/*
- * Builds an entry for a new file and sets up "CVS/file",[pt] by
- * interrogating the user. Returns non-zero on error.
- */
-static int
-build_entry (repository, user, options, message, entries, tag)
- const char *repository;
- const char *user;
- const char *options;
- const char *message;
- List *entries;
- const char *tag;
-{
- char *fname;
- char *line;
- FILE *fp;
-
- if (noexec)
- return 0;
-
- /*
- * The requested log is read directly from the user and stored in the
- * file user,t. If the "message" argument is set, use it as the
- * initial creation log (which typically describes the file).
- */
- fname = xmalloc (strlen (user) + 80);
- (void) sprintf (fname, "%s/%s%s", CVSADM, user, CVSEXT_LOG);
- fp = open_file (fname, "w+");
- if (message && fputs (message, fp) == EOF)
- error (1, errno, "cannot write to %s", fname);
- if (fclose(fp) == EOF)
- error(1, errno, "cannot close %s", fname);
- free (fname);
-
- /*
- * Create the entry now, since this allows the user to interrupt us above
- * without needing to clean anything up (well, we could clean up the
- * ,t file, but who cares).
- */
- line = xmalloc (strlen (user) + 20);
- (void) sprintf (line, "Initial %s", user);
- Register (entries, user, "0", line, options, tag, (char *) 0, (char *) 0);
- free (line);
- return 0;
-}
diff --git a/contrib/cvs/src/admin.c b/contrib/cvs/src/admin.c
deleted file mode 100644
index 186e27c9dc8b..000000000000
--- a/contrib/cvs/src/admin.c
+++ /dev/null
@@ -1,950 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (c) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (c) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Administration ("cvs admin")
- *
- */
-
-#include "cvs.h"
-#ifdef CVS_ADMIN_GROUP
-#include <grp.h>
-#endif
-#include <assert.h>
-
-static Dtype admin_dirproc PROTO ((void *callerdat, const char *dir,
- const char *repos, const char *update_dir,
- List *entries));
-static int admin_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-
-static const char *const admin_usage[] =
-{
- "Usage: %s %s [options] files...\n",
- "\t-a users Append (comma-separated) user names to access list.\n",
- "\t-A file Append another file's access list.\n",
- "\t-b[rev] Set default branch (highest branch on trunk if omitted).\n",
- "\t-c string Set comment leader.\n",
- "\t-e[users] Remove (comma-separated) user names from access list\n",
- "\t (all names if omitted).\n",
- "\t-I Run interactively.\n",
- "\t-k subst Set keyword substitution mode:\n",
- "\t kv (Default) Substitute keyword and value.\n",
- "\t kvl Substitute keyword, value, and locker (if any).\n",
- "\t k Substitute keyword only.\n",
- "\t o Preserve original string.\n",
- "\t b Like o, but mark file as binary.\n",
- "\t v Substitute value only.\n",
- "\t-l[rev] Lock revision (latest revision on branch,\n",
- "\t latest revision on trunk if omitted).\n",
- "\t-L Set strict locking.\n",
- "\t-m rev:msg Replace revision's log message.\n",
- "\t-n tag[:[rev]] Tag branch or revision. If :rev is omitted,\n",
- "\t delete the tag; if rev is omitted, tag the latest\n",
- "\t revision on the default branch.\n",
- "\t-N tag[:[rev]] Same as -n except override existing tag.\n",
- "\t-o range Delete (outdate) specified range of revisions:\n",
- "\t rev1:rev2 Between rev1 and rev2, including rev1 and rev2.\n",
- "\t rev1::rev2 Between rev1 and rev2, excluding rev1 and rev2.\n",
- "\t rev: rev and following revisions on the same branch.\n",
- "\t rev:: After rev on the same branch.\n",
- "\t :rev rev and previous revisions on the same branch.\n",
- "\t ::rev Before rev on the same branch.\n",
- "\t rev Just rev.\n",
- "\t-q Run quietly.\n",
- "\t-s state[:rev] Set revision state (latest revision on branch,\n",
- "\t latest revision on trunk if omitted).\n",
- "\t-t[file] Get descriptive text from file (stdin if omitted).\n",
- "\t-t-string Set descriptive text.\n",
- "\t-u[rev] Unlock the revision (latest revision on branch,\n",
- "\t latest revision on trunk if omitted).\n",
- "\t-U Unset strict locking.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-/* This structure is used to pass information through start_recursion. */
-struct admin_data
-{
- /* Set default branch (-b). It is "-b" followed by the value
- given, or NULL if not specified, or merely "-b" if -b is
- specified without a value. */
- char *branch;
-
- /* Set comment leader (-c). It is "-c" followed by the value
- given, or NULL if not specified. The comment leader is
- relevant only for old versions of RCS, but we let people set it
- anyway. */
- char *comment;
-
- /* Set strict locking (-L). */
- int set_strict;
-
- /* Set nonstrict locking (-U). */
- int set_nonstrict;
-
- /* Delete revisions (-o). It is "-o" followed by the value specified. */
- char *delete_revs;
-
- /* Keyword substitution mode (-k), e.g. "-kb". */
- char *kflag;
-
- /* Description (-t). */
- char *desc;
-
- /* Interactive (-I). Problematic with client/server. */
- int interactive;
-
- /* This is the cheesy part. It is a vector with the options which
- we don't deal with above (e.g. "-afoo" "-abar,baz"). In the future
- this presumably will be replaced by other variables which break
- out the data in a more convenient fashion. AV as well as each of
- the strings it points to is malloc'd. */
- int ac;
- char **av;
- int av_alloc;
-};
-
-/* Add an argument. OPT is the option letter, e.g. 'a'. ARG is the
- argument to that option, or NULL if omitted (whether NULL can actually
- happen depends on whether the option was specified as optional to
- getopt). */
-static void
-arg_add (dat, opt, arg)
- struct admin_data *dat;
- int opt;
- char *arg;
-{
- char *newelt = xmalloc ((arg == NULL ? 0 : strlen (arg)) + 3);
- strcpy (newelt, "-");
- newelt[1] = opt;
- if (arg == NULL)
- newelt[2] = '\0';
- else
- strcpy (newelt + 2, arg);
-
- if (dat->av_alloc == 0)
- {
- dat->av_alloc = 1;
- dat->av = (char **) xmalloc (dat->av_alloc * sizeof (*dat->av));
- }
- else if (dat->ac >= dat->av_alloc)
- {
- dat->av_alloc *= 2;
- dat->av = (char **) xrealloc (dat->av,
- dat->av_alloc * sizeof (*dat->av));
- }
- dat->av[dat->ac++] = newelt;
-}
-
-int
-admin (argc, argv)
- int argc;
- char **argv;
-{
- int err;
-#ifdef CVS_ADMIN_GROUP
- struct group *grp;
- struct group *getgrnam();
-#endif
- struct admin_data admin_data;
- int c;
- int i;
- int only_k_option;
-
- if (argc <= 1)
- usage (admin_usage);
-
- wrap_setup ();
-
- memset (&admin_data, 0, sizeof admin_data);
-
- /* TODO: get rid of `-' switch notation in admin_data. For
- 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)
- {
- if (c != 'k' && c != 'q')
- only_k_option = 0;
-
- switch (c)
- {
- case 'i':
- /* This has always been documented as useless in cvs.texinfo
- and it really is--admin_fileproc silently does nothing
- if vers->vn_user is NULL. */
- error (0, 0, "the -i option to admin is not supported");
- error (0, 0, "run add or import to create an RCS file");
- goto usage_error;
-
- case 'b':
- if (admin_data.branch != NULL)
- {
- error (0, 0, "duplicate 'b' option");
- goto usage_error;
- }
- if (optarg == NULL)
- admin_data.branch = xstrdup ("-b");
- else
- {
- admin_data.branch = xmalloc (strlen (optarg) + 5);
- strcpy (admin_data.branch, "-b");
- strcat (admin_data.branch, optarg);
- }
- break;
-
- case 'c':
- if (admin_data.comment != NULL)
- {
- error (0, 0, "duplicate 'c' option");
- goto usage_error;
- }
- admin_data.comment = xmalloc (strlen (optarg) + 5);
- strcpy (admin_data.comment, "-c");
- strcat (admin_data.comment, optarg);
- break;
-
- case 'a':
- arg_add (&admin_data, 'a', optarg);
- break;
-
- case 'A':
- /* In the client/server case, this is cheesy because
- we just pass along the name of the RCS file, which
- then will want to exist on the server. This is
- accidental; having the client specify a pathname on
- the server is not a design feature of the protocol. */
- arg_add (&admin_data, 'A', optarg);
- break;
-
- case 'e':
- arg_add (&admin_data, 'e', optarg);
- break;
-
- case 'l':
- /* Note that multiple -l options are legal. */
- arg_add (&admin_data, 'l', optarg);
- break;
-
- case 'u':
- /* Note that multiple -u options are legal. */
- arg_add (&admin_data, 'u', optarg);
- break;
-
- case 'L':
- /* Probably could also complain if -L is specified multiple
- times, although RCS doesn't and I suppose it is reasonable
- just to have it mean the same as a single -L. */
- if (admin_data.set_nonstrict)
- {
- error (0, 0, "-U and -L are incompatible");
- goto usage_error;
- }
- admin_data.set_strict = 1;
- break;
-
- case 'U':
- /* Probably could also complain if -U is specified multiple
- times, although RCS doesn't and I suppose it is reasonable
- just to have it mean the same as a single -U. */
- if (admin_data.set_strict)
- {
- error (0, 0, "-U and -L are incompatible");
- goto usage_error;
- }
- admin_data.set_nonstrict = 1;
- break;
-
- case 'n':
- /* Mostly similar to cvs tag. Could also be parsing
- the syntax of optarg, although for now we just pass
- it to rcs as-is. Note that multiple -n options are
- legal. */
- arg_add (&admin_data, 'n', optarg);
- break;
-
- case 'N':
- /* Mostly similar to cvs tag. Could also be parsing
- the syntax of optarg, although for now we just pass
- it to rcs as-is. Note that multiple -N options are
- legal. */
- arg_add (&admin_data, 'N', optarg);
- break;
-
- case 'm':
- /* Change log message. Could also be parsing the syntax
- of optarg, although for now we just pass it to rcs
- as-is. Note that multiple -m options are legal. */
- arg_add (&admin_data, 'm', optarg);
- break;
-
- case 'o':
- /* Delete revisions. Probably should also be parsing the
- syntax of optarg, so that the client can give errors
- rather than making the server take care of that.
- Other than that I'm not sure whether it matters much
- whether we parse it here or in admin_fileproc.
-
- Note that multiple -o options are illegal, in RCS
- as well as here. */
-
- if (admin_data.delete_revs != NULL)
- {
- error (0, 0, "duplicate '-o' option");
- goto usage_error;
- }
- admin_data.delete_revs = xmalloc (strlen (optarg) + 5);
- strcpy (admin_data.delete_revs, "-o");
- strcat (admin_data.delete_revs, optarg);
- break;
-
- case 's':
- /* Note that multiple -s options are legal. */
- arg_add (&admin_data, 's', optarg);
- break;
-
- case 't':
- if (admin_data.desc != NULL)
- {
- error (0, 0, "duplicate 't' option");
- goto usage_error;
- }
- if (optarg != NULL && optarg[0] == '-')
- admin_data.desc = xstrdup (optarg + 1);
- else
- {
- size_t bufsize = 0;
- size_t len;
-
- get_file (optarg, optarg, "r", &admin_data.desc,
- &bufsize, &len);
- }
- break;
-
- case 'I':
- /* At least in RCS this can be specified several times,
- with the same meaning as being specified once. */
- admin_data.interactive = 1;
- break;
-
- case 'q':
- /* Silently set the global really_quiet flag. This keeps admin in
- * sync with the RCS man page and allows us to silently support
- * older servers when necessary.
- *
- * Some logic says we might want to output a deprecation warning
- * here, but I'm opting not to in order to stay quietly in sync
- * with the RCS man page.
- */
- really_quiet = 1;
- break;
-
- case 'x':
- error (0, 0, "the -x option has never done anything useful");
- error (0, 0, "RCS files in CVS always end in ,v");
- goto usage_error;
-
- case 'V':
- /* No longer supported. */
- error (0, 0, "the `-V' option is obsolete");
- break;
-
- case 'k':
- if (admin_data.kflag != NULL)
- {
- error (0, 0, "duplicate '-k' option");
- goto usage_error;
- }
- admin_data.kflag = RCS_check_kflag (optarg);
- break;
- default:
- case '?':
- /* getopt will have printed an error message. */
-
- usage_error:
- /* Don't use cvs_cmd_name; it might be "server". */
- error (1, 0, "specify %s -H admin for usage information",
- program_name);
- }
- }
- argc -= optind;
- argv += optind;
-
-#ifdef CVS_ADMIN_GROUP
- /* The use of `cvs admin -k' is unrestricted. However, any other
- option is restricted if the group CVS_ADMIN_GROUP exists on the
- server. */
- /* This is only "secure" on the server, since the user could edit the
- * RCS file on a local host, but some people like this kind of
- * check anyhow. The alternative would be to check only when
- * (server_active) rather than when not on the client.
- */
- if (!current_parsed_root->isremote && !only_k_option &&
- (grp = getgrnam(CVS_ADMIN_GROUP)) != NULL)
- {
-#ifdef HAVE_GETGROUPS
- gid_t *grps;
- int n;
-
- /* get number of auxiliary groups */
- n = getgroups (0, NULL);
- if (n < 0)
- error (1, errno, "unable to get number of auxiliary groups");
- grps = (gid_t *) xmalloc((n + 1) * sizeof *grps);
- n = getgroups (n, grps);
- if (n < 0)
- error (1, errno, "unable to get list of auxiliary groups");
- grps[n] = getgid();
- for (i = 0; i <= n; i++)
- if (grps[i] == grp->gr_gid) break;
- free (grps);
- if (i > n)
- error (1, 0, "usage is restricted to members of the group %s",
- CVS_ADMIN_GROUP);
-#else
- char *me = getcaller();
- char **grnam;
-
- for (grnam = grp->gr_mem; *grnam; grnam++)
- if (strcmp (*grnam, me) == 0) break;
- if (!*grnam && getgid() != grp->gr_gid)
- error (1, 0, "usage is restricted to members of the group %s",
- CVS_ADMIN_GROUP);
-#endif
- }
-#endif /* defined CVS_ADMIN_GROUP */
-
- for (i = 0; i < admin_data.ac; ++i)
- {
- assert (admin_data.av[i][0] == '-');
- switch (admin_data.av[i][1])
- {
- case 'm':
- case 'l':
- case 'u':
- check_numeric (&admin_data.av[i][2], argc, argv);
- break;
- default:
- break;
- }
- }
- if (admin_data.branch != NULL)
- check_numeric (admin_data.branch + 2, argc, argv);
- if (admin_data.delete_revs != NULL)
- {
- char *p;
-
- check_numeric (admin_data.delete_revs + 2, argc, argv);
- p = strchr (admin_data.delete_revs + 2, ':');
- if (p != NULL && isdigit ((unsigned char) p[1]))
- check_numeric (p + 1, argc, argv);
- else if (p != NULL && p[1] == ':' && isdigit ((unsigned char) p[2]))
- check_numeric (p + 2, argc, argv);
- }
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- /* We're the client side. Fire up the remote server. */
- start_server ();
-
- ign_setup ();
-
- /* Note that option_with_arg does not work for us, because some
- of the options must be sent without a space between the option
- and its argument. */
- if (admin_data.interactive)
- error (1, 0, "-I option not useful with client/server");
- if (admin_data.branch != NULL)
- send_arg (admin_data.branch);
- if (admin_data.comment != NULL)
- send_arg (admin_data.comment);
- if (admin_data.set_strict)
- send_arg ("-L");
- if (admin_data.set_nonstrict)
- send_arg ("-U");
- if (admin_data.delete_revs != NULL)
- send_arg (admin_data.delete_revs);
- if (admin_data.desc != NULL)
- {
- char *p = admin_data.desc;
- send_to_server ("Argument -t-", 0);
- while (*p)
- {
- if (*p == '\n')
- {
- send_to_server ("\012Argumentx ", 0);
- ++p;
- }
- else
- {
- char *q = strchr (p, '\n');
- if (q == NULL) q = p + strlen (p);
- send_to_server (p, q - p);
- p = q;
- }
- }
- send_to_server ("\012", 1);
- }
- /* Send this for all really_quiets since we know that it will be silently
- * ignored when unneeded. This supports old servers.
- */
- if (really_quiet)
- send_arg ("-q");
- if (admin_data.kflag != NULL)
- send_arg (admin_data.kflag);
-
- for (i = 0; i < admin_data.ac; ++i)
- send_arg (admin_data.av[i]);
-
- send_arg ("--");
- 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;
- }
-#endif /* CLIENT_SUPPORT */
-
- lock_tree_for_write (argc, argv, 0, W_LOCAL, 0);
-
- err = start_recursion (admin_fileproc, (FILESDONEPROC) NULL, admin_dirproc,
- (DIRLEAVEPROC) NULL, (void *)&admin_data,
- argc, argv, 0,
- W_LOCAL, 0, CVS_LOCK_NONE, (char *) NULL, 1,
- (char *) NULL);
- Lock_Cleanup ();
-
- return_it:
- if (admin_data.branch != NULL)
- free (admin_data.branch);
- if (admin_data.comment != NULL)
- free (admin_data.comment);
- if (admin_data.delete_revs != NULL)
- free (admin_data.delete_revs);
- if (admin_data.kflag != NULL)
- free (admin_data.kflag);
- if (admin_data.desc != NULL)
- free (admin_data.desc);
- for (i = 0; i < admin_data.ac; ++i)
- free (admin_data.av[i]);
- if (admin_data.av != NULL)
- free (admin_data.av);
-
- return (err);
-}
-
-/*
- * Called to run "rcs" on a particular file.
- */
-/* ARGSUSED */
-static int
-admin_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- struct admin_data *admin_data = (struct admin_data *) callerdat;
- Vers_TS *vers;
- char *version;
- int i;
- int status = 0;
- RCSNode *rcs, *rcs2;
-
- vers = Version_TS (finfo, NULL, NULL, NULL, 0, 0);
-
- version = vers->vn_user;
- if (version != NULL && strcmp (version, "0") == 0)
- {
- error (0, 0, "cannot admin newly added file `%s'", finfo->file);
- status = 1;
- goto exitfunc;
- }
-
- rcs = vers->srcfile;
- if (rcs == NULL)
- {
- if (!really_quiet)
- error (0, 0, "nothing known about %s", finfo->file);
- status = 1;
- goto exitfunc;
- }
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- if (!really_quiet)
- {
- cvs_output ("RCS file: ", 0);
- cvs_output (rcs->path, 0);
- cvs_output ("\n", 1);
- }
-
- if (admin_data->branch != NULL)
- {
- char *branch = &admin_data->branch[2];
- if (*branch != '\0' && ! isdigit ((unsigned char) *branch))
- {
- branch = RCS_whatbranch (rcs, admin_data->branch + 2);
- if (branch == NULL)
- {
- error (0, 0, "%s: Symbolic name %s is undefined.",
- rcs->path, admin_data->branch + 2);
- status = 1;
- }
- }
- if (status == 0)
- RCS_setbranch (rcs, branch);
- if (branch != NULL && branch != &admin_data->branch[2])
- free (branch);
- }
- if (admin_data->comment != NULL)
- {
- if (rcs->comment != NULL)
- free (rcs->comment);
- rcs->comment = xstrdup (admin_data->comment + 2);
- }
- if (admin_data->set_strict)
- rcs->strict_locks = 1;
- if (admin_data->set_nonstrict)
- rcs->strict_locks = 0;
- if (admin_data->delete_revs != NULL)
- {
- char *s, *t, *rev1, *rev2;
- /* Set for :, clear for ::. */
- int inclusive;
- char *t2;
-
- s = admin_data->delete_revs + 2;
- inclusive = 1;
- t = strchr (s, ':');
- if (t != NULL)
- {
- if (t[1] == ':')
- {
- inclusive = 0;
- t2 = t + 2;
- }
- else
- t2 = t + 1;
- }
-
- /* Note that we don't support '-' for ranges. RCS considers it
- obsolete and it is problematic with tags containing '-'. "cvs log"
- has made the same decision. */
-
- if (t == NULL)
- {
- /* -orev */
- rev1 = xstrdup (s);
- rev2 = xstrdup (s);
- }
- else if (t == s)
- {
- /* -o:rev2 */
- rev1 = NULL;
- rev2 = xstrdup (t2);
- }
- else
- {
- *t = '\0';
- rev1 = xstrdup (s);
- *t = ':'; /* probably unnecessary */
- if (*t2 == '\0')
- /* -orev1: */
- rev2 = NULL;
- else
- /* -orev1:rev2 */
- rev2 = xstrdup (t2);
- }
-
- if (rev1 == NULL && rev2 == NULL)
- {
- /* RCS segfaults if `-o:' is given */
- error (0, 0, "no valid revisions specified in `%s' option",
- admin_data->delete_revs);
- status = 1;
- }
- else
- {
- status |= RCS_delete_revs (rcs, rev1, rev2, inclusive);
- if (rev1)
- free (rev1);
- if (rev2)
- free (rev2);
- }
- }
- if (admin_data->desc != NULL)
- {
- free (rcs->desc);
- rcs->desc = xstrdup (admin_data->desc);
- }
- if (admin_data->kflag != NULL)
- {
- char *kflag = admin_data->kflag + 2;
- 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
- of these should have their own fields in the admin_data
- structure. */
- for (i = 0; i < admin_data->ac; ++i)
- {
- char *arg;
- char *p, *rev, *revnum, *tag, *msg;
- char **users;
- int argc, u;
- Node *n;
- RCSVers *delta;
-
- arg = admin_data->av[i];
- switch (arg[1])
- {
- case 'a': /* fall through */
- case 'e':
- line2argv (&argc, &users, arg + 2, " ,\t\n");
- if (arg[1] == 'a')
- for (u = 0; u < argc; ++u)
- RCS_addaccess (rcs, users[u]);
- else if (argc == 0)
- RCS_delaccess (rcs, NULL);
- else
- for (u = 0; u < argc; ++u)
- RCS_delaccess (rcs, users[u]);
- free_names (&argc, users);
- break;
- case 'A':
-
- /* See admin-19a-admin and friends in sanity.sh for
- relative pathnames. It makes sense to think in
- terms of a syntax which give pathnames relative to
- the repository or repository corresponding to the
- current directory or some such (and perhaps don't
- include ,v), but trying to worry about such things
- is a little pointless unless you first worry about
- whether "cvs admin -A" as a whole makes any sense
- (currently probably not, as access lists don't
- affect the behavior of CVS). */
-
- rcs2 = RCS_parsercsfile (arg + 2);
- if (rcs2 == NULL)
- error (1, 0, "cannot continue");
-
- p = xstrdup (RCS_getaccess (rcs2));
- line2argv (&argc, &users, p, " \t\n");
- free (p);
- freercsnode (&rcs2);
-
- for (u = 0; u < argc; ++u)
- RCS_addaccess (rcs, users[u]);
- free_names (&argc, users);
- break;
- case 'n': /* fall through */
- case 'N':
- if (arg[2] == '\0')
- {
- cvs_outerr ("missing symbolic name after ", 0);
- cvs_outerr (arg, 0);
- cvs_outerr ("\n", 1);
- break;
- }
- p = strchr (arg, ':');
- if (p == NULL)
- {
- if (RCS_deltag (rcs, arg + 2) != 0)
- {
- error (0, 0, "%s: Symbolic name %s is undefined.",
- rcs->path,
- arg + 2);
- status = 1;
- continue;
- }
- break;
- }
- *p = '\0';
- tag = xstrdup (arg + 2);
- *p++ = ':';
-
- /* Option `n' signals an error if this tag is already bound. */
- if (arg[1] == 'n')
- {
- n = findnode (RCS_symbols (rcs), tag);
- if (n != NULL)
- {
- error (0, 0,
- "%s: symbolic name %s already bound to %s",
- rcs->path,
- tag, (char *)n->data);
- status = 1;
- free (tag);
- continue;
- }
- }
-
- /* Attempt to perform the requested tagging. */
-
- if ((*p == 0 && (rev = RCS_head (rcs)))
- || (rev = RCS_tag2rev (rcs, p))) /* tag2rev may exit */
- {
- RCS_check_tag (tag); /* exit if not a valid tag */
- RCS_settag (rcs, tag, rev);
- free (rev);
- }
- else
- {
- if (!really_quiet)
- error (0, 0,
- "%s: Symbolic name or revision %s is undefined.",
- rcs->path, p);
- status = 1;
- }
- free (tag);
- break;
- case 's':
- p = strchr (arg, ':');
- if (p == NULL)
- {
- tag = xstrdup (arg + 2);
- rev = RCS_head (rcs);
- if (!rev)
- {
- error (0, 0, "No head revision in archive file `%s'.",
- rcs->path);
- status = 1;
- continue;
- }
- }
- else
- {
- *p = '\0';
- tag = xstrdup (arg + 2);
- *p++ = ':';
- rev = xstrdup (p);
- }
- revnum = RCS_gettag (rcs, rev, 0, NULL);
- if (revnum != NULL)
- {
- n = findnode (rcs->versions, revnum);
- free (revnum);
- }
- else
- n = NULL;
- if (n == NULL)
- {
- error (0, 0,
- "%s: can't set state of nonexisting revision %s",
- rcs->path,
- rev);
- free (rev);
- status = 1;
- continue;
- }
- free (rev);
- delta = n->data;
- free (delta->state);
- delta->state = tag;
- break;
-
- case 'm':
- p = strchr (arg, ':');
- if (p == NULL)
- {
- error (0, 0, "%s: -m option lacks revision number",
- rcs->path);
- status = 1;
- continue;
- }
- *p = '\0'; /* temporarily make arg+2 its own string */
- rev = RCS_gettag (rcs, arg + 2, 1, NULL); /* Force tag match */
- if (rev == NULL)
- {
- error (0, 0, "%s: no such revision %s", rcs->path, arg+2);
- status = 1;
- *p = ':'; /* restore the full text of the -m argument */
- continue;
- }
- msg = p+1;
-
- n = findnode (rcs->versions, rev);
- /* tags may exist against non-existing versions */
- if (n == NULL)
- {
- error (0, 0, "%s: no such revision %s: %s",
- rcs->path, arg+2, rev);
- status = 1;
- *p = ':'; /* restore the full text of the -m argument */
- free (rev);
- continue;
- }
- *p = ':'; /* restore the full text of the -m argument */
- free (rev);
-
- delta = n->data;
- if (delta->text == NULL)
- {
- delta->text = (Deltatext *) xmalloc (sizeof (Deltatext));
- memset ((void *) delta->text, 0, sizeof (Deltatext));
- }
- delta->text->version = xstrdup (delta->version);
- delta->text->log = make_message_rcslegal (msg);
- break;
-
- case 'l':
- status |= RCS_lock (rcs, arg[2] ? arg + 2 : NULL, 0);
- break;
- case 'u':
- status |= RCS_unlock (rcs, arg[2] ? arg + 2 : NULL, 0);
- break;
- default: assert(0); /* can't happen */
- }
- }
-
- if (status == 0)
- {
- RCS_rewrite (rcs, NULL, NULL);
- if (!really_quiet)
- cvs_output ("done\n", 5);
- }
- else
- {
- /* Note that this message should only occur after another
- message has given a more specific error. The point of this
- additional message is to make it clear that the previous problems
- caused CVS to forget about the idea of modifying the RCS file. */
- if (!really_quiet)
- error (0, 0, "RCS file for `%s' not modified.", finfo->file);
- RCS_abandon (rcs);
- }
-
- exitfunc:
- freevers_ts (&vers);
- return status;
-}
-
-/*
- * Print a warm fuzzy message
- */
-/* ARGSUSED */
-static Dtype
-admin_dirproc (callerdat, dir, repos, update_dir, entries)
- void *callerdat;
- const char *dir;
- const char *repos;
- const char *update_dir;
- List *entries;
-{
- if (!quiet)
- error (0, 0, "Administrating %s", update_dir);
- return (R_PROCESS);
-}
diff --git a/contrib/cvs/src/annotate.c b/contrib/cvs/src/annotate.c
deleted file mode 100644
index d6d0acc1bbff..000000000000
--- a/contrib/cvs/src/annotate.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (c) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (c) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Show last revision where each line modified
- *
- * Prints the specified files with each line annotated with the revision
- * number where it was last modified. With no argument, annotates all
- * all the files in the directory (recursive by default).
- */
-
-#include "cvs.h"
-
-/* Options from the command line. */
-
-static int force_tag_match = 1;
-static int force_binary = 0;
-static char *tag = NULL;
-static int tag_validated;
-static char *date = NULL;
-
-static int is_rannotate;
-
-static int annotate_fileproc PROTO ((void *callerdat, struct file_info *));
-static int rannotate_proc PROTO((int argc, char **argv, char *xwhere,
- char *mwhere, char *mfile, int shorten,
- int local, char *mname, char *msg));
-
-static const char *const annotate_usage[] =
-{
- "Usage: %s %s [-lRfF] [-r rev] [-D date] [files...]\n",
- "\t-l\tLocal directory only, no recursion.\n",
- "\t-R\tProcess directories recursively.\n",
- "\t-f\tUse head revision if tag/date not found.\n",
- "\t-F\tAnnotate binary files.\n",
- "\t-r rev\tAnnotate file as of specified revision/tag.\n",
- "\t-D date\tAnnotate file as of specified date.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-/* Command to show the revision, date, and author where each line of a
- file was modified. */
-
-int
-annotate (argc, argv)
- int argc;
- char **argv;
-{
- int local = 0;
- int err = 0;
- int c;
-
- is_rannotate = (strcmp(cvs_cmd_name, "rannotate") == 0);
-
- if (argc == -1)
- usage (annotate_usage);
-
- optind = 0;
- while ((c = getopt (argc, argv, "+lr:D:fFR")) != -1)
- {
- switch (c)
- {
- case 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case 'r':
- tag = optarg;
- break;
- case 'D':
- date = Make_Date (optarg);
- break;
- case 'f':
- force_tag_match = 0;
- break;
- case 'F':
- force_binary = 1;
- break;
- case '?':
- default:
- usage (annotate_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- start_server ();
-
- if (is_rannotate && !supported_request ("rannotate"))
- error (1, 0, "server does not support rannotate");
-
- ign_setup ();
-
- if (local)
- send_arg ("-l");
- if (!force_tag_match)
- send_arg ("-f");
- if (force_binary)
- send_arg ("-F");
- option_with_arg ("-r", tag);
- if (date)
- client_senddate (date);
- send_arg ("--");
- if (is_rannotate)
- {
- int i;
- for (i = 0; i < argc; i++)
- send_arg (argv[i]);
- send_to_server ("rannotate\012", 0);
- }
- else
- {
- send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
- send_file_names (argc, argv, SEND_EXPAND_WILD);
- send_to_server ("annotate\012", 0);
- }
- return get_responses_and_close ();
- }
-#endif /* CLIENT_SUPPORT */
-
- if (is_rannotate)
- {
- DBM *db;
- int i;
- db = open_module ();
- for (i = 0; i < argc; i++)
- {
- err += do_module (db, argv[i], MISC, "Annotating", rannotate_proc,
- (char *) NULL, 0, local, 0, 0, (char *) NULL);
- }
- close_module (db);
- }
- else
- {
- err = rannotate_proc (argc + 1, argv - 1, (char *) NULL,
- (char *) NULL, (char *) NULL, 0, local, (char *) NULL,
- (char *) NULL);
- }
-
- return err;
-}
-
-
-static int
-rannotate_proc (argc, argv, xwhere, mwhere, mfile, shorten, local, mname, msg)
- int argc;
- char **argv;
- char *xwhere;
- char *mwhere;
- char *mfile;
- int shorten;
- int local;
- char *mname;
- char *msg;
-{
- /* Begin section which is identical to patch_proc--should this
- be abstracted out somehow? */
- char *myargv[2];
- int err = 0;
- int which;
- char *repository;
- char *where;
-
- if (is_rannotate)
- {
- repository = xmalloc (strlen (current_parsed_root->directory) + strlen (argv[0])
- + (mfile == NULL ? 0 : strlen (mfile) + 1) + 2);
- (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
- where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile) + 1)
- + 1);
- (void) strcpy (where, argv[0]);
-
- /* if mfile isn't null, we need to set up to do only part of the module */
- if (mfile != NULL)
- {
- char *cp;
- char *path;
-
- /* if the portion of the module is a path, put the dir part on repos */
- if ((cp = strrchr (mfile, '/')) != NULL)
- {
- *cp = '\0';
- (void) strcat (repository, "/");
- (void) strcat (repository, mfile);
- (void) strcat (where, "/");
- (void) strcat (where, mfile);
- mfile = cp + 1;
- }
-
- /* take care of the rest */
- path = xmalloc (strlen (repository) + strlen (mfile) + 5);
- (void) sprintf (path, "%s/%s", repository, mfile);
- if (isdir (path))
- {
- /* directory means repository gets the dir tacked on */
- (void) strcpy (repository, path);
- (void) strcat (where, "/");
- (void) strcat (where, mfile);
- }
- else
- {
- myargv[0] = argv[0];
- myargv[1] = mfile;
- argc = 2;
- argv = myargv;
- }
- free (path);
- }
-
- /* cd to the starting repository */
- if ( CVS_CHDIR (repository) < 0)
- {
- error (0, errno, "cannot chdir to %s", repository);
- free (repository);
- free (where);
- return (1);
- }
- /* End section which is identical to patch_proc. */
-
- if (force_tag_match && tag != NULL)
- which = W_REPOS | W_ATTIC;
- else
- which = W_REPOS;
- }
- else
- {
- where = NULL;
- which = W_LOCAL;
- repository = "";
- }
-
- if (tag != NULL && !tag_validated)
- {
- tag_check_valid (tag, argc - 1, argv + 1, local, 0, repository);
- tag_validated = 1;
- }
-
- err = start_recursion (annotate_fileproc, (FILESDONEPROC) NULL,
- (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
- argc - 1, argv + 1, local, which, 0, CVS_LOCK_READ,
- where, 1, repository);
- if ( which & W_REPOS )
- free ( repository );
- if ( where != NULL )
- free (where);
- return err;
-}
-
-
-static int
-annotate_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- char *expand, *version;
-
- if (finfo->rcs == NULL)
- return (1);
-
- if (finfo->rcs->flags & PARTIAL)
- RCS_reparsercsfile (finfo->rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- expand = RCS_getexpand (finfo->rcs);
- version = RCS_getversion (finfo->rcs, tag, date, force_tag_match,
- (int *) NULL);
-
- if (version == NULL)
- return 0;
-
- /* Distinguish output for various files if we are processing
- several files. */
- cvs_outerr ("\nAnnotations for ", 0);
- cvs_outerr (finfo->fullname, 0);
- cvs_outerr ("\n***************\n", 0);
-
- if (!force_binary && expand && expand[0] == 'b')
- {
- cvs_outerr ("Skipping binary file -- -F not specified.\n", 0);
- }
- else
- {
- RCS_deltas (finfo->rcs, (FILE *) NULL, (struct rcsbuffer *) NULL,
- version, RCS_ANNOTATE, NULL, NULL, NULL, NULL);
- }
- free (version);
- return 0;
-}
diff --git a/contrib/cvs/src/buffer.c b/contrib/cvs/src/buffer.c
deleted file mode 100644
index db2bea0d663d..000000000000
--- a/contrib/cvs/src/buffer.c
+++ /dev/null
@@ -1,1980 +0,0 @@
-/*
- * Copyright (C) 1996-2005 The Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-/* Code for the buffer data structure. */
-
-/* $FreeBSD$ */
-
-#include <assert.h>
-#include "cvs.h"
-#include "buffer.h"
-
-#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
-
-#ifdef HAVE_WINSOCK_H
-# include <winsock.h>
-#else
-# include <sys/socket.h>
-#endif
-
-/* OS/2 doesn't have EIO. FIXME: this whole notion of turning
- a different error into EIO strikes me as pretty dubious. */
-#if !defined (EIO)
-#define EIO EBADPOS
-#endif
-
-/* Linked list of available buffer_data structures. */
-static struct buffer_data *free_buffer_data;
-
-/* Local functions. */
-static void buf_default_memory_error PROTO ((struct buffer *));
-static void allocate_buffer_datas PROTO((void));
-static struct buffer_data *get_buffer_data PROTO((void));
-
-/* Initialize a buffer structure. */
-
-struct buffer *
-buf_initialize (input, output, flush, block, shutdown, memory, closure)
- int (*input) PROTO((void *, char *, int, int, int *));
- int (*output) PROTO((void *, const char *, int, int *));
- int (*flush) PROTO((void *));
- int (*block) PROTO((void *, int));
- int (*shutdown) PROTO((struct buffer *));
- void (*memory) PROTO((struct buffer *));
- void *closure;
-{
- struct buffer *buf;
-
- buf = (struct buffer *) xmalloc (sizeof (struct buffer));
- buf->data = NULL;
- buf->last = NULL;
- buf->nonblocking = 0;
- buf->input = input;
- buf->output = output;
- buf->flush = flush;
- buf->block = block;
- buf->shutdown = shutdown;
- buf->memory_error = memory ? memory : buf_default_memory_error;
- buf->closure = closure;
- return buf;
-}
-
-/* Free a buffer structure. */
-
-void
-buf_free (buf)
- struct buffer *buf;
-{
- if (buf->closure != NULL)
- {
- free (buf->closure);
- buf->closure = NULL;
- }
- if (buf->data != NULL)
- {
- buf->last->next = free_buffer_data;
- free_buffer_data = buf->data;
- }
- free (buf);
-}
-
-/* Initialize a buffer structure which is not to be used for I/O. */
-
-struct buffer *
-buf_nonio_initialize (memory)
- void (*memory) PROTO((struct buffer *));
-{
- return (buf_initialize
- ((int (*) PROTO((void *, char *, int, int, int *))) NULL,
- (int (*) PROTO((void *, const char *, int, int *))) NULL,
- (int (*) PROTO((void *))) NULL,
- (int (*) PROTO((void *, int))) NULL,
- (int (*) PROTO((struct buffer *))) NULL,
- memory,
- (void *) NULL));
-}
-
-/* Default memory error handler. */
-
-static void
-buf_default_memory_error (buf)
- struct buffer *buf;
-{
- error (1, 0, "out of memory");
-}
-
-/* Allocate more buffer_data structures. */
-
-static void
-allocate_buffer_datas ()
-{
- struct buffer_data *alc;
- char *space;
- int i;
-
- /* Allocate buffer_data structures in blocks of 16. */
-#define ALLOC_COUNT (16)
-
- alc = xmalloc (ALLOC_COUNT * sizeof (struct buffer_data));
- space = (char *) valloc (ALLOC_COUNT * BUFFER_DATA_SIZE);
- if (!space)
- {
- free (alc);
- return;
- }
- for (i = 0; i < ALLOC_COUNT; i++, alc++, space += BUFFER_DATA_SIZE)
- {
- alc->next = free_buffer_data;
- free_buffer_data = alc;
- alc->text = space;
- }
-}
-
-/* Get a new buffer_data structure. */
-
-static struct buffer_data *
-get_buffer_data ()
-{
- struct buffer_data *ret;
-
- if (free_buffer_data == NULL)
- {
- allocate_buffer_datas ();
- if (free_buffer_data == NULL)
- return NULL;
- }
-
- ret = free_buffer_data;
- free_buffer_data = ret->next;
- return ret;
-}
-
-
-
-/* See whether a buffer and its file descriptor is empty. */
-int
-buf_empty (buf)
- struct buffer *buf;
-{
- /* Try and read any data on the file descriptor first.
- * We already know the descriptor is non-blocking.
- */
- buf_input_data (buf, NULL);
- return buf_empty_p (buf);
-}
-
-
-
-/* See whether a buffer is empty. */
-int
-buf_empty_p (buf)
- struct buffer *buf;
-{
- struct buffer_data *data;
-
- for (data = buf->data; data != NULL; data = data->next)
- if (data->size > 0)
- return 0;
- return 1;
-}
-
-
-
-#ifdef SERVER_FLOWCONTROL
-/*
- * Count how much data is stored in the buffer..
- * Note that each buffer is a xmalloc'ed chunk BUFFER_DATA_SIZE.
- */
-
-int
-buf_count_mem (buf)
- struct buffer *buf;
-{
- struct buffer_data *data;
- int mem = 0;
-
- for (data = buf->data; data != NULL; data = data->next)
- mem += BUFFER_DATA_SIZE;
-
- return mem;
-}
-#endif /* SERVER_FLOWCONTROL */
-
-/* Add data DATA of length LEN to BUF. */
-
-void
-buf_output (buf, data, len)
- struct buffer *buf;
- const char *data;
- int len;
-{
- if (buf->data != NULL
- && (((buf->last->text + BUFFER_DATA_SIZE)
- - (buf->last->bufp + buf->last->size))
- >= len))
- {
- memcpy (buf->last->bufp + buf->last->size, data, len);
- buf->last->size += len;
- return;
- }
-
- while (1)
- {
- struct buffer_data *newdata;
-
- newdata = get_buffer_data ();
- if (newdata == NULL)
- {
- (*buf->memory_error) (buf);
- return;
- }
-
- if (buf->data == NULL)
- buf->data = newdata;
- else
- buf->last->next = newdata;
- newdata->next = NULL;
- buf->last = newdata;
-
- newdata->bufp = newdata->text;
-
- if (len <= BUFFER_DATA_SIZE)
- {
- newdata->size = len;
- memcpy (newdata->text, data, len);
- return;
- }
-
- newdata->size = BUFFER_DATA_SIZE;
- memcpy (newdata->text, data, BUFFER_DATA_SIZE);
-
- data += BUFFER_DATA_SIZE;
- len -= BUFFER_DATA_SIZE;
- }
-
- /*NOTREACHED*/
-}
-
-/* Add a '\0' terminated string to BUF. */
-
-void
-buf_output0 (buf, string)
- struct buffer *buf;
- const char *string;
-{
- buf_output (buf, string, strlen (string));
-}
-
-/* Add a single character to BUF. */
-
-void
-buf_append_char (buf, ch)
- struct buffer *buf;
- int ch;
-{
- if (buf->data != NULL
- && (buf->last->text + BUFFER_DATA_SIZE
- != buf->last->bufp + buf->last->size))
- {
- *(buf->last->bufp + buf->last->size) = ch;
- ++buf->last->size;
- }
- else
- {
- char b;
-
- b = ch;
- buf_output (buf, &b, 1);
- }
-}
-
-/*
- * Send all the output we've been saving up. Returns 0 for success or
- * errno code. If the buffer has been set to be nonblocking, this
- * will just write until the write would block.
- */
-
-int
-buf_send_output (buf)
- struct buffer *buf;
-{
- if (buf->output == NULL)
- abort ();
-
- while (buf->data != NULL)
- {
- struct buffer_data *data;
-
- data = buf->data;
-
- if (data->size > 0)
- {
- int status, nbytes;
-
- status = (*buf->output) (buf->closure, data->bufp, data->size,
- &nbytes);
- if (status != 0)
- {
- /* Some sort of error. Discard the data, and return. */
-
- buf->last->next = free_buffer_data;
- free_buffer_data = buf->data;
- buf->data = NULL;
- buf->last = NULL;
-
- return status;
- }
-
- if (nbytes != data->size)
- {
- /* Not all the data was written out. This is only
- permitted in nonblocking mode. Adjust the buffer,
- and return. */
-
- assert (buf->nonblocking);
-
- data->size -= nbytes;
- data->bufp += nbytes;
-
- return 0;
- }
- }
-
- buf->data = data->next;
- data->next = free_buffer_data;
- free_buffer_data = data;
- }
-
- buf->last = NULL;
-
- return 0;
-}
-
-/*
- * Flush any data queued up in the buffer. If BLOCK is nonzero, then
- * if the buffer is in nonblocking mode, put it into blocking mode for
- * the duration of the flush. This returns 0 on success, or an error
- * code.
- */
-
-int
-buf_flush (buf, block)
- struct buffer *buf;
- int block;
-{
- int nonblocking;
- int status;
-
- if (buf->flush == NULL)
- abort ();
-
- nonblocking = buf->nonblocking;
- if (nonblocking && block)
- {
- status = set_block (buf);
- if (status != 0)
- return status;
- }
-
- status = buf_send_output (buf);
- if (status == 0)
- status = (*buf->flush) (buf->closure);
-
- if (nonblocking && block)
- {
- int blockstat;
-
- blockstat = set_nonblock (buf);
- if (status == 0)
- status = blockstat;
- }
-
- return status;
-}
-
-/*
- * Set buffer BUF to nonblocking I/O. Returns 0 for success or errno
- * code.
- */
-
-int
-set_nonblock (buf)
- struct buffer *buf;
-{
- int status;
-
- if (buf->nonblocking)
- return 0;
- if (buf->block == NULL)
- abort ();
- status = (*buf->block) (buf->closure, 0);
- if (status != 0)
- return status;
- buf->nonblocking = 1;
- return 0;
-}
-
-/*
- * Set buffer BUF to blocking I/O. Returns 0 for success or errno
- * code.
- */
-
-int
-set_block (buf)
- struct buffer *buf;
-{
- int status;
-
- if (! buf->nonblocking)
- return 0;
- if (buf->block == NULL)
- abort ();
- status = (*buf->block) (buf->closure, 1);
- if (status != 0)
- return status;
- buf->nonblocking = 0;
- return 0;
-}
-
-/*
- * Send a character count and some output. Returns errno code or 0 for
- * success.
- *
- * Sending the count in binary is OK since this is only used on a pipe
- * within the same system.
- */
-
-int
-buf_send_counted (buf)
- struct buffer *buf;
-{
- int size;
- struct buffer_data *data;
-
- size = 0;
- for (data = buf->data; data != NULL; data = data->next)
- size += data->size;
-
- data = get_buffer_data ();
- if (data == NULL)
- {
- (*buf->memory_error) (buf);
- return ENOMEM;
- }
-
- data->next = buf->data;
- buf->data = data;
- if (buf->last == NULL)
- buf->last = data;
-
- data->bufp = data->text;
- data->size = sizeof (int);
-
- *((int *) data->text) = size;
-
- return buf_send_output (buf);
-}
-
-/*
- * Send a special count. COUNT should be negative. It will be
- * handled speciallyi by buf_copy_counted. This function returns 0 or
- * an errno code.
- *
- * Sending the count in binary is OK since this is only used on a pipe
- * within the same system.
- */
-
-int
-buf_send_special_count (buf, count)
- struct buffer *buf;
- int count;
-{
- struct buffer_data *data;
-
- data = get_buffer_data ();
- if (data == NULL)
- {
- (*buf->memory_error) (buf);
- return ENOMEM;
- }
-
- data->next = buf->data;
- buf->data = data;
- if (buf->last == NULL)
- buf->last = data;
-
- data->bufp = data->text;
- data->size = sizeof (int);
-
- *((int *) data->text) = count;
-
- return buf_send_output (buf);
-}
-
-/* Append a list of buffer_data structures to an buffer. */
-
-void
-buf_append_data (buf, data, last)
- struct buffer *buf;
- struct buffer_data *data;
- struct buffer_data *last;
-{
- if (data != NULL)
- {
- if (buf->data == NULL)
- buf->data = data;
- else
- buf->last->next = data;
- buf->last = last;
- }
-}
-
-/* Append the data on one buffer to another. This removes the data
- from the source buffer. */
-
-void
-buf_append_buffer (to, from)
- struct buffer *to;
- struct buffer *from;
-{
- buf_append_data (to, from->data, from->last);
- from->data = NULL;
- from->last = NULL;
-}
-
-/*
- * Copy the contents of file F into buffer_data structures. We can't
- * copy directly into an buffer, because we want to handle failure and
- * succeess differently. Returns 0 on success, or -2 if out of
- * memory, or a status code on error. Since the caller happens to
- * know the size of the file, it is passed in as SIZE. On success,
- * this function sets *RETP and *LASTP, which may be passed to
- * buf_append_data.
- */
-
-int
-buf_read_file (f, size, retp, lastp)
- FILE *f;
- long size;
- struct buffer_data **retp;
- struct buffer_data **lastp;
-{
- int status;
-
- *retp = NULL;
- *lastp = NULL;
-
- while (size > 0)
- {
- struct buffer_data *data;
- int get;
-
- data = get_buffer_data ();
- if (data == NULL)
- {
- status = -2;
- goto error_return;
- }
-
- if (*retp == NULL)
- *retp = data;
- else
- (*lastp)->next = data;
- data->next = NULL;
- *lastp = data;
-
- data->bufp = data->text;
- data->size = 0;
-
- if (size > BUFFER_DATA_SIZE)
- get = BUFFER_DATA_SIZE;
- else
- get = size;
-
- errno = EIO;
- if (fread (data->text, get, 1, f) != 1)
- {
- status = errno;
- goto error_return;
- }
-
- data->size += get;
- size -= get;
- }
-
- return 0;
-
- error_return:
- if (*retp != NULL)
- {
- (*lastp)->next = free_buffer_data;
- free_buffer_data = *retp;
- }
- return status;
-}
-
-/*
- * Copy the contents of file F into buffer_data structures. We can't
- * copy directly into an buffer, because we want to handle failure and
- * succeess differently. Returns 0 on success, or -2 if out of
- * memory, or a status code on error. On success, this function sets
- * *RETP and *LASTP, which may be passed to buf_append_data.
- */
-
-int
-buf_read_file_to_eof (f, retp, lastp)
- FILE *f;
- struct buffer_data **retp;
- struct buffer_data **lastp;
-{
- int status;
-
- *retp = NULL;
- *lastp = NULL;
-
- while (!feof (f))
- {
- struct buffer_data *data;
- int get, nread;
-
- data = get_buffer_data ();
- if (data == NULL)
- {
- status = -2;
- goto error_return;
- }
-
- if (*retp == NULL)
- *retp = data;
- else
- (*lastp)->next = data;
- data->next = NULL;
- *lastp = data;
-
- data->bufp = data->text;
- data->size = 0;
-
- get = BUFFER_DATA_SIZE;
-
- errno = EIO;
- nread = fread (data->text, 1, get, f);
- if (nread == 0 && !feof (f))
- {
- status = errno;
- goto error_return;
- }
-
- data->size = nread;
- }
-
- return 0;
-
- error_return:
- if (*retp != NULL)
- {
- (*lastp)->next = free_buffer_data;
- free_buffer_data = *retp;
- }
- return status;
-}
-
-/* Return the number of bytes in a chain of buffer_data structures. */
-
-int
-buf_chain_length (buf)
- struct buffer_data *buf;
-{
- int size = 0;
- while (buf)
- {
- size += buf->size;
- buf = buf->next;
- }
- return size;
-}
-
-/* Return the number of bytes in a buffer. */
-
-int
-buf_length (buf)
- struct buffer *buf;
-{
- return buf_chain_length (buf->data);
-}
-
-/*
- * Read an arbitrary amount of data into an input buffer. The buffer
- * will be in nonblocking mode, and we just grab what we can. Return
- * 0 on success, or -1 on end of file, or -2 if out of memory, or an
- * error code. If COUNTP is not NULL, *COUNTP is set to the number of
- * bytes read.
- */
-
-int
-buf_input_data (buf, countp)
- struct buffer *buf;
- int *countp;
-{
- if (buf->input == NULL)
- abort ();
-
- if (countp != NULL)
- *countp = 0;
-
- while (1)
- {
- int get;
- int status, nbytes;
-
- if (buf->data == NULL
- || (buf->last->bufp + buf->last->size
- == buf->last->text + BUFFER_DATA_SIZE))
- {
- struct buffer_data *data;
-
- data = get_buffer_data ();
- if (data == NULL)
- {
- (*buf->memory_error) (buf);
- return -2;
- }
-
- if (buf->data == NULL)
- buf->data = data;
- else
- buf->last->next = data;
- data->next = NULL;
- buf->last = data;
-
- data->bufp = data->text;
- data->size = 0;
- }
-
- get = ((buf->last->text + BUFFER_DATA_SIZE)
- - (buf->last->bufp + buf->last->size));
-
- status = (*buf->input) (buf->closure,
- buf->last->bufp + buf->last->size,
- 0, get, &nbytes);
- if (status != 0)
- return status;
-
- buf->last->size += nbytes;
- if (countp != NULL)
- *countp += nbytes;
-
- if (nbytes < get)
- {
- /* If we did not fill the buffer, then presumably we read
- all the available data. */
- return 0;
- }
- }
-
- /*NOTREACHED*/
-}
-
-/*
- * Read a line (characters up to a \012) from an input buffer. (We
- * use \012 rather than \n for the benefit of non Unix clients for
- * which \n means something else). This returns 0 on success, or -1
- * on end of file, or -2 if out of memory, or an error code. If it
- * succeeds, it sets *LINE to an allocated buffer holding the contents
- * of the line. The trailing \012 is not included in the buffer. If
- * LENP is not NULL, then *LENP is set to the number of bytes read;
- * strlen may not work, because there may be embedded null bytes.
- */
-
-int
-buf_read_line (buf, line, lenp)
- struct buffer *buf;
- char **line;
- int *lenp;
-{
- if (buf->input == NULL)
- abort ();
-
- *line = NULL;
-
- while (1)
- {
- int len, finallen = 0;
- struct buffer_data *data;
- char *nl;
-
- /* See if there is a newline in BUF. */
- len = 0;
- for (data = buf->data; data != NULL; data = data->next)
- {
- nl = memchr (data->bufp, '\012', data->size);
- if (nl != NULL)
- {
- finallen = nl - data->bufp;
- len += finallen;
- break;
- }
- len += data->size;
- }
-
- /* If we found a newline, copy the line into a memory buffer,
- and remove it from BUF. */
- if (data != NULL)
- {
- char *p;
- struct buffer_data *nldata;
-
- p = xmalloc (len + 1);
- if (p == NULL)
- return -2;
- *line = p;
-
- nldata = data;
- data = buf->data;
- while (data != nldata)
- {
- struct buffer_data *next;
-
- memcpy (p, data->bufp, data->size);
- p += data->size;
- next = data->next;
- data->next = free_buffer_data;
- free_buffer_data = data;
- data = next;
- }
-
- memcpy (p, data->bufp, finallen);
- p[finallen] = '\0';
-
- data->size -= finallen + 1;
- data->bufp = nl + 1;
- buf->data = data;
-
- if (lenp != NULL)
- *lenp = len;
-
- return 0;
- }
-
- /* Read more data until we get a newline. */
- while (1)
- {
- int size, status, nbytes;
- char *mem;
-
- if (buf->data == NULL
- || (buf->last->bufp + buf->last->size
- == buf->last->text + BUFFER_DATA_SIZE))
- {
- data = get_buffer_data ();
- if (data == NULL)
- {
- (*buf->memory_error) (buf);
- return -2;
- }
-
- if (buf->data == NULL)
- buf->data = data;
- else
- buf->last->next = data;
- data->next = NULL;
- buf->last = data;
-
- data->bufp = data->text;
- data->size = 0;
- }
-
- mem = buf->last->bufp + buf->last->size;
- size = (buf->last->text + BUFFER_DATA_SIZE) - mem;
-
- /* We need to read at least 1 byte. We can handle up to
- SIZE bytes. This will only be efficient if the
- underlying communication stream does its own buffering,
- or is clever about getting more than 1 byte at a time. */
- status = (*buf->input) (buf->closure, mem, 1, size, &nbytes);
- if (status != 0)
- return status;
-
- buf->last->size += nbytes;
-
- /* Optimize slightly to avoid an unnecessary call to
- memchr. */
- if (nbytes == 1)
- {
- if (*mem == '\012')
- break;
- }
- else
- {
- if (memchr (mem, '\012', nbytes) != NULL)
- break;
- }
- }
- }
-}
-
-/*
- * Extract data from the input buffer BUF. This will read up to WANT
- * bytes from the buffer. It will set *RETDATA to point at the bytes,
- * and set *GOT to the number of bytes to be found there. Any buffer
- * call which uses BUF may change the contents of the buffer at *DATA,
- * so the data should be fully processed before any further calls are
- * made. This returns 0 on success, or -1 on end of file, or -2 if
- * out of memory, or an error code.
- */
-
-int
-buf_read_data (buf, want, retdata, got)
- struct buffer *buf;
- int want;
- char **retdata;
- int *got;
-{
- if (buf->input == NULL)
- abort ();
-
- while (buf->data != NULL && buf->data->size == 0)
- {
- struct buffer_data *next;
-
- next = buf->data->next;
- buf->data->next = free_buffer_data;
- free_buffer_data = buf->data;
- buf->data = next;
- if (next == NULL)
- buf->last = NULL;
- }
-
- if (buf->data == NULL)
- {
- struct buffer_data *data;
- int get, status, nbytes;
-
- data = get_buffer_data ();
- if (data == NULL)
- {
- (*buf->memory_error) (buf);
- return -2;
- }
-
- buf->data = data;
- buf->last = data;
- data->next = NULL;
- data->bufp = data->text;
- data->size = 0;
-
- if (want < BUFFER_DATA_SIZE)
- get = want;
- else
- get = BUFFER_DATA_SIZE;
- status = (*buf->input) (buf->closure, data->bufp, get,
- BUFFER_DATA_SIZE, &nbytes);
- if (status != 0)
- return status;
-
- data->size = nbytes;
- }
-
- *retdata = buf->data->bufp;
- if (want < buf->data->size)
- {
- *got = want;
- buf->data->size -= want;
- buf->data->bufp += want;
- }
- else
- {
- *got = buf->data->size;
- buf->data->size = 0;
- }
-
- return 0;
-}
-
-/*
- * Copy lines from an input buffer to an output buffer. This copies
- * all complete lines (characters up to a newline) from INBUF to
- * OUTBUF. Each line in OUTBUF is preceded by the character COMMAND
- * and a space.
- */
-
-void
-buf_copy_lines (outbuf, inbuf, command)
- struct buffer *outbuf;
- struct buffer *inbuf;
- int command;
-{
- while (1)
- {
- struct buffer_data *data;
- struct buffer_data *nldata;
- char *nl;
- int len;
-
- /* See if there is a newline in INBUF. */
- nldata = NULL;
- nl = NULL;
- for (data = inbuf->data; data != NULL; data = data->next)
- {
- nl = memchr (data->bufp, '\n', data->size);
- if (nl != NULL)
- {
- nldata = data;
- break;
- }
- }
-
- if (nldata == NULL)
- {
- /* There are no more lines in INBUF. */
- return;
- }
-
- /* Put in the command. */
- buf_append_char (outbuf, command);
- buf_append_char (outbuf, ' ');
-
- if (inbuf->data != nldata)
- {
- /*
- * Simply move over all the buffers up to the one containing
- * the newline.
- */
- for (data = inbuf->data; data->next != nldata; data = data->next)
- ;
- data->next = NULL;
- buf_append_data (outbuf, inbuf->data, data);
- inbuf->data = nldata;
- }
-
- /*
- * If the newline is at the very end of the buffer, just move
- * the buffer onto OUTBUF. Otherwise we must copy the data.
- */
- len = nl + 1 - nldata->bufp;
- if (len == nldata->size)
- {
- inbuf->data = nldata->next;
- if (inbuf->data == NULL)
- inbuf->last = NULL;
-
- nldata->next = NULL;
- buf_append_data (outbuf, nldata, nldata);
- }
- else
- {
- buf_output (outbuf, nldata->bufp, len);
- nldata->bufp += len;
- nldata->size -= len;
- }
- }
-}
-
-/*
- * Copy counted data from one buffer to another. The count is an
- * integer, host size, host byte order (it is only used across a
- * pipe). If there is enough data, it should be moved over. If there
- * is not enough data, it should remain on the original buffer. A
- * negative count is a special case. if one is seen, *SPECIAL is set
- * to the (negative) count value and no additional data is gathered
- * from the buffer; normally *SPECIAL is set to 0. This function
- * returns the number of bytes it needs to see in order to actually
- * copy something over.
- */
-
-int
-buf_copy_counted (outbuf, inbuf, special)
- struct buffer *outbuf;
- struct buffer *inbuf;
- int *special;
-{
- *special = 0;
-
- while (1)
- {
- struct buffer_data *data;
- int need;
- union
- {
- char intbuf[sizeof (int)];
- int i;
- } u;
- char *intp;
- int count;
- struct buffer_data *start;
- int startoff;
- struct buffer_data *stop;
- int stopwant;
-
- /* See if we have enough bytes to figure out the count. */
- need = sizeof (int);
- intp = u.intbuf;
- for (data = inbuf->data; data != NULL; data = data->next)
- {
- if (data->size >= need)
- {
- memcpy (intp, data->bufp, need);
- break;
- }
- memcpy (intp, data->bufp, data->size);
- intp += data->size;
- need -= data->size;
- }
- if (data == NULL)
- {
- /* We don't have enough bytes to form an integer. */
- return need;
- }
-
- count = u.i;
- start = data;
- startoff = need;
-
- if (count < 0)
- {
- /* A negative COUNT is a special case meaning that we
- don't need any further information. */
- stop = start;
- stopwant = 0;
- }
- else
- {
- /*
- * We have an integer in COUNT. We have gotten all the
- * data from INBUF in all buffers before START, and we
- * have gotten STARTOFF bytes from START. See if we have
- * enough bytes remaining in INBUF.
- */
- need = count - (start->size - startoff);
- if (need <= 0)
- {
- stop = start;
- stopwant = count;
- }
- else
- {
- for (data = start->next; data != NULL; data = data->next)
- {
- if (need <= data->size)
- break;
- need -= data->size;
- }
- if (data == NULL)
- {
- /* We don't have enough bytes. */
- return need;
- }
- stop = data;
- stopwant = need;
- }
- }
-
- /*
- * We have enough bytes. Free any buffers in INBUF before
- * START, and remove STARTOFF bytes from START, so that we can
- * forget about STARTOFF.
- */
- start->bufp += startoff;
- start->size -= startoff;
-
- if (start->size == 0)
- start = start->next;
-
- if (stop->size == stopwant)
- {
- stop = stop->next;
- stopwant = 0;
- }
-
- while (inbuf->data != start)
- {
- data = inbuf->data;
- inbuf->data = data->next;
- data->next = free_buffer_data;
- free_buffer_data = data;
- }
-
- /* If COUNT is negative, set *SPECIAL and get out now. */
- if (count < 0)
- {
- *special = count;
- return 0;
- }
-
- /*
- * We want to copy over the bytes from START through STOP. We
- * only want STOPWANT bytes from STOP.
- */
-
- if (start != stop)
- {
- /* Attach the buffers from START through STOP to OUTBUF. */
- for (data = start; data->next != stop; data = data->next)
- ;
- inbuf->data = stop;
- data->next = NULL;
- buf_append_data (outbuf, start, data);
- }
-
- if (stopwant > 0)
- {
- buf_output (outbuf, stop->bufp, stopwant);
- stop->bufp += stopwant;
- stop->size -= stopwant;
- }
- }
-
- /*NOTREACHED*/
-}
-
-/* Shut down a buffer. This returns 0 on success, or an errno code. */
-
-int
-buf_shutdown (buf)
- struct buffer *buf;
-{
- if (buf->shutdown)
- return (*buf->shutdown) (buf);
- return 0;
-}
-
-
-
-/* The simplest type of buffer is one built on top of a stdio FILE.
- For simplicity, and because it is all that is required, we do not
- implement setting this type of buffer into nonblocking mode. The
- closure field is just a FILE *. */
-
-static int stdio_buffer_input PROTO((void *, char *, int, int, int *));
-static int stdio_buffer_output PROTO((void *, const char *, int, int *));
-static int stdio_buffer_flush PROTO((void *));
-static int stdio_buffer_shutdown PROTO((struct buffer *buf));
-
-
-
-/* Initialize a buffer built on a stdio FILE. */
-struct stdio_buffer_closure
-{
- FILE *fp;
- int child_pid;
-};
-
-
-
-struct buffer *
-stdio_buffer_initialize (fp, child_pid, input, memory)
- FILE *fp;
- int child_pid;
- int input;
- void (*memory) PROTO((struct buffer *));
-{
- struct stdio_buffer_closure *bc = xmalloc (sizeof (*bc));
-
- bc->fp = fp;
- bc->child_pid = child_pid;
-
- return buf_initialize (input ? stdio_buffer_input : NULL,
- input ? NULL : stdio_buffer_output,
- input ? NULL : stdio_buffer_flush,
- (int (*) PROTO((void *, int))) NULL,
- stdio_buffer_shutdown,
- memory,
- (void *) bc);
-}
-
-/* Return the file associated with a stdio buffer. */
-FILE *
-stdio_buffer_get_file (buf)
- struct buffer *buf;
-{
- struct stdio_buffer_closure *bc;
-
- assert(buf->shutdown == stdio_buffer_shutdown);
-
- bc = (struct stdio_buffer_closure *) buf->closure;
-
- return(bc->fp);
-}
-
-/* The buffer input function for a buffer built on a stdio FILE. */
-
-static int
-stdio_buffer_input (closure, data, need, size, got)
- void *closure;
- char *data;
- int need;
- int size;
- int *got;
-{
- struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure;
- int nbytes;
-
- /* Since stdio does its own buffering, we don't worry about
- getting more bytes than we need. */
-
- if (need == 0 || need == 1)
- {
- int ch;
-
- ch = getc (bc->fp);
-
- if (ch == EOF)
- {
- if (feof (bc->fp))
- return -1;
- else if (errno == 0)
- return EIO;
- else
- return errno;
- }
-
- *data = ch;
- *got = 1;
- return 0;
- }
-
- nbytes = fread (data, 1, need, bc->fp);
-
- if (nbytes == 0)
- {
- *got = 0;
- if (feof (bc->fp))
- return -1;
- else if (errno == 0)
- return EIO;
- else
- return errno;
- }
-
- *got = nbytes;
-
- return 0;
-}
-
-/* The buffer output function for a buffer built on a stdio FILE. */
-
-static int
-stdio_buffer_output (closure, data, have, wrote)
- void *closure;
- const char *data;
- int have;
- int *wrote;
-{
- struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure;
-
- *wrote = 0;
-
- while (have > 0)
- {
- int nbytes;
-
- nbytes = fwrite (data, 1, have, bc->fp);
-
- if (nbytes != have)
- {
- if (errno == 0)
- return EIO;
- else
- return errno;
- }
-
- *wrote += nbytes;
- have -= nbytes;
- data += nbytes;
- }
-
- return 0;
-}
-
-
-
-/* The buffer flush function for a buffer built on a stdio FILE. */
-static int
-stdio_buffer_flush (closure)
- void *closure;
-{
- struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure;
-
- if (fflush (bc->fp) != 0)
- {
- if (errno == 0)
- return EIO;
- else
- return errno;
- }
-
- return 0;
-}
-
-
-
-static int
-stdio_buffer_shutdown (buf)
- struct buffer *buf;
-{
- struct stdio_buffer_closure *bc = buf->closure;
- struct stat s;
- int closefp, statted;
-
- /* Must be a pipe or a socket. What could go wrong?
- * Well, apparently for disconnected clients under AIX, the
- * fstat() will return -1 on the server if the client has gone
- * away.
- */
- if (fstat(fileno(bc->fp), &s) == -1) statted = 0;
- else statted = 1;
- closefp = statted;
-
- /* Flush the buffer if we can */
- if (buf->flush)
- {
- buf_flush (buf, 1);
- buf->flush = NULL;
- }
-
- if (buf->input)
- {
- /* There used to be a check here for unread data in the buffer of on
- * the pipe, but it was deemed unnecessary and possibly dangerous. In
- * some sense it could be second-guessing the caller who requested it
- * closed, as well.
- */
-
-# ifdef SHUTDOWN_SERVER
- if (current_parsed_root->method != server_method)
-# endif
-# ifndef NO_SOCKET_TO_FD
- {
- /* shutdown() sockets */
- if (statted && S_ISSOCK (s.st_mode))
- shutdown (fileno (bc->fp), 0);
- }
-# endif /* NO_SOCKET_TO_FD */
-# ifdef START_RSH_WITH_POPEN_RW
- /* Can't be set with SHUTDOWN_SERVER defined */
- else if (pclose (bc->fp) == EOF)
- {
- error (0, errno, "closing connection to %s",
- current_parsed_root->hostname);
- closefp = 0;
- }
-# endif /* START_RSH_WITH_POPEN_RW */
-
- buf->input = NULL;
- }
- else if (buf->output)
- {
-# ifdef SHUTDOWN_SERVER
- /* FIXME: Should have a SHUTDOWN_SERVER_INPUT &
- * SHUTDOWN_SERVER_OUTPUT
- */
- if (current_parsed_root->method == server_method)
- SHUTDOWN_SERVER (fileno (bc->fp));
- else
-# endif
-# ifndef NO_SOCKET_TO_FD
- /* shutdown() sockets */
- if (statted && S_ISSOCK (s.st_mode))
- shutdown (fileno (bc->fp), 1);
-# else
- {
- /* I'm not sure I like this empty block, but the alternative
- * is a another nested NO_SOCKET_TO_FD switch above.
- */
- }
-# endif /* NO_SOCKET_TO_FD */
-
- buf->output = NULL;
- }
-
- if (statted && closefp && fclose (bc->fp) == EOF)
- {
- if (server_active)
- {
- /* Syslog this? */
- }
-# ifdef CLIENT_SUPPORT
- /* We are already closing the connection.
- * On error, print a warning and try to
- * continue to avoid infinte loops.
- */
- else
- error (0, errno,
- "closing down connection to %s",
- current_parsed_root->hostname);
-# endif /* CLIENT_SUPPORT */
- }
-
- /* If we were talking to a process, make sure it exited */
- if (bc->child_pid)
- {
- int w;
-
- do
- w = waitpid (bc->child_pid, (int *) 0, 0);
- while (w == -1 && errno == EINTR);
-
- /* We are already closing the connection.
- * On error, print a warning and try to
- * continue to avoid infinte loops.
- */
- if (w == -1)
- error (0, errno, "waiting for process %d", bc->child_pid);
- }
- return 0;
-}
-
-
-
-/* Certain types of communication input and output data in packets,
- where each packet is translated in some fashion. The packetizing
- buffer type supports that, given a buffer which handles lower level
- I/O and a routine to translate the data in a packet.
-
- This code uses two bytes for the size of a packet, so packets are
- restricted to 65536 bytes in total.
-
- The translation functions should just translate; they may not
- significantly increase or decrease the amount of data. The actual
- size of the initial data is part of the translated data. The
- output translation routine may add up to PACKET_SLOP additional
- bytes, and the input translation routine should shrink the data
- correspondingly. */
-
-#define PACKET_SLOP (100)
-
-/* This structure is the closure field of a packetizing buffer. */
-
-struct packetizing_buffer
-{
- /* The underlying buffer. */
- struct buffer *buf;
- /* The input translation function. Exactly one of inpfn and outfn
- will be NULL. The input translation function should
- untranslate the data in INPUT, storing the result in OUTPUT.
- SIZE is the amount of data in INPUT, and is also the size of
- OUTPUT. This should return 0 on success, or an errno code. */
- int (*inpfn) PROTO((void *fnclosure, const char *input, char *output,
- int size));
- /* The output translation function. This should translate the
- data in INPUT, storing the result in OUTPUT. The first two
- bytes in INPUT will be the size of the data, and so will SIZE.
- This should set *TRANSLATED to the amount of translated data in
- OUTPUT. OUTPUT is large enough to hold SIZE + PACKET_SLOP
- bytes. This should return 0 on success, or an errno code. */
- int (*outfn) PROTO((void *fnclosure, const char *input, char *output,
- int size, int *translated));
- /* A closure for the translation function. */
- void *fnclosure;
- /* For an input buffer, we may have to buffer up data here. */
- /* This is non-zero if the buffered data has been translated.
- Otherwise, the buffered data has not been translated, and starts
- with the two byte packet size. */
- int translated;
- /* The amount of buffered data. */
- int holdsize;
- /* The buffer allocated to hold the data. */
- char *holdbuf;
- /* The size of holdbuf. */
- int holdbufsize;
- /* If translated is set, we need another data pointer to track
- where we are in holdbuf. If translated is clear, then this
- pointer is not used. */
- char *holddata;
-};
-
-static int packetizing_buffer_input PROTO((void *, char *, int, int, int *));
-static int packetizing_buffer_output PROTO((void *, const char *, int, int *));
-static int packetizing_buffer_flush PROTO((void *));
-static int packetizing_buffer_block PROTO((void *, int));
-static int packetizing_buffer_shutdown PROTO((struct buffer *));
-
-/* Create a packetizing buffer. */
-
-struct buffer *
-packetizing_buffer_initialize (buf, inpfn, outfn, fnclosure, memory)
- struct buffer *buf;
- int (*inpfn) PROTO ((void *, const char *, char *, int));
- int (*outfn) PROTO ((void *, const char *, char *, int, int *));
- void *fnclosure;
- void (*memory) PROTO((struct buffer *));
-{
- struct packetizing_buffer *pb;
-
- pb = (struct packetizing_buffer *) xmalloc (sizeof *pb);
- memset (pb, 0, sizeof *pb);
-
- pb->buf = buf;
- pb->inpfn = inpfn;
- pb->outfn = outfn;
- pb->fnclosure = fnclosure;
-
- if (inpfn != NULL)
- {
- /* Add PACKET_SLOP to handle larger translated packets, and
- add 2 for the count. This buffer is increased if
- necessary. */
- pb->holdbufsize = BUFFER_DATA_SIZE + PACKET_SLOP + 2;
- pb->holdbuf = xmalloc (pb->holdbufsize);
- }
-
- return buf_initialize (inpfn != NULL ? packetizing_buffer_input : NULL,
- inpfn != NULL ? NULL : packetizing_buffer_output,
- inpfn != NULL ? NULL : packetizing_buffer_flush,
- packetizing_buffer_block,
- packetizing_buffer_shutdown,
- memory,
- pb);
-}
-
-/* Input data from a packetizing buffer. */
-
-static int
-packetizing_buffer_input (closure, data, need, size, got)
- void *closure;
- char *data;
- int need;
- int size;
- int *got;
-{
- struct packetizing_buffer *pb = (struct packetizing_buffer *) closure;
-
- *got = 0;
-
- if (pb->holdsize > 0 && pb->translated)
- {
- int copy;
-
- copy = pb->holdsize;
-
- if (copy > size)
- {
- memcpy (data, pb->holddata, size);
- pb->holdsize -= size;
- pb->holddata += size;
- *got = size;
- return 0;
- }
-
- memcpy (data, pb->holddata, copy);
- pb->holdsize = 0;
- pb->translated = 0;
-
- data += copy;
- need -= copy;
- size -= copy;
- *got = copy;
- }
-
- while (need > 0 || *got == 0)
- {
- int get, status, nread, count, tcount;
- char *bytes;
- char stackoutbuf[BUFFER_DATA_SIZE + PACKET_SLOP];
- char *inbuf, *outbuf;
-
- /* If we don't already have the two byte count, get it. */
- if (pb->holdsize < 2)
- {
- get = 2 - pb->holdsize;
- status = buf_read_data (pb->buf, get, &bytes, &nread);
- if (status != 0)
- {
- /* buf_read_data can return -2, but a buffer input
- function is only supposed to return -1, 0, or an
- error code. */
- if (status == -2)
- status = ENOMEM;
- return status;
- }
-
- if (nread == 0)
- {
- /* The buffer is in nonblocking mode, and we didn't
- manage to read anything. */
- return 0;
- }
-
- if (get == 1)
- pb->holdbuf[1] = bytes[0];
- else
- {
- pb->holdbuf[0] = bytes[0];
- if (nread < 2)
- {
- /* We only got one byte, but we needed two. Stash
- the byte we got, and try again. */
- pb->holdsize = 1;
- continue;
- }
- pb->holdbuf[1] = bytes[1];
- }
- pb->holdsize = 2;
- }
-
- /* Read the packet. */
-
- count = (((pb->holdbuf[0] & 0xff) << 8)
- + (pb->holdbuf[1] & 0xff));
-
- if (count + 2 > pb->holdbufsize)
- {
- char *n;
-
- /* We didn't allocate enough space in the initialize
- function. */
-
- n = xrealloc (pb->holdbuf, count + 2);
- if (n == NULL)
- {
- (*pb->buf->memory_error) (pb->buf);
- return ENOMEM;
- }
- pb->holdbuf = n;
- pb->holdbufsize = count + 2;
- }
-
- get = count - (pb->holdsize - 2);
-
- status = buf_read_data (pb->buf, get, &bytes, &nread);
- if (status != 0)
- {
- /* buf_read_data can return -2, but a buffer input
- function is only supposed to return -1, 0, or an error
- code. */
- if (status == -2)
- status = ENOMEM;
- return status;
- }
-
- if (nread == 0)
- {
- /* We did not get any data. Presumably the buffer is in
- nonblocking mode. */
- return 0;
- }
-
- if (nread < get)
- {
- /* We did not get all the data we need to fill the packet.
- buf_read_data does not promise to return all the bytes
- requested, so we must try again. */
- memcpy (pb->holdbuf + pb->holdsize, bytes, nread);
- pb->holdsize += nread;
- continue;
- }
-
- /* We have a complete untranslated packet of COUNT bytes. */
-
- if (pb->holdsize == 2)
- {
- /* We just read the entire packet (the 2 bytes in
- PB->HOLDBUF are the size). Save a memcpy by
- translating directly from BYTES. */
- inbuf = bytes;
- }
- else
- {
- /* We already had a partial packet in PB->HOLDBUF. We
- need to copy the new data over to make the input
- contiguous. */
- memcpy (pb->holdbuf + pb->holdsize, bytes, nread);
- inbuf = pb->holdbuf + 2;
- }
-
- if (count <= sizeof stackoutbuf)
- outbuf = stackoutbuf;
- else
- {
- outbuf = xmalloc (count);
- if (outbuf == NULL)
- {
- (*pb->buf->memory_error) (pb->buf);
- return ENOMEM;
- }
- }
-
- status = (*pb->inpfn) (pb->fnclosure, inbuf, outbuf, count);
- if (status != 0)
- return status;
-
- /* The first two bytes in the translated buffer are the real
- length of the translated data. */
- tcount = ((outbuf[0] & 0xff) << 8) + (outbuf[1] & 0xff);
-
- if (tcount > count)
- error (1, 0, "Input translation failure");
-
- if (tcount > size)
- {
- /* We have more data than the caller has provided space
- for. We need to save some of it for the next call. */
-
- memcpy (data, outbuf + 2, size);
- *got += size;
-
- pb->holdsize = tcount - size;
- memcpy (pb->holdbuf, outbuf + 2 + size, tcount - size);
- pb->holddata = pb->holdbuf;
- pb->translated = 1;
-
- if (outbuf != stackoutbuf)
- free (outbuf);
-
- return 0;
- }
-
- memcpy (data, outbuf + 2, tcount);
-
- if (outbuf != stackoutbuf)
- free (outbuf);
-
- pb->holdsize = 0;
-
- data += tcount;
- need -= tcount;
- size -= tcount;
- *got += tcount;
- }
-
- return 0;
-}
-
-/* Output data to a packetizing buffer. */
-
-static int
-packetizing_buffer_output (closure, data, have, wrote)
- void *closure;
- const char *data;
- int have;
- int *wrote;
-{
- struct packetizing_buffer *pb = (struct packetizing_buffer *) closure;
- char inbuf[BUFFER_DATA_SIZE + 2];
- char stack_outbuf[BUFFER_DATA_SIZE + PACKET_SLOP + 4];
- struct buffer_data *outdata = NULL;
- char *outbuf;
- int size, status, translated;
-
- if (have > BUFFER_DATA_SIZE)
- {
- /* It would be easy to xmalloc a buffer, but I don't think this
- case can ever arise. */
- abort ();
- }
-
- inbuf[0] = (have >> 8) & 0xff;
- inbuf[1] = have & 0xff;
- memcpy (inbuf + 2, data, have);
-
- size = have + 2;
-
- /* The output function is permitted to add up to PACKET_SLOP
- bytes, and we need 2 bytes for the size of the translated data.
- If we can guarantee that the result will fit in a buffer_data,
- we translate directly into one to avoid a memcpy in buf_output. */
- if (size + PACKET_SLOP + 2 > BUFFER_DATA_SIZE)
- outbuf = stack_outbuf;
- else
- {
- outdata = get_buffer_data ();
- if (outdata == NULL)
- {
- (*pb->buf->memory_error) (pb->buf);
- return ENOMEM;
- }
-
- outdata->next = NULL;
- outdata->bufp = outdata->text;
-
- outbuf = outdata->text;
- }
-
- status = (*pb->outfn) (pb->fnclosure, inbuf, outbuf + 2, size,
- &translated);
- if (status != 0)
- return status;
-
- /* The output function is permitted to add up to PACKET_SLOP
- bytes. */
- if (translated > size + PACKET_SLOP)
- abort ();
-
- outbuf[0] = (translated >> 8) & 0xff;
- outbuf[1] = translated & 0xff;
-
- if (outbuf == stack_outbuf)
- buf_output (pb->buf, outbuf, translated + 2);
- else
- {
- /* if ((have + PACKET_SLOP + 4) > BUFFER_DATA_SIZE), then
- outdata may be NULL. */
- if (outdata == NULL)
- abort ();
-
- outdata->size = translated + 2;
- buf_append_data (pb->buf, outdata, outdata);
- }
-
- *wrote = have;
-
- /* We will only be here because buf_send_output was called on the
- packetizing buffer. That means that we should now call
- buf_send_output on the underlying buffer. */
- return buf_send_output (pb->buf);
-}
-
-
-
-/* Flush data to a packetizing buffer. */
-static int
-packetizing_buffer_flush (closure)
- void *closure;
-{
- struct packetizing_buffer *pb = (struct packetizing_buffer *) closure;
-
- /* Flush the underlying buffer. Note that if the original call to
- buf_flush passed 1 for the BLOCK argument, then the buffer will
- already have been set into blocking mode, so we should always
- pass 0 here. */
- return buf_flush (pb->buf, 0);
-}
-
-
-
-/* The block routine for a packetizing buffer. */
-static int
-packetizing_buffer_block (closure, block)
- void *closure;
- int block;
-{
- struct packetizing_buffer *pb = (struct packetizing_buffer *) closure;
-
- if (block)
- return set_block (pb->buf);
- else
- return set_nonblock (pb->buf);
-}
-
-/* Shut down a packetizing buffer. */
-
-static int
-packetizing_buffer_shutdown (buf)
- struct buffer *buf;
-{
- struct packetizing_buffer *pb = (struct packetizing_buffer *) buf->closure;
-
- return buf_shutdown (pb->buf);
-}
-
-#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
diff --git a/contrib/cvs/src/buffer.h b/contrib/cvs/src/buffer.h
deleted file mode 100644
index 345905898702..000000000000
--- a/contrib/cvs/src/buffer.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 1996-2005 The Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-/* Declarations concerning the buffer data structure. */
-
-#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
-
-/*
- * We must read data from a child process and send it across the
- * network. We do not want to block on writing to the network, so we
- * store the data from the child process in memory. A BUFFER
- * structure holds the status of one communication, and uses a linked
- * list of buffer_data structures to hold data.
- */
-
-struct buffer
-{
- /* Data. */
- struct buffer_data *data;
-
- /* Last buffer on data chain. */
- struct buffer_data *last;
-
- /* Nonzero if the buffer is in nonblocking mode. */
- int nonblocking;
-
- /* Functions must be provided to transfer data in and out of the
- buffer. Either the input or output field must be set, but not
- both. */
-
- /* Read data into the buffer DATA. There is room for up to SIZE
- bytes. In blocking mode, wait until some input, at least NEED
- bytes, is available (NEED may be 0 but that is the same as NEED
- == 1). In non-blocking mode return immediately no matter how
- much input is available; NEED is ignored. Return 0 on success,
- or -1 on end of file, or an errno code. Set the number of
- bytes read in *GOT.
-
- If there are a nonzero number of bytes available, less than NEED,
- followed by end of file, just read those bytes and return 0. */
- int (*input) PROTO((void *closure, char *data, int need, int size,
- int *got));
-
- /* Write data. This should write up to HAVE bytes from DATA.
- This should return 0 on success, or an errno code. It should
- set the number of bytes written in *WROTE. */
- int (*output) PROTO((void *closure, const char *data, int have,
- int *wrote));
-
- /* Flush any data which may be buffered up after previous calls to
- OUTPUT. This should return 0 on success, or an errno code. */
- int (*flush) PROTO((void *closure));
-
- /* Change the blocking mode of the underlying communication
- stream. If BLOCK is non-zero, it should be placed into
- blocking mode. Otherwise, it should be placed into
- non-blocking mode. This should return 0 on success, or an
- errno code. */
- int (*block) PROTO ((void *closure, int block));
-
- /* Shut down the communication stream. This does not mean that it
- should be closed. It merely means that no more data will be
- read or written, and that any final processing that is
- appropriate should be done at this point. This may be NULL.
- It should return 0 on success, or an errno code. This entry
- point exists for the compression code. */
- int (*shutdown) PROTO((struct buffer *));
-
- /* This field is passed to the INPUT, OUTPUT, and BLOCK functions. */
- void *closure;
-
- /* Function to call if we can't allocate memory. */
- void (*memory_error) PROTO((struct buffer *));
-};
-
-/* Data is stored in lists of these structures. */
-
-struct buffer_data
-{
- /* Next buffer in linked list. */
- struct buffer_data *next;
-
- /*
- * A pointer into the data area pointed to by the text field. This
- * is where to find data that has not yet been written out.
- */
- char *bufp;
-
- /* The number of data bytes found at BUFP. */
- int size;
-
- /*
- * Actual buffer. This never changes after the structure is
- * allocated. The buffer is BUFFER_DATA_SIZE bytes.
- */
- char *text;
-};
-
-/* The size we allocate for each buffer_data structure. */
-#define BUFFER_DATA_SIZE (4096)
-
-/* The type of a function passed as a memory error handler. */
-typedef void (*BUFMEMERRPROC) PROTO ((struct buffer *));
-
-extern struct buffer *buf_initialize PROTO((int (*) (void *, char *, int,
- int, int *),
- int (*) (void *, const char *,
- int, int *),
- int (*) (void *),
- int (*) (void *, int),
- int (*) (struct buffer *),
- void (*) (struct buffer *),
- void *));
-extern void buf_free PROTO((struct buffer *));
-extern struct buffer *buf_nonio_initialize PROTO((void (*) (struct buffer *)));
-extern struct buffer *stdio_buffer_initialize
- PROTO((FILE *, int, int, void (*) (struct buffer *)));
-extern FILE *stdio_buffer_get_file PROTO((struct buffer *));
-extern struct buffer *compress_buffer_initialize
- PROTO((struct buffer *, int, int, void (*) (struct buffer *)));
-extern struct buffer *packetizing_buffer_initialize
- PROTO((struct buffer *, int (*) (void *, const char *, char *, int),
- int (*) (void *, const char *, char *, int, int *), void *,
- void (*) (struct buffer *)));
-extern int buf_empty PROTO((struct buffer *));
-extern int buf_empty_p PROTO((struct buffer *));
-extern void buf_output PROTO((struct buffer *, const char *, int));
-extern void buf_output0 PROTO((struct buffer *, const char *));
-extern void buf_append_char PROTO((struct buffer *, int));
-extern int buf_send_output PROTO((struct buffer *));
-extern int buf_flush PROTO((struct buffer *, int));
-extern int set_nonblock PROTO((struct buffer *));
-extern int set_block PROTO((struct buffer *));
-extern int buf_send_counted PROTO((struct buffer *));
-extern int buf_send_special_count PROTO((struct buffer *, int));
-extern void buf_append_data PROTO((struct buffer *,
- struct buffer_data *,
- struct buffer_data *));
-extern void buf_append_buffer PROTO((struct buffer *, struct buffer *));
-extern int buf_read_file PROTO((FILE *, long, struct buffer_data **,
- struct buffer_data **));
-extern int buf_read_file_to_eof PROTO((FILE *, struct buffer_data **,
- struct buffer_data **));
-extern int buf_input_data PROTO((struct buffer *, int *));
-extern int buf_read_line PROTO((struct buffer *, char **, int *));
-extern int buf_read_data PROTO((struct buffer *, int, char **, int *));
-extern void buf_copy_lines PROTO((struct buffer *, struct buffer *, int));
-extern int buf_copy_counted PROTO((struct buffer *, struct buffer *, int *));
-extern int buf_chain_length PROTO((struct buffer_data *));
-extern int buf_length PROTO((struct buffer *));
-extern int buf_shutdown PROTO((struct buffer *));
-
-#ifdef SERVER_FLOWCONTROL
-extern int buf_count_mem PROTO((struct buffer *));
-#endif /* SERVER_FLOWCONTROL */
-
-#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
diff --git a/contrib/cvs/src/checkin.c b/contrib/cvs/src/checkin.c
deleted file mode 100644
index 06d431ff0b89..000000000000
--- a/contrib/cvs/src/checkin.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Check In
- *
- * Does a very careful checkin of the file "user", and tries not to spoil its
- * modification time (to avoid needless recompilations). When RCS ID keywords
- * get expanded on checkout, however, the modification time is updated and
- * there is no good way to get around this.
- *
- * Returns non-zero on error.
- */
-
-#include <assert.h>
-#include "cvs.h"
-#include "fileattr.h"
-#include "edit.h"
-
-int
-Checkin (type, finfo, rev, tag, options, message)
- int type;
- struct file_info *finfo;
- char *rev;
- char *tag;
- char *options;
- char *message;
-{
- Vers_TS *vers;
- int set_time;
- char *tocvsPath = NULL;
-
- /* Hmm. This message goes to stdout and the "foo,v <-- foo"
- message from "ci" goes to stderr. This doesn't make a whole
- lot of sense, but making everything go to stdout can only be
- gracefully achieved once RCS_checkin is librarified. */
- cvs_output ("Checking in ", 0);
- cvs_output (finfo->fullname, 0);
- cvs_output (";\n", 0);
-
- tocvsPath = wrap_tocvs_process_file (finfo->file);
- if (!noexec)
- {
- if (tocvsPath)
- {
- if (unlink_file_dir (finfo->file) < 0)
- if (! existence_error (errno))
- error (1, errno, "cannot remove %s", finfo->fullname);
- rename_file (tocvsPath, finfo->file);
- }
- }
-
- /* There use to be a check for finfo->rcs == NULL here and then a
- * call to RCS_parse when necessary, but Checkin() isn't called
- * if the RCS file hasn't already been parsed in one of the
- * check functions.
- */
- assert (finfo->rcs != NULL);
-
- switch (RCS_checkin (finfo->rcs, finfo->file, message, rev, 0,
- RCS_FLAGS_KEEPFILE))
- {
- case 0: /* everything normal */
-
- /* The checkin succeeded. If checking the file out again
- would not cause any changes, we are done. Otherwise,
- we need to check out the file, which will change the
- modification time of the file.
-
- The only way checking out the file could cause any
- changes is if the file contains RCS keywords. So we if
- we are not expanding RCS keywords, we are done. */
-
- if (options != NULL
- && strcmp (options, "-V4") == 0) /* upgrade to V5 now */
- options[0] = '\0';
-
- /* FIXME: If PreservePermissions is on, RCS_cmp_file is
- going to call RCS_checkout into a temporary file
- anyhow. In that case, it would be more efficient to
- call RCS_checkout here, compare the resulting files
- using xcmp, and rename if necessary. I think this
- should be fixed in RCS_cmp_file. */
- if( ( ! preserve_perms
- && options != NULL
- && ( strcmp( options, "-ko" ) == 0
- || strcmp( options, "-kb" ) == 0 ) )
- || RCS_cmp_file( finfo->rcs, rev, (char **)NULL, (char *)NULL,
- options, finfo->file ) == 0 )
- {
- /* The existing file is correct. We don't have to do
- anything. */
- set_time = 0;
- }
- else
- {
- /* The existing file is incorrect. We need to check
- out the correct file contents. */
- if (RCS_checkout (finfo->rcs, finfo->file, rev, (char *) NULL,
- options, RUN_TTY, (RCSCHECKOUTPROC) NULL,
- (void *) NULL) != 0)
- error (1, 0, "failed when checking out new copy of %s",
- finfo->fullname);
- xchmod (finfo->file, 1);
- set_time = 1;
- }
-
- wrap_fromcvs_process_file (finfo->file);
-
- /*
- * If we want read-only files, muck the permissions here, before
- * getting the file time-stamp.
- */
- if (!cvswrite || fileattr_get (finfo->file, "_watched"))
- xchmod (finfo->file, 0);
-
- /* Re-register with the new data. */
- vers = Version_TS (finfo, NULL, tag, NULL, 1, set_time);
- if (strcmp (vers->options, "-V4") == 0)
- vers->options[0] = '\0';
- Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_user,
- vers->options, vers->tag, vers->date, (char *) 0);
- history_write (type, NULL, vers->vn_rcs,
- finfo->file, finfo->repository);
-
- if (tocvsPath)
- if (unlink_file_dir (tocvsPath) < 0)
- error (0, errno, "cannot remove %s", tocvsPath);
-
- break;
-
- case -1: /* fork failed */
- if (tocvsPath)
- if (unlink_file_dir (tocvsPath) < 0)
- error (0, errno, "cannot remove %s", tocvsPath);
-
- if (!noexec)
- error (1, errno, "could not check in %s -- fork failed",
- finfo->fullname);
- return (1);
-
- default: /* ci failed */
-
- /* The checkin failed, for some unknown reason, so we
- print an error, and return an error. We assume that
- the original file has not been touched. */
- if (tocvsPath)
- if (unlink_file_dir (tocvsPath) < 0)
- error (0, errno, "cannot remove %s", tocvsPath);
-
- if (!noexec)
- error (0, 0, "could not check in %s", finfo->fullname);
- return (1);
- }
-
- /*
- * When checking in a specific revision, we may have locked the wrong
- * branch, so to be sure, we do an extra unlock here before
- * returning.
- */
- if (rev)
- {
- (void) RCS_unlock (finfo->rcs, NULL, 1);
- RCS_rewrite (finfo->rcs, NULL, NULL);
- }
-
-#ifdef SERVER_SUPPORT
- if (server_active)
- {
- if (set_time)
- /* Need to update the checked out file on the client side. */
- server_updated (finfo, vers, SERVER_UPDATED,
- (mode_t) -1, (unsigned char *) NULL,
- (struct buffer *) NULL);
- else
- server_checked_in (finfo->file, finfo->update_dir, finfo->repository);
- }
- else
-#endif
- mark_up_to_date (finfo->file);
-
- freevers_ts (&vers);
- return 0;
-}
diff --git a/contrib/cvs/src/checkout.c b/contrib/cvs/src/checkout.c
deleted file mode 100644
index a1cd6cc9fe2e..000000000000
--- a/contrib/cvs/src/checkout.c
+++ /dev/null
@@ -1,1284 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Create Version
- *
- * "checkout" creates a "version" of an RCS repository. This version is owned
- * totally by the user and is actually an independent copy, to be dealt with
- * as seen fit. Once "checkout" has been called in a given directory, it
- * never needs to be called again. The user can keep up-to-date by calling
- * "update" when he feels like it; this will supply him with a merge of his
- * own modifications and the changes made in the RCS original. See "update"
- * for details.
- *
- * "checkout" can be given a list of directories or files to be updated and in
- * the case of a directory, will recursivley create any sub-directories that
- * exist in the repository.
- *
- * When the user is satisfied with his own modifications, the present version
- * can be committed by "commit"; this keeps the present version in tact,
- * usually.
- *
- * The call is cvs checkout [options] <module-name>...
- *
- * "checkout" creates a directory ./CVS, in which it keeps its administration,
- * in two files, Repository and Entries. The first contains the name of the
- * repository. The second contains one line for each registered file,
- * consisting of the version number it derives from, its time stamp at
- * derivation time and its name. Both files are normal files and can be
- * edited by the user, if necessary (when the repository is moved, e.g.)
- */
-
-/*
- * $FreeBSD$
- */
-
-#include <assert.h>
-#include "cvs.h"
-
-static char *findslash PROTO((char *start, char *p));
-static int checkout_proc PROTO((int argc, char **argv, char *where,
- char *mwhere, char *mfile, int shorten,
- int local_specified, char *omodule,
- char *msg));
-
-static const char *const checkout_usage[] =
-{
- "Usage:\n %s %s [-ANPRcflnps] [-r rev] [-D date] [-d dir]\n",
- " [-j rev1] [-j rev2] [-k kopt] modules...\n",
- "\t-A\tReset any sticky tags/date/kopts.\n",
- "\t-N\tDon't shorten module paths if -d specified.\n",
- "\t-P\tPrune empty directories.\n",
- "\t-R\tProcess directories recursively.\n",
- "\t-T\tCreate Template file from local repository for remote commit.\n",
- "\t-c\t\"cat\" the module database.\n",
- "\t-f\tForce a head revision match if tag/date not found.\n",
- "\t-l\tLocal directory only, not recursive\n",
- "\t-n\tDo not run module program (if any).\n",
- "\t-p\tCheck out files to standard output (avoids stickiness).\n",
- "\t-s\tLike -c, but include module status.\n",
- "\t-r rev\tCheck out revision or tag. (implies -P) (is sticky)\n",
- "\t-D date\tCheck out revisions as of date. (implies -P) (is sticky)\n",
- "\t-d dir\tCheck out into dir instead of module name.\n",
- "\t-k kopt\tUse RCS kopt -k option on checkout. (is sticky)\n",
- "\t-j rev\tMerge in changes made between current revision and rev.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-static const char *const export_usage[] =
-{
- "Usage: %s %s [-NRfln] [-r tag] [-D date] [-d dir] [-k kopt] module...\n",
- "\t-N\tDon't shorten module paths if -d specified.\n",
- "\t-f\tForce a head revision match if tag/date not found.\n",
- "\t-l\tLocal directory only, not recursive\n",
- "\t-R\tProcess directories recursively (default).\n",
- "\t-n\tDo not run module program (if any).\n",
- "\t-r tag\tExport tagged revisions.\n",
- "\t-D date\tExport revisions as of date.\n",
- "\t-d dir\tExport into dir instead of module name.\n",
- "\t-k kopt\tUse RCS kopt -k option on checkout.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-static int checkout_prune_dirs;
-static int force_tag_match;
-static int pipeout;
-static int aflag;
-static char *options;
-static char *tag;
-static int tag_validated;
-static char *date;
-static char *join_rev1;
-static char *join_rev2;
-static int join_tags_validated;
-static int pull_template;
-static char *preload_update_dir;
-static char *history_name;
-static enum mtype m_type;
-
-int
-checkout (argc, argv)
- int argc;
- char **argv;
-{
- int i;
- int c;
- DBM *db;
- int cat = 0, err = 0, status = 0;
- int run_module_prog = 1;
- int local = 0;
- int shorten = -1;
- char *where = NULL;
- char *valid_options;
- const char *const *valid_usage;
-
- /* initialize static options */
- force_tag_match = 1;
- if (options)
- {
- free (options);
- options = NULL;
- }
- tag = date = join_rev1 = join_rev2 = preload_update_dir = NULL;
- history_name = NULL;
- tag_validated = join_tags_validated = 0;
-
-
- /*
- * A smaller subset of options are allowed for the export command, which
- * is essentially like checkout, except that it hard-codes certain
- * options to be default (like -kv) and takes care to remove the CVS
- * directory when it has done its duty
- */
- if (strcmp (cvs_cmd_name, "export") == 0)
- {
- m_type = EXPORT;
- valid_options = "+Nnk:d:flRQqr:D:";
- valid_usage = export_usage;
- }
- else
- {
- m_type = CHECKOUT;
- valid_options = "+ANnk:d:flRpTQqcsr:D:j:P";
- valid_usage = checkout_usage;
- }
-
- if (argc == -1)
- usage (valid_usage);
-
- ign_setup ();
- wrap_setup ();
-
- optind = 0;
- while ((c = getopt (argc, argv, valid_options)) != -1)
- {
- switch (c)
- {
- case 'A':
- aflag = 1;
- break;
- case 'N':
- shorten = 0;
- break;
- case 'k':
- if (options)
- free (options);
- options = RCS_check_kflag (optarg);
- break;
- case 'n':
- run_module_prog = 0;
- break;
- case 'T':
- pull_template = 1;
- break;
- case 'Q':
- case 'q':
- /* The CVS 1.5 client sends these options (in addition to
- Global_option requests), so we must ignore them. */
- if (!server_active)
- error (1, 0,
- "-q or -Q must be specified before \"%s\"",
- cvs_cmd_name);
- break;
- case 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case 'P':
- checkout_prune_dirs = 1;
- break;
- case 'p':
- pipeout = 1;
- run_module_prog = 0; /* don't run module prog when piping */
- noexec = 1; /* so no locks will be created */
- break;
- case 'c':
- cat = 1;
- break;
- case 'd':
- where = optarg;
- if (shorten == -1)
- shorten = 1;
- break;
- case 's':
- cat = status = 1;
- break;
- case 'f':
- force_tag_match = 0;
- break;
- case 'r':
- tag = optarg;
- checkout_prune_dirs = 1;
- break;
- case 'D':
- date = Make_Date (optarg);
- checkout_prune_dirs = 1;
- break;
- case 'j':
- if (join_rev2)
- error (1, 0, "only two -j options can be specified");
- if (join_rev1)
- join_rev2 = optarg;
- else
- join_rev1 = optarg;
- break;
- case '?':
- default:
- usage (valid_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- if (shorten == -1)
- shorten = 0;
-
- if (cat && argc != 0)
- error (1, 0, "-c and -s must not get any arguments");
-
- if (!cat && argc == 0)
- error (1, 0, "must specify at least one module or directory");
-
- if (where && pipeout)
- error (1, 0, "-d and -p are mutually exclusive");
-
- if (m_type == EXPORT)
- {
- if (!tag && !date)
- error (1, 0, "must specify a tag or date");
-
- if (tag && isdigit ((unsigned char) tag[0]))
- error (1, 0, "tag `%s' must be a symbolic tag", tag);
- }
-
-#ifdef SERVER_SUPPORT
- if (server_active && where != NULL)
- {
- server_pathname_check (where);
- }
-#endif
-
- if (!cat && !pipeout && !safe_location( where )) {
- error(1, 0, "Cannot check out files into the repository itself");
- }
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- int expand_modules;
-
- start_server ();
-
- ign_setup ();
-
- expand_modules = (!cat && !pipeout
- && supported_request ("expand-modules"));
-
- if (expand_modules)
- {
- /* This is done here because we need to read responses
- from the server before we send the command checkout or
- export files. */
-
- client_expand_modules (argc, argv, local);
- }
-
- if (!run_module_prog)
- send_arg ("-n");
- if (local)
- send_arg ("-l");
- if (pipeout)
- send_arg ("-p");
- if (!force_tag_match)
- send_arg ("-f");
- if (aflag)
- send_arg("-A");
- if (!shorten)
- send_arg("-N");
- if (checkout_prune_dirs && m_type == CHECKOUT)
- send_arg("-P");
- client_prune_dirs = checkout_prune_dirs;
- if (cat && !status)
- send_arg("-c");
- if (where != NULL)
- option_with_arg ("-d", where);
- if (status)
- send_arg("-s");
- if (options != NULL && options[0] != '\0')
- send_arg (options);
- option_with_arg ("-r", tag);
- if (date)
- client_senddate (date);
- if (join_rev1 != NULL)
- option_with_arg ("-j", join_rev1);
- if (join_rev2 != NULL)
- option_with_arg ("-j", join_rev2);
- send_arg ("--");
-
- if (expand_modules)
- {
- client_send_expansions (local, where, 1);
- }
- else
- {
- int i;
- for (i = 0; i < argc; ++i)
- send_arg (argv[i]);
- client_nonexpanded_setup ();
- }
-
- send_to_server (m_type == EXPORT ? "export\012" : "co\012", 0);
- return get_responses_and_close ();
- }
-#endif /* CLIENT_SUPPORT */
-
- if (cat)
- {
- cat_module (status);
- if (options)
- {
- free (options);
- options = NULL;
- }
- return (0);
- }
- db = open_module ();
-
-
- /* If we've specified something like "cvs co foo/bar baz/quux"
- don't try to shorten names. There are a few cases in which we
- could shorten (e.g. "cvs co foo/bar foo/baz"), but we don't
- handle those yet. Better to have an extra directory created
- than the thing checked out under the wrong directory name. */
-
- if (argc > 1)
- shorten = 0;
-
-
- /* If we will be calling history_write, work out the name to pass
- it. */
- if (!pipeout)
- {
- if (!date)
- history_name = tag;
- else if (!tag)
- history_name = date;
- else
- {
- history_name = xmalloc (strlen (tag) + strlen (date) + 2);
- sprintf (history_name, "%s:%s", tag, date);
- }
- }
-
-
- for (i = 0; i < argc; i++)
- err += do_module (db, argv[i], m_type, "Updating", checkout_proc,
- where, shorten, local, run_module_prog, !pipeout,
- (char *) NULL);
- close_module (db);
- if (options)
- {
- free (options);
- options = NULL;
- }
- if (history_name != tag && history_name != date && history_name != NULL)
- free (history_name);
- return (err);
-}
-
-/* FIXME: This is and emptydir_name are in checkout.c for historical
- reasons, probably want to move them. */
-
-/* int
- * safe_location ( char *where )
- *
- * Return true if where is a safe destination for a checkout.
- *
- * INPUTS
- * where The requested destination directory.
- *
- * GLOBALS
- * current_parsed_root->directory
- * current_parsed_root->isremote
- * Used to locate our CVSROOT.
- *
- * RETURNS
- * true If we are running in client mode or if where is not located
- * within the CVSROOT.
- * false Otherwise.
- *
- * ERRORS
- * Exits with a fatal error message when various events occur, such as not
- * being able to resolve a path or failing ot chdir to a path.
- */
-int
-safe_location (where)
- char *where;
-{
- char *current;
- char *where_location;
- char *hardpath;
- size_t hardpath_len;
- int retval;
-
- if (trace)
- (void) fprintf (stderr, "%s-> safe_location( where=%s )\n",
- CLIENT_SERVER_STR,
- where ? where : "(null)");
-
- /* Don't compare remote CVSROOTs to our destination directory. */
- if (current_parsed_root->isremote) return 1;
-
- /* set current - even if where is set we'll need to cd back... */
- current = xgetwd ();
- if (current == NULL)
- error (1, errno, "could not get working directory");
-
- hardpath = xresolvepath ( current_parsed_root->directory );
-
- /* if where is set, set current to where, where - last_component( where ),
- * or fail, depending on whether the directories exist or not.
- */
- if( where != NULL )
- {
- if( chdir( where ) != -1 )
- {
- /* where */
- where_location = xgetwd();
- if( where_location == NULL )
- error( 1, errno, "could not get working directory" );
-
- if( chdir( current ) == -1 )
- error( 1, errno, "could not change directory to `%s'", current );
-
- free( current );
- current = where_location;
- }
- else if( errno == ENOENT )
- {
- if ( last_component( where ) != where )
- {
- /* where - last_component( where ) */
- char *parent;
-
- /* strip the last_component */
- where_location = xstrdup (where);
- /* It's okay to cast out the const below since we know we just
- * allocated where_location and can do what we like with it.
- */
- parent = (char *)last_component (where_location);
- parent[-1] = '\0';
-
- if( chdir( where_location ) != -1 )
- {
- free( where_location );
- where_location = xgetwd();
- if( where_location == NULL )
- error( 1, errno, "could not get working directory (nominally `%s')", where_location );
-
- if( chdir( current ) == -1 )
- error( 1, errno, "could not change directory to `%s'", current );
-
- free( current );
- current = where_location;
- }
- else
- /* fail */
- error( 1, errno, "could not change directory to requested checkout directory `%s'", where_location );
- }
- /* else: ERRNO == ENOENT & last_component(where) == where
- * for example, 'cvs co -d newdir module', where newdir hasn't
- * been created yet, so leave current set to '.' and check that
- */
- }
- else
- /* fail */
- error( 1, errno, "could not change directory to requested checkout directory `%s'", where );
- }
-
- hardpath_len = strlen (hardpath);
- if (strlen (current) >= hardpath_len
- && strncmp (current, hardpath, hardpath_len) == 0)
- {
- if (/* Current is a subdirectory of hardpath. */
- current[hardpath_len] == '/'
-
- /* Current is hardpath itself. */
- || current[hardpath_len] == '\0')
- retval = 0;
- else
- /* It isn't a problem. For example, current is
- "/foo/cvsroot-bar" and hardpath is "/foo/cvsroot". */
- retval = 1;
- }
- else
- retval = 1;
- free (current);
- free (hardpath);
- return retval;
-}
-
-struct dir_to_build
-{
- /* What to put in CVS/Repository. */
- char *repository;
- /* The path to the directory. */
- char *dirpath;
-
- /* If set, don't build the directory, just change to it.
- The caller will also want to set REPOSITORY to NULL. */
- int just_chdir;
-
- struct dir_to_build *next;
-};
-
-static int build_dirs_and_chdir PROTO ((struct dir_to_build *list,
- int sticky));
-
-static void build_one_dir PROTO ((char *, char *, int));
-
-static void
-build_one_dir (repository, dirpath, sticky)
- char *repository;
- char *dirpath;
- int sticky;
-{
- FILE *fp;
-
- if (isfile (CVSADM))
- {
- if (m_type == EXPORT)
- error (1, 0, "cannot export into a working directory");
- }
- else if (m_type == CHECKOUT)
- {
- /* I suspect that this check could be omitted. */
- if (!isdir (repository))
- error (1, 0, "there is no repository %s", repository);
-
- if (Create_Admin (".", dirpath, repository,
- sticky ? tag : (char *) NULL,
- sticky ? date : (char *) NULL,
-
- /* FIXME? This is a guess. If it is important
- for nonbranch to be set correctly here I
- think we need to write it one way now and
- then rewrite it later via WriteTag, once
- we've had a chance to call RCS_nodeisbranch
- on each file. */
- 0, 1, 1))
- return;
-
- if (!noexec)
- {
- fp = open_file (CVSADM_ENTSTAT, "w+");
- if (fclose (fp) == EOF)
- error (1, errno, "cannot close %s", CVSADM_ENTSTAT);
-#ifdef SERVER_SUPPORT
- if (server_active)
- server_set_entstat (dirpath, repository);
-#endif
- }
- }
-}
-
-/*
- * process_module calls us back here so we do the actual checkout stuff
- */
-/* ARGSUSED */
-static int
-checkout_proc (argc, argv, where_orig, mwhere, mfile, shorten,
- local_specified, omodule, msg)
- int argc;
- char **argv;
- char *where_orig;
- char *mwhere;
- char *mfile;
- int shorten;
- int local_specified;
- char *omodule;
- char *msg;
-{
- char *myargv[2];
- int err = 0;
- int which;
- char *cp;
- char *repository;
- char *oldupdate = NULL;
- char *where;
-
- /*
- * OK, so we're doing the checkout! Our args are as follows:
- * argc,argv contain either dir or dir followed by a list of files
- * where contains where to put it (if supplied by checkout)
- * mwhere contains the module name or -d from module file
- * mfile says do only that part of the module
- * shorten = 1 says shorten as much as possible
- * omodule is the original arg to do_module()
- */
-
- /* Set up the repository (maybe) for the bottom directory.
- Allocate more space than we need so we don't need to keep
- reallocating this string. */
- repository = xmalloc (strlen (current_parsed_root->directory)
- + strlen (argv[0])
- + (mfile == NULL ? 0 : strlen (mfile))
- + 10);
- (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
- Sanitize_Repository_Name (repository);
-
-
- /* save the original value of preload_update_dir */
- if (preload_update_dir != NULL)
- oldupdate = xstrdup (preload_update_dir);
-
-
- /* Allocate space and set up the where variable. We allocate more
- space than necessary here so that we don't have to keep
- reallocaing it later on. */
-
- where = xmalloc (strlen (argv[0])
- + (mfile == NULL ? 0 : strlen (mfile))
- + (mwhere == NULL ? 0 : strlen (mwhere))
- + (where_orig == NULL ? 0 : strlen (where_orig))
- + 10);
-
- /* Yes, this could be written in a less verbose way, but in this
- form it is quite easy to read.
-
- FIXME? The following code that sets should probably be moved
- to do_module in modules.c, since there is similar code in
- patch.c and rtag.c. */
-
- if (shorten)
- {
- if (where_orig != NULL)
- {
- /* If the user has specified a directory with `-d' on the
- command line, use it preferentially, even over the `-d'
- flag in the modules file. */
-
- (void) strcpy (where, where_orig);
- }
- else if (mwhere != NULL)
- {
- /* Second preference is the value of mwhere, which is from
- the `-d' flag in the modules file. */
-
- (void) strcpy (where, mwhere);
- }
- else
- {
- /* Third preference is the directory specified in argv[0]
- which is this module'e directory in the repository. */
-
- (void) strcpy (where, argv[0]);
- }
- }
- else
- {
- /* Use the same preferences here, bug don't shorten -- that
- is, tack on where_orig if it exists. */
-
- *where = '\0';
-
- if (where_orig != NULL)
- {
- (void) strcat (where, where_orig);
- (void) strcat (where, "/");
- }
-
- /* If the -d flag in the modules file specified an absolute
- directory, let the user override it with the command-line
- -d option. */
-
- if ((mwhere != NULL) && (! isabsolute (mwhere)))
- (void) strcat (where, mwhere);
- else
- (void) strcat (where, argv[0]);
- }
- strip_trailing_slashes (where); /* necessary? */
-
-
- /* At this point, the user may have asked for a single file or
- directory from within a module. In that case, we should modify
- where, repository, and argv as appropriate. */
-
- if (mfile != NULL)
- {
- /* The mfile variable can have one or more path elements. If
- it has multiple elements, we want to tack those onto both
- repository and where. The last element may refer to either
- a file or directory. Here's what to do:
-
- it refers to a directory
- -> simply tack it on to where and repository
- it refers to a file
- -> munge argv to contain `basename mfile` */
-
- char *cp;
- char *path;
-
-
- /* Paranoia check. */
-
- if (mfile[strlen (mfile) - 1] == '/')
- {
- error (0, 0, "checkout_proc: trailing slash on mfile (%s)!",
- mfile);
- }
-
-
- /* Does mfile have multiple path elements? */
-
- cp = strrchr (mfile, '/');
- if (cp != NULL)
- {
- *cp = '\0';
- (void) strcat (repository, "/");
- (void) strcat (repository, mfile);
- (void) strcat (where, "/");
- (void) strcat (where, mfile);
- mfile = cp + 1;
- }
-
-
- /* Now mfile is a single path element. */
-
- path = xmalloc (strlen (repository) + strlen (mfile) + 5);
- (void) sprintf (path, "%s/%s", repository, mfile);
- if (isdir (path))
- {
- /* It's a directory, so tack it on to repository and
- where, as we did above. */
-
- (void) strcat (repository, "/");
- (void) strcat (repository, mfile);
- (void) strcat (where, "/");
- (void) strcat (where, mfile);
- }
- else
- {
- /* It's a file, which means we have to screw around with
- argv. */
- myargv[0] = argv[0];
- myargv[1] = mfile;
- argc = 2;
- argv = myargv;
- }
- free (path);
- }
-
- if (preload_update_dir != NULL)
- {
- preload_update_dir =
- xrealloc (preload_update_dir,
- strlen (preload_update_dir) + strlen (where) + 5);
- strcat (preload_update_dir, "/");
- strcat (preload_update_dir, where);
- }
- else
- preload_update_dir = xstrdup (where);
-
- /*
- * At this point, where is the directory we want to build, repository is
- * the repository for the lowest level of the path.
- *
- * We need to tell build_dirs not only the path we want it to
- * build, but also the repositories we want it to populate the
- * path with. To accomplish this, we walk the path backwards, one
- * pathname component at a time, constucting a linked list of
- * struct dir_to_build.
- */
-
- /*
- * If we are sending everything to stdout, we can skip a whole bunch of
- * work from here
- */
- if (!pipeout)
- {
- struct dir_to_build *head;
- char *reposcopy;
-
- if (strncmp (repository, current_parsed_root->directory,
- strlen (current_parsed_root->directory)) != 0)
- error (1, 0, "\
-internal error: %s doesn't start with %s in checkout_proc",
- repository, current_parsed_root->directory);
-
- /* We always create at least one directory, which corresponds to
- the entire strings for WHERE and REPOSITORY. */
- head = (struct dir_to_build *) xmalloc (sizeof (struct dir_to_build));
- /* Special marker to indicate that we don't want build_dirs_and_chdir
- to create the CVSADM directory for us. */
- head->repository = NULL;
- head->dirpath = xstrdup (where);
- head->next = NULL;
- head->just_chdir = 0;
-
-
- /* Make a copy of the repository name to play with. */
- reposcopy = xstrdup (repository);
-
- /* FIXME: this should be written in terms of last_component
- instead of hardcoding '/'. This presumably affects OS/2,
- NT, &c, if the user specifies '\'. Likewise for the call
- to findslash. */
- cp = where + strlen (where);
- while (cp > where)
- {
- struct dir_to_build *new;
-
- cp = findslash (where, cp - 1);
- if (cp == NULL)
- break; /* we're done */
-
- new = (struct dir_to_build *)
- xmalloc (sizeof (struct dir_to_build));
- new->dirpath = xmalloc (strlen (where));
-
- /* If the user specified an absolute path for where, the
- last path element we create should be the top-level
- directory. */
-
- if (cp > where)
- {
- strncpy (new->dirpath, where, cp - where);
- new->dirpath[cp - where] = '\0';
- }
- else
- {
- /* where should always be at least one character long. */
- assert (where[0] != '\0');
- strcpy (new->dirpath, "/");
- }
- new->next = head;
- head = new;
-
- /* If where consists of multiple pathname components,
- then we want to just cd into it, without creating
- directories or modifying CVS directories as we go.
- In CVS 1.9 and earlier, the code actually does a
- CVS_CHDIR up-front; I'm not going to try to go back
- to that exact code but this is somewhat similar
- in spirit. */
- if (where_orig != NULL
- && cp - where < strlen (where_orig))
- {
- new->repository = NULL;
- new->just_chdir = 1;
- continue;
- }
-
- new->just_chdir = 0;
-
- /* Now figure out what repository directory to generate.
- The most complete case would be something like this:
-
- The modules file contains
- foo -d bar/baz quux
-
- The command issued was:
- cvs co -d what/ever -N foo
-
- The results in the CVS/Repository files should be:
- . -> (don't touch CVS/Repository)
- (I think this case might be buggy currently)
- what -> (don't touch CVS/Repository)
- ever -> . (same as "cd what/ever; cvs co -N foo")
- bar -> Emptydir (generated dir -- not in repos)
- baz -> quux (finally!) */
-
- if (strcmp (reposcopy, current_parsed_root->directory) == 0)
- {
- /* We can't walk up past CVSROOT. Instead, the
- repository should be Emptydir. */
- new->repository = emptydir_name ();
- }
- else
- {
- /* It's a directory in the repository! */
-
- char *rp;
-
- /* We'll always be below CVSROOT, but check for
- paranoia's sake. */
- rp = strrchr (reposcopy, '/');
- if (rp == NULL)
- error (1, 0,
- "internal error: %s doesn't contain a slash",
- reposcopy);
-
- *rp = '\0';
- new->repository = xmalloc (strlen (reposcopy) + 5);
- (void) strcpy (new->repository, reposcopy);
-
- if (strcmp (reposcopy, current_parsed_root->directory) == 0)
- {
- /* Special case -- the repository name needs
- to be "/path/to/repos/." (the trailing dot
- is important). We might be able to get rid
- of this after the we check out the other
- code that handles repository names. */
- (void) strcat (new->repository, "/.");
- }
- }
- }
-
- /* clean up */
- free (reposcopy);
-
- /* The top-level CVSADM directory should always be
- current_parsed_root->directory. Create it, but only if WHERE is
- relative. If WHERE is absolute, our current directory
- may not have a thing to do with where the sources are
- being checked out. If it does, build_dirs_and_chdir
- will take care of creating adm files here. */
- /* FIXME: checking is_absolute (where) is a horrid kludge;
- I suspect we probably can just skip the call to
- build_one_dir whenever the -d command option was specified
- to checkout. */
-
- if (!isabsolute (where) && top_level_admin && m_type == CHECKOUT)
- {
- /* It may be argued that we shouldn't set any sticky
- bits for the top-level repository. FIXME? */
- build_one_dir (current_parsed_root->directory, ".", argc <= 1);
-
-#ifdef SERVER_SUPPORT
- /* We _always_ want to have a top-level admin
- directory. If we're running in client/server mode,
- send a "Clear-static-directory" command to make
- sure it is created on the client side. (See 5.10
- in cvsclient.dvi to convince yourself that this is
- OK.) If this is a duplicate command being sent, it
- will be ignored on the client side. */
-
- if (server_active)
- server_clear_entstat (".", current_parsed_root->directory);
-#endif
- }
-
-
- /* Build dirs on the path if necessary and leave us in the
- bottom directory (where if where was specified) doesn't
- contain a CVS subdir yet, but all the others contain
- CVS and Entries.Static files */
-
- if (build_dirs_and_chdir (head, argc <= 1) != 0)
- {
- error (0, 0, "ignoring module %s", omodule);
- err = 1;
- goto out;
- }
-
- /* set up the repository (or make sure the old one matches) */
- if (!isfile (CVSADM))
- {
- FILE *fp;
-
- if (!noexec && argc > 1)
- {
- /* I'm not sure whether this check is redundant. */
- if (!isdir (repository))
- error (1, 0, "there is no repository %s", repository);
-
- Create_Admin (".", preload_update_dir, repository,
- (char *) NULL, (char *) NULL, 0, 0,
- m_type == CHECKOUT);
- fp = open_file (CVSADM_ENTSTAT, "w+");
- if (fclose(fp) == EOF)
- error(1, errno, "cannot close %s", CVSADM_ENTSTAT);
-#ifdef SERVER_SUPPORT
- if (server_active)
- server_set_entstat (where, repository);
-#endif
- }
- else
- {
- /* I'm not sure whether this check is redundant. */
- if (!isdir (repository))
- error (1, 0, "there is no repository %s", repository);
-
- Create_Admin (".", preload_update_dir, repository, tag, date,
-
- /* FIXME? This is a guess. If it is important
- for nonbranch to be set correctly here I
- think we need to write it one way now and
- then rewrite it later via WriteTag, once
- we've had a chance to call RCS_nodeisbranch
- on each file. */
- 0, 0, m_type == CHECKOUT);
- }
- }
- else
- {
- char *repos;
-
- if (m_type == EXPORT)
- error (1, 0, "cannot export into working directory");
-
- /* get the contents of the previously existing repository */
- repos = Name_Repository ((char *) NULL, preload_update_dir);
- if (fncmp (repository, repos) != 0)
- {
- error (0, 0, "existing repository %s does not match %s",
- repos, repository);
- error (0, 0, "ignoring module %s", omodule);
- free (repos);
- err = 1;
- goto out;
- }
- free (repos);
- }
- }
-
- /*
- * If we are going to be updating to stdout, we need to cd to the
- * repository directory so the recursion processor can use the current
- * directory as the place to find repository information
- */
- if (pipeout)
- {
- if ( CVS_CHDIR (repository) < 0)
- {
- error (0, errno, "cannot chdir to %s", repository);
- err = 1;
- goto out;
- }
- which = W_REPOS;
- if (tag != NULL && !tag_validated)
- {
- tag_check_valid (tag, argc - 1, argv + 1, 0, aflag,
- repository);
- tag_validated = 1;
- }
- }
- else
- {
- which = W_LOCAL | W_REPOS;
- if (tag != NULL && !tag_validated)
- {
- tag_check_valid (tag, argc - 1, argv + 1, 0, aflag,
- repository);
- tag_validated = 1;
- }
- }
-
- if (tag != NULL || date != NULL || join_rev1 != NULL)
- which |= W_ATTIC;
-
- if (! join_tags_validated)
- {
- if (join_rev1 != NULL)
- tag_check_valid_join (join_rev1, argc - 1, argv + 1, 0, aflag,
- repository);
- if (join_rev2 != NULL)
- tag_check_valid_join (join_rev2, argc - 1, argv + 1, 0, aflag,
- repository);
- join_tags_validated = 1;
- }
-
- /*
- * if we are going to be recursive (building dirs), go ahead and call the
- * update recursion processor. We will be recursive unless either local
- * only was specified, or we were passed arguments
- */
- if (!(local_specified || argc > 1))
- {
- if (!pipeout)
- history_write (m_type == CHECKOUT ? 'O' : 'E', preload_update_dir,
- history_name, where, repository);
- err += do_update (0, (char **) NULL, options, tag, date,
- force_tag_match, 0 /* !local */ ,
- 1 /* update -d */ , aflag, checkout_prune_dirs,
- pipeout, which, join_rev1, join_rev2,
- preload_update_dir, pull_template, repository);
- goto out;
- }
-
- if (!pipeout)
- {
- int i;
- List *entries;
-
- /* we are only doing files, so register them */
- entries = Entries_Open (0, NULL);
- for (i = 1; i < argc; i++)
- {
- char *line;
- Vers_TS *vers;
- struct file_info finfo;
-
- memset (&finfo, 0, sizeof finfo);
- finfo.file = argv[i];
- /* Shouldn't be used, so set to arbitrary value. */
- finfo.update_dir = NULL;
- finfo.fullname = argv[i];
- finfo.repository = repository;
- finfo.entries = entries;
- /* The rcs slot is needed to get the options from the RCS
- file */
- finfo.rcs = RCS_parse (finfo.file, repository);
-
- vers = Version_TS (&finfo, options, tag, date,
- force_tag_match, 0);
- if (vers->ts_user == NULL)
- {
- line = xmalloc (strlen (finfo.file) + 15);
- (void) sprintf (line, "Initial %s", finfo.file);
- Register (entries, finfo.file,
- vers->vn_rcs ? vers->vn_rcs : "0",
- line, vers->options, vers->tag,
- vers->date, (char *) 0);
- free (line);
- }
- freevers_ts (&vers);
- freercsnode (&finfo.rcs);
- }
-
- Entries_Close (entries);
- }
-
- /* Don't log "export", just regular "checkouts" */
- if (m_type == CHECKOUT && !pipeout)
- history_write ('O', preload_update_dir, history_name, where,
- repository);
-
- /* go ahead and call update now that everything is set */
- err += do_update (argc - 1, argv + 1, options, tag, date,
- force_tag_match, local_specified, 1 /* update -d */,
- aflag, checkout_prune_dirs, pipeout, which, join_rev1,
- join_rev2, preload_update_dir, pull_template, repository);
-out:
- free (preload_update_dir);
- preload_update_dir = oldupdate;
- free (where);
- free (repository);
- return (err);
-}
-
-static char *
-findslash (start, p)
- char *start;
- char *p;
-{
- for (;;)
- {
- if (*p == '/') return p;
- if (p == start) break;
- --p;
- }
- return NULL;
-}
-
-/* Return a newly malloc'd string containing a pathname for CVSNULLREPOS,
- and make sure that it exists. If there is an error creating the
- directory, give a fatal error. Otherwise, the directory is guaranteed
- to exist when we return. */
-char *
-emptydir_name ()
-{
- char *repository;
-
- repository = xmalloc (strlen (current_parsed_root->directory)
- + sizeof (CVSROOTADM)
- + sizeof (CVSNULLREPOS)
- + 3);
- (void) sprintf (repository, "%s/%s/%s", current_parsed_root->directory,
- CVSROOTADM, CVSNULLREPOS);
- if (!isfile (repository))
- {
- mode_t omask;
- omask = umask (cvsumask);
- if (CVS_MKDIR (repository, 0777) < 0)
- error (1, errno, "cannot create %s", repository);
- (void) umask (omask);
- }
- return repository;
-}
-
-/* Build all the dirs along the path to DIRS with CVS subdirs with appropriate
- * repositories. If DIRS->repository is NULL or the directory already exists,
- * do not create a CVSADM directory for that subdirectory; just CVS_CHDIR into
- * it. Frees all storage used by DIRS.
- *
- * ASSUMPTIONS
- * 1. Parent directories will be listed in DIRS before their children.
- * 2. At most a single directory will need to be changed at one time. In
- * other words, if we are in /a/b/c, and our final destination is
- * /a/b/c/d/e/f, then we will build d, then d/e, then d/e/f.
- *
- * INPUTS
- * dirs Simple list composed of dir_to_build structures, listing
- * information about directories to build.
- * sticky Passed to build_one_dir to tell it whether there are any sticky
- * tags or dates to be concerned with.
- *
- * RETURNS
- * 1 on error, 0 otherwise.
- *
- * ERRORS
- * The only nonfatal error this function may return is if the CHDIR fails.
- */
-static int
-build_dirs_and_chdir (dirs, sticky)
- struct dir_to_build *dirs;
- int sticky;
-{
- int retval = 0;
- struct dir_to_build *nextdir;
-
- while (dirs != NULL)
- {
- const char *dir = last_component (dirs->dirpath);
-
- if (!dirs->just_chdir)
- {
- mkdir_if_needed (dir);
- Subdir_Register (NULL, NULL, dir);
- }
-
- if (CVS_CHDIR (dir) < 0)
- {
- error (0, errno, "cannot chdir to %s", dir);
- retval = 1;
- goto out;
- }
- if (dirs->repository != NULL)
- {
- build_one_dir (dirs->repository, dirs->dirpath, sticky);
- free (dirs->repository);
- }
- nextdir = dirs->next;
- free (dirs->dirpath);
- free (dirs);
- dirs = nextdir;
- }
-
- out:
- while (dirs != NULL)
- {
- if (dirs->repository != NULL)
- free (dirs->repository);
- nextdir = dirs->next;
- free (dirs->dirpath);
- free (dirs);
- dirs = nextdir;
- }
- return retval;
-}
diff --git a/contrib/cvs/src/classify.c b/contrib/cvs/src/classify.c
deleted file mode 100644
index 28d7263e2a13..000000000000
--- a/contrib/cvs/src/classify.c
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "cvs.h"
-
-static void sticky_ck PROTO ((struct file_info *finfo, int aflag,
- Vers_TS * vers));
-
-
-
-static inline int keywords_may_change PROTO ((int aflag, Vers_TS * vers));
-static inline int
-keywords_may_change (aflag, vers)
- int aflag;
- Vers_TS * vers;
-{
- int retval;
-
- if (/* Options are different... */
- strcmp (vers->entdata->options, vers->options)
- /* ...or... */
- || (/* ...clearing stickies... */
- aflag
- /* ...and... */
- && (/* ...there used to be a tag which subs in Name keys... */
- (vers->entdata->tag && !isdigit (vers->entdata->tag[0])
- && vers->tag && !isdigit (vers->tag[0])
- && strcmp (vers->entdata->tag, vers->tag))
- /* ...or there used to be a keyword mode which may be
- * changed by -A...
- */
- || (strlen (vers->entdata->options)
- && strcmp (vers->entdata->options, vers->options)
- && strcmp (vers->entdata->options, "-kkv")
- && strcmp (vers->entdata->options, "-kb"))))
- /* ...or... */
- || (/* ...this is not commit... */
- strcmp (cvs_cmd_name, "commit")
- /* ...and... */
- && (/* ...the tag is changing in a way that affects Name keys... */
- (vers->entdata->tag && vers->tag
- && strcmp (vers->entdata->tag, vers->tag)
- && !(isdigit (vers->entdata->tag[0])
- && isdigit (vers->entdata->tag[0])))
- || (!vers->entdata->tag && vers->tag
- && !isdigit (vers->tag[0])))))
- retval = 1;
- else
- retval = 0;
-
- return retval;
-}
-
-
-
-/*
- * Classify the state of a file
- */
-Ctype
-Classify_File (finfo, tag, date, options, force_tag_match, aflag, versp,
- pipeout)
- struct file_info *finfo;
- char *tag;
- char *date;
-
- /* Keyword expansion options. Can be either NULL or "" to
- indicate none are specified here. */
- char *options;
-
- int force_tag_match;
- int aflag;
- Vers_TS **versp;
- int pipeout;
-{
- Vers_TS *vers;
- Ctype ret;
-
- /* get all kinds of good data about the file */
- vers = Version_TS (finfo, options, tag, date,
- force_tag_match, 0);
-
- if (vers->vn_user == NULL)
- {
- /* No entry available, ts_rcs is invalid */
- if (vers->vn_rcs == NULL)
- {
- /* there is no RCS file either */
- if (vers->ts_user == NULL)
- {
- /* there is no user file */
- /* FIXME: Why do we skip this message if vers->tag or
- vers->date is set? It causes "cvs update -r tag98 foo"
- to silently do nothing, which is seriously confusing
- behavior. "cvs update foo" gives this message, which
- is what I would expect. */
- if (!force_tag_match || !(vers->tag || vers->date))
- if (!really_quiet)
- error (0, 0, "nothing known about %s", finfo->fullname);
- ret = T_UNKNOWN;
- }
- else
- {
- /* there is a user file */
- /* FIXME: Why do we skip this message if vers->tag or
- vers->date is set? It causes "cvs update -r tag98 foo"
- to silently do nothing, which is seriously confusing
- behavior. "cvs update foo" gives this message, which
- is what I would expect. */
- if (!force_tag_match || !(vers->tag || vers->date))
- if (!really_quiet)
- error (0, 0, "use `%s add' to create an entry for %s",
- program_name, finfo->fullname);
- ret = T_UNKNOWN;
- }
- }
- else if (RCS_isdead (vers->srcfile, vers->vn_rcs))
- {
- /* there is an RCS file, but it's dead */
- if (vers->ts_user == NULL)
- ret = T_UPTODATE;
- else
- {
- error (0, 0, "use `%s add' to create an entry for %s",
- program_name, finfo->fullname);
- ret = T_UNKNOWN;
- }
- }
- else if (!pipeout && vers->ts_user && No_Difference (finfo, vers))
- {
- /* the files were different so it is a conflict */
- if (!really_quiet)
- error (0, 0, "move away %s; it is in the way",
- finfo->fullname);
- ret = T_CONFLICT;
- }
- else
- /* no user file or no difference, just checkout */
- ret = T_CHECKOUT;
- }
- else if (strcmp (vers->vn_user, "0") == 0)
- {
- /* An entry for a new-born file; ts_rcs is dummy */
-
- if (vers->ts_user == NULL)
- {
- if (pipeout)
- {
- ret = T_CHECKOUT;
- }
- else
- {
- /*
- * There is no user file, but there should be one; remove the
- * entry
- */
- if (!really_quiet)
- error (0, 0, "warning: new-born %s has disappeared",
- finfo->fullname);
- ret = T_REMOVE_ENTRY;
- }
- }
- else if (vers->vn_rcs == NULL ||
- RCS_isdead (vers->srcfile, vers->vn_rcs))
- /* No RCS file or RCS file revision is dead */
- ret = T_ADDED;
- else
- {
- if (pipeout)
- {
- ret = T_CHECKOUT;
- }
- else
- {
- if (vers->srcfile->flags & INATTIC
- && vers->srcfile->flags & VALID)
- {
- /* This file has been added on some branch other than
- the one we are looking at. In the branch we are
- looking at, the file was already valid. */
- if (!really_quiet)
- error (0, 0,
- "conflict: %s has been added, but already exists",
- finfo->fullname);
- }
- else
- {
- /*
- * There is an RCS file, so someone else must have checked
- * one in behind our back; conflict
- */
- if (!really_quiet)
- error (0, 0,
- "conflict: %s created independently by second party",
- finfo->fullname);
- }
- ret = T_CONFLICT;
- }
- }
- }
- else if (vers->vn_user[0] == '-')
- {
- /* An entry for a removed file, ts_rcs is invalid */
-
- if (vers->ts_user == NULL)
- {
- /* There is no user file (as it should be) */
-
- if (vers->vn_rcs == NULL
- || RCS_isdead (vers->srcfile, vers->vn_rcs))
- {
-
- /*
- * There is no RCS file; this is all-right, but it has been
- * removed independently by a second party; remove the entry
- */
- ret = T_REMOVE_ENTRY;
- }
- else if (strcmp (vers->vn_rcs, vers->vn_user + 1) == 0)
- /*
- * The RCS file is the same version as the user file was, and
- * that's OK; remove it
- */
- ret = T_REMOVED;
- else if (pipeout)
- /*
- * The RCS file doesn't match the user's file, but it doesn't
- * matter in this case
- */
- ret = T_NEEDS_MERGE;
- else
- {
-
- /*
- * The RCS file is a newer version than the removed user file
- * and this is definitely not OK; make it a conflict.
- */
- if (!really_quiet)
- error (0, 0,
- "conflict: removed %s was modified by second party",
- finfo->fullname);
- ret = T_CONFLICT;
- }
- }
- else
- {
- /* The user file shouldn't be there */
- if (!really_quiet)
- error (0, 0, "%s should be removed and is still there",
- finfo->fullname);
- ret = T_REMOVED;
- }
- }
- else
- {
- /* A normal entry, TS_Rcs is valid */
- if (vers->vn_rcs == NULL || RCS_isdead (vers->srcfile, vers->vn_rcs))
- {
- /* There is no RCS file */
-
- if (vers->ts_user == NULL)
- {
- /* There is no user file, so just remove the entry */
- if (!really_quiet)
- error (0, 0, "warning: %s is not (any longer) pertinent",
- finfo->fullname);
- ret = T_REMOVE_ENTRY;
- }
- else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
- {
-
- /*
- * The user file is still unmodified, so just remove it from
- * the entry list
- */
- if (!really_quiet)
- error (0, 0, "%s is no longer in the repository",
- finfo->fullname);
- ret = T_REMOVE_ENTRY;
- }
- else if (No_Difference (finfo, vers))
- {
- /* they are different -> conflict */
- if (!really_quiet)
- error (0, 0,
- "conflict: %s is modified but no longer in the repository",
- finfo->fullname);
- ret = T_CONFLICT;
- }
- else
- {
- /* they weren't really different */
- if (!really_quiet)
- error (0, 0,
- "warning: %s is not (any longer) pertinent",
- finfo->fullname);
- ret = T_REMOVE_ENTRY;
- }
- }
- else if (strcmp (vers->vn_rcs, vers->vn_user) == 0)
- {
- /* The RCS file is the same version as the user file */
-
- if (vers->ts_user == NULL)
- {
-
- /*
- * There is no user file, so note that it was lost and
- * extract a new version
- */
- /* Comparing the cvs_cmd_name against "update", in
- addition to being an ugly way to operate, means
- that this message does not get printed by the
- server. That might be considered just a straight
- bug, although there is one subtlety: that case also
- gets hit when a patch fails and the client fetches
- a file. I'm not sure there is currently any way
- for the server to distinguish those two cases. */
- if (strcmp (cvs_cmd_name, "update") == 0)
- if (!really_quiet)
- error (0, 0, "warning: %s was lost", finfo->fullname);
- ret = T_CHECKOUT;
- }
- else if (!strcmp (vers->ts_user,
- vers->ts_conflict
- ? vers->ts_conflict : vers->ts_rcs))
- {
-
- /*
- * The user file is still unmodified, so nothing special at
- * all to do -- no lists updated, unless the sticky -k option
- * has changed. If the sticky tag has changed, we just need
- * to re-register the entry
- */
- /* TODO: decide whether we need to check file permissions
- for a mismatch, and return T_CONFLICT if so. */
- if (keywords_may_change (aflag, vers))
- ret = T_PATCH;
- else if (vers->ts_conflict)
- ret = T_CONFLICT;
- else
- {
- ret = T_UPTODATE;
- sticky_ck (finfo, aflag, vers);
- }
- }
- else if (No_Difference (finfo, vers))
- {
-
- /*
- * they really are different; modified if we aren't
- * changing any sticky -k options, else needs merge
- */
-#ifdef XXX_FIXME_WHEN_RCSMERGE_IS_FIXED
- if (strcmp (vers->entdata->options ?
- vers->entdata->options : "", vers->options) == 0)
- ret = T_MODIFIED;
- else
- ret = T_NEEDS_MERGE;
-#else
- /* Files with conflict markers and new timestamps fall through
- * here, but they need to. T_CONFLICT is an error in
- * commit_fileproc, whereas T_CONFLICT with conflict markers
- * is caught but only warned about. Similarly, update_fileproc
- * currently reregisters a file that was conflicted but lost
- * its markers.
- */
- ret = T_MODIFIED;
- sticky_ck (finfo, aflag, vers);
-#endif
- }
- else if (strcmp (vers->entdata->options ?
- vers->entdata->options : "", vers->options) != 0)
- {
- /* file has not changed; check out if -k changed */
- ret = T_CHECKOUT;
- }
- else
- {
-
- /*
- * else -> note that No_Difference will Register the
- * file already for us, using the new tag/date. This
- * is the desired behaviour
- */
- ret = T_UPTODATE;
- }
- }
- else
- {
- /* The RCS file is a newer version than the user file */
-
- if (vers->ts_user == NULL)
- {
- /* There is no user file, so just get it */
-
- /* See comment at other "update" compare, for more
- thoughts on this comparison. */
- if (strcmp (cvs_cmd_name, "update") == 0)
- if (!really_quiet)
- error (0, 0, "warning: %s was lost", finfo->fullname);
- ret = T_CHECKOUT;
- }
- else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
-
- /*
- * The user file is still unmodified, so just get it as well
- */
- ret = T_PATCH;
- else if (No_Difference (finfo, vers))
- /* really modified, needs to merge */
- ret = T_NEEDS_MERGE;
- else
- ret = T_PATCH;
- }
- }
-
- /* free up the vers struct, or just return it */
- if (versp != (Vers_TS **) NULL)
- *versp = vers;
- else
- freevers_ts (&vers);
-
- /* return the status of the file */
- return (ret);
-}
-
-static void
-sticky_ck (finfo, aflag, vers)
- struct file_info *finfo;
- int aflag;
- Vers_TS *vers;
-{
- if (aflag || vers->tag || vers->date)
- {
- char *enttag = vers->entdata->tag;
- char *entdate = vers->entdata->date;
-
- if ((enttag && vers->tag && strcmp (enttag, vers->tag)) ||
- ((enttag && !vers->tag) || (!enttag && vers->tag)) ||
- (entdate && vers->date && strcmp (entdate, vers->date)) ||
- ((entdate && !vers->date) || (!entdate && vers->date)))
- {
- Register (finfo->entries, finfo->file, vers->vn_user, vers->ts_rcs,
- vers->options, vers->tag, vers->date, vers->ts_conflict);
-
-#ifdef SERVER_SUPPORT
- if (server_active)
- {
- /* We need to update the entries line on the client side.
- It is possible we will later update it again via
- server_updated or some such, but that is OK. */
- server_update_entries
- (finfo->file, finfo->update_dir, finfo->repository,
- strcmp (vers->ts_rcs, vers->ts_user) == 0 ?
- SERVER_UPDATED : SERVER_MERGED);
- }
-#endif
- }
- }
-}
diff --git a/contrib/cvs/src/client.c b/contrib/cvs/src/client.c
deleted file mode 100644
index 1c8a5d0971e6..000000000000
--- a/contrib/cvs/src/client.c
+++ /dev/null
@@ -1,5948 +0,0 @@
-/* CVS client-related stuff.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-/*
- * $FreeBSD$
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include <assert.h>
-#include "cvs.h"
-#include "getline.h"
-#include "edit.h"
-#include "buffer.h"
-#include "savecwd.h"
-
-#ifdef CLIENT_SUPPORT
-
-# include "md5.h"
-
-# if defined(AUTH_CLIENT_SUPPORT) || defined(HAVE_KERBEROS) || defined(HAVE_GSSAPI) || defined(SOCK_ERRNO) || defined(SOCK_STRERROR)
-# ifdef HAVE_WINSOCK_H
-# include <winsock.h>
-# else /* No winsock.h */
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-# include <netdb.h>
-# endif /* No winsock.h */
-# endif
-
-/* If SOCK_ERRNO is defined, then send()/recv() and other socket calls
- do not set errno, but that this macro should be used to obtain an
- error code. This probably doesn't make sense unless
- NO_SOCKET_TO_FD is also defined. */
-# ifndef SOCK_ERRNO
-# define SOCK_ERRNO errno
-# endif
-
-/* If SOCK_STRERROR is defined, then the error codes returned by
- socket operations are not known to strerror, and this macro must be
- used instead to convert those error codes to strings. */
-# ifndef SOCK_STRERROR
-# define SOCK_STRERROR strerror
-
-# if STDC_HEADERS
-# include <string.h>
-# endif
-
-# ifndef strerror
-extern char *strerror ();
-# endif
-# endif /* ! SOCK_STRERROR */
-
-# if HAVE_KERBEROS
-
-# include <krb.h>
-
-extern char *krb_realmofhost ();
-# ifndef HAVE_KRB_GET_ERR_TEXT
-# define krb_get_err_text(status) krb_err_txt[status]
-# endif /* HAVE_KRB_GET_ERR_TEXT */
-
-/* Information we need if we are going to use Kerberos encryption. */
-static C_Block kblock;
-static Key_schedule sched;
-
-# endif /* HAVE_KERBEROS */
-
-# ifdef HAVE_GSSAPI
-
-# include "xgssapi.h"
-
-/* This is needed for GSSAPI encryption. */
-static gss_ctx_id_t gcontext;
-
-static int connect_to_gserver PROTO((cvsroot_t *, int, struct hostent *));
-
-# endif /* HAVE_GSSAPI */
-
-
-
-/* Keep track of any paths we are sending for Max-dotdot so that we can verify
- * that uplevel paths coming back form the server are valid.
- *
- * FIXME: The correct way to do this is probably provide some sort of virtual
- * path map on the client side. This would be generic enough to be applied to
- * absolute paths supplied by the user too.
- */
-static List *uppaths = NULL;
-
-
-
-static void add_prune_candidate PROTO((const char *));
-
-/* All the commands. */
-int add PROTO((int argc, char **argv));
-int admin PROTO((int argc, char **argv));
-int checkout PROTO((int argc, char **argv));
-int commit PROTO((int argc, char **argv));
-int diff PROTO((int argc, char **argv));
-int history PROTO((int argc, char **argv));
-int import PROTO((int argc, char **argv));
-int cvslog PROTO((int argc, char **argv));
-int patch PROTO((int argc, char **argv));
-int release PROTO((int argc, char **argv));
-int cvsremove PROTO((int argc, char **argv));
-int rtag PROTO((int argc, char **argv));
-int status PROTO((int argc, char **argv));
-int tag PROTO((int argc, char **argv));
-int update PROTO((int argc, char **argv));
-
-/* All the response handling functions. */
-static void handle_ok PROTO((char *, int));
-static void handle_error PROTO((char *, int));
-static void handle_valid_requests PROTO((char *, int));
-static void handle_checked_in PROTO((char *, int));
-static void handle_new_entry PROTO((char *, int));
-static void handle_checksum PROTO((char *, int));
-static void handle_copy_file PROTO((char *, int));
-static void handle_updated PROTO((char *, int));
-static void handle_merged PROTO((char *, int));
-static void handle_patched PROTO((char *, int));
-static void handle_rcs_diff PROTO((char *, int));
-static void handle_removed PROTO((char *, int));
-static void handle_remove_entry PROTO((char *, int));
-static void handle_set_static_directory PROTO((char *, int));
-static void handle_clear_static_directory PROTO((char *, int));
-static void handle_set_sticky PROTO((char *, int));
-static void handle_clear_sticky PROTO((char *, int));
-static void handle_module_expansion PROTO((char *, int));
-static void handle_wrapper_rcs_option PROTO((char *, int));
-static void handle_m PROTO((char *, int));
-static void handle_e PROTO((char *, int));
-static void handle_f PROTO((char *, int));
-static void handle_notified PROTO((char *, int));
-
-static size_t try_read_from_server PROTO ((char *, size_t));
-
-static void auth_server PROTO ((cvsroot_t *, struct buffer *, struct buffer *,
- int, int, struct hostent *));
-
-/* 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 = xstrdup (d); /* this argv element */
- int retval;
-
- /* 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. */
-
- strip_trailing_slashes (this_argv_elem);
- if (strncmp (directory, this_argv_elem, strlen (this_argv_elem)) == 0)
- retval = 1;
- else
- retval = 0;
-
- free (this_argv_elem);
- return retval;
-}
-
-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.
-
- */
-
- 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, *root_string;
- cvsroot_t *this_root = NULL;
-
- /* 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);
- root_string = this_root->original;
- *t = c;
- }
- else
- {
- /* We're at the beginning of the string. Look at the
- CVSADM files in cwd. */
- if (CVSroot_cmdline)
- root_string = CVSroot_cmdline;
- else
- {
- this_root = Name_Root ((char *) NULL, (char *) NULL);
- root_string = this_root->original;
- }
- }
-
- /* Now check the value for root. */
- if (CVSroot_cmdline == NULL &&
- root_string && current_parsed_root
- && (strcmp (root_string, current_parsed_root->original) != 0))
- {
- /* Don't send this, since the CVSROOTs don't match. */
- if (this_root) free_cvsroot_t (this_root);
- return 1;
- }
- if (this_root) free_cvsroot_t (this_root);
- }
-
- /* OK, let's send it. */
- return 0;
-}
-
-
-
-#endif /* CLIENT_SUPPORT */
-
-
-
-#if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT)
-
-/* Shared with server. */
-
-/*
- * Return a malloc'd, '\0'-terminated string
- * corresponding to the mode in SB.
- */
-char *
-#ifdef __STDC__
-mode_to_string (mode_t mode)
-#else /* ! __STDC__ */
-mode_to_string (mode)
- mode_t mode;
-#endif /* __STDC__ */
-{
- char buf[18], u[4], g[4], o[4];
- int i;
-
- i = 0;
- if (mode & S_IRUSR) u[i++] = 'r';
- if (mode & S_IWUSR) u[i++] = 'w';
- if (mode & S_IXUSR) u[i++] = 'x';
- u[i] = '\0';
-
- i = 0;
- if (mode & S_IRGRP) g[i++] = 'r';
- if (mode & S_IWGRP) g[i++] = 'w';
- if (mode & S_IXGRP) g[i++] = 'x';
- g[i] = '\0';
-
- i = 0;
- if (mode & S_IROTH) o[i++] = 'r';
- if (mode & S_IWOTH) o[i++] = 'w';
- if (mode & S_IXOTH) o[i++] = 'x';
- o[i] = '\0';
-
- sprintf(buf, "u=%s,g=%s,o=%s", u, g, o);
- return xstrdup(buf);
-}
-
-/*
- * Change mode of FILENAME to MODE_STRING.
- * Returns 0 for success or errno code.
- * If RESPECT_UMASK is set, then honor the umask.
- */
-int
-change_mode (filename, mode_string, respect_umask)
- char *filename;
- char *mode_string;
- int respect_umask;
-{
-#ifdef CHMOD_BROKEN
- char *p;
- int writeable = 0;
-
- /* We can only distinguish between
- 1) readable
- 2) writeable
- 3) Picasso's "Blue Period"
- We handle the first two. */
- p = mode_string;
- while (*p != '\0')
- {
- if ((p[0] == 'u' || p[0] == 'g' || p[0] == 'o') && p[1] == '=')
- {
- char *q = p + 2;
- while (*q != ',' && *q != '\0')
- {
- if (*q == 'w')
- writeable = 1;
- ++q;
- }
- }
- /* Skip to the next field. */
- while (*p != ',' && *p != '\0')
- ++p;
- if (*p == ',')
- ++p;
- }
-
- /* xchmod honors the umask for us. In the !respect_umask case, we
- don't try to cope with it (probably to handle that well, the server
- needs to deal with modes in data structures, rather than via the
- modes in temporary files). */
- xchmod (filename, writeable);
- return 0;
-
-#else /* ! CHMOD_BROKEN */
-
- char *p;
- mode_t mode = 0;
- mode_t oumask;
-
- p = mode_string;
- while (*p != '\0')
- {
- if ((p[0] == 'u' || p[0] == 'g' || p[0] == 'o') && p[1] == '=')
- {
- int can_read = 0, can_write = 0, can_execute = 0;
- char *q = p + 2;
- while (*q != ',' && *q != '\0')
- {
- if (*q == 'r')
- can_read = 1;
- else if (*q == 'w')
- can_write = 1;
- else if (*q == 'x')
- can_execute = 1;
- ++q;
- }
- if (p[0] == 'u')
- {
- if (can_read)
- mode |= S_IRUSR;
- if (can_write)
- mode |= S_IWUSR;
- if (can_execute)
- mode |= S_IXUSR;
- }
- else if (p[0] == 'g')
- {
- if (can_read)
- mode |= S_IRGRP;
- if (can_write)
- mode |= S_IWGRP;
- if (can_execute)
- mode |= S_IXGRP;
- }
- else if (p[0] == 'o')
- {
- if (can_read)
- mode |= S_IROTH;
- if (can_write)
- mode |= S_IWOTH;
- if (can_execute)
- mode |= S_IXOTH;
- }
- }
- /* Skip to the next field. */
- while (*p != ',' && *p != '\0')
- ++p;
- if (*p == ',')
- ++p;
- }
-
- if (respect_umask)
- {
- oumask = umask (0);
- (void) umask (oumask);
- mode &= ~oumask;
- }
-
- if (chmod (filename, mode) < 0)
- return errno;
- return 0;
-#endif /* ! CHMOD_BROKEN */
-}
-
-#endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
-
-#ifdef CLIENT_SUPPORT
-
-int client_prune_dirs;
-
-static List *ignlist = (List *) NULL;
-
-/* Buffer to write to the server. */
-static struct buffer *to_server;
-
-/* Buffer used to read from the server. */
-static struct buffer *from_server;
-
-
-/* We want to be able to log data sent between us and the server. We
- do it using log buffers. Each log buffer has another buffer which
- handles the actual I/O, and a file to log information to.
-
- This structure is the closure field of a log buffer. */
-
-struct log_buffer
-{
- /* The underlying buffer. */
- struct buffer *buf;
- /* The file to log information to. */
- FILE *log;
-};
-
-static struct buffer *log_buffer_initialize
- PROTO((struct buffer *, FILE *, int, void (*) (struct buffer *)));
-static int log_buffer_input PROTO((void *, char *, int, int, int *));
-static int log_buffer_output PROTO((void *, const char *, int, int *));
-static int log_buffer_flush PROTO((void *));
-static int log_buffer_block PROTO((void *, int));
-static int log_buffer_shutdown PROTO((struct buffer *));
-
-/* Create a log buffer. */
-
-static struct buffer *
-log_buffer_initialize (buf, fp, input, memory)
- struct buffer *buf;
- FILE *fp;
- int input;
- void (*memory) PROTO((struct buffer *));
-{
- struct log_buffer *n;
-
- n = (struct log_buffer *) xmalloc (sizeof *n);
- n->buf = buf;
- n->log = fp;
- return buf_initialize (input ? log_buffer_input : NULL,
- input ? NULL : log_buffer_output,
- input ? NULL : log_buffer_flush,
- log_buffer_block,
- log_buffer_shutdown,
- memory,
- n);
-}
-
-/* The input function for a log buffer. */
-
-static int
-log_buffer_input (closure, data, need, size, got)
- void *closure;
- char *data;
- int need;
- int size;
- int *got;
-{
- struct log_buffer *lb = (struct log_buffer *) closure;
- int status;
- size_t n_to_write;
-
- if (lb->buf->input == NULL)
- abort ();
-
- status = (*lb->buf->input) (lb->buf->closure, data, need, size, got);
- if (status != 0)
- return status;
-
- if (*got > 0)
- {
- n_to_write = *got;
- if (fwrite (data, 1, n_to_write, lb->log) != n_to_write)
- error (0, errno, "writing to log file");
- }
-
- return 0;
-}
-
-/* The output function for a log buffer. */
-
-static int
-log_buffer_output (closure, data, have, wrote)
- void *closure;
- const char *data;
- int have;
- int *wrote;
-{
- struct log_buffer *lb = (struct log_buffer *) closure;
- int status;
- size_t n_to_write;
-
- if (lb->buf->output == NULL)
- abort ();
-
- status = (*lb->buf->output) (lb->buf->closure, data, have, wrote);
- if (status != 0)
- return status;
-
- if (*wrote > 0)
- {
- n_to_write = *wrote;
- if (fwrite (data, 1, n_to_write, lb->log) != n_to_write)
- error (0, errno, "writing to log file");
- }
-
- return 0;
-}
-
-/* The flush function for a log buffer. */
-
-static int
-log_buffer_flush (closure)
- void *closure;
-{
- struct log_buffer *lb = (struct log_buffer *) closure;
-
- if (lb->buf->flush == NULL)
- abort ();
-
- /* We don't really have to flush the log file here, but doing it
- will let tail -f on the log file show what is sent to the
- network as it is sent. */
- if (fflush (lb->log) != 0)
- error (0, errno, "flushing log file");
-
- return (*lb->buf->flush) (lb->buf->closure);
-}
-
-/* The block function for a log buffer. */
-
-static int
-log_buffer_block (closure, block)
- void *closure;
- int block;
-{
- struct log_buffer *lb = (struct log_buffer *) closure;
-
- if (block)
- return set_block (lb->buf);
- else
- return set_nonblock (lb->buf);
-}
-
-/* The shutdown function for a log buffer. */
-
-static int
-log_buffer_shutdown (buf)
- struct buffer *buf;
-{
- struct log_buffer *lb = (struct log_buffer *) buf->closure;
- int retval;
-
- retval = buf_shutdown (lb->buf);
- if (fclose (lb->log) < 0)
- error (0, errno, "closing log file");
- return retval;
-}
-
-#ifdef NO_SOCKET_TO_FD
-
-/* Under certain circumstances, we must communicate with the server
- via a socket using send() and recv(). This is because under some
- operating systems (OS/2 and Windows 95 come to mind), a socket
- cannot be converted to a file descriptor -- it must be treated as a
- socket and nothing else.
-
- We may also need to deal with socket routine error codes differently
- in these cases. This is handled through the SOCK_ERRNO and
- SOCK_STRERROR macros. */
-
-/* These routines implement a buffer structure which uses send and
- recv. The buffer is always in blocking mode so we don't implement
- the block routine. */
-
-/* Note that it is important that these routines always handle errors
- internally and never return a positive errno code, since it would in
- general be impossible for the caller to know in general whether any
- error code came from a socket routine (to decide whether to use
- SOCK_STRERROR or simply strerror to print an error message). */
-
-/* We use an instance of this structure as the closure field. */
-
-struct socket_buffer
-{
- /* The socket number. */
- int socket;
-};
-
-static struct buffer *socket_buffer_initialize
- PROTO ((int, int, void (*) (struct buffer *)));
-static int socket_buffer_input PROTO((void *, char *, int, int, int *));
-static int socket_buffer_output PROTO((void *, const char *, int, int *));
-static int socket_buffer_flush PROTO((void *));
-static int socket_buffer_shutdown PROTO((struct buffer *));
-
-
-
-/* Create a buffer based on a socket. */
-
-static struct buffer *
-socket_buffer_initialize (socket, input, memory)
- int socket;
- int input;
- void (*memory) PROTO((struct buffer *));
-{
- struct socket_buffer *n;
-
- n = (struct socket_buffer *) xmalloc (sizeof *n);
- n->socket = socket;
- return buf_initialize (input ? socket_buffer_input : NULL,
- input ? NULL : socket_buffer_output,
- input ? NULL : socket_buffer_flush,
- (int (*) PROTO((void *, int))) NULL,
- socket_buffer_shutdown,
- memory,
- n);
-}
-
-
-
-/* The buffer input function for a buffer built on a socket. */
-
-static int
-socket_buffer_input (closure, data, need, size, got)
- void *closure;
- char *data;
- int need;
- int size;
- int *got;
-{
- struct socket_buffer *sb = (struct socket_buffer *) closure;
- int nbytes;
-
- /* I believe that the recv function gives us exactly the semantics
- we want. If there is a message, it returns immediately with
- whatever it could get. If there is no message, it waits until
- one comes in. In other words, it is not like read, which in
- blocking mode normally waits until all the requested data is
- available. */
-
- *got = 0;
-
- do
- {
-
- /* Note that for certain (broken?) networking stacks, like
- VMS's UCX (not sure what version, problem reported with
- recv() in 1997), and (according to windows-NT/config.h)
- Windows NT 3.51, we must call recv or send with a
- moderately sized buffer (say, less than 200K or something),
- or else there may be network errors (somewhat hard to
- produce, e.g. WAN not LAN or some such). buf_read_data
- makes sure that we only recv() BUFFER_DATA_SIZE bytes at
- a time. */
-
- nbytes = recv (sb->socket, data, size, 0);
- if (nbytes < 0)
- error (1, 0, "reading from server: %s", SOCK_STRERROR (SOCK_ERRNO));
- if (nbytes == 0)
- {
- /* End of file (for example, the server has closed
- the connection). If we've already read something, we
- just tell the caller about the data, not about the end of
- file. If we've read nothing, we return end of file. */
- if (*got == 0)
- return -1;
- else
- return 0;
- }
- need -= nbytes;
- size -= nbytes;
- data += nbytes;
- *got += nbytes;
- }
- while (need > 0);
-
- return 0;
-}
-
-
-
-/* The buffer output function for a buffer built on a socket. */
-
-static int
-socket_buffer_output (closure, data, have, wrote)
- void *closure;
- const char *data;
- int have;
- int *wrote;
-{
- struct socket_buffer *sb = (struct socket_buffer *) closure;
-
- *wrote = have;
-
- /* See comment in socket_buffer_input regarding buffer size we pass
- to send and recv. */
-
-#ifdef SEND_NEVER_PARTIAL
- /* If send() never will produce a partial write, then just do it. This
- is needed for systems where its return value is something other than
- the number of bytes written. */
- if (send (sb->socket, data, have, 0) < 0)
- error (1, 0, "writing to server socket: %s", SOCK_STRERROR (SOCK_ERRNO));
-#else
- while (have > 0)
- {
- int nbytes;
-
- nbytes = send (sb->socket, data, have, 0);
- if (nbytes < 0)
- error (1, 0, "writing to server socket: %s", SOCK_STRERROR (SOCK_ERRNO));
-
- have -= nbytes;
- data += nbytes;
- }
-#endif
-
- return 0;
-}
-
-
-
-/* The buffer flush function for a buffer built on a socket. */
-
-/*ARGSUSED*/
-static int
-socket_buffer_flush (closure)
- void *closure;
-{
- /* Nothing to do. Sockets are always flushed. */
- return 0;
-}
-
-
-
-static int
-socket_buffer_shutdown (buf)
- struct buffer *buf;
-{
- struct socket_buffer *n = (struct socket_buffer *) buf->closure;
- char tmp;
-
- /* no need to flush children of an endpoint buffer here */
-
- if (buf->input)
- {
- int err = 0;
- if (! buf_empty_p (buf)
- || (err = recv (n->socket, &tmp, 1, 0)) > 0)
- error (0, 0, "dying gasps from %s unexpected", current_parsed_root->hostname);
- else if (err == -1)
- error (0, 0, "reading from %s: %s", current_parsed_root->hostname, SOCK_STRERROR (SOCK_ERRNO));
-
- /* shutdown() socket */
-# ifdef SHUTDOWN_SERVER
- if (current_parsed_root->method != server_method)
-# endif
- if (shutdown (n->socket, 0) < 0)
- {
- error (1, 0, "shutting down server socket: %s", SOCK_STRERROR (SOCK_ERRNO));
- }
-
- buf->input = NULL;
- }
- else if (buf->output)
- {
- /* shutdown() socket */
-# ifdef SHUTDOWN_SERVER
- /* FIXME: Should have a SHUTDOWN_SERVER_INPUT &
- * SHUTDOWN_SERVER_OUTPUT
- */
- if (current_parsed_root->method == server_method)
- SHUTDOWN_SERVER (n->socket);
- else
-# endif
- if (shutdown (n->socket, 1) < 0)
- {
- error (1, 0, "shutting down server socket: %s", SOCK_STRERROR (SOCK_ERRNO));
- }
-
- buf->output = NULL;
- }
-
- return 0;
-}
-
-#endif /* NO_SOCKET_TO_FD */
-
-/*
- * Read a line from the server. Result does not include the terminating \n.
- *
- * Space for the result is malloc'd and should be freed by the caller.
- *
- * Returns number of bytes read.
- */
-static int
-read_line (resultp)
- char **resultp;
-{
- int status;
- char *result;
- int len;
-
- status = buf_flush (to_server, 1);
- if (status != 0)
- error (1, status, "writing to server");
-
- status = buf_read_line (from_server, &result, &len);
- if (status != 0)
- {
- if (status == -1)
- error (1, 0, "end of file from server (consult above messages if any)");
- else if (status == -2)
- error (1, 0, "out of memory");
- else
- error (1, status, "reading from server");
- }
-
- if (resultp != NULL)
- *resultp = result;
- else
- free (result);
-
- return len;
-}
-
-#endif /* CLIENT_SUPPORT */
-
-
-#if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT)
-
-/*
- * Level of compression to use when running gzip on a single file.
- */
-int file_gzip_level;
-
-#endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
-
-#ifdef CLIENT_SUPPORT
-
-/*
- * 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 = 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
- storing a name. */
-char *toplevel_wd;
-
-static void
-handle_ok (args, len)
- char *args;
- int len;
-{
- return;
-}
-
-static void
-handle_error (args, len)
- char *args;
- int len;
-{
- int something_printed;
-
- /*
- * First there is a symbolic error code followed by a space, which
- * we ignore.
- */
- char *p = strchr (args, ' ');
- if (p == NULL)
- {
- error (0, 0, "invalid data from cvs server");
- 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)
- {
- something_printed = 1;
- putc (*p++, stderr);
- }
- if (something_printed)
- putc ('\n', stderr);
-}
-
-static void
-handle_valid_requests (args, len)
- char *args;
- int len;
-{
- char *p = args;
- char *q;
- struct request *rq;
- do
- {
- q = strchr (p, ' ');
- if (q != NULL)
- *q++ = '\0';
- for (rq = requests; rq->name != NULL; ++rq)
- {
- if (strcmp (rq->name, p) == 0)
- break;
- }
- if (rq->name == NULL)
- /*
- * It is a request we have never heard of (and thus never
- * will want to use). So don't worry about it.
- */
- ;
- else
- {
- if (rq->flags & RQ_ENABLEME)
- {
- /*
- * Server wants to know if we have this, to enable the
- * feature.
- */
- send_to_server (rq->name, 0);
- send_to_server ("\012", 0);
- }
- else
- rq->flags |= RQ_SUPPORTED;
- }
- p = q;
- } while (q != NULL);
- for (rq = requests; rq->name != NULL; ++rq)
- {
- 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);
- }
-}
-
-
-
-/*
- * This is a proc for walklist(). It inverts the error return premise of
- * walklist.
- *
- * RETURNS
- * True If this path is prefixed by one of the paths in walklist and
- * does not step above the prefix path.
- * False Otherwise.
- */
-static
-int path_list_prefixed (p, closure)
- Node *p;
- void *closure;
-{
- const char *questionable = closure;
- const char *prefix = p->key;
- if (strncmp (prefix, questionable, strlen (prefix))) return 0;
- questionable += strlen (prefix);
- while (ISDIRSEP (*questionable)) questionable++;
- if (*questionable == '\0') return 1;
- return pathname_levels (questionable);
-}
-
-
-
-/*
- * Need to validate the client pathname. Disallowed paths include:
- *
- * 1. Absolute paths.
- * 2. Pathnames that do not reference a specifically requested update
- * directory.
- *
- * In case 2, we actually only check that the directory is under the uppermost
- * directories mentioned on the command line.
- *
- * RETURNS
- * True If the path is valid.
- * False Otherwise.
- */
-static
-int is_valid_client_path (pathname)
- const char *pathname;
-{
- /* 1. Absolute paths. */
- if (isabsolute (pathname)) return 0;
- /* 2. No up-references in path. */
- if (pathname_levels (pathname) == 0) return 1;
- /* 2. No Max-dotdot paths registered. */
- if (uppaths == NULL) return 0;
-
- return walklist (uppaths, path_list_prefixed, (void *)pathname);
-}
-
-
-
-/*
- * Do all the processing for PATHNAME, where pathname consists of the
- * repository and the filename. The parameters we pass to FUNC are:
- * DATA is just the DATA parameter which was passed to
- * call_in_directory; ENT_LIST is a pointer to an entries list (which
- * we manage the storage for); SHORT_PATHNAME is the pathname of the
- * file relative to the (overall) directory in which the command is
- * taking place; and FILENAME is the filename portion only of
- * SHORT_PATHNAME. When we call FUNC, the curent directory points to
- * the directory portion of SHORT_PATHNAME. */
-
-static void
-call_in_directory (pathname, func, data)
- char *pathname;
- void (*func) PROTO((char *data, List *ent_list, char *short_pathname,
- char *filename));
- char *data;
-{
- /* This variable holds the result of Entries_Open. */
- List *last_entries = NULL;
- char *dir_name;
- char *filename;
- /* This is what we get when we hook up the directory (working directory
- name) from PATHNAME with the filename from REPOSNAME. For example:
- pathname: ccvs/src/
- reposname: /u/src/master/ccvs/foo/ChangeLog
- short_pathname: ccvs/src/ChangeLog
- */
- char *short_pathname;
- char *p;
-
- /*
- * Do the whole descent in parallel for the repositories, so we
- * know what to put in CVS/Repository files. I'm not sure the
- * full hair is necessary since the server does a similar
- * computation; I suspect that we only end up creating one
- * directory at a time anyway.
- *
- * Also note that we must *only* worry about this stuff when we
- * are creating directories; `cvs co foo/bar; cd foo/bar; cvs co
- * CVSROOT; cvs update' is legitimate, but in this case
- * foo/bar/CVSROOT/CVS/Repository is not a subdirectory of
- * foo/bar/CVS/Repository.
- */
- char *reposname;
- char *short_repos;
- char *reposdirname;
- char *rdirp;
- int reposdirname_absolute;
- int newdir = 0;
-
- assert (pathname);
-
- reposname = NULL;
- read_line (&reposname);
- assert (reposname != NULL);
-
- reposdirname_absolute = 0;
- if (strncmp (reposname, toplevel_repos, strlen (toplevel_repos)) != 0)
- {
- reposdirname_absolute = 1;
- short_repos = reposname;
- }
- else
- {
- short_repos = reposname + strlen (toplevel_repos) + 1;
- if (short_repos[-1] != '/')
- {
- reposdirname_absolute = 1;
- short_repos = reposname;
- }
- }
-
- /* Now that we have SHORT_REPOS, we can calculate the path to the file we
- * are being requested to operate on.
- */
- filename = strrchr (short_repos, '/');
- if (filename == NULL)
- filename = short_repos;
- else
- ++filename;
-
- short_pathname = xmalloc (strlen (pathname) + strlen (filename) + 5);
- strcpy (short_pathname, pathname);
- strcat (short_pathname, filename);
-
- /* Now that we know the path to the file we were requested to operate on,
- * we can verify that it is valid.
- *
- * For security reasons, if SHORT_PATHNAME is absolute or attempts to
- * ascend outside of the current sanbbox, we abort. The server should not
- * send us anything but relative paths which remain inside the sandbox
- * here. Anything less means a trojan CVS server could create and edit
- * arbitrary files on the client.
- */
- if (!is_valid_client_path (short_pathname))
- {
- error (0, 0,
- "Server attempted to update a file via an invalid pathname:");
- error (1, 0, "`%s'.", short_pathname);
- }
-
- reposdirname = xstrdup (short_repos);
- p = strrchr (reposdirname, '/');
- if (p == NULL)
- {
- reposdirname = xrealloc (reposdirname, 2);
- reposdirname[0] = '.'; reposdirname[1] = '\0';
- }
- else
- *p = '\0';
-
- dir_name = xstrdup (pathname);
- p = strrchr (dir_name, '/');
- if (p == NULL)
- {
- dir_name = xrealloc (dir_name, 2);
- dir_name[0] = '.'; dir_name[1] = '\0';
- }
- else
- *p = '\0';
- if (client_prune_dirs)
- add_prune_candidate (dir_name);
-
- if (toplevel_wd == NULL)
- {
- toplevel_wd = xgetwd ();
- if (toplevel_wd == NULL)
- error (1, errno, "could not get working directory");
- }
-
- if (CVS_CHDIR (toplevel_wd) < 0)
- error (1, errno, "could not chdir to %s", toplevel_wd);
-
- if (CVS_CHDIR (dir_name) < 0)
- {
- char *dir;
- char *dirp;
-
- if (! existence_error (errno))
- error (1, errno, "could not chdir to %s", dir_name);
-
- /* Directory does not exist, we need to create it. */
- newdir = 1;
-
- /* Provided we are willing to assume that directories get
- created one at a time, we could simplify this a lot.
- Do note that one aspect still would need to walk the
- dir_name path: the checking for "fncmp (dir, CVSADM)". */
-
- dir = xmalloc (strlen (dir_name) + 1);
- dirp = dir_name;
- rdirp = reposdirname;
-
- /* This algorithm makes nested directories one at a time
- and create CVS administration files in them. For
- example, we're checking out foo/bar/baz from the
- repository:
-
- 1) create foo, point CVS/Repository to <root>/foo
- 2) .. foo/bar .. <root>/foo/bar
- 3) .. foo/bar/baz .. <root>/foo/bar/baz
-
- As you can see, we're just stepping along DIR_NAME (with
- DIRP) and REPOSDIRNAME (with RDIRP) respectively.
-
- We need to be careful when we are checking out a
- module, however, since DIR_NAME and REPOSDIRNAME are not
- going to be the same. Since modules will not have any
- slashes in their names, we should watch the output of
- STRCHR to decide whether or not we should use STRCHR on
- the RDIRP. That is, if we're down to a module name,
- don't keep picking apart the repository directory name. */
-
- do
- {
- dirp = strchr (dirp, '/');
- if (dirp)
- {
- strncpy (dir, dir_name, dirp - dir_name);
- dir[dirp - dir_name] = '\0';
- /* Skip the slash. */
- ++dirp;
- if (rdirp == NULL)
- /* This just means that the repository string has
- fewer components than the dir_name string. But
- that is OK (e.g. see modules3-8 in testsuite). */
- ;
- else
- rdirp = strchr (rdirp, '/');
- }
- else
- {
- /* If there are no more slashes in the dir name,
- we're down to the most nested directory -OR- to
- the name of a module. In the first case, we
- should be down to a DIRP that has no slashes,
- so it won't help/hurt to do another STRCHR call
- on DIRP. It will definitely hurt, however, if
- we're down to a module name, since a module
- name can point to a nested directory (that is,
- DIRP will still have slashes in it. Therefore,
- we should set it to NULL so the routine below
- copies the contents of REMOTEDIRNAME onto the
- root repository directory (does this if rdirp
- is set to NULL, because we used to do an extra
- STRCHR call here). */
-
- rdirp = NULL;
- strcpy (dir, dir_name);
- }
-
- if (fncmp (dir, CVSADM) == 0)
- {
- error (0, 0, "cannot create a directory named %s", dir);
- error (0, 0, "because CVS uses \"%s\" for its own uses",
- CVSADM);
- error (1, 0, "rename the directory and try again");
- }
-
- if (mkdir_if_needed (dir))
- {
- /* It already existed, fine. Just keep going. */
- }
- else if (strcmp (cvs_cmd_name, "export") == 0)
- /* Don't create CVSADM directories if this is export. */
- ;
- else
- {
- /*
- * Put repository in CVS/Repository. For historical
- * (pre-CVS/Root) reasons, this is an absolute pathname,
- * but what really matters is the part of it which is
- * relative to cvsroot.
- */
- char *repo;
- char *r, *b;
-
- repo = xmalloc (strlen (reposdirname)
- + strlen (toplevel_repos)
- + 80);
- if (reposdirname_absolute)
- r = repo;
- else
- {
- strcpy (repo, toplevel_repos);
- strcat (repo, "/");
- r = repo + strlen (repo);
- }
-
- if (rdirp)
- {
- /* See comment near start of function; the only
- way that the server can put the right thing
- in each CVS/Repository file is to create the
- directories one at a time. I think that the
- CVS server has been doing this all along. */
- error (0, 0, "\
-warning: server is not creating directories one at a time");
- strncpy (r, reposdirname, rdirp - reposdirname);
- r[rdirp - reposdirname] = '\0';
- }
- else
- strcpy (r, reposdirname);
-
- Create_Admin (dir, dir, repo,
- (char *)NULL, (char *)NULL, 0, 0, 1);
- free (repo);
-
- b = strrchr (dir, '/');
- if (b == NULL)
- Subdir_Register ((List *) NULL, (char *) NULL, dir);
- else
- {
- *b = '\0';
- Subdir_Register ((List *) NULL, dir, b + 1);
- *b = '/';
- }
- }
-
- if (rdirp != NULL)
- {
- /* Skip the slash. */
- ++rdirp;
- }
-
- } while (dirp != NULL);
- free (dir);
- /* Now it better work. */
- if ( CVS_CHDIR (dir_name) < 0)
- error (1, errno, "could not chdir to %s", dir_name);
- }
- else if (strcmp (cvs_cmd_name, "export") == 0)
- /* Don't create CVSADM directories if this is export. */
- ;
- else if (!isdir (CVSADM))
- {
- /*
- * Put repository in CVS/Repository. For historical
- * (pre-CVS/Root) reasons, this is an absolute pathname,
- * but what really matters is the part of it which is
- * relative to cvsroot.
- */
- char *repo;
-
- if (reposdirname_absolute)
- repo = reposdirname;
- else
- {
- repo = xmalloc (strlen (reposdirname)
- + strlen (toplevel_repos)
- + 10);
- strcpy (repo, toplevel_repos);
- strcat (repo, "/");
- strcat (repo, reposdirname);
- }
-
- Create_Admin (".", ".", repo, (char *)NULL, (char *)NULL, 0, 1, 1);
- if (repo != reposdirname)
- free (repo);
- }
-
- if (strcmp (cvs_cmd_name, "export") != 0)
- {
- last_entries = Entries_Open (0, dir_name);
-
- /* If this is a newly created directory, we will record
- all subdirectory information, so call Subdirs_Known in
- case there are no subdirectories. If this is not a
- newly created directory, it may be an old working
- directory from before we recorded subdirectory
- information in the Entries file. We force a search for
- all subdirectories now, to make sure our subdirectory
- information is up to date. If the Entries file does
- record subdirectory information, then this call only
- does list manipulation. */
- if (newdir)
- Subdirs_Known (last_entries);
- else
- {
- List *dirlist;
-
- dirlist = Find_Directories ((char *) NULL, W_LOCAL,
- last_entries);
- dellist (&dirlist);
- }
- }
- free (reposdirname);
- (*func) (data, last_entries, short_pathname, filename);
- if (last_entries != NULL)
- Entries_Close (last_entries);
- free (dir_name);
- free (short_pathname);
- free (reposname);
-}
-
-static void
-copy_a_file (data, ent_list, short_pathname, filename)
- char *data;
- List *ent_list;
- char *short_pathname;
- char *filename;
-{
- char *newname;
-#ifdef USE_VMS_FILENAMES
- char *p;
-#endif
-
- read_line (&newname);
-
-#ifdef USE_VMS_FILENAMES
- /* Mogrify the filename so VMS is happy with it. */
- 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);
-}
-
-static void
-handle_copy_file (args, len)
- char *args;
- int len;
-{
- call_in_directory (args, copy_a_file, (char *)NULL);
-}
-
-
-
-/* Attempt to read a file size from a string. Accepts base 8 (0N), base 16
- * (0xN), or base 10. Exits on error.
- *
- * RETURNS
- * The file size, in a size_t.
- *
- * FATAL ERRORS
- * 1. As strtoul().
- * 2. If the number read exceeds SIZE_MAX.
- */
-static size_t
-strto_file_size (const char *s)
-{
- unsigned long tmp;
- char *endptr;
-
- /* Read it. */
- errno = 0;
- tmp = strtoul (s, &endptr, 0);
-
- /* Check for errors. */
- if (errno || endptr == s)
- error (1, errno, "Server sent invalid file size `%s'", s);
- if (*endptr != '\0')
- error (1, 0,
- "Server sent trailing characters in file size `%s'",
- endptr);
- if (tmp > SIZE_MAX)
- error (1, 0, "Server sent file size exceeding client max.");
-
- /* Return it. */
- return (size_t)tmp;
-}
-
-
-
-static void read_counted_file PROTO ((char *, char *));
-
-/* Read from the server the count for the length of a file, then read
- the contents of that file and write them to FILENAME. FULLNAME is
- the name of the file for use in error messages. FIXME-someday:
- extend this to deal with compressed files and make update_entries
- use it. On error, gives a fatal error. */
-static void
-read_counted_file (filename, fullname)
- char *filename;
- char *fullname;
-{
- char *size_string;
- size_t size;
- char *buf;
-
- /* Pointers in buf to the place to put data which will be read,
- and the data which needs to be written, respectively. */
- char *pread;
- char *pwrite;
- /* Number of bytes left to read and number of bytes in buf waiting to
- be written, respectively. */
- size_t nread;
- size_t nwrite;
-
- FILE *fp;
-
- read_line (&size_string);
- if (size_string[0] == 'z')
- error (1, 0, "\
-protocol error: compressed files not supported for that operation");
- size = strto_file_size (size_string);
- free (size_string);
-
- /* A more sophisticated implementation would use only a limited amount
- of buffer space (8K perhaps), and read that much at a time. We allocate
- a buffer for the whole file only to make it easy to keep track what
- needs to be read and written. */
- buf = xmalloc (size);
-
- /* FIXME-someday: caller should pass in a flag saying whether it
- is binary or not. I haven't carefully looked into whether
- CVS/Template files should use local text file conventions or
- not. */
- fp = CVS_FOPEN (filename, "wb");
- if (fp == NULL)
- error (1, errno, "cannot write %s", fullname);
- nread = size;
- nwrite = 0;
- pread = buf;
- pwrite = buf;
- while (nread > 0 || nwrite > 0)
- {
- size_t n;
-
- if (nread > 0)
- {
- n = try_read_from_server (pread, nread);
- nread -= n;
- pread += n;
- nwrite += n;
- }
-
- if (nwrite > 0)
- {
- n = fwrite (pwrite, 1, nwrite, fp);
- if (ferror (fp))
- error (1, errno, "cannot write %s", fullname);
- nwrite -= n;
- pwrite += n;
- }
- }
- free (buf);
- if (fclose (fp) < 0)
- error (1, errno, "cannot close %s", fullname);
-}
-
-/* OK, we want to swallow the "U foo.c" response and then output it only
- if we can update the file. In the future we probably want some more
- systematic approach to parsing tagged text, but for now we keep it
- ad hoc. "Why," I hear you cry, "do we not just look at the
- Update-existing and Created responses?" That is an excellent question,
- and the answer is roughly conservatism/laziness--I haven't read through
- update.c enough to figure out the exact correspondence or lack thereof
- between those responses and a "U foo.c" line (note that Merged, from
- join_file, can be either "C foo" or "U foo" depending on the context). */
-/* Nonzero if we have seen +updated and not -updated. */
-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;
-
-
-/*
- * The time stamp of the last file we registered.
- */
-static time_t last_register_time;
-
-/*
- * The Checksum response gives the checksum for the file transferred
- * over by the next Updated, Merged or Patch response. We just store
- * it here, and then check it in update_entries.
- */
-
-static int stored_checksum_valid;
-static unsigned char stored_checksum[16];
-
-static void
-handle_checksum (args, len)
- char *args;
- int len;
-{
- char *s;
- char buf[3];
- int i;
-
- if (stored_checksum_valid)
- error (1, 0, "Checksum received before last one was used");
-
- s = args;
- buf[2] = '\0';
- for (i = 0; i < 16; i++)
- {
- char *bufend;
-
- buf[0] = *s++;
- buf[1] = *s++;
- stored_checksum[i] = (char) strtol (buf, &bufend, 16);
- if (bufend != buf + 2)
- break;
- }
-
- if (i < 16 || *s != '\0')
- error (1, 0, "Invalid Checksum response: `%s'", args);
-
- stored_checksum_valid = 1;
-}
-
-/* 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));
-
-static void
-handle_mode (args, len)
- char *args;
- int len;
-{
- if (stored_mode != NULL)
- error (1, 0, "protocol error: duplicate Mode");
- stored_mode = xstrdup (args);
-}
-
-/* Nonzero if time was specified in Mod-time. */
-static int stored_modtime_valid;
-/* Time specified in Mod-time. */
-static time_t stored_modtime;
-
-static void handle_mod_time PROTO ((char *, int));
-
-static void
-handle_mod_time (args, len)
- char *args;
- int len;
-{
- if (stored_modtime_valid)
- error (0, 0, "protocol error: duplicate Mod-time");
- stored_modtime = get_date (args, NULL);
- if (stored_modtime == (time_t) -1)
- error (0, 0, "protocol error: cannot parse date %s", args);
- else
- stored_modtime_valid = 1;
-}
-
-/*
- * If we receive a patch, but the patch program fails to apply it, we
- * want to request the original file. We keep a list of files whose
- * patches have failed.
- */
-
-char **failed_patches;
-int failed_patches_count;
-
-struct update_entries_data
-{
- enum {
- /*
- * We are just getting an Entries line; the local file is
- * correct.
- */
- UPDATE_ENTRIES_CHECKIN,
- /* We are getting the file contents as well. */
- UPDATE_ENTRIES_UPDATE,
- /*
- * We are getting a patch against the existing local file, not
- * an entire new file.
- */
- UPDATE_ENTRIES_PATCH,
- /*
- * We are getting an RCS change text (diff -n output) against
- * the existing local file, not an entire new file.
- */
- UPDATE_ENTRIES_RCS_DIFF
- } contents;
-
- enum {
- /* We are replacing an existing file. */
- UPDATE_ENTRIES_EXISTING,
- /* We are creating a new file. */
- UPDATE_ENTRIES_NEW,
- /* We don't know whether it is existing or new. */
- UPDATE_ENTRIES_EXISTING_OR_NEW
- } existp;
-
- /*
- * String to put in the timestamp field or NULL to use the timestamp
- * of the file.
- */
- char *timestamp;
-};
-
-/* Update the Entries line for this file. */
-static void
-update_entries (data_arg, ent_list, short_pathname, filename)
- char *data_arg;
- List *ent_list;
- char *short_pathname;
- char *filename;
-{
- char *entries_line;
- struct update_entries_data *data = (struct update_entries_data *)data_arg;
-
- char *cp;
- char *user;
- char *vn;
- /* Timestamp field. Always empty according to the protocol. */
- char *ts;
- char *options = NULL;
- char *tag = NULL;
- char *date = NULL;
- char *tag_or_date;
- char *scratch_entries = NULL;
- int bin;
-
-#ifdef UTIME_EXPECTS_WRITABLE
- int change_it_back = 0;
-#endif
-
- read_line (&entries_line);
-
- /*
- * Parse the entries line.
- */
- scratch_entries = xstrdup (entries_line);
-
- if (scratch_entries[0] != '/')
- error (1, 0, "bad entries line `%s' from server", entries_line);
- user = scratch_entries + 1;
- if ((cp = strchr (user, '/')) == NULL)
- error (1, 0, "bad entries line `%s' from server", entries_line);
- *cp++ = '\0';
- vn = cp;
- if ((cp = strchr (vn, '/')) == NULL)
- error (1, 0, "bad entries line `%s' from server", entries_line);
- *cp++ = '\0';
-
- ts = cp;
- if ((cp = strchr (ts, '/')) == NULL)
- error (1, 0, "bad entries line `%s' from server", entries_line);
- *cp++ = '\0';
- options = cp;
- if ((cp = strchr (options, '/')) == NULL)
- error (1, 0, "bad entries line `%s' from server", entries_line);
- *cp++ = '\0';
- tag_or_date = cp;
-
- /* If a slash ends the tag_or_date, ignore everything after it. */
- cp = strchr (tag_or_date, '/');
- if (cp != NULL)
- *cp = '\0';
- if (*tag_or_date == 'T')
- tag = tag_or_date + 1;
- else if (*tag_or_date == 'D')
- date = tag_or_date + 1;
-
- /* Done parsing the entries line. */
-
- if (data->contents == UPDATE_ENTRIES_UPDATE
- || data->contents == UPDATE_ENTRIES_PATCH
- || data->contents == UPDATE_ENTRIES_RCS_DIFF)
- {
- char *size_string;
- char *mode_string;
- size_t size;
- char *buf;
- char *temp_filename;
- int use_gzip;
- int patch_failed;
- char *s;
-
- read_line (&mode_string);
-
- read_line (&size_string);
- if (size_string[0] == 'z')
- {
- use_gzip = 1;
- s = size_string + 1;
- }
- else
- {
- use_gzip = 0;
- s = size_string;
- }
- size = strto_file_size (s);
- free (size_string);
-
- /* Note that checking this separately from writing the file is
- 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
- does the right thing, and (c) it isn't clear this needs to
- work. */
- if (data->existp == UPDATE_ENTRIES_EXISTING
- && !isfile (filename))
- /* Emit a warning and update the file anyway. */
- error (0, 0, "warning: %s unexpectedly disappeared",
- short_pathname);
-
- if (data->existp == UPDATE_ENTRIES_NEW
- && isfile (filename))
- {
- /* Emit a warning and refuse to update the file; we don't want
- to clobber a user's file. */
- size_t nread;
- size_t toread;
-
- /* size should be unsigned, but until we get around to fixing
- that, work around it. */
- size_t usize;
-
- char buf[8192];
-
- /* This error might be confusing; it isn't really clear to
- the user what to do about it. Keep in mind that it has
- several causes: (1) something/someone creates the file
- during the time that CVS is running, (2) the repository
- has two files whose names clash for the client because
- of case-insensitivity or similar causes, See 3 for
- additional notes. (3) a special case of this is that a
- file gets renamed for example from a.c to A.C. A
- "cvs update" on a case-insensitive client will get this
- error. In this case and in case 2, the filename
- (short_pathname) printed in the error message will likely _not_
- have the same case as seen by the user in a directory listing.
- (4) the client has a file which the server doesn't know
- about (e.g. "? foo" file), and that name clashes with a file
- the server does know about, (5) classify.c will print the same
- message for other reasons.
-
- I hope the above paragraph makes it clear that making this
- clearer is not a one-line fix. */
- error (0, 0, "move away %s; it is in the way", short_pathname);
- if (updated_fname != NULL)
- {
- cvs_output ("C ", 0);
- cvs_output (updated_fname, 0);
- cvs_output ("\n", 1);
- }
- failure_exit = 1;
-
- discard_file_and_return:
- /* Now read and discard the file contents. */
- usize = size;
- nread = 0;
- while (nread < usize)
- {
- toread = usize - nread;
- if (toread > sizeof buf)
- toread = sizeof buf;
-
- nread += try_read_from_server (buf, toread);
- if (nread == usize)
- break;
- }
-
- free (mode_string);
- free (scratch_entries);
- free (entries_line);
-
- /* The Mode, Mod-time, and Checksum responses should not carry
- over to a subsequent Created (or whatever) response, even
- in the error case. */
- if (stored_mode != NULL)
- {
- free (stored_mode);
- stored_mode = NULL;
- }
- stored_modtime_valid = 0;
- stored_checksum_valid = 0;
-
- if (updated_fname != NULL)
- {
- free (updated_fname);
- updated_fname = NULL;
- }
- return;
- }
-
- temp_filename = xmalloc (strlen (filename) + 80);
-#ifdef USE_VMS_FILENAMES
- /* A VMS rename of "blah.dat" to "foo" to implies a
- destination of "foo.dat" which is unfortinate for CVS */
- sprintf (temp_filename, "%s_new_", filename);
-#else
-#ifdef _POSIX_NO_TRUNC
- sprintf (temp_filename, ".new.%.9s", filename);
-#else /* _POSIX_NO_TRUNC */
- sprintf (temp_filename, ".new.%s", filename);
-#endif /* _POSIX_NO_TRUNC */
-#endif /* USE_VMS_FILENAMES */
-
- buf = xmalloc (size);
-
- /* Some systems, like OS/2 and Windows NT, end lines with CRLF
- instead of just LF. Format translation is done in the C
- library I/O funtions. Here we tell them whether or not to
- convert -- if this file is marked "binary" with the RCS -kb
- flag, then we don't want to convert, else we do (because
- CVS assumes text files by default). */
-
- if (options)
- bin = !(strcmp (options, "-kb"));
- else
- bin = 0;
-
- if (data->contents == UPDATE_ENTRIES_RCS_DIFF)
- {
- /* This is an RCS change text. We just hold the change
- text in memory. */
-
- if (use_gzip)
- error (1, 0,
- "server error: gzip invalid with RCS change text");
-
- read_from_server (buf, size);
- }
- else
- {
- int fd;
-
- fd = CVS_OPEN (temp_filename,
- (O_WRONLY | O_CREAT | O_TRUNC
- | (bin ? OPEN_BINARY : 0)),
- 0777);
-
- if (fd < 0)
- {
- /* I can see a case for making this a fatal error; for
- a condition like disk full or network unreachable
- (for a file server), carrying on and giving an
- error on each file seems unnecessary. But if it is
- a permission problem, or some such, then it is
- entirely possible that future files will not have
- the same problem. */
- error (0, errno, "cannot write %s", short_pathname);
- free (temp_filename);
- free (buf);
- goto discard_file_and_return;
- }
-
- if (size > 0)
- {
- read_from_server (buf, size);
-
- if (use_gzip)
- {
- if (gunzip_and_write (fd, short_pathname,
- (unsigned char *) buf, size))
- error (1, 0, "aborting due to compression error");
- }
- else if (write (fd, buf, size) != size)
- error (1, errno, "writing %s", short_pathname);
- }
-
- if (close (fd) < 0)
- error (1, errno, "writing %s", short_pathname);
- }
-
- /* This is after we have read the file from the net (a change
- from previous versions, where the server would send us
- "M U foo.c" before Update-existing or whatever), but before
- we finish writing the file (arguably a bug). The timing
- affects a user who wants status info about how far we have
- gotten, and also affects whether "U foo.c" appears in addition
- to various error messages. */
- if (updated_fname != NULL)
- {
- cvs_output ("U ", 0);
- cvs_output (updated_fname, 0);
- cvs_output ("\n", 1);
- free (updated_fname);
- updated_fname = 0;
- }
-
- patch_failed = 0;
-
- if (data->contents == UPDATE_ENTRIES_UPDATE)
- {
- rename_file (temp_filename, filename);
- }
- else if (data->contents == UPDATE_ENTRIES_PATCH)
- {
- /* 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
- {
- char *filebuf;
- size_t filebufsize;
- size_t nread;
- char *patchedbuf;
- size_t patchedlen;
-
- /* Handle UPDATE_ENTRIES_RCS_DIFF. */
-
- if (!isfile (filename))
- error (1, 0, "patch original file %s does not exist",
- short_pathname);
- filebuf = NULL;
- filebufsize = 0;
- nread = 0;
-
- get_file (filename, short_pathname, bin ? FOPEN_BINARY_READ : "r",
- &filebuf, &filebufsize, &nread);
- /* At this point the contents of the existing file are in
- FILEBUF, and the length of the contents is in NREAD.
- The contents of the patch from the network are in BUF,
- and the length of the patch is in SIZE. */
-
- if (! rcs_change_text (short_pathname, filebuf, nread, buf, size,
- &patchedbuf, &patchedlen))
- patch_failed = 1;
- else
- {
- if (stored_checksum_valid)
- {
- 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. */
- cvs_MD5Init (&context);
- cvs_MD5Update (&context,
- (unsigned char *) patchedbuf, patchedlen);
- cvs_MD5Final (checksum, &context);
- if (memcmp (checksum, stored_checksum, 16) != 0)
- {
- error (0, 0,
- "checksum failure after patch to %s; will refetch",
- short_pathname);
-
- patch_failed = 1;
- }
-
- stored_checksum_valid = 0;
- }
-
- if (! patch_failed)
- {
- FILE *e;
-
- e = open_file (temp_filename,
- bin ? FOPEN_BINARY_WRITE : "w");
- if (fwrite (patchedbuf, 1, patchedlen, e) != patchedlen)
- error (1, errno, "cannot write %s", temp_filename);
- if (fclose (e) == EOF)
- error (1, errno, "cannot close %s", temp_filename);
- rename_file (temp_filename, filename);
- }
-
- free (patchedbuf);
- }
-
- free (filebuf);
- }
-
- free (temp_filename);
-
- if (stored_checksum_valid && ! patch_failed)
- {
- FILE *e;
- struct cvs_MD5Context context;
- unsigned char buf[8192];
- unsigned len;
- unsigned char checksum[16];
-
- /*
- * Compute the MD5 checksum. This will normally only be
- * used when receiving a patch, so we always compute it
- * here on the final file, rather than on the received
- * data.
- *
- * Note that if the file is a text file, we should read it
- * here using text mode, so its lines will be terminated the same
- * way they were transmitted.
- */
- e = CVS_FOPEN (filename, "r");
- if (e == NULL)
- error (1, errno, "could not open %s", short_pathname);
-
- cvs_MD5Init (&context);
- while ((len = fread (buf, 1, sizeof buf, e)) != 0)
- cvs_MD5Update (&context, buf, len);
- if (ferror (e))
- error (1, errno, "could not read %s", short_pathname);
- cvs_MD5Final (checksum, &context);
-
- fclose (e);
-
- stored_checksum_valid = 0;
-
- if (memcmp (checksum, stored_checksum, 16) != 0)
- {
- if (data->contents != UPDATE_ENTRIES_PATCH)
- error (1, 0, "checksum failure on %s",
- short_pathname);
-
- error (0, 0,
- "checksum failure after patch to %s; will refetch",
- short_pathname);
-
- patch_failed = 1;
- }
- }
-
- if (patch_failed)
- {
- /* Save this file to retrieve later. */
- failed_patches = (char **) xrealloc ((char *) failed_patches,
- ((failed_patches_count + 1)
- * sizeof (char *)));
- failed_patches[failed_patches_count] = xstrdup (short_pathname);
- ++failed_patches_count;
-
- stored_checksum_valid = 0;
-
- free (mode_string);
- free (buf);
- free (scratch_entries);
- free (entries_line);
-
- return;
- }
-
- {
- int status = change_mode (filename, mode_string, 1);
- if (status != 0)
- error (0, status, "cannot change mode of %s", short_pathname);
- }
-
- free (mode_string);
- free (buf);
- }
-
- if (stored_mode != NULL)
- {
- change_mode (filename, stored_mode, 1);
- free (stored_mode);
- stored_mode = NULL;
- }
-
- if (stored_modtime_valid)
- {
- struct utimbuf t;
-
- memset (&t, 0, sizeof (t));
- t.modtime = stored_modtime;
- (void) time (&t.actime);
-
-#ifdef UTIME_EXPECTS_WRITABLE
- if (!iswritable (filename))
- {
- xchmod (filename, 1);
- change_it_back = 1;
- }
-#endif /* UTIME_EXPECTS_WRITABLE */
-
- if (utime (filename, &t) < 0)
- error (0, errno, "cannot set time on %s", filename);
-
-#ifdef UTIME_EXPECTS_WRITABLE
- if (change_it_back)
- {
- xchmod (filename, 0);
- change_it_back = 0;
- }
-#endif /* UTIME_EXPECTS_WRITABLE */
-
- stored_modtime_valid = 0;
- }
-
- /*
- * Process the entries line. Do this after we've written the file,
- * since we need the timestamp.
- */
- if (strcmp (cvs_cmd_name, "export") != 0)
- {
- char *local_timestamp;
- char *file_timestamp;
-
- (void) time (&last_register_time);
-
- local_timestamp = data->timestamp;
- if (local_timestamp == NULL || ts[0] == '+')
- file_timestamp = time_stamp (filename);
- else
- file_timestamp = NULL;
-
- /*
- * These special version numbers signify that it is not up to
- * date. Create a dummy timestamp which will never compare
- * equal to the timestamp of the file.
- */
- if (vn[0] == '\0' || strcmp (vn, "0") == 0 || vn[0] == '-')
- local_timestamp = "dummy timestamp";
- else if (local_timestamp == NULL)
- {
- local_timestamp = file_timestamp;
-
- /* Checking for cvs_cmd_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 (cvs_cmd_name, "commit"))
- mark_up_to_date (filename);
- }
-
- Register (ent_list, filename, vn, local_timestamp,
- options, tag, date, ts[0] == '+' ? file_timestamp : NULL);
-
- if (file_timestamp)
- free (file_timestamp);
-
- }
- free (scratch_entries);
- free (entries_line);
-}
-
-static void
-handle_checked_in (args, len)
- char *args;
- int len;
-{
- struct update_entries_data dat;
- dat.contents = UPDATE_ENTRIES_CHECKIN;
- dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
- dat.timestamp = NULL;
- call_in_directory (args, update_entries, (char *)&dat);
-}
-
-static void
-handle_new_entry (args, len)
- char *args;
- int len;
-{
- struct update_entries_data dat;
- dat.contents = UPDATE_ENTRIES_CHECKIN;
- dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
- dat.timestamp = "dummy timestamp from new-entry";
- call_in_directory (args, update_entries, (char *)&dat);
-}
-
-static void
-handle_updated (args, len)
- char *args;
- int len;
-{
- struct update_entries_data dat;
- dat.contents = UPDATE_ENTRIES_UPDATE;
- dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
- dat.timestamp = NULL;
- call_in_directory (args, update_entries, (char *)&dat);
-}
-
-static void handle_created PROTO((char *, int));
-
-static void
-handle_created (args, len)
- char *args;
- int len;
-{
- struct update_entries_data dat;
- dat.contents = UPDATE_ENTRIES_UPDATE;
- dat.existp = UPDATE_ENTRIES_NEW;
- dat.timestamp = NULL;
- call_in_directory (args, update_entries, (char *)&dat);
-}
-
-static void handle_update_existing PROTO((char *, int));
-
-static void
-handle_update_existing (args, len)
- char *args;
- int len;
-{
- struct update_entries_data dat;
- dat.contents = UPDATE_ENTRIES_UPDATE;
- dat.existp = UPDATE_ENTRIES_EXISTING;
- dat.timestamp = NULL;
- call_in_directory (args, update_entries, (char *)&dat);
-}
-
-static void
-handle_merged (args, len)
- char *args;
- int len;
-{
- struct update_entries_data dat;
- dat.contents = UPDATE_ENTRIES_UPDATE;
- /* Think this could be UPDATE_ENTRIES_EXISTING, but just in case... */
- dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
- dat.timestamp = "Result of merge";
- call_in_directory (args, update_entries, (char *)&dat);
-}
-
-static void
-handle_patched (args, len)
- char *args;
- int len;
-{
- struct update_entries_data dat;
- dat.contents = UPDATE_ENTRIES_PATCH;
- /* Think this could be UPDATE_ENTRIES_EXISTING, but just in case... */
- dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
- dat.timestamp = NULL;
- call_in_directory (args, update_entries, (char *)&dat);
-}
-
-static void
-handle_rcs_diff (args, len)
- char *args;
- int len;
-{
- struct update_entries_data dat;
- dat.contents = UPDATE_ENTRIES_RCS_DIFF;
- /* Think this could be UPDATE_ENTRIES_EXISTING, but just in case... */
- dat.existp = UPDATE_ENTRIES_EXISTING_OR_NEW;
- dat.timestamp = NULL;
- call_in_directory (args, update_entries, (char *)&dat);
-}
-
-static void
-remove_entry (data, ent_list, short_pathname, filename)
- char *data;
- List *ent_list;
- char *short_pathname;
- char *filename;
-{
- Scratch_Entry (ent_list, filename);
-}
-
-static void
-handle_remove_entry (args, len)
- char *args;
- int len;
-{
- call_in_directory (args, remove_entry, (char *)NULL);
-}
-
-static void
-remove_entry_and_file (data, ent_list, short_pathname, filename)
- char *data;
- List *ent_list;
- char *short_pathname;
- char *filename;
-{
- Scratch_Entry (ent_list, filename);
- /* Note that we don't ignore existence_error's here. The server
- should be sending Remove-entry rather than Removed in cases
- where the file does not exist. And if the user removes the
- file halfway through a cvs command, we should be printing an
- error. */
- if (unlink_file (filename) < 0)
- error (0, errno, "unable to remove %s", short_pathname);
-}
-
-static void
-handle_removed (args, len)
- char *args;
- int len;
-{
- call_in_directory (args, remove_entry_and_file, (char *)NULL);
-}
-
-/* Is this the top level (directory containing CVSROOT)? */
-static int
-is_cvsroot_level (pathname)
- char *pathname;
-{
- if (strcmp (toplevel_repos, current_parsed_root->directory) != 0)
- return 0;
-
- return strchr (pathname, '/') == NULL;
-}
-
-static void
-set_static (data, ent_list, short_pathname, filename)
- char *data;
- List *ent_list;
- char *short_pathname;
- char *filename;
-{
- FILE *fp;
- fp = open_file (CVSADM_ENTSTAT, "w+");
- if (fclose (fp) == EOF)
- error (1, errno, "cannot close %s", CVSADM_ENTSTAT);
-}
-
-static void
-handle_set_static_directory (args, len)
- char *args;
- int len;
-{
- if (strcmp (cvs_cmd_name, "export") == 0)
- {
- /* Swallow the repository. */
- read_line (NULL);
- return;
- }
- call_in_directory (args, set_static, (char *)NULL);
-}
-
-static void
-clear_static (data, ent_list, short_pathname, filename)
- char *data;
- List *ent_list;
- char *short_pathname;
- char *filename;
-{
- if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno))
- error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
-}
-
-static void
-handle_clear_static_directory (pathname, len)
- char *pathname;
- int len;
-{
- if (strcmp (cvs_cmd_name, "export") == 0)
- {
- /* Swallow the repository. */
- read_line (NULL);
- return;
- }
-
- if (is_cvsroot_level (pathname))
- {
- /*
- * Top level (directory containing CVSROOT). This seems to normally
- * lack a CVS directory, so don't try to create files in it.
- */
- return;
- }
- call_in_directory (pathname, clear_static, (char *)NULL);
-}
-
-static void
-set_sticky (data, ent_list, short_pathname, filename)
- char *data;
- List *ent_list;
- char *short_pathname;
- char *filename;
-{
- char *tagspec;
- FILE *f;
-
- read_line (&tagspec);
-
- /* 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)
- error (1, errno, "closing %s", CVSADM_TAG);
- free (tagspec);
-}
-
-static void
-handle_set_sticky (pathname, len)
- char *pathname;
- int len;
-{
- if (strcmp (cvs_cmd_name, "export") == 0)
- {
- /* Swallow the repository. */
- read_line (NULL);
- /* Swallow the tag line. */
- read_line (NULL);
- return;
- }
- if (is_cvsroot_level (pathname))
- {
- /*
- * Top level (directory containing CVSROOT). This seems to normally
- * lack a CVS directory, so don't try to create files in it.
- */
-
- /* Swallow the repository. */
- read_line (NULL);
- /* Swallow the tag line. */
- read_line (NULL);
- return;
- }
-
- call_in_directory (pathname, set_sticky, (char *)NULL);
-}
-
-static void
-clear_sticky (data, ent_list, short_pathname, filename)
- char *data;
- List *ent_list;
- char *short_pathname;
- char *filename;
-{
- if (unlink_file (CVSADM_TAG) < 0 && ! existence_error (errno))
- error (1, errno, "cannot remove %s", CVSADM_TAG);
-}
-
-static void
-handle_clear_sticky (pathname, len)
- char *pathname;
- int len;
-{
- if (strcmp (cvs_cmd_name, "export") == 0)
- {
- /* Swallow the repository. */
- read_line (NULL);
- return;
- }
-
- if (is_cvsroot_level (pathname))
- {
- /*
- * Top level (directory containing CVSROOT). This seems to normally
- * lack a CVS directory, so don't try to create files in it.
- */
- return;
- }
-
- call_in_directory (pathname, clear_sticky, (char *)NULL);
-}
-
-
-static void template PROTO ((char *, List *, char *, char *));
-
-static void
-template (data, ent_list, short_pathname, filename)
- char *data;
- List *ent_list;
- char *short_pathname;
- char *filename;
-{
- char *buf = xmalloc ( strlen ( short_pathname )
- + strlen ( CVSADM_TEMPLATE )
- + 2 );
- sprintf ( buf, "%s/%s", short_pathname, CVSADM_TEMPLATE );
- read_counted_file ( CVSADM_TEMPLATE, buf );
- free ( buf );
-}
-
-static void handle_template PROTO ((char *, int));
-
-static void
-handle_template (pathname, len)
- char *pathname;
- int len;
-{
- call_in_directory (pathname, template, NULL);
-}
-
-
-
-struct save_dir {
- char *dir;
- struct save_dir *next;
-};
-
-struct save_dir *prune_candidates;
-
-static void
-add_prune_candidate (dir)
- const char *dir;
-{
- struct save_dir *p;
-
- if ((dir[0] == '.' && dir[1] == '\0')
- || (prune_candidates != NULL
- && strcmp (dir, prune_candidates->dir) == 0))
- return;
- p = (struct save_dir *) xmalloc (sizeof (struct save_dir));
- p->dir = xstrdup (dir);
- p->next = prune_candidates;
- prune_candidates = p;
-}
-
-static void process_prune_candidates PROTO((void));
-
-static void
-process_prune_candidates ()
-{
- struct save_dir *p;
- struct save_dir *q;
-
- if (toplevel_wd != NULL)
- {
- if (CVS_CHDIR (toplevel_wd) < 0)
- error (1, errno, "could not chdir to %s", toplevel_wd);
- }
- for (p = prune_candidates; p != NULL; )
- {
- if (isemptydir (p->dir, 1))
- {
- char *b;
-
- if (unlink_file_dir (p->dir) < 0)
- error (0, errno, "cannot remove %s", p->dir);
- b = strrchr (p->dir, '/');
- if (b == NULL)
- Subdir_Deregister ((List *) NULL, (char *) NULL, p->dir);
- else
- {
- *b = '\0';
- Subdir_Deregister ((List *) NULL, p->dir, b + 1);
- }
- }
- free (p->dir);
- q = p->next;
- free (p);
- p = q;
- }
- prune_candidates = NULL;
-}
-
-/* Send a Repository line. */
-
-static char *last_repos;
-static char *last_update_dir;
-
-static void send_repository PROTO((const char *, const char *, const char *));
-
-static void
-send_repository (dir, repos, update_dir)
- const char *dir;
- const char *repos;
- const char *update_dir;
-{
- char *adm_name;
-
- /* FIXME: this is probably not the best place to check; I wish I
- * knew where in here's callers to really trap this bug. To
- * reproduce the bug, just do this:
- *
- * mkdir junk
- * cd junk
- * cvs -d some_repos update foo
- *
- * Poof, CVS seg faults and dies! It's because it's trying to
- * send a NULL string to the server but dies in send_to_server.
- * That string was supposed to be the repository, but it doesn't
- * get set because there's no CVSADM dir, and somehow it's not
- * getting set from the -d argument either... ?
- */
- if (repos == NULL)
- {
- /* Lame error. I want a real fix but can't stay up to track
- this down right now. */
- error (1, 0, "no repository");
- }
-
- if (update_dir == NULL || update_dir[0] == '\0')
- update_dir = ".";
-
- if (last_repos != NULL
- && strcmp (repos, last_repos) == 0
- && last_update_dir != NULL
- && strcmp (update_dir, last_update_dir) == 0)
- /* We've already sent it. */
- return;
-
- 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 = NT_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);
-
- send_to_server ("Directory ", 0);
- {
- /* Send the directory name. I know that this
- sort of duplicates code elsewhere, but each
- case seems slightly different... */
- char buf[1];
- const char *p = update_dir;
- while (*p != '\0')
- {
- assert (*p != '\012');
- if (ISDIRSEP (*p))
- {
- buf[0] = '/';
- send_to_server (buf, 1);
- }
- else
- {
- buf[0] = *p;
- send_to_server (buf, 1);
- }
- ++p;
- }
- }
- send_to_server ("\012", 1);
- send_to_server (repos, 0);
- send_to_server ("\012", 1);
-
- if (strcmp (cvs_cmd_name, "import")
- && supported_request ("Static-directory"))
- {
- adm_name[0] = '\0';
- if (dir[0] != '\0')
- {
- strcat (adm_name, dir);
- strcat (adm_name, "/");
- }
- strcat (adm_name, CVSADM_ENTSTAT);
- if (isreadable (adm_name))
- {
- send_to_server ("Static-directory\012", 0);
- }
- }
- if (strcmp (cvs_cmd_name, "import")
- && supported_request ("Sticky"))
- {
- FILE *f;
- if (dir[0] == '\0')
- strcpy (adm_name, CVSADM_TAG);
- else
- sprintf (adm_name, "%s/%s", dir, CVSADM_TAG);
-
- f = CVS_FOPEN (adm_name, "r");
- if (f == NULL)
- {
- if (! existence_error (errno))
- error (1, errno, "reading %s", adm_name);
- }
- else
- {
- char line[80];
- char *nl = NULL;
- send_to_server ("Sticky ", 0);
- while (fgets (line, sizeof (line), f) != NULL)
- {
- send_to_server (line, 0);
- nl = strchr (line, '\n');
- if (nl != NULL)
- break;
- }
- if (nl == NULL)
- send_to_server ("\012", 1);
- if (fclose (f) == EOF)
- error (0, errno, "closing %s", adm_name);
- }
- }
- free (adm_name);
- if (last_repos != NULL)
- free (last_repos);
- if (last_update_dir != NULL)
- free (last_update_dir);
- last_repos = xstrdup (repos);
- last_update_dir = xstrdup (update_dir);
-}
-
-/* Send a Repository line and set toplevel_repos. */
-
-void
-send_a_repository (dir, repository, update_dir_in)
- const char *dir;
- const char *repository;
- const char *update_dir_in;
-{
- char *update_dir;
-
- assert (update_dir_in);
- update_dir = xstrdup (update_dir_in);
-
- if (toplevel_repos == NULL && repository != NULL)
- {
- if (update_dir[0] == '\0'
- || (update_dir[0] == '.' && update_dir[1] == '\0'))
- toplevel_repos = xstrdup (repository);
- else
- {
- /*
- * Get the repository from a CVS/Repository file if update_dir
- * is absolute. This is not correct in general, because
- * the CVS/Repository file might not be the top-level one.
- * This is for cases like "cvs update /foo/bar" (I'm not
- * sure it matters what toplevel_repos we get, but it does
- * matter that we don't hit the "internal error" code below).
- */
- if (update_dir[0] == '/')
- toplevel_repos = Name_Repository (update_dir, update_dir);
- else
- {
- /*
- * Guess the repository of that directory by looking at a
- * subdirectory and removing as many pathname components
- * as are in update_dir. I think that will always (or at
- * least almost always) be 1.
- *
- * So this deals with directories which have been
- * renamed, though it doesn't necessarily deal with
- * directories which have been put inside other
- * 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 repository_len, update_dir_len;
-
- strip_trailing_slashes (update_dir);
-
- 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"
- current_parsed_root->directory, set toplevel_repos to
- current_parsed_root->directory. */
- if ((repository_len > update_dir_len)
- && (strcmp (repository + repository_len - update_dir_len,
- update_dir) == 0)
- /* TOPLEVEL_REPOS shouldn't be above current_parsed_root->directory */
- && ((size_t)(repository_len - update_dir_len)
- > strlen (current_parsed_root->directory)))
- {
- /* 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 (current_parsed_root->directory);
- }
- }
- }
- }
-
- send_repository (dir, repository, update_dir);
- free (update_dir);
-}
-
-
-
-/* The "expanded" modules. */
-static int modules_count;
-static int modules_allocated;
-static char **modules_vector;
-
-static void
-handle_module_expansion (args, len)
- char *args;
- int len;
-{
- if (modules_vector == NULL)
- {
- modules_allocated = 1; /* Small for testing */
- modules_vector = (char **) xmalloc
- (modules_allocated * sizeof (modules_vector[0]));
- }
- else if (modules_count >= modules_allocated)
- {
- modules_allocated *= 2;
- modules_vector = (char **) xrealloc
- ((char *) modules_vector,
- modules_allocated * sizeof (modules_vector[0]));
- }
- modules_vector[modules_count] = xmalloc (strlen (args) + 1);
- strcpy (modules_vector[modules_count], args);
- ++modules_count;
-}
-
-/* Original, not "expanded" modules. */
-static int module_argc;
-static char **module_argv;
-
-void
-client_expand_modules (argc, argv, local)
- int argc;
- char **argv;
- int local;
-{
- int errs;
- int i;
-
- module_argc = argc;
- module_argv = (char **) xmalloc ((argc + 1) * sizeof (module_argv[0]));
- for (i = 0; i < argc; ++i)
- module_argv[i] = xstrdup (argv[i]);
- module_argv[argc] = NULL;
-
- for (i = 0; i < argc; ++i)
- send_arg (argv[i]);
- send_a_repository ("", current_parsed_root->directory, "");
-
- send_to_server ("expand-modules\012", 0);
-
- errs = get_server_responses ();
- if (last_repos != NULL)
- free (last_repos);
- last_repos = NULL;
- if (last_update_dir != NULL)
- free (last_update_dir);
- last_update_dir = NULL;
- if (errs)
- error (errs, 0, "cannot expand modules");
-}
-
-void
-client_send_expansions (local, where, build_dirs)
- int local;
- char *where;
- int build_dirs;
-{
- int i;
- char *argv[1];
-
- /* Send the original module names. The "expanded" module name might
- not be suitable as an argument to a co request (e.g. it might be
- the result of a -d argument in the modules file). It might be
- cleaner if we genuinely expanded module names, all the way to a
- local directory and repository, but that isn't the way it works
- now. */
- send_file_names (module_argc, module_argv, 0);
-
- for (i = 0; i < modules_count; ++i)
- {
- argv[0] = where ? where : modules_vector[i];
- if (isfile (argv[0]))
- send_files (1, argv, local, 0, build_dirs ? SEND_BUILD_DIRS : 0);
- }
- send_a_repository ("", current_parsed_root->directory, "");
-}
-
-void
-client_nonexpanded_setup ()
-{
- send_a_repository ("", current_parsed_root->directory, "");
-}
-
-/* Receive a cvswrappers line from the server; it must be a line
- containing an RCS option (e.g., "*.exe -k 'b'").
-
- Note that this doesn't try to handle -t/-f options (which are a
- whole separate issue which noone has thought much about, as far
- as I know).
-
- We need to know the keyword expansion mode so we know whether to
- read the file in text or binary mode. */
-
-static void
-handle_wrapper_rcs_option (args, len)
- char *args;
- int len;
-{
- char *p;
-
- /* Enforce the notes in cvsclient.texi about how the response is not
- as free-form as it looks. */
- p = strchr (args, ' ');
- if (p == NULL)
- goto handle_error;
- if (*++p != '-'
- || *++p != 'k'
- || *++p != ' '
- || *++p != '\'')
- goto handle_error;
- if (strchr (p, '\'') == NULL)
- goto handle_error;
-
- /* Add server-side cvswrappers line to our wrapper list. */
- wrap_add (args, 0);
- return;
- handle_error:
- error (0, errno, "protocol error: ignoring invalid wrappers %s", args);
-}
-
-
-static void
-handle_m (args, len)
- char *args;
- int len;
-{
- /* In the case where stdout and stderr point to the same place,
- fflushing stderr will make output happen in the correct order.
- Often stderr will be line-buffered and this won't be needed,
- but not always (is that true? I think the comment is probably
- based on being confused between default buffering between
- stdout and stderr. But I'm not sure). */
- fflush (stderr);
- fwrite (args, len, sizeof (*args), stdout);
- putc ('\n', stdout);
-}
-
-static void handle_mbinary PROTO ((char *, int));
-
-static void
-handle_mbinary (args, len)
- char *args;
- int len;
-{
- char *size_string;
- size_t size;
- size_t totalread;
- size_t nread;
- size_t toread;
- char buf[8192];
-
- /* See comment at handle_m about (non)flush of stderr. */
-
- /* Get the size. */
- read_line (&size_string);
- size = strto_file_size (size_string);
- free (size_string);
-
- /* OK, now get all the data. The algorithm here is that we read
- as much as the network wants to give us in
- try_read_from_server, and then we output it all, and then
- repeat, until we get all the data. */
- totalread = 0;
- while (totalread < size)
- {
- toread = size - totalread;
- if (toread > sizeof buf)
- toread = sizeof buf;
-
- nread = try_read_from_server (buf, toread);
- cvs_output_binary (buf, nread);
- totalread += nread;
- }
-}
-
-static void
-handle_e (args, len)
- char *args;
- int len;
-{
- /* In the case where stdout and stderr point to the same place,
- fflushing stdout will make output happen in the correct order. */
- fflush (stdout);
- fwrite (args, len, sizeof (*args), stderr);
- putc ('\n', stderr);
-}
-
-/*ARGSUSED*/
-static void
-handle_f (args, len)
- char *args;
- int len;
-{
- fflush (stderr);
-}
-
-static void handle_mt PROTO ((char *, int));
-
-static void
-handle_mt (args, len)
- char *args;
- int len;
-{
- char *p;
- char *tag = args;
- char *text;
-
- /* See comment at handle_m for more details. */
- fflush (stderr);
-
- p = strchr (args, ' ');
- if (p == NULL)
- text = NULL;
- else
- {
- *p++ = '\0';
- text = p;
- }
-
- switch (tag[0])
- {
- 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)
- {
- if (strcmp (tag, "fname") == 0)
- {
- if (updated_fname != NULL)
- {
- /* Output the previous message now. This can happen
- if there was no Update-existing or other such
- response, due to the -n global option. */
- cvs_output ("U ", 0);
- cvs_output (updated_fname, 0);
- cvs_output ("\n", 1);
- free (updated_fname);
- }
- updated_fname = xstrdup (text);
- }
- /* Swallow all other tags. Either they are extraneous
- or they reflect future extensions that we can
- safely ignore. */
- }
- else if (importmergecmd.seen)
- {
- if (strcmp (tag, "conflicts") == 0)
- importmergecmd.conflicts = text ? atoi (text) : -1;
- 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)
- printf ("%s", text);
- }
-}
-
-#endif /* CLIENT_SUPPORT */
-#if defined(CLIENT_SUPPORT) || defined(SERVER_SUPPORT)
-
-/* This table must be writeable if the server code is included. */
-struct response responses[] =
-{
-#ifdef CLIENT_SUPPORT
-#define RSP_LINE(n, f, t, s) {n, f, t, s}
-#else /* ! CLIENT_SUPPORT */
-#define RSP_LINE(n, f, t, s) {n, s}
-#endif /* CLIENT_SUPPORT */
-
- RSP_LINE("ok", handle_ok, response_type_ok, rs_essential),
- RSP_LINE("error", handle_error, response_type_error, rs_essential),
- RSP_LINE("Valid-requests", handle_valid_requests, response_type_normal,
- rs_essential),
- RSP_LINE("Checked-in", handle_checked_in, response_type_normal,
- rs_essential),
- RSP_LINE("New-entry", handle_new_entry, response_type_normal, rs_optional),
- RSP_LINE("Checksum", handle_checksum, response_type_normal, rs_optional),
- RSP_LINE("Copy-file", handle_copy_file, response_type_normal, rs_optional),
- RSP_LINE("Updated", handle_updated, response_type_normal, rs_essential),
- RSP_LINE("Created", handle_created, response_type_normal, rs_optional),
- RSP_LINE("Update-existing", handle_update_existing, response_type_normal,
- rs_optional),
- RSP_LINE("Merged", handle_merged, response_type_normal, rs_essential),
- RSP_LINE("Patched", handle_patched, response_type_normal, rs_optional),
- RSP_LINE("Rcs-diff", handle_rcs_diff, response_type_normal, rs_optional),
- RSP_LINE("Mode", handle_mode, response_type_normal, rs_optional),
- RSP_LINE("Mod-time", handle_mod_time, response_type_normal, rs_optional),
- RSP_LINE("Removed", handle_removed, response_type_normal, rs_essential),
- RSP_LINE("Remove-entry", handle_remove_entry, response_type_normal,
- rs_optional),
- RSP_LINE("Set-static-directory", handle_set_static_directory,
- response_type_normal,
- rs_optional),
- RSP_LINE("Clear-static-directory", handle_clear_static_directory,
- response_type_normal,
- rs_optional),
- RSP_LINE("Set-sticky", handle_set_sticky, response_type_normal,
- rs_optional),
- RSP_LINE("Clear-sticky", handle_clear_sticky, response_type_normal,
- rs_optional),
- RSP_LINE("Template", handle_template, response_type_normal,
- rs_optional),
- RSP_LINE("Notified", handle_notified, response_type_normal, rs_optional),
- RSP_LINE("Module-expansion", handle_module_expansion, response_type_normal,
- rs_optional),
- RSP_LINE("Wrapper-rcsOption", handle_wrapper_rcs_option,
- response_type_normal,
- rs_optional),
- RSP_LINE("M", handle_m, response_type_normal, rs_essential),
- RSP_LINE("Mbinary", handle_mbinary, response_type_normal, rs_optional),
- RSP_LINE("E", handle_e, response_type_normal, rs_essential),
- RSP_LINE("F", handle_f, response_type_normal, rs_optional),
- RSP_LINE("MT", handle_mt, response_type_normal, rs_optional),
- /* Possibly should be response_type_error. */
- RSP_LINE(NULL, NULL, response_type_normal, rs_essential)
-
-#undef RSP_LINE
-};
-
-#endif /* CLIENT_SUPPORT or SERVER_SUPPORT */
-#ifdef CLIENT_SUPPORT
-
-/*
- * If LEN is 0, then send_to_server() computes string's length itself.
- *
- * Therefore, pass the real length when transmitting data that might
- * contain 0's.
- */
-void
-send_to_server (str, len)
- const char *str;
- size_t len;
-{
- static int nbytes;
-
- if (len == 0)
- len = strlen (str);
-
- buf_output (to_server, str, len);
-
- /* There is no reason not to send data to the server, so do it
- whenever we've accumulated enough information in the buffer to
- make it worth sending. */
- nbytes += len;
- if (nbytes >= 2 * BUFFER_DATA_SIZE)
- {
- int status;
-
- status = buf_send_output (to_server);
- if (status != 0)
- error (1, status, "error writing to server");
- nbytes = 0;
- }
-}
-
-/* Read up to LEN bytes from the server. Returns actual number of
- bytes read, which will always be at least one; blocks if there is
- no data available at all. Gives a fatal error on EOF or error. */
-static size_t
-try_read_from_server (buf, len)
- char *buf;
- size_t len;
-{
- int status, nread;
- char *data;
-
- status = buf_read_data (from_server, len, &data, &nread);
- if (status != 0)
- {
- if (status == -1)
- error (1, 0,
- "end of file from server (consult above messages if any)");
- else if (status == -2)
- error (1, 0, "out of memory");
- else
- error (1, status, "reading from server");
- }
-
- memcpy (buf, data, nread);
-
- return nread;
-}
-
-/*
- * Read LEN bytes from the server or die trying.
- */
-void
-read_from_server (buf, len)
- char *buf;
- size_t len;
-{
- size_t red = 0;
- while (red < len)
- {
- red += try_read_from_server (buf + red, len - red);
- if (red == len)
- break;
- }
-}
-
-/*
- * Get some server responses and process them. Returns nonzero for
- * error, 0 for success. */
-int
-get_server_responses ()
-{
- struct response *rs;
- do
- {
- char *cmd;
- int len;
-
- len = read_line (&cmd);
- for (rs = responses; rs->name != NULL; ++rs)
- if (strncmp (cmd, rs->name, strlen (rs->name)) == 0)
- {
- int cmdlen = strlen (rs->name);
- if (cmd[cmdlen] == '\0')
- ;
- else if (cmd[cmdlen] == ' ')
- ++cmdlen;
- else
- /*
- * The first len characters match, but it's a different
- * response. e.g. the response is "oklahoma" but we
- * matched "ok".
- */
- continue;
- (*rs->func) (cmd + cmdlen, len - cmdlen);
- break;
- }
- if (rs->name == NULL)
- /* It's OK to print just to the first '\0'. */
- /* We might want to handle control characters and the like
- in some other way other than just sending them to stdout.
- One common reason for this error is if people use :ext:
- with a version of rsh which is doing CRLF translation or
- something, and so the client gets "ok^M" instead of "ok".
- Right now that will tend to print part of this error
- message over the other part of it. It seems like we could
- do better (either in general, by quoting or omitting all
- control characters, and/or specifically, by detecting the CRLF
- case and printing a specific error message). */
- error (0, 0,
- "warning: unrecognized response `%s' from cvs server",
- cmd);
- free (cmd);
- } while (rs->type == response_type_normal);
-
- if (updated_fname != NULL)
- {
- /* Output the previous message now. This can happen
- if there was no Update-existing or other such
- response, due to the -n global option. */
- cvs_output ("U ", 0);
- cvs_output (updated_fname, 0);
- cvs_output ("\n", 1);
- free (updated_fname);
- updated_fname = NULL;
- }
-
- if (rs->type == response_type_error)
- return 1;
- if (failure_exit)
- return 1;
- return 0;
-}
-
-
-
-/* Get the responses and then close the connection. */
-
-/*
- * Flag var; we'll set it in start_server() and not one of its
- * callees, such as start_rsh_server(). This means that there might
- * be a small window between the starting of the server and the
- * setting of this var, but all the code in that window shouldn't care
- * because it's busy checking return values to see if the server got
- * started successfully anyway.
- */
-int server_started = 0;
-
-int
-get_responses_and_close ()
-{
- int errs = get_server_responses ();
- int status;
-
- /* The following is necessary when working with multiple cvsroots, at least
- * with commit. It used to be buried nicely in do_deferred_progs() before
- * that function was removed. I suspect it wouldn't be necessary if
- * call_in_directory() saved its working directory via save_cwd() before
- * changing its directory and restored the saved working directory via
- * restore_cwd() before exiting. Of course, calling CVS_CHDIR only once,
- * here, may be more efficient.
- */
- if( toplevel_wd != NULL )
- {
- if( CVS_CHDIR( toplevel_wd ) < 0 )
- error( 1, errno, "could not chdir to %s", toplevel_wd );
- }
-
- if (client_prune_dirs)
- process_prune_candidates ();
-
- /* First we shut down TO_SERVER. That tells the server that its input is
- * finished. It then shuts down the buffer it is sending to us, at which
- * point our shut down of FROM_SERVER will complete.
- */
-
- status = buf_shutdown (to_server);
- if (status != 0)
- error (0, status, "shutting down buffer to server");
- buf_free (to_server);
- to_server = NULL;
-
- status = buf_shutdown (from_server);
- if (status != 0)
- error (0, status, "shutting down buffer from server");
- buf_free (from_server);
- from_server = NULL;
- server_started = 0;
-
- /* see if we need to sleep before returning to avoid time-stamp races */
- if (last_register_time)
- {
- sleep_past (last_register_time);
- }
-
- return errs;
-}
-
-#ifndef NO_EXT_METHOD
-static void start_rsh_server PROTO((cvsroot_t *, struct buffer **, struct buffer **));
-#endif
-
-int
-supported_request (name)
- char *name;
-{
- struct request *rq;
-
- for (rq = requests; rq->name; rq++)
- if (!strcmp (rq->name, name))
- return (rq->flags & RQ_SUPPORTED) != 0;
- error (1, 0, "internal error: testing support for unknown option?");
- /* NOTREACHED */
- return 0;
-}
-
-
-
-#if defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
-static struct hostent *init_sockaddr PROTO ((struct sockaddr_in *, char *,
- unsigned int));
-
-static struct hostent *
-init_sockaddr (name, hostname, port)
- struct sockaddr_in *name;
- char *hostname;
- unsigned int port;
-{
- struct hostent *hostinfo;
- unsigned short shortport = port;
-
- memset (name, 0, sizeof (*name));
- name->sin_family = AF_INET;
- name->sin_port = htons (shortport);
- hostinfo = gethostbyname (hostname);
- if (hostinfo == NULL)
- {
- fprintf (stderr, "Unknown host %s.\n", hostname);
- error_exit ();
- }
- name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
- return hostinfo;
-}
-
-
-
-/* Generic function to do port number lookup tasks.
- *
- * In order of precedence, will return:
- * getenv (envname), if defined
- * getservbyname (portname), if defined
- * defaultport
- */
-static int
-get_port_number (envname, portname, defaultport)
- const char *envname;
- const char *portname;
- int defaultport;
-{
- struct servent *s;
- char *port_s;
-
- if (envname && (port_s = getenv (envname)))
- {
- int port = atoi (port_s);
- if (port <= 0)
- {
- error (0, 0, "%s must be a positive integer! If you", envname);
- error (0, 0, "are trying to force a connection via rsh, please");
- error (0, 0, "put \":server:\" at the beginning of your CVSROOT");
- error (1, 0, "variable.");
- }
- return port;
- }
- else if (portname && (s = getservbyname (portname, "tcp")))
- return ntohs (s->s_port);
- else
- return defaultport;
-}
-
-
-
-/* get the port number for a client to connect to based on the port
- * and method of a cvsroot_t.
- *
- * we do this here instead of in parse_cvsroot so that we can keep network
- * code confined to a localized area and also to delay the lookup until the
- * last possible moment so it remains possible to run cvs client commands that
- * skip opening connections to the server (i.e. skip network operations
- * entirely)
- *
- * and yes, I know none of the commands do that now, but here's to planning
- * for the future, eh? cheers.
- *
- * FIXME - We could cache the port lookup safely right now as we never change
- * it for a single root on the fly, but we'd have to un'const some other
- * functions - REMOVE_FIXME? This may be unecessary. We're talking about,
- * what, usually one, sometimes two lookups of the port per invocation. I
- * think twice is by far the rarer of the two cases - only the login function
- * will need to do it to save the canonical CVSROOT. -DRP
- */
-int
-get_cvs_port_number (root)
- const cvsroot_t *root;
-{
-
- if (root->port) return root->port;
-
- switch (root->method)
- {
-# ifdef HAVE_GSSAPI
- case gserver_method:
-# endif /* HAVE_GSSAPI */
-# ifdef AUTH_CLIENT_SUPPORT
- case pserver_method:
-# endif /* AUTH_CLIENT_SUPPORT */
-# if defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_GSSAPI)
- return get_port_number ("CVS_CLIENT_PORT", "cvspserver", CVS_AUTH_PORT);
-# endif /* defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_GSSAPI) */
-# ifdef HAVE_KERBEROS
- case kserver_method:
- return get_port_number ("CVS_CLIENT_PORT", "cvs", CVS_PORT);
-# endif /* HAVE_KERBEROS */
- default:
- error(1, EINVAL, "internal error: get_cvs_port_number called for invalid connection method (%s)",
- method_names[root->method]);
- break;
- }
- /* NOTREACHED */
- return -1;
-}
-
-
-
-void
-make_bufs_from_fds (tofd, fromfd, child_pid, to_server, from_server, is_sock)
- int tofd;
- int fromfd;
- int child_pid;
- struct buffer **to_server;
- struct buffer **from_server;
- int is_sock;
-{
- FILE *to_server_fp;
- FILE *from_server_fp;
-
-# ifdef NO_SOCKET_TO_FD
- if (is_sock)
- {
- assert (tofd == fromfd);
- *to_server = socket_buffer_initialize (tofd, 0,
- (BUFMEMERRPROC) NULL);
- *from_server = socket_buffer_initialize (tofd, 1,
- (BUFMEMERRPROC) NULL);
- }
- else
-# endif /* NO_SOCKET_TO_FD */
- {
- /* todo: some OS's don't need these calls... */
- close_on_exec (tofd);
- close_on_exec (fromfd);
-
- /* SCO 3 and AIX have a nasty bug in the I/O libraries which precludes
- fdopening the same file descriptor twice, so dup it if it is the
- same. */
- if (tofd == fromfd)
- {
- fromfd = dup (tofd);
- if (fromfd < 0)
- error (1, errno, "cannot dup net connection");
- }
-
- /* These will use binary mode on systems which have it. */
- /*
- * Also, we know that from_server is shut down second, so we pass
- * child_pid in there. In theory, it should be stored in both
- * buffers with a ref count...
- */
- to_server_fp = fdopen (tofd, FOPEN_BINARY_WRITE);
- if (to_server_fp == NULL)
- error (1, errno, "cannot fdopen %d for write", tofd);
- *to_server = stdio_buffer_initialize (to_server_fp, 0, 0,
- (BUFMEMERRPROC) NULL);
-
- from_server_fp = fdopen (fromfd, FOPEN_BINARY_READ);
- if (from_server_fp == NULL)
- error (1, errno, "cannot fdopen %d for read", fromfd);
- *from_server = stdio_buffer_initialize (from_server_fp, child_pid, 1,
- (BUFMEMERRPROC) NULL);
- }
-}
-#endif /* defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_KERBEROS) || defined(HAVE_GSSAPI) */
-
-
-
-#if defined (AUTH_CLIENT_SUPPORT) || defined(HAVE_GSSAPI)
-/* Connect to the authenticating server.
-
- If VERIFY_ONLY is non-zero, then just verify that the password is
- correct and then shutdown the connection.
-
- If VERIFY_ONLY is 0, then really connect to the server.
-
- If DO_GSSAPI is non-zero, then we use GSSAPI authentication rather
- than the pserver password authentication.
-
- If we fail to connect or if access is denied, then die with fatal
- error. */
-void
-connect_to_pserver (root, to_server_p, from_server_p, verify_only, do_gssapi)
- cvsroot_t *root;
- struct buffer **to_server_p;
- struct buffer **from_server_p;
- int verify_only;
- int do_gssapi;
-{
- int sock;
- int port_number;
- struct sockaddr_in client_sai;
- struct hostent *hostinfo;
- struct buffer *to_server, *from_server;
-
- sock = socket (AF_INET, SOCK_STREAM, 0);
- if (sock == -1)
- {
- error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO));
- }
- port_number = get_cvs_port_number (root);
- hostinfo = init_sockaddr (&client_sai, root->hostname, port_number);
- if (trace)
- {
- fprintf (stderr, " -> Connecting to %s(%s):%d\n",
- root->hostname,
- inet_ntoa (client_sai.sin_addr), port_number);
- }
- if (connect (sock, (struct sockaddr *) &client_sai, sizeof (client_sai))
- < 0)
- error (1, 0, "connect to %s(%s):%d failed: %s",
- root->hostname,
- inet_ntoa (client_sai.sin_addr),
- port_number, SOCK_STRERROR (SOCK_ERRNO));
-
- make_bufs_from_fds (sock, sock, 0, &to_server, &from_server, 1);
-
- auth_server (root, to_server, from_server, verify_only, do_gssapi, hostinfo);
-
- if (verify_only)
- {
- int status;
-
- status = buf_shutdown (to_server);
- if (status != 0)
- error (0, status, "shutting down buffer to server");
- buf_free (to_server);
- to_server = NULL;
-
- status = buf_shutdown (from_server);
- if (status != 0)
- error (0, status, "shutting down buffer from server");
- buf_free (from_server);
- from_server = NULL;
-
- /* Don't need to set server_started = 0 since we don't set it to 1
- * until returning from this call.
- */
- }
- else
- {
- *to_server_p = to_server;
- *from_server_p = from_server;
- }
-
- return;
-}
-
-
-
-static void
-auth_server (root, lto_server, lfrom_server, verify_only, do_gssapi, hostinfo)
- cvsroot_t *root;
- struct buffer *lto_server;
- struct buffer *lfrom_server;
- int verify_only;
- int do_gssapi;
- struct hostent *hostinfo;
-{
- char *username = ""; /* the username we use to connect */
- char no_passwd = 0; /* gets set if no password found */
-
- /* FIXME!!!!!!!!!!!!!!!!!!
- *
- * THIS IS REALLY UGLY!
- *
- * I'm setting the globals here so we can make calls to send_to_server &
- * read_line. This happens again _after_ we return if we're not in
- * verify_only mode. We should be relying on the values we passed in, but
- * sent_to_server and read_line don't require an outside buf yet.
- */
- to_server = lto_server;
- from_server = lfrom_server;
-
- /* Run the authorization mini-protocol before anything else. */
- if (do_gssapi)
- {
-# ifdef HAVE_GSSAPI
- FILE *fp = stdio_buffer_get_file(lto_server);
- int fd = fp ? fileno(fp) : -1;
- struct stat s;
-
- if ((fd < 0) || (fstat (fd, &s) < 0) || !S_ISSOCK(s.st_mode))
- {
- error (1, 0, "gserver currently only enabled for socket connections");
- }
-
- if (! connect_to_gserver (root, fd, hostinfo))
- {
- error (1, 0,
- "authorization failed: server %s rejected access to %s",
- root->hostname, root->directory);
- }
-# else /* ! HAVE_GSSAPI */
- error (1, 0, "INTERNAL ERROR: This client does not support GSSAPI authentication");
-# endif /* HAVE_GSSAPI */
- }
- else /* ! do_gssapi */
- {
-# ifdef AUTH_CLIENT_SUPPORT
- char *begin = NULL;
- char *password = NULL;
- char *end = NULL;
-
- if (verify_only)
- {
- begin = "BEGIN VERIFICATION REQUEST";
- end = "END VERIFICATION REQUEST";
- }
- else
- {
- begin = "BEGIN AUTH REQUEST";
- end = "END AUTH REQUEST";
- }
-
- /* Get the password, probably from ~/.cvspass. */
- password = get_cvs_password ();
- username = root->username ? root->username : getcaller();
-
- /* Send the empty string by default. This is so anonymous CVS
- access doesn't require client to have done "cvs login". */
- if (password == NULL)
- {
- no_passwd = 1;
- password = scramble ("");
- }
-
- /* Announce that we're starting the authorization protocol. */
- send_to_server(begin, 0);
- send_to_server("\012", 1);
-
- /* Send the data the server needs. */
- send_to_server(root->directory, 0);
- send_to_server("\012", 1);
- send_to_server(username, 0);
- send_to_server("\012", 1);
- send_to_server(password, 0);
- send_to_server("\012", 1);
-
- /* Announce that we're ending the authorization protocol. */
- send_to_server(end, 0);
- send_to_server("\012", 1);
-
- free_cvs_password (password);
- password = NULL;
-# else /* ! AUTH_CLIENT_SUPPORT */
- error (1, 0, "INTERNAL ERROR: This client does not support pserver authentication");
-# endif /* AUTH_CLIENT_SUPPORT */
- } /* if (do_gssapi) */
-
- {
- char *read_buf;
-
- /* Loop, getting responses from the server. */
- while (1)
- {
- read_line (&read_buf);
-
- if (strcmp (read_buf, "I HATE YOU") == 0)
- {
- /* Authorization not granted.
- *
- * This is a little confusing since we can reach this while loop in GSSAPI
- * mode, but if GSSAPI authentication failed, we already jumped to the
- * rejected label (there is no case where the connect_to_gserver function
- * can return 1 and we will not receive "I LOVE YOU" from the server, barring
- * broken connections and garbled messages, of course).
- *
- * i.e. This is a pserver specific error message and should be since
- * GSSAPI doesn't use username.
- */
- error (0, 0,
- "authorization failed: server %s rejected access to %s for user %s",
- root->hostname, root->directory, username);
-
- /* Output a special error message if authentication was attempted
- with no password -- the user should be made aware that they may
- have missed a step. */
- if (no_passwd)
- {
- error (0, 0,
- "used empty password; try \"cvs login\" with a real password");
- }
- error_exit();
- }
- else if (strncmp (read_buf, "E ", 2) == 0)
- {
- fprintf (stderr, "%s\n", read_buf + 2);
-
- /* Continue with the authentication protocol. */
- }
- else if (strncmp (read_buf, "error ", 6) == 0)
- {
- char *p;
-
- /* First skip the code. */
- p = read_buf + 6;
- while (*p != ' ' && *p != '\0')
- ++p;
-
- /* Skip the space that follows the code. */
- if (*p == ' ')
- ++p;
-
- /* Now output the text. */
- fprintf (stderr, "%s\n", p);
- error_exit();
- }
- else if (strcmp (read_buf, "I LOVE YOU") == 0)
- {
- free (read_buf);
- break;
- }
- else
- {
- error (1, 0,
- "unrecognized auth response from %s: %s",
- root->hostname, read_buf);
- }
- free (read_buf);
- }
- }
-}
-#endif /* defined (AUTH_CLIENT_SUPPORT) || defined(HAVE_GSSAPI) */
-
-
-
-#ifdef CLIENT_SUPPORT
-/* void
- * connect_to_forked_server ( struct buffer **to_server,
- * struct buffer **from_server )
- *
- * Connect to a forked server process.
- */
-void
-connect_to_forked_server (to_server, from_server)
- struct buffer **to_server;
- struct buffer **from_server;
-{
- int tofd, fromfd;
- int child_pid;
-
- /* This is pretty simple. All we need to do is choose the correct
- cvs binary and call piped_child. */
-
- const char *command[3];
-
- command[0] = getenv ("CVS_SERVER");
- if (! command[0])
- command[0] = program_path;
-
- command[1] = "server";
- command[2] = NULL;
-
- if (trace)
- {
- fprintf (stderr, " -> Forking server: %s %s\n", command[0], command[1]);
- }
-
- child_pid = piped_child (command, &tofd, &fromfd, 0);
- if (child_pid < 0)
- error (1, 0, "could not fork server process");
-
- make_bufs_from_fds (tofd, fromfd, child_pid, to_server, from_server, 0);
-}
-#endif /* CLIENT_SUPPORT */
-
-
-
-#ifdef HAVE_KERBEROS
-/* This function has not been changed to deal with NO_SOCKET_TO_FD
- (i.e., systems on which sockets cannot be converted to file
- descriptors). The first person to try building a kerberos client
- on such a system (OS/2, Windows 95, and maybe others) will have to
- take care of this. */
-void
-start_tcp_server (root, to_server, from_server)
- cvsroot_t *root;
- struct buffer **to_server;
- struct buffer **from_server;
-{
- int s;
- const char *portenv;
- int port;
- struct hostent *hp;
- struct sockaddr_in sin;
- char *hname;
-
- s = socket (AF_INET, SOCK_STREAM, 0);
- if (s < 0)
- error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO));
-
- port = get_cvs_port_number (root);
-
- hp = init_sockaddr (&sin, root->hostname, port);
-
- hname = xstrdup (hp->h_name);
-
- if (trace)
- {
- fprintf (stderr, " -> Connecting to %s(%s):%d\n",
- root->hostname,
- inet_ntoa (sin.sin_addr), port);
- }
-
- if (connect (s, (struct sockaddr *) &sin, sizeof sin) < 0)
- error (1, 0, "connect to %s(%s):%d failed: %s",
- root->hostname,
- inet_ntoa (sin.sin_addr),
- port, SOCK_STRERROR (SOCK_ERRNO));
-
- {
- const char *realm;
- struct sockaddr_in laddr;
- int laddrlen;
- KTEXT_ST ticket;
- MSG_DAT msg_data;
- CREDENTIALS cred;
- int status;
-
- realm = krb_realmofhost (hname);
-
- laddrlen = sizeof (laddr);
- if (getsockname (s, (struct sockaddr *) &laddr, &laddrlen) < 0)
- error (1, 0, "getsockname failed: %s", SOCK_STRERROR (SOCK_ERRNO));
-
- /* We don't care about the checksum, and pass it as zero. */
- status = krb_sendauth (KOPT_DO_MUTUAL, s, &ticket, "rcmd",
- hname, realm, (unsigned long) 0, &msg_data,
- &cred, sched, &laddr, &sin, "KCVSV1.0");
- if (status != KSUCCESS)
- error (1, 0, "kerberos authentication failed: %s",
- krb_get_err_text (status));
- memcpy (kblock, cred.session, sizeof (C_Block));
- }
-
- close_on_exec (s);
-
- free (hname);
-
- /* Give caller the values it wants. */
- make_bufs_from_fds (s, s, 0, to_server, from_server, 1);
-}
-
-#endif /* HAVE_KERBEROS */
-
-#ifdef HAVE_GSSAPI
-
-/* Receive a given number of bytes. */
-
-static void
-recv_bytes (sock, buf, need)
- int sock;
- char *buf;
- int need;
-{
- while (need > 0)
- {
- int got;
-
- got = recv (sock, buf, need, 0);
- if (got <= 0)
- error (1, 0, "recv() from server %s: %s", current_parsed_root->hostname,
- got == 0 ? "EOF" : SOCK_STRERROR (SOCK_ERRNO));
-
- buf += got;
- need -= got;
- }
-}
-
-/* Connect to the server using GSSAPI authentication. */
-
-/* FIXME
- *
- * This really needs to be rewritten to use a buffer and not a socket.
- * This would enable gserver to work with the SSL code I'm about to commit
- * since the SSL connection is going to look like a FIFO and not a socket.
- *
- * I think, basically, it will need to use buf_output and buf_read directly
- * since I don't think there is a read_bytes function - only read_line.
- *
- * recv_bytes could then be removed too.
- *
- * Besides, I added some cruft to reenable the socket which shouldn't be
- * there. This would also enable its removal.
- */
-#define BUFSIZE 1024
-static int
-connect_to_gserver (root, sock, hostinfo)
- cvsroot_t *root;
- int sock;
- struct hostent *hostinfo;
-{
- char *str;
- char buf[BUFSIZE];
- gss_buffer_desc *tok_in_ptr, tok_in, tok_out;
- OM_uint32 stat_min, stat_maj;
- gss_name_t server_name;
-
- str = "BEGIN GSSAPI REQUEST\012";
-
- if (send (sock, str, strlen (str), 0) < 0)
- error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
-
- if (strlen (hostinfo->h_name) > BUFSIZE - 5)
- error (1, 0, "Internal error: hostname exceeds length of buffer");
- sprintf (buf, "cvs@%s", hostinfo->h_name);
- tok_in.length = strlen (buf);
- tok_in.value = buf;
- gss_import_name (&stat_min, &tok_in, GSS_C_NT_HOSTBASED_SERVICE,
- &server_name);
-
- tok_in_ptr = GSS_C_NO_BUFFER;
- gcontext = GSS_C_NO_CONTEXT;
-
- do
- {
- stat_maj = gss_init_sec_context (&stat_min, GSS_C_NO_CREDENTIAL,
- &gcontext, server_name,
- GSS_C_NULL_OID,
- (GSS_C_MUTUAL_FLAG
- | GSS_C_REPLAY_FLAG),
- 0, NULL, tok_in_ptr, NULL, &tok_out,
- NULL, NULL);
- if (stat_maj != GSS_S_COMPLETE && stat_maj != GSS_S_CONTINUE_NEEDED)
- {
- OM_uint32 message_context;
- OM_uint32 new_stat_min;
-
- message_context = 0;
- gss_display_status (&new_stat_min, stat_maj, GSS_C_GSS_CODE,
- GSS_C_NULL_OID, &message_context, &tok_out);
- error (0, 0, "GSSAPI authentication failed: %s",
- (char *) tok_out.value);
-
- message_context = 0;
- gss_display_status (&new_stat_min, stat_min, GSS_C_MECH_CODE,
- GSS_C_NULL_OID, &message_context, &tok_out);
- error (1, 0, "GSSAPI authentication failed: %s",
- (char *) tok_out.value);
- }
-
- if (tok_out.length == 0)
- {
- tok_in.length = 0;
- }
- else
- {
- char cbuf[2];
- int need;
-
- cbuf[0] = (tok_out.length >> 8) & 0xff;
- cbuf[1] = tok_out.length & 0xff;
- if (send (sock, cbuf, 2, 0) < 0)
- error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
- if (send (sock, tok_out.value, tok_out.length, 0) < 0)
- error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO));
-
- recv_bytes (sock, cbuf, 2);
- need = ((cbuf[0] & 0xff) << 8) | (cbuf[1] & 0xff);
-
- if (need > sizeof buf)
- {
- ssize_t got;
- size_t total;
-
- /* This usually means that the server sent us an error
- message. Read it byte by byte and print it out.
- FIXME: This is a terrible error handling strategy.
- However, even if we fix the server, we will still
- want to do this to work with older servers. */
- buf[0] = cbuf[0];
- buf[1] = cbuf[1];
- total = 2;
- while (got = recv (sock, buf + total, sizeof buf - total, 0))
- {
- if (got < 0)
- error (1, 0, "recv() from server %s: %s",
- root->hostname, SOCK_STRERROR (SOCK_ERRNO));
- total += got;
- if (strrchr (buf + total - got, '\n'))
- break;
- }
- buf[total] = '\0';
- if (buf[total - 1] == '\n')
- buf[total - 1] = '\0';
- error (1, 0, "error from server %s: %s", root->hostname,
- buf);
- }
-
- recv_bytes (sock, buf, need);
- tok_in.length = need;
- }
-
- tok_in.value = buf;
- tok_in_ptr = &tok_in;
- }
- while (stat_maj == GSS_S_CONTINUE_NEEDED);
-
- return 1;
-}
-
-#endif /* HAVE_GSSAPI */
-
-
-
-static int send_variable_proc PROTO ((Node *, void *));
-
-static int
-send_variable_proc (node, closure)
- Node *node;
- void *closure;
-{
- send_to_server ("Set ", 0);
- send_to_server (node->key, 0);
- send_to_server ("=", 1);
- send_to_server (node->data, 0);
- send_to_server ("\012", 1);
- return 0;
-}
-
-
-
-/* Contact the server. */
-void
-start_server ()
-{
- int rootless;
- 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
- which supports several ways of connecting is with access methods. */
-
- switch (current_parsed_root->method)
- {
-
-#ifdef AUTH_CLIENT_SUPPORT
- case pserver_method:
- /* Toss the return value. It will die with an error message if
- * anything goes wrong anyway.
- */
- connect_to_pserver (current_parsed_root, &to_server, &from_server, 0, 0);
- break;
-#endif /* AUTH_CLIENT_SUPPORT */
-
-#if HAVE_KERBEROS
- case kserver_method:
- start_tcp_server (current_parsed_root, &to_server, &from_server);
- break;
-#endif /* HAVE_KERBEROS */
-
-#ifdef HAVE_GSSAPI
- case gserver_method:
- /* GSSAPI authentication is handled by the pserver. */
- connect_to_pserver (current_parsed_root, &to_server, &from_server, 0, 1);
- break;
-#endif /* HAVE_GSSAPI */
-
- case ext_method:
- case extssh_method:
-#ifdef NO_EXT_METHOD
- error (0, 0, ":ext: method not supported by this port of CVS");
- error (1, 0, "try :server: instead");
-#else /* ! NO_EXT_METHOD */
- start_rsh_server (current_parsed_root, &to_server, &from_server);
-#endif /* NO_EXT_METHOD */
- break;
-
- case server_method:
-#ifdef START_SERVER
- {
- int tofd, fromfd;
- START_SERVER (&tofd, &fromfd, getcaller (),
- current_parsed_root->username, current_parsed_root->hostname,
- current_parsed_root->directory);
-# ifdef START_SERVER_RETURNS_SOCKET
- make_bufs_from_fds (tofd, fromfd, 0, &to_server, &from_server, 1);
-# else /* ! START_SERVER_RETURNS_SOCKET */
- make_bufs_from_fds (tofd, fromfd, 0, &to_server, &from_server, 0);
-# endif /* START_SERVER_RETURNS_SOCKET */
- }
-#else /* ! START_SERVER */
- /* FIXME: It should be possible to implement this portably,
- like pserver, which would get rid of the duplicated code
- in {vms,windows-NT,...}/startserver.c. */
- error (1, 0,
-"the :server: access method is not supported by this port of CVS");
-#endif /* START_SERVER */
- break;
-
- case fork_method:
- connect_to_forked_server (&to_server, &from_server);
- break;
-
- default:
- error (1, 0, "\
-(start_server internal error): unknown access method");
- break;
- }
-
- /* "Hi, I'm Darlene and I'll be your server tonight..." */
- server_started = 1;
-
- /* Set up logfiles, if any.
- *
- * We do this _after_ authentication on purpose. Wouldn't really like to
- * worry about logging passwords...
- */
- if (log)
- {
- int len = strlen (log);
- char *buf = xmalloc (len + 5);
- char *p;
- FILE *fp;
-
- strcpy (buf, log);
- p = buf + len;
-
- /* Open logfiles in binary mode so that they reflect
- exactly what was transmitted and received (that is
- more important than that they be maximally
- convenient to view). */
- /* Note that if we create several connections in a single CVS client
- (currently used by update.c), then the last set of logfiles will
- overwrite the others. There is currently no way around this. */
- strcpy (p, ".in");
- fp = open_file (buf, "wb");
- if (fp == NULL)
- error (0, errno, "opening to-server logfile %s", buf);
- else
- to_server = log_buffer_initialize (to_server, fp, 0,
- (BUFMEMERRPROC) NULL);
-
- strcpy (p, ".out");
- fp = open_file (buf, "wb");
- if (fp == NULL)
- error (0, errno, "opening from-server logfile %s", buf);
- else
- from_server = log_buffer_initialize (from_server, fp, 1,
- (BUFMEMERRPROC) NULL);
-
- free (buf);
- }
-
- /* Clear static variables. */
- if (toplevel_repos != NULL)
- free (toplevel_repos);
- toplevel_repos = NULL;
- if (last_repos != NULL)
- free (last_repos);
- last_repos = NULL;
- if (last_update_dir != NULL)
- free (last_update_dir);
- last_update_dir = NULL;
- stored_checksum_valid = 0;
- if (stored_mode != NULL)
- {
- free (stored_mode);
- stored_mode = NULL;
- }
-
- rootless = (strcmp (cvs_cmd_name, "init") == 0);
- if (!rootless)
- {
- send_to_server ("Root ", 0);
- send_to_server (current_parsed_root->directory, 0);
- send_to_server ("\012", 1);
- }
-
- {
- struct response *rs;
-
- send_to_server ("Valid-responses", 0);
-
- for (rs = responses; rs->name != NULL; ++rs)
- {
- send_to_server (" ", 0);
- send_to_server (rs->name, 0);
- }
- send_to_server ("\012", 1);
- }
- send_to_server ("valid-requests\012", 0);
-
- if (get_server_responses ())
- error_exit ();
-
- /*
- * Now handle global options.
- *
- * -H, -f, -d, -e should be handled OK locally.
- *
- * -b we ignore (treating it as a server installation issue).
- * FIXME: should be an error message.
- *
- * -v we print local version info; FIXME: Add a protocol request to get
- * the version from the server so we can print that too.
- *
- * -l -t -r -w -q -n and -Q need to go to the server.
- */
-
- {
- int have_global = supported_request ("Global_option");
-
- if (noexec)
- {
- if (have_global)
- {
- send_to_server ("Global_option -n\012", 0);
- }
- else
- error (1, 0,
- "This server does not support the global -n option.");
- }
- if (quiet)
- {
- if (have_global)
- {
- send_to_server ("Global_option -q\012", 0);
- }
- else
- error (1, 0,
- "This server does not support the global -q option.");
- }
- if (really_quiet)
- {
- if (have_global)
- {
- send_to_server ("Global_option -Q\012", 0);
- }
- else
- error (1, 0,
- "This server does not support the global -Q option.");
- }
- if (!cvswrite)
- {
- if (have_global)
- {
- send_to_server ("Global_option -r\012", 0);
- }
- else
- error (1, 0,
- "This server does not support the global -r option.");
- }
- if (trace)
- {
- if (have_global)
- {
- send_to_server ("Global_option -t\012", 0);
- }
- else
- error (1, 0,
- "This server does not support the global -t option.");
- }
- }
-
- /* Find out about server-side cvswrappers. An extra network
- turnaround for cvs import seems to be unavoidable, unless we
- want to add some kind of client-side place to configure which
- filenames imply binary. For cvs add, we could avoid the
- problem by keeping a copy of the wrappers in CVSADM (the main
- reason to bother would be so we could make add work without
- contacting the server, I suspect). */
-
- if ((strcmp (cvs_cmd_name, "import") == 0)
- || (strcmp (cvs_cmd_name, "add") == 0))
- {
- if (supported_request ("wrapper-sendme-rcsOptions"))
- {
- int err;
- send_to_server ("wrapper-sendme-rcsOptions\012", 0);
- err = get_server_responses ();
- if (err != 0)
- error (err, 0, "error reading from server");
- }
- }
-
- if (cvsencrypt && !rootless)
- {
-#ifdef ENCRYPTION
- /* Turn on encryption before turning on compression. We do
- not want to try to compress the encrypted stream. Instead,
- we want to encrypt the compressed stream. If we can't turn
- on encryption, bomb out; don't let the user think the data
- is being encrypted when it is not. */
-#ifdef HAVE_KERBEROS
- if (current_parsed_root->method == kserver_method)
- {
- if (! supported_request ("Kerberos-encrypt"))
- error (1, 0, "This server does not support encryption");
- send_to_server ("Kerberos-encrypt\012", 0);
- to_server = krb_encrypt_buffer_initialize (to_server, 0, sched,
- kblock,
- (BUFMEMERRPROC) NULL);
- from_server = krb_encrypt_buffer_initialize (from_server, 1,
- sched, kblock,
- (BUFMEMERRPROC) NULL);
- }
- else
-#endif /* HAVE_KERBEROS */
-#ifdef HAVE_GSSAPI
- if (current_parsed_root->method == gserver_method)
- {
- if (! supported_request ("Gssapi-encrypt"))
- error (1, 0, "This server does not support encryption");
- send_to_server ("Gssapi-encrypt\012", 0);
- to_server = cvs_gssapi_wrap_buffer_initialize (to_server, 0,
- gcontext,
- ((BUFMEMERRPROC)
- NULL));
- from_server = cvs_gssapi_wrap_buffer_initialize (from_server, 1,
- gcontext,
- ((BUFMEMERRPROC)
- NULL));
- cvs_gssapi_encrypt = 1;
- }
- else
-#endif /* HAVE_GSSAPI */
- error (1, 0, "Encryption is only supported when using GSSAPI or Kerberos");
-#else /* ! ENCRYPTION */
- error (1, 0, "This client does not support encryption");
-#endif /* ! ENCRYPTION */
- }
-
- if (gzip_level && !rootless)
- {
- if (supported_request ("Gzip-stream"))
- {
- char gzip_level_buf[5];
- send_to_server ("Gzip-stream ", 0);
- sprintf (gzip_level_buf, "%d", gzip_level);
- send_to_server (gzip_level_buf, 0);
- send_to_server ("\012", 1);
-
- /* All further communication with the server will be
- compressed. */
-
- to_server = compress_buffer_initialize (to_server, 0, gzip_level,
- (BUFMEMERRPROC) NULL);
- from_server = compress_buffer_initialize (from_server, 1,
- gzip_level,
- (BUFMEMERRPROC) NULL);
- }
-#ifndef NO_CLIENT_GZIP_PROCESS
- else if (supported_request ("gzip-file-contents"))
- {
- char gzip_level_buf[5];
- send_to_server ("gzip-file-contents ", 0);
- sprintf (gzip_level_buf, "%d", gzip_level);
- send_to_server (gzip_level_buf, 0);
-
- send_to_server ("\012", 1);
-
- file_gzip_level = gzip_level;
- }
-#endif
- else
- {
- fprintf (stderr, "server doesn't support gzip-file-contents\n");
- /* Setting gzip_level to 0 prevents us from giving the
- error twice if update has to contact the server again
- to fetch unpatchable files. */
- gzip_level = 0;
- }
- }
-
- if (cvsauthenticate && ! cvsencrypt && !rootless)
- {
- /* Turn on authentication after turning on compression, so
- that we can compress the authentication information. We
- assume that encrypted data is always authenticated--the
- ability to decrypt the data stream is itself a form of
- authentication. */
-#ifdef HAVE_GSSAPI
- if (current_parsed_root->method == gserver_method)
- {
- if (! supported_request ("Gssapi-authenticate"))
- error (1, 0,
- "This server does not support stream authentication");
- send_to_server ("Gssapi-authenticate\012", 0);
- to_server = cvs_gssapi_wrap_buffer_initialize (to_server, 0,
- gcontext,
- ((BUFMEMERRPROC)
- NULL));
- from_server = cvs_gssapi_wrap_buffer_initialize (from_server, 1,
- gcontext,
- ((BUFMEMERRPROC)
- NULL));
- }
- else
- error (1, 0, "Stream authentication is only supported when using GSSAPI");
-#else /* ! HAVE_GSSAPI */
- error (1, 0, "This client does not support stream authentication");
-#endif /* ! HAVE_GSSAPI */
- }
-
- /* If "Set" is not supported, just silently fail to send the variables.
- Users with an old server should get a useful error message when it
- fails to recognize the ${=foo} syntax. This way if someone uses
- several servers, some of which are new and some old, they can still
- set user variables in their .cvsrc without trouble. */
- if (supported_request ("Set"))
- walklist (variable_list, send_variable_proc, NULL);
-}
-
-
-
-#ifndef NO_EXT_METHOD
-
-/* Contact the server by starting it with rsh. */
-
-/* Right now, we have two different definitions for this function,
- depending on whether we start the rsh server using popenRW or not.
- This isn't ideal, and the best thing would probably be to change
- the OS/2 port to be more like the regular Unix client (i.e., by
- implementing piped_child)... but I'm doing something else at the
- moment, and wish to make only one change at a time. -Karl */
-
-# ifdef START_RSH_WITH_POPEN_RW
-
-/* This is actually a crock -- it's OS/2-specific, for no one else
- uses it. If I get time, I want to make piped_child and all the
- other stuff in os2/run.c work right. In the meantime, this gets us
- up and running, and that's most important. */
-
-static void
-start_rsh_server (root, to_server, from_server)
- cvsroot_t *root;
- struct buffer **to_server;
- struct buffer **from_server;
-{
- int pipes[2];
- int child_pid;
-
- /* If you're working through firewalls, you can set the
- CVS_RSH environment variable to a script which uses rsh to
- invoke another rsh on a proxy machine. */
- char *env_cvs_rsh = getenv ("CVS_RSH");
- char *env_cvs_ssh = getenv ("CVS_SSH");
- char *cvs_rsh;
- char *cvs_server = getenv ("CVS_SERVER");
- int i = 0;
- /* This needs to fit "rsh", "-b", "-l", "USER", "host",
- "cmd (w/ args)", and NULL. We leave some room to grow. */
- char *rsh_argv[10];
-
- if (root->method == extssh_method)
- cvs_rsh = env_cvs_ssh ? env_cvs_ssh : SSH_DFLT;
- else
- cvs_rsh = env_cvs_rsh ? env_cvs_rsh : RSH_DFLT;
-
- if (!cvs_server)
- cvs_server = "cvs";
-
- /* The command line starts out with rsh. */
- rsh_argv[i++] = cvs_rsh;
-
-# ifdef RSH_NEEDS_BINARY_FLAG
- /* "-b" for binary, under OS/2. */
- rsh_argv[i++] = "-b";
-# endif /* RSH_NEEDS_BINARY_FLAG */
-
- /* Then we strcat more things on the end one by one. */
- if (root->username != NULL)
- {
- rsh_argv[i++] = "-l";
- rsh_argv[i++] = root->username;
- }
-
- rsh_argv[i++] = root->hostname;
- rsh_argv[i++] = cvs_server;
- rsh_argv[i++] = "server";
-
- /* Mark the end of the arg list. */
- rsh_argv[i] = (char *) NULL;
-
- if (trace)
- {
- fprintf (stderr, " -> Starting server: ");
- for (i = 0; rsh_argv[i]; i++)
- fprintf (stderr, "%s ", rsh_argv[i]);
- putc ('\n', stderr);
- }
-
- /* Do the deed. */
- child_pid = popenRW (rsh_argv, pipes);
- if (child_pid < 0)
- error (1, errno, "cannot start server via rsh");
-
- /* Give caller the file descriptors in a form it can deal with. */
- make_bufs_from_fds (pipes[0], pipes[1], child_pid, to_server, from_server, 0);
-}
-
-# else /* ! START_RSH_WITH_POPEN_RW */
-
-static void
-start_rsh_server (root, to_server, from_server)
- cvsroot_t *root;
- struct buffer **to_server;
- struct buffer **from_server;
-{
- /* If you're working through firewalls, you can set the
- CVS_RSH environment variable to a script which uses rsh to
- invoke another rsh on a proxy machine. */
- char *env_cvs_rsh = getenv ("CVS_RSH");
- char *env_cvs_ssh = getenv ("CVS_SSH");
- char *cvs_rsh;
- char *cvs_server = getenv ("CVS_SERVER");
- char *command;
- int tofd, fromfd;
- int child_pid;
-
- if (root->method == extssh_method)
- cvs_rsh = env_cvs_ssh ? env_cvs_ssh : SSH_DFLT;
- else
- cvs_rsh = env_cvs_rsh ? env_cvs_rsh : RSH_DFLT;
-
- if (!cvs_server)
- cvs_server = "cvs";
-
- /* Pass the command to rsh as a single string. This shouldn't
- affect most rsh servers at all, and will pacify some buggy
- versions of rsh that grab switches out of the middle of the
- command (they're calling the GNU getopt routines incorrectly). */
- command = xmalloc (strlen (cvs_server) + 8);
-
- /* If you are running a very old (Nov 3, 1994, before 1.5)
- * version of the server, you need to make sure that your .bashrc
- * on the server machine does not set CVSROOT to something
- * containing a colon (or better yet, upgrade the server). */
- sprintf (command, "%s server", cvs_server);
-
- {
- const char *argv[10];
- const char **p = argv;
-
- *p++ = cvs_rsh;
-
- /* If the login names differ between client and server
- * pass it on to rsh.
- */
- if (root->username != NULL)
- {
- *p++ = "-l";
- *p++ = root->username;
- }
-
- *p++ = root->hostname;
- *p++ = command;
- *p++ = NULL;
-
- if (trace)
- {
- int i;
-
- fprintf (stderr, " -> Starting server: ");
- for (i = 0; argv[i]; i++)
- fprintf (stderr, "%s ", argv[i]);
- putc ('\n', stderr);
- }
- child_pid = piped_child (argv, &tofd, &fromfd, 1);
-
- if (child_pid < 0)
- error (1, errno, "cannot start server via rsh");
- }
- free (command);
-
- make_bufs_from_fds (tofd, fromfd, child_pid, to_server, from_server, 0);
-}
-
-# endif /* START_RSH_WITH_POPEN_RW */
-
-#endif /* NO_EXT_METHOD */
-
-
-
-/* Send an argument STRING. */
-void
-send_arg (string)
- const char *string;
-{
- char buf[1];
- const char *p = string;
-
- send_to_server ("Argument ", 0);
-
- while (*p)
- {
- if (*p == '\n')
- {
- send_to_server ("\012Argumentx ", 0);
- }
- else
- {
- buf[0] = *p;
- send_to_server (buf, 1);
- }
- ++p;
- }
- send_to_server ("\012", 1);
-}
-
-
-
-static void send_modified PROTO ((const char *, const char *, Vers_TS *));
-
-/* VERS->OPTIONS specifies whether the file is binary or not. NOTE: BEFORE
- using any other fields of the struct vers, we would need to fix
- client_process_import_file to set them up. */
-
-static void
-send_modified (file, short_pathname, vers)
- const char *file;
- const char *short_pathname;
- Vers_TS *vers;
-{
- /* File was modified, send it. */
- struct stat sb;
- int fd;
- char *buf;
- char *mode_string;
- size_t bufsize;
- int bin;
-
- if (trace)
- (void) fprintf (stderr, " -> Sending file `%s' to server\n", file);
-
- /* Don't think we can assume fstat exists. */
- if ( CVS_STAT (file, &sb) < 0)
- error (1, errno, "reading %s", short_pathname);
-
- mode_string = mode_to_string (sb.st_mode);
-
- /* Beware: on systems using CRLF line termination conventions,
- the read and write functions will convert CRLF to LF, so the
- number of characters read is not the same as sb.st_size. Text
- files should always be transmitted using the LF convention, so
- we don't want to disable this conversion. */
- bufsize = sb.st_size;
- buf = xmalloc (bufsize);
-
- /* Is the file marked as containing binary data by the "-kb" flag?
- If so, make sure to open it in binary mode: */
-
- if (vers && vers->options)
- bin = !(strcmp (vers->options, "-kb"));
- else
- bin = 0;
-
-#ifdef BROKEN_READWRITE_CONVERSION
- if (!bin)
- {
- /* If only stdio, not open/write/etc., do text/binary
- conversion, use convert_file which can compensate
- (FIXME: we could just use stdio instead which would
- avoid the whole problem). */
- char tfile[1024]; strcpy(tfile, file); strcat(tfile, ".CVSBFCTMP");
- convert_file (file, O_RDONLY,
- tfile, O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY);
- fd = CVS_OPEN (tfile, O_RDONLY | OPEN_BINARY);
- if (fd < 0)
- error (1, errno, "reading %s", short_pathname);
- }
- else
- fd = CVS_OPEN (file, O_RDONLY | OPEN_BINARY);
-#else
- fd = CVS_OPEN (file, O_RDONLY | (bin ? OPEN_BINARY : 0));
-#endif
-
- if (fd < 0)
- error (1, errno, "reading %s", short_pathname);
-
- if (file_gzip_level && sb.st_size > 100)
- {
- size_t newsize = 0;
-
- 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);
-
- {
- char tmp[80];
-
- send_to_server ("Modified ", 0);
- send_to_server (file, 0);
- send_to_server ("\012", 1);
- send_to_server (mode_string, 0);
- send_to_server ("\012z", 2);
- sprintf (tmp, "%lu\n", (unsigned long) newsize);
- send_to_server (tmp, 0);
-
- send_to_server (buf, newsize);
- }
- }
- else
- {
- int newsize;
-
- {
- char *bufp = buf;
- int len;
-
- /* FIXME: This is gross. It assumes that we might read
- less than st_size bytes (true on NT), but not more.
- Instead of this we should just be reading a block of
- data (e.g. 8192 bytes), writing it to the network, and
- so on until EOF. */
- while ((len = read (fd, bufp, (buf + sb.st_size) - bufp)) > 0)
- bufp += len;
-
- if (len < 0)
- error (1, errno, "reading %s", short_pathname);
-
- newsize = bufp - buf;
- }
- if (close (fd) < 0)
- error (0, errno, "warning: can't close %s", short_pathname);
-
- {
- char tmp[80];
-
- send_to_server ("Modified ", 0);
- send_to_server (file, 0);
- send_to_server ("\012", 1);
- send_to_server (mode_string, 0);
- send_to_server ("\012", 1);
- sprintf (tmp, "%lu\012", (unsigned long) newsize);
- send_to_server (tmp, 0);
- }
-#ifdef BROKEN_READWRITE_CONVERSION
- if (!bin)
- {
- char tfile[1024]; strcpy(tfile, file); strcat(tfile, ".CVSBFCTMP");
- if (CVS_UNLINK (tfile) < 0)
- error (0, errno, "warning: can't remove temp file %s", tfile);
- }
-#endif
-
- /*
- * Note that this only ends with a newline if the file ended with
- * one.
- */
- if (newsize > 0)
- send_to_server (buf, newsize);
- }
- free (buf);
- free (mode_string);
-}
-
-/* The address of an instance of this structure is passed to
- send_fileproc, send_filesdoneproc, and send_direntproc, as the
- callerdat parameter. */
-
-struct send_data
-{
- /* Each of the following flags are zero for clear or nonzero for set. */
- int build_dirs;
- int force;
- int no_contents;
- int backup_modified;
-};
-
-static int send_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-
-/* Deal with one file. */
-static int
-send_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- struct send_data *args = (struct send_data *) callerdat;
- Vers_TS *vers;
- struct file_info xfinfo;
- /* File name to actually use. Might differ in case from
- finfo->file. */
- const char *filename;
-
- send_a_repository ("", finfo->repository, finfo->update_dir);
-
- xfinfo = *finfo;
- xfinfo.repository = NULL;
- xfinfo.rcs = NULL;
- vers = Version_TS (&xfinfo, NULL, NULL, NULL, 0, 0);
-
- if (vers->entdata != NULL)
- filename = vers->entdata->user;
- else
- filename = finfo->file;
-
- if (vers->vn_user != NULL)
- {
- /* The Entries request. */
- send_to_server ("Entry /", 0);
- send_to_server (filename, 0);
- send_to_server ("/", 0);
- send_to_server (vers->vn_user, 0);
- send_to_server ("/", 0);
- if (vers->ts_conflict != NULL)
- {
- if (vers->ts_user != NULL &&
- strcmp (vers->ts_conflict, vers->ts_user) == 0)
- send_to_server ("+=", 0);
- else
- send_to_server ("+modified", 0);
- }
- send_to_server ("/", 0);
- send_to_server (vers->entdata != NULL
- ? vers->entdata->options
- : vers->options,
- 0);
- send_to_server ("/", 0);
- if (vers->entdata != NULL && vers->entdata->tag)
- {
- send_to_server ("T", 0);
- send_to_server (vers->entdata->tag, 0);
- }
- else if (vers->entdata != NULL && vers->entdata->date)
- {
- send_to_server ("D", 0);
- send_to_server (vers->entdata->date, 0);
- }
- send_to_server ("\012", 1);
- }
- else
- {
- /* It seems a little silly to re-read this on each file, but
- send_dirent_proc doesn't get called if filenames are specified
- explicitly on the command line. */
- wrap_add_file (CVSDOTWRAPPER, 1);
-
- if (wrap_name_has (filename, WRAP_RCSOPTION))
- {
- /* No "Entry", but the wrappers did give us a kopt so we better
- send it with "Kopt". As far as I know this only happens
- for "cvs add". Question: is there any reason why checking
- for options from wrappers isn't done in Version_TS?
-
- Note: it might have been better to just remember all the
- kopts on the client side, rather than send them to the server,
- and have it send us back the same kopts. But that seemed like
- a bigger change than I had in mind making now. */
-
- if (supported_request ("Kopt"))
- {
- char *opt;
-
- send_to_server ("Kopt ", 0);
- opt = wrap_rcsoption (filename, 1);
- send_to_server (opt, 0);
- send_to_server ("\012", 1);
- free (opt);
- }
- else
- error (0, 0,
- "\
-warning: ignoring -k options due to server limitations");
- }
- }
-
- if (vers->ts_user == NULL)
- {
- /*
- * Do we want to print "file was lost" like normal CVS?
- * Would it always be appropriate?
- */
- /* File no longer exists. Don't do anything, missing files
- just happen. */
- }
- else if (vers->ts_rcs == NULL
- || args->force
- || strcmp (vers->ts_conflict
- && supported_request ("Empty-conflicts")
- ? vers->ts_conflict : vers->ts_rcs, vers->ts_user)
- || (vers->ts_conflict && !strcmp (cvs_cmd_name, "diff"))
- || (vers->vn_user && *vers->vn_user == '0'))
- {
- if (args->no_contents
- && supported_request ("Is-modified"))
- {
- send_to_server ("Is-modified ", 0);
- send_to_server (filename, 0);
- send_to_server ("\012", 1);
- }
- else
- send_modified (filename, finfo->fullname, vers);
-
- if (args->backup_modified)
- {
- char *bakname;
- bakname = backup_file (filename, vers->vn_user);
- /* This behavior is sufficiently unexpected to
- justify overinformativeness, I think. */
- if (! really_quiet)
- printf ("(Locally modified %s moved to %s)\n",
- filename, bakname);
- free (bakname);
- }
- }
- else
- {
- send_to_server ("Unchanged ", 0);
- send_to_server (filename, 0);
- send_to_server ("\012", 1);
- }
-
- /* if this directory has an ignore list, add this file to it */
- if (ignlist)
- {
- Node *p;
-
- p = getnode ();
- p->type = FILES;
- p->key = xstrdup (finfo->file);
- (void) addnode (ignlist, p);
- }
-
- freevers_ts (&vers);
- return 0;
-}
-
-
-
-static void send_ignproc PROTO ((const char *, const char *));
-
-static void
-send_ignproc (file, dir)
- const char *file;
- const char *dir;
-{
- if (ign_inhibit_server || !supported_request ("Questionable"))
- {
- if (dir[0] != '\0')
- (void) printf ("? %s/%s\n", dir, file);
- else
- (void) printf ("? %s\n", file);
- }
- else
- {
- send_to_server ("Questionable ", 0);
- send_to_server (file, 0);
- send_to_server ("\012", 1);
- }
-}
-
-
-
-static int send_filesdoneproc PROTO ((void *, int, const char *, const char *,
- List *));
-
-static int
-send_filesdoneproc (callerdat, err, repository, update_dir, entries)
- void *callerdat;
- int err;
- const char *repository;
- const char *update_dir;
- List *entries;
-{
- /* if this directory has an ignore list, process it then free it */
- if (ignlist)
- {
- ignore_files (ignlist, entries, update_dir, send_ignproc);
- dellist (&ignlist);
- }
-
- return (err);
-}
-
-static Dtype send_dirent_proc PROTO ((void *, const char *, const char *,
- const char *, List *));
-
-/*
- * send_dirent_proc () is called back by the recursion processor before a
- * sub-directory is processed for update.
- * A return code of 0 indicates the directory should be
- * processed by the recursion code. A return of non-zero indicates the
- * recursion code should skip this directory.
- *
- */
-static Dtype
-send_dirent_proc (callerdat, dir, repository, update_dir, entries)
- void *callerdat;
- const char *dir;
- const char *repository;
- const char *update_dir;
- List *entries;
-{
- struct send_data *args = (struct send_data *) callerdat;
- int dir_exists;
- char *cvsadm_name;
-
- if (ignore_directory (update_dir))
- {
- /* print the warm fuzzy message */
- if (!quiet)
- error (0, 0, "Ignoring %s", update_dir);
- return (R_SKIP_ALL);
- }
-
- /*
- * If the directory does not exist yet (e.g. "cvs update -d foo"),
- * no need to send any files from it. If the directory does not
- * have a CVS directory, then we pretend that it does not exist.
- * Otherwise, we will fail when trying to open the Entries file.
- * This case will happen when checking out a module defined as
- * ``-a .''.
- */
- cvsadm_name = xmalloc (strlen (dir) + sizeof (CVSADM) + 10);
- sprintf (cvsadm_name, "%s/%s", dir, CVSADM);
- dir_exists = isdir (cvsadm_name);
- free (cvsadm_name);
-
- /*
- * If there is an empty directory (e.g. we are doing `cvs add' on a
- * newly-created directory), the server still needs to know about it.
- */
-
- if (dir_exists)
- {
- /*
- * Get the repository from a CVS/Repository file whenever possible.
- * The repository variable is wrong if the names in the local
- * directory don't match the names in the repository.
- */
- char *repos = Name_Repository (dir, update_dir);
- send_a_repository (dir, repos, update_dir);
- free (repos);
-
- /* initialize the ignore list for this directory */
- ignlist = getlist ();
- }
- else
- {
- /* It doesn't make sense to send a non-existent directory,
- because there is no way to get the correct value for
- the repository (I suppose maybe via the expand-modules
- request). In the case where the "obvious" choice for
- repository is correct, the server can figure out whether
- to recreate the directory; in the case where it is wrong
- (that is, does not match what modules give us), we might as
- well just fail to recreate it.
-
- Checking for noexec is a kludge for "cvs -n add dir". */
- /* Don't send a non-existent directory unless we are building
- new directories (build_dirs is true). Otherwise, CVS may
- see a D line in an Entries file, and recreate a directory
- which the user removed by hand. */
- if (args->build_dirs && noexec)
- send_a_repository (dir, repository, update_dir);
- }
-
- return (dir_exists ? R_PROCESS : R_SKIP_ALL);
-}
-
-
-
-static int send_dirleave_proc PROTO ((void *, const char *, int, const char *,
- List *));
-
-/*
- * send_dirleave_proc () is called back by the recursion code upon leaving
- * a directory. All it does is delete the ignore list if it hasn't already
- * been done (by send_filesdone_proc).
- */
-/* ARGSUSED */
-static int
-send_dirleave_proc (callerdat, dir, err, update_dir, entries)
- void *callerdat;
- const char *dir;
- int err;
- const char *update_dir;
- List *entries;
-{
-
- /* Delete the ignore list if it hasn't already been done. */
- if (ignlist)
- dellist (&ignlist);
- return err;
-}
-
-/*
- * Send each option in an array to the server, one by one.
- * argv might be "--foo=bar", "-C", "5", "-y".
- */
-void
-send_options (int argc, char *const *argv)
-{
- int i;
- for (i = 0; i < argc; i++)
- send_arg (argv[i]);
-}
-
-
-
-/* Send the names of all the argument files to the server. */
-void
-send_file_names (argc, argv, flags)
- int argc;
- char **argv;
- unsigned int flags;
-{
- int i;
-
- /* 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)
- expand_wild (argc, argv, &argc, &argv);
-
- for (i = 0; i < argc; ++i)
- {
- char buf[1];
- char *p;
-#ifdef FILENAMES_CASE_INSENSITIVE
- char *line = xmalloc (1);
- *line = '\0';
-#endif /* FILENAMES_CASE_INSENSITIVE */
-
- if (arg_should_not_be_sent_to_server (argv[i]))
- continue;
-
-#ifdef FILENAMES_CASE_INSENSITIVE
- /* We want to send the path as it appears in the
- CVS/Entries files. We put this inside an ifdef
- to avoid doing all these system calls in
- cases where fncmp is just strcmp anyway. */
- /* The isdir (CVSADM) check could more gracefully be replaced
- with a way of having Entries_Open report back the
- error to us and letting us ignore existence_error.
- Or some such. */
- {
- List *stack;
- size_t line_len = 0;
- char *q, *r;
- struct saved_cwd sdir;
-
- /* Split the argument onto the stack. */
- stack = getlist();
- r = xstrdup (argv[i]);
- /* It's okay to discard the const from the last_component return
- * below since we know we passed in an arg that was not const.
- */
- while ((q = (char *)last_component (r)) != r)
- {
- push (stack, xstrdup (q));
- *--q = '\0';
- }
- push (stack, r);
-
- /* Normalize the path into outstr. */
- save_cwd (&sdir);
- while (q = pop (stack))
- {
- Node *node = NULL;
- if (isdir (CVSADM))
- {
- List *entries;
-
- /* Note that if we are adding a directory,
- the following will read the entry
- that we just wrote there, that is, we
- will get the case specified on the
- command line, not the case of the
- directory in the filesystem. This
- is correct behavior. */
- entries = Entries_Open (0, NULL);
- node = findnode_fn (entries, q);
- if (node != NULL)
- {
- /* Add the slash unless this is our first element. */
- if (line_len)
- xrealloc_and_strcat (&line, &line_len, "/");
- xrealloc_and_strcat (&line, &line_len, node->key);
- delnode (node);
- }
- Entries_Close (entries);
- }
-
- /* If node is still NULL then we either didn't find CVSADM or
- * we didn't find an entry there.
- */
- if (node == NULL)
- {
- /* Add the slash unless this is our first element. */
- if (line_len)
- xrealloc_and_strcat (&line, &line_len, "/");
- xrealloc_and_strcat (&line, &line_len, q);
- break;
- }
-
- /* And descend the tree. */
- if (isdir (q))
- CVS_CHDIR (q);
- free (q);
- }
- restore_cwd (&sdir, NULL);
- free_cwd (&sdir);
-
- /* Now put everything we didn't find entries for back on. */
- while (q = pop (stack))
- {
- if (line_len)
- xrealloc_and_strcat (&line, &line_len, "/");
- xrealloc_and_strcat (&line, &line_len, q);
- free (q);
- }
-
- p = line;
-
- dellist (&stack);
- }
-#else /* !FILENAMES_CASE_INSENSITIVE */
- p = argv[i];
-#endif /* FILENAMES_CASE_INSENSITIVE */
-
- send_to_server ("Argument ", 0);
-
- while (*p)
- {
- if (*p == '\n')
- {
- send_to_server ("\012Argumentx ", 0);
- }
- else if (ISDIRSEP (*p))
- {
- buf[0] = '/';
- send_to_server (buf, 1);
- }
- else
- {
- buf[0] = *p;
- send_to_server (buf, 1);
- }
- ++p;
- }
- send_to_server ("\012", 1);
-#ifdef FILENAMES_CASE_INSENSITIVE
- free (line);
-#endif /* FILENAMES_CASE_INSENSITIVE */
- }
-
- if (flags & SEND_EXPAND_WILD)
- {
- int i;
- for (i = 0; i < argc; ++i)
- free (argv[i]);
- free (argv);
- }
-}
-
-
-
-/* Calculate and send max-dotdot to the server */
-static void
-send_max_dotdot (argc, argv)
- int argc;
- char **argv;
-{
- int i;
- int level = 0;
- int max_level = 0;
-
- /* Send Max-dotdot if needed. */
- for (i = 0; i < argc; ++i)
- {
- level = pathname_levels (argv[i]);
- if (level > 0)
- {
- if (uppaths == NULL) uppaths = getlist();
- push_string (uppaths, xstrdup (argv[i]));
- }
- if (level > max_level)
- max_level = level;
- }
-
- if (max_level > 0)
- {
- if (supported_request ("Max-dotdot"))
- {
- char buf[10];
- sprintf (buf, "%d", max_level);
-
- send_to_server ("Max-dotdot ", 0);
- send_to_server (buf, 0);
- send_to_server ("\012", 1);
- }
- else
- {
- error (1, 0,
-"backreference in path (`..') not supported by old (pre-Max-dotdot) servers");
- }
- }
-}
-
-
-
-/* Send Repository, Modified and Entry. argc and argv contain only
- the files to operate on (or empty for everything), not options.
- local is nonzero if we should not recurse (-l option). flags &
- SEND_BUILD_DIRS is nonzero if nonexistent directories should be
- sent. flags & SEND_FORCE is nonzero if we should send unmodified
- files to the server as though they were modified. flags &
- SEND_NO_CONTENTS means that this command only needs to know
- _whether_ a file is modified, not the contents. Also sends Argument
- lines for argc and argv, so should be called after options are sent. */
-void
-send_files (argc, argv, local, aflag, flags)
- int argc;
- char **argv;
- int local;
- int aflag;
- unsigned int flags;
-{
- struct send_data args;
- int err;
-
- send_max_dotdot (argc, argv);
-
- /*
- * aflag controls whether the tag/date is copied into the vers_ts.
- * But we don't actually use it, so I don't think it matters what we pass
- * for aflag here.
- */
- args.build_dirs = flags & SEND_BUILD_DIRS;
- args.force = flags & SEND_FORCE;
- args.no_contents = flags & SEND_NO_CONTENTS;
- args.backup_modified = flags & BACKUP_MODIFIED_FILES;
- err = start_recursion
- (send_fileproc, send_filesdoneproc,
- send_dirent_proc, send_dirleave_proc, (void *) &args,
- argc, argv, local, W_LOCAL, aflag, CVS_LOCK_NONE, (char *) NULL, 0,
- (char *) NULL);
- if (err)
- error_exit ();
- if (toplevel_repos == NULL)
- /*
- * This happens if we are not processing any files,
- * or for checkouts in directories without any existing stuff
- * checked out. The following assignment is correct for the
- * latter case; I don't think toplevel_repos matters for the
- * former.
- */
- toplevel_repos = xstrdup (current_parsed_root->directory);
- send_repository ("", toplevel_repos, ".");
-}
-
-void
-client_import_setup (repository)
- char *repository;
-{
- if (toplevel_repos == NULL) /* should always be true */
- send_a_repository ("", repository, "");
-}
-
-/*
- * Process the argument import file.
- */
-int
-client_process_import_file (message, vfile, vtag, targc, targv, repository,
- all_files_binary, modtime)
- char *message;
- char *vfile;
- char *vtag;
- int targc;
- char *targv[];
- char *repository;
- int all_files_binary;
-
- /* Nonzero for "import -d". */
- int modtime;
-{
- char *update_dir;
- char *fullname;
- Vers_TS vers;
-
- assert (toplevel_repos != NULL);
-
- if (strncmp (repository, toplevel_repos, strlen (toplevel_repos)) != 0)
- error (1, 0,
- "internal error: pathname `%s' doesn't specify file in `%s'",
- repository, toplevel_repos);
-
- if (strcmp (repository, toplevel_repos) == 0)
- {
- update_dir = "";
- fullname = xstrdup (vfile);
- }
- else
- {
- update_dir = repository + strlen (toplevel_repos) + 1;
-
- fullname = xmalloc (strlen (vfile) + strlen (update_dir) + 10);
- strcpy (fullname, update_dir);
- strcat (fullname, "/");
- strcat (fullname, vfile);
- }
-
- send_a_repository ("", repository, update_dir);
- if (all_files_binary)
- {
- vers.options = xmalloc (4); /* strlen("-kb") + 1 */
- strcpy (vers.options, "-kb");
- }
- else
- {
- vers.options = wrap_rcsoption (vfile, 1);
- }
- if (vers.options != NULL)
- {
- if (supported_request ("Kopt"))
- {
- send_to_server ("Kopt ", 0);
- send_to_server (vers.options, 0);
- send_to_server ("\012", 1);
- }
- else
- 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);
- free (fullname);
- return 0;
-}
-
-void
-client_import_done ()
-{
- if (toplevel_repos == NULL)
- /*
- * This happens if we are not processing any files,
- * or for checkouts in directories without any existing stuff
- * checked out. The following assignment is correct for the
- * latter case; I don't think toplevel_repos matters for the
- * former.
- */
- /* FIXME: "can't happen" now that we call client_import_setup
- at the beginning. */
- toplevel_repos = xstrdup (current_parsed_root->directory);
- send_repository ("", toplevel_repos, ".");
-}
-
-
-
-static void
-notified_a_file (data, ent_list, short_pathname, filename)
- char *data;
- List *ent_list;
- char *short_pathname;
- char *filename;
-{
- FILE *fp;
- FILE *newf;
- size_t line_len = 8192;
- char *line = xmalloc (line_len);
- char *cp;
- int nread;
- int nwritten;
- char *p;
-
- fp = open_file (CVSADM_NOTIFY, "r");
- if (getline (&line, &line_len, fp) < 0)
- {
- if (feof (fp))
- error (0, 0, "cannot read %s: end of file", CVSADM_NOTIFY);
- else
- error (0, errno, "cannot read %s", CVSADM_NOTIFY);
- goto error_exit;
- }
- cp = strchr (line, '\t');
- if (cp == NULL)
- {
- error (0, 0, "malformed %s file", CVSADM_NOTIFY);
- goto error_exit;
- }
- *cp = '\0';
- if (strcmp (filename, line + 1) != 0)
- {
- error (0, 0, "protocol error: notified %s, expected %s", filename,
- line + 1);
- }
-
- if (getline (&line, &line_len, fp) < 0)
- {
- if (feof (fp))
- {
- free (line);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", CVSADM_NOTIFY);
- if ( CVS_UNLINK (CVSADM_NOTIFY) < 0)
- error (0, errno, "cannot remove %s", CVSADM_NOTIFY);
- return;
- }
- else
- {
- error (0, errno, "cannot read %s", CVSADM_NOTIFY);
- goto error_exit;
- }
- }
- newf = open_file (CVSADM_NOTIFYTMP, "w");
- if (fputs (line, newf) < 0)
- {
- error (0, errno, "cannot write %s", CVSADM_NOTIFYTMP);
- goto error2;
- }
- while ((nread = fread (line, 1, line_len, fp)) > 0)
- {
- p = line;
- while ((nwritten = fwrite (p, 1, nread, newf)) > 0)
- {
- nread -= nwritten;
- p += nwritten;
- }
- if (ferror (newf))
- {
- error (0, errno, "cannot write %s", CVSADM_NOTIFYTMP);
- goto error2;
- }
- }
- if (ferror (fp))
- {
- error (0, errno, "cannot read %s", CVSADM_NOTIFY);
- goto error2;
- }
- if (fclose (newf) < 0)
- {
- error (0, errno, "cannot close %s", CVSADM_NOTIFYTMP);
- goto error_exit;
- }
- free (line);
- if (fclose (fp) < 0)
- {
- error (0, errno, "cannot close %s", CVSADM_NOTIFY);
- return;
- }
-
- {
- /* In this case, we want rename_file() to ignore noexec. */
- int saved_noexec = noexec;
- noexec = 0;
- rename_file (CVSADM_NOTIFYTMP, CVSADM_NOTIFY);
- noexec = saved_noexec;
- }
-
- return;
- error2:
- (void) fclose (newf);
- error_exit:
- free (line);
- (void) fclose (fp);
-}
-
-static void
-handle_notified (args, len)
- char *args;
- int len;
-{
- call_in_directory (args, notified_a_file, NULL);
-}
-
-void
-client_notify (repository, update_dir, filename, notif_type, val)
- const char *repository;
- const char *update_dir;
- const char *filename;
- int notif_type;
- const char *val;
-{
- char buf[2];
-
- send_a_repository ("", repository, update_dir);
- send_to_server ("Notify ", 0);
- send_to_server (filename, 0);
- send_to_server ("\012", 1);
- buf[0] = notif_type;
- buf[1] = '\0';
- send_to_server (buf, 1);
- send_to_server ("\t", 1);
- send_to_server (val, 0);
-}
-
-/*
- * Send an option with an argument, dealing correctly with newlines in
- * the argument. If ARG is NULL, forget the whole thing.
- */
-void
-option_with_arg (option, arg)
- char *option;
- char *arg;
-{
- if (arg == NULL)
- return;
-
- send_to_server ("Argument ", 0);
- send_to_server (option, 0);
- send_to_server ("\012", 1);
-
- send_arg (arg);
-}
-
-/* Send a date to the server. The input DATE is in RCS format.
- The time will be GMT.
-
- 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. */
-
-void
-client_senddate (date)
- const char *date;
-{
- char buf[MAXDATELEN];
-
- date_to_internet (buf, (char *)date);
- option_with_arg ("-D", buf);
-}
-
-void
-send_init_command ()
-{
- /* This is here because we need the current_parsed_root->directory variable. */
- send_to_server ("init ", 0);
- send_to_server (current_parsed_root->directory, 0);
- send_to_server ("\012", 0);
-}
-
-#endif /* CLIENT_SUPPORT */
diff --git a/contrib/cvs/src/client.h b/contrib/cvs/src/client.h
deleted file mode 100644
index 9afa4e7c1964..000000000000
--- a/contrib/cvs/src/client.h
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 1994-2008 The Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-/* Interface between the client and the rest of CVS. */
-
-/* Stuff shared with the server. */
-extern char *mode_to_string PROTO((mode_t));
-extern int change_mode PROTO((char *, char *, int));
-
-extern int gzip_level;
-extern int file_gzip_level;
-
-#if defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT)
-
-/* Whether the connection should be encrypted. */
-extern int cvsencrypt;
-
-/* Whether the connection should use per-packet authentication. */
-extern int cvsauthenticate;
-
-#ifdef __STDC__
-struct buffer;
-#endif
-
-# ifdef ENCRYPTION
-
-# ifdef HAVE_KERBEROS
-
-/* We can't declare the arguments without including krb.h, and I don't
- want to do that in every file. */
-extern struct buffer *krb_encrypt_buffer_initialize ();
-
-# endif /* HAVE_KERBEROS */
-
-# ifdef HAVE_GSSAPI
-
-/* Set this to turn on GSSAPI encryption. */
-extern int cvs_gssapi_encrypt;
-
-# endif /* HAVE_GSSAPI */
-
-# endif /* ENCRYPTION */
-
-# ifdef HAVE_GSSAPI
-
-/* We can't declare the arguments without including gssapi.h, and I
- don't want to do that in every file. */
-extern struct buffer *cvs_gssapi_wrap_buffer_initialize ();
-
-# endif /* HAVE_GSSAPI */
-
-#endif /* defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT) */
-
-#ifdef CLIENT_SUPPORT
-/*
- * Flag variable for seeing whether the server has been started yet.
- * As of this writing, only edit.c:cvs_notify_check() uses it.
- */
-extern int server_started;
-
-/* Is the -P option to checkout or update specified? */
-extern int client_prune_dirs;
-
-# ifdef AUTH_CLIENT_SUPPORT
-extern int use_authenticating_server;
-# endif /* AUTH_CLIENT_SUPPORT */
-# if defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_GSSAPI)
-void connect_to_pserver PROTO ((cvsroot_t *,
- struct buffer **,
- struct buffer **,
- int, int ));
-# ifndef CVS_AUTH_PORT
-# define CVS_AUTH_PORT 2401
-# endif /* CVS_AUTH_PORT */
-# endif /* (AUTH_CLIENT_SUPPORT) || defined (HAVE_GSSAPI) */
-
-# if HAVE_KERBEROS
-# ifndef CVS_PORT
-# define CVS_PORT 1999
-# endif
-# endif /* HAVE_KERBEROS */
-
-/* Talking to the server. */
-void send_to_server PROTO((const char *str, size_t len));
-void read_from_server PROTO((char *buf, size_t len));
-
-/* Internal functions that handle client communication to server, etc. */
-int supported_request PROTO ((char *));
-void option_with_arg PROTO((char *option, char *arg));
-
-/* Get the responses and then close the connection. */
-extern int get_responses_and_close PROTO((void));
-
-extern int get_server_responses PROTO((void));
-
-/* Start up the connection to the server on the other end. */
-void
-start_server PROTO((void));
-
-/* Send the names of all the argument files to the server. */
-void
-send_file_names PROTO((int argc, char **argv, unsigned int flags));
-
-/* Flags for send_file_names. */
-/* Expand wild cards? */
-# define SEND_EXPAND_WILD 1
-
-/*
- * Send Repository, Modified and Entry. argc and argv contain only
- * the files to operate on (or empty for everything), not options.
- * local is nonzero if we should not recurse (-l option).
- */
-void
-send_files PROTO((int argc, char **argv, int local, int aflag,
- unsigned int flags));
-
-/* Flags for send_files. */
-# define SEND_BUILD_DIRS 1
-# define SEND_FORCE 2
-# define SEND_NO_CONTENTS 4
-# define BACKUP_MODIFIED_FILES 8
-
-/* Send an argument to the remote server. */
-void
-send_arg PROTO((const char *string));
-
-/* Send a string of single-char options to the remote server, one by one. */
-void send_options PROTO ((int argc, char * const *argv));
-
-extern void send_a_repository PROTO ((const char *, const char *,
- const char *));
-
-#endif /* CLIENT_SUPPORT */
-
-/*
- * This structure is used to catalog the responses the client is
- * prepared to see from the server.
- */
-
-struct response
-{
- /* Name of the response. */
- char *name;
-
-#ifdef CLIENT_SUPPORT
- /*
- * Function to carry out the response. ARGS is the text of the
- * command after name and, if present, a single space, have been
- * stripped off. The function can scribble into ARGS if it wants.
- * Note that although LEN is given, ARGS is also guaranteed to be
- * '\0' terminated.
- */
- void (*func) PROTO((char *args, int len));
-
- /*
- * ok and error are special; they indicate we are at the end of the
- * responses, and error indicates we should exit with nonzero
- * exitstatus.
- */
- enum {response_type_normal, response_type_ok, response_type_error} type;
-#endif
-
- /* Used by the server to indicate whether response is supported by
- the client, as set by the Valid-responses request. */
- enum {
- /*
- * Failure to implement this response can imply a fatal
- * error. This should be set only for responses which were in the
- * original version of the protocol; it should not be set for new
- * responses.
- */
- rs_essential,
-
- /* Some clients might not understand this response. */
- rs_optional,
-
- /*
- * Set by the server to one of the following based on what this
- * client actually supports.
- */
- rs_supported,
- rs_not_supported
- } status;
-};
-
-/* Table of responses ending in an entry with a NULL name. */
-
-extern struct response responses[];
-
-#ifdef CLIENT_SUPPORT
-
-extern void client_senddate PROTO((const char *date));
-extern void client_expand_modules PROTO((int argc, char **argv, int local));
-extern void client_send_expansions PROTO((int local, char *where,
- int build_dirs));
-extern void client_nonexpanded_setup PROTO((void));
-
-extern void send_init_command PROTO ((void));
-
-extern char **failed_patches;
-extern int failed_patches_count;
-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 modtime));
-extern void client_import_done PROTO((void));
-extern void client_notify PROTO((const char *, const char *, const char *, int,
- const char *));
-#endif /* CLIENT_SUPPORT */
diff --git a/contrib/cvs/src/commit.c b/contrib/cvs/src/commit.c
deleted file mode 100644
index b3ba47b38dbe..000000000000
--- a/contrib/cvs/src/commit.c
+++ /dev/null
@@ -1,2433 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Commit Files
- *
- * "commit" commits the present version to the RCS repository, AFTER
- * having done a test on conflicts.
- *
- * The call is: cvs commit [options] files...
- *
- * $FreeBSD$
- */
-
-#include <assert.h>
-#include "cvs.h"
-#include "getline.h"
-#include "edit.h"
-#include "fileattr.h"
-#include "hardlink.h"
-
-static Dtype check_direntproc PROTO ((void *callerdat, const char *dir,
- const char *repos,
- const char *update_dir,
- List *entries));
-static int check_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-static int check_filesdoneproc PROTO ((void *callerdat, int err,
- const char *repos,
- const char *update_dir,
- List *entries));
-static int checkaddfile PROTO((const char *file, const char *repository,
- const char *tag, const char *options,
- RCSNode **rcsnode));
-static Dtype commit_direntproc PROTO ((void *callerdat, const char *dir,
- const char *repos,
- const char *update_dir,
- List *entries));
-static int commit_dirleaveproc PROTO ((void *callerdat, const char *dir,
- int err, const char *update_dir,
- List *entries));
-static int commit_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-static int commit_filesdoneproc PROTO ((void *callerdat, int err,
- const char *repository,
- const char *update_dir,
- List *entries));
-static int finaladd PROTO((struct file_info *finfo, char *revision, char *tag,
- char *options));
-static int findmaxrev PROTO((Node * p, void *closure));
-static int lock_RCS PROTO((const char *user, RCSNode *rcs, const char *rev,
- const char *repository));
-static int precommit_list_proc PROTO((Node * p, void *closure));
-static int precommit_proc PROTO((const char *repository, const char *filter));
-static int remove_file PROTO ((struct file_info *finfo, char *tag,
- char *message));
-static void fixaddfile PROTO((const char *rcs));
-static void fixbranch PROTO((RCSNode *, char *branch));
-static void unlockrcs PROTO((RCSNode *rcs));
-static void ci_delproc PROTO((Node *p));
-static void masterlist_delproc PROTO((Node *p));
-
-struct commit_info
-{
- Ctype status; /* as returned from Classify_File() */
- char *rev; /* a numeric rev, if we know it */
- char *tag; /* any sticky tag, or -r option */
- char *options; /* Any sticky -k option */
-};
-struct master_lists
-{
- List *ulist; /* list for Update_Logfile */
- List *cilist; /* list with commit_info structs */
-};
-
-static int force_ci = 0;
-static int got_message;
-static int aflag;
-static char *saved_tag;
-static char *write_dirtag;
-static int write_dirnonbranch;
-static char *logfile;
-static List *mulist;
-static List *saved_ulist;
-static char *saved_message;
-static time_t last_register_time;
-
-static const char *const commit_usage[] =
-{
- "Usage: %s %s [-Rlf] [-m msg | -F logfile] [-r rev] files...\n",
- " -R Process directories recursively.\n",
- " -l Local directory only (not recursive).\n",
- " -f Force the file to be committed; disables recursion.\n",
- " -F logfile Read the log message from file.\n",
- " -m msg Log message.\n",
- " -r rev Commit to this branch or trunk revision.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-#ifdef CLIENT_SUPPORT
-/* Identify a file which needs "? foo" or a Questionable request. */
-struct question {
- /* The two fields for the Directory request. */
- char *dir;
- char *repos;
-
- /* The file name. */
- char *file;
-
- struct question *next;
-};
-
-struct find_data {
- List *ulist;
- int argc;
- char **argv;
-
- /* This is used from dirent to filesdone time, for each directory,
- to make a list of files we have already seen. */
- List *ignlist;
-
- /* Linked list of files which need "? foo" or a Questionable request. */
- struct question *questionables;
-
- /* Only good within functions called from the filesdoneproc. Stores
- the repository (pointer into storage managed by the recursion
- processor. */
- const char *repository;
-
- /* Non-zero if we should force the commit. This is enabled by
- either -f or -r options, unlike force_ci which is just -f. */
- int force;
-};
-
-
-
-static Dtype find_dirent_proc PROTO ((void *callerdat, const char *dir,
- const char *repository,
- const char *update_dir,
- List *entries));
-
-static Dtype
-find_dirent_proc (callerdat, dir, repository, update_dir, entries)
- void *callerdat;
- const char *dir;
- const char *repository;
- const char *update_dir;
- List *entries;
-{
- struct find_data *find_data = (struct find_data *)callerdat;
-
- /* This check seems to slowly be creeping throughout CVS (update
- and send_dirent_proc by CVS 1.5, diff in 31 Oct 1995. My guess
- is that it (or some variant thereof) should go in all the
- dirent procs. Unless someone has some better idea... */
- if (!isdir (dir))
- return R_SKIP_ALL;
-
- /* initialize the ignore list for this directory */
- find_data->ignlist = getlist ();
-
- /* Print the same warm fuzzy as in check_direntproc, since that
- code will never be run during client/server operation and we
- want the messages to match. */
- if (!quiet)
- error (0, 0, "Examining %s", update_dir);
-
- return R_PROCESS;
-}
-
-
-
-/* Here as a static until we get around to fixing ignore_files to pass
- it along as an argument. */
-static struct find_data *find_data_static;
-
-
-
-static void find_ignproc PROTO ((const char *, const char *));
-
-static void
-find_ignproc (file, dir)
- const char *file;
- const char *dir;
-{
- struct question *p;
-
- p = (struct question *) xmalloc (sizeof (struct question));
- p->dir = xstrdup (dir);
- p->repos = xstrdup (find_data_static->repository);
- p->file = xstrdup (file);
- p->next = find_data_static->questionables;
- find_data_static->questionables = p;
-}
-
-
-
-static int find_filesdoneproc PROTO ((void *callerdat, int err,
- const char *repository,
- const char *update_dir,
- List *entries));
-
-static int
-find_filesdoneproc (callerdat, err, repository, update_dir, entries)
- void *callerdat;
- int err;
- const char *repository;
- const char *update_dir;
- List *entries;
-{
- struct find_data *find_data = (struct find_data *)callerdat;
- find_data->repository = repository;
-
- /* if this directory has an ignore list, process it then free it */
- if (find_data->ignlist)
- {
- find_data_static = find_data;
- ignore_files (find_data->ignlist, entries, update_dir, find_ignproc);
- dellist (&find_data->ignlist);
- }
-
- find_data->repository = NULL;
-
- return err;
-}
-
-
-
-static int find_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-
-/* Machinery to find out what is modified, added, and removed. It is
- possible this should be broken out into a new client_classify function;
- merging it with classify_file is almost sure to be a mess, though,
- because classify_file has all kinds of repository processing. */
-static int
-find_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- Vers_TS *vers;
- enum classify_type status;
- Node *node;
- struct find_data *args = (struct find_data *)callerdat;
- struct logfile_info *data;
- struct file_info xfinfo;
-
- /* if this directory has an ignore list, add this file to it */
- if (args->ignlist)
- {
- Node *p;
-
- p = getnode ();
- p->type = FILES;
- p->key = xstrdup (finfo->file);
- if (addnode (args->ignlist, p) != 0)
- freenode (p);
- }
-
- xfinfo = *finfo;
- xfinfo.repository = NULL;
- xfinfo.rcs = NULL;
-
- vers = Version_TS (&xfinfo, NULL, saved_tag, NULL, 0, 0);
- if (vers->vn_user == NULL)
- {
- if (vers->ts_user == NULL)
- error (0, 0, "nothing known about `%s'", finfo->fullname);
- else
- error (0, 0, "use `%s add' to create an entry for %s",
- program_name, finfo->fullname);
- freevers_ts (&vers);
- return 1;
- }
- if (vers->vn_user[0] == '-')
- {
- if (vers->ts_user != NULL)
- {
- error (0, 0,
- "`%s' should be removed and is still there (or is back"
- " again)", finfo->fullname);
- freevers_ts (&vers);
- return 1;
- }
- /* else */
- status = T_REMOVED;
- }
- else if (strcmp (vers->vn_user, "0") == 0)
- {
- if (vers->ts_user == NULL)
- {
- /* This happens when one has `cvs add'ed a file, but it no
- longer exists in the working directory at commit time.
- FIXME: What classify_file does in this case is print
- "new-born %s has disappeared" and removes the entry.
- We probably should do the same. */
- if (!really_quiet)
- error (0, 0, "warning: new-born %s has disappeared",
- finfo->fullname);
- status = T_REMOVE_ENTRY;
- }
- else
- status = T_ADDED;
- }
- else if (vers->ts_user == NULL)
- {
- /* FIXME: What classify_file does in this case is print
- "%s was lost". We probably should do the same. */
- freevers_ts (&vers);
- return 0;
- }
- else if (vers->ts_rcs != NULL
- && (args->force || strcmp (vers->ts_user, vers->ts_rcs) != 0))
- /* If we are forcing commits, pretend that the file is
- modified. */
- status = T_MODIFIED;
- else
- {
- /* This covers unmodified files, as well as a variety of other
- cases. FIXME: we probably should be printing a message and
- returning 1 for many of those cases (but I'm not sure
- exactly which ones). */
- freevers_ts (&vers);
- return 0;
- }
-
- node = getnode ();
- node->key = xstrdup (finfo->fullname);
-
- data = (struct logfile_info *) xmalloc (sizeof (struct logfile_info));
- data->type = status;
- data->tag = xstrdup (vers->tag);
- data->rev_old = data->rev_new = NULL;
-
- node->type = UPDATE;
- node->delproc = update_delproc;
- node->data = data;
- (void)addnode (args->ulist, node);
-
- ++args->argc;
-
- freevers_ts (&vers);
- return 0;
-}
-
-
-
-static int copy_ulist PROTO ((Node *, void *));
-
-static int
-copy_ulist (node, data)
- Node *node;
- void *data;
-{
- struct find_data *args = (struct find_data *)data;
- args->argv[args->argc++] = node->key;
- return 0;
-}
-#endif /* CLIENT_SUPPORT */
-
-#ifdef SERVER_SUPPORT
-# define COMMIT_OPTIONS "+nlRm:fF:r:"
-#else /* !SERVER_SUPPORT */
-# define COMMIT_OPTIONS "+lRm:fF:r:"
-#endif /* SERVER_SUPPORT */
-int
-commit (argc, argv)
- int argc;
- char **argv;
-{
- int c;
- int err = 0;
- int local = 0;
-
- if (argc == -1)
- usage (commit_usage);
-
-#ifdef CVS_BADROOT
- /*
- * For log purposes, do not allow "root" to commit files. If you look
- * like root, but are really logged in as a non-root user, it's OK.
- */
- /* FIXME: Shouldn't this check be much more closely related to the
- readonly user stuff (CVSROOT/readers, &c). That is, why should
- root be able to "cvs init", "cvs import", &c, but not "cvs ci"? */
- /* Who we are on the client side doesn't affect logging. */
- if (geteuid () == (uid_t) 0 && !current_parsed_root->isremote)
- {
- struct passwd *pw;
-
- if ((pw = (struct passwd *) getpwnam (getcaller ())) == NULL)
- error (1, 0,
- "your apparent username (%s) is unknown to this system",
- getcaller ());
- if (pw->pw_uid == (uid_t) 0)
- error (1, 0, "'root' is not allowed to commit files");
- }
-#endif /* CVS_BADROOT */
-
- optind = 0;
- while ((c = getopt (argc, argv, COMMIT_OPTIONS)) != -1)
- {
- switch (c)
- {
-#ifdef SERVER_SUPPORT
- case 'n':
- /* Silently ignore -n for compatibility with old
- * clients.
- */
- if (!server_active) error(0, 0, "the `-n' option is obsolete");
- break;
-#endif /* SERVER_SUPPORT */
- case 'm':
-#ifdef FORCE_USE_EDITOR
- use_editor = 1;
-#else
- use_editor = 0;
-#endif
- if (saved_message)
- {
- free (saved_message);
- saved_message = NULL;
- }
-
- saved_message = xstrdup(optarg);
- break;
- case 'r':
- if (saved_tag)
- free (saved_tag);
- saved_tag = xstrdup (optarg);
- break;
- case 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case 'f':
- force_ci = 1;
- local = 1; /* also disable recursion */
- break;
- case 'F':
-#ifdef FORCE_USE_EDITOR
- use_editor = 1;
-#else
- use_editor = 0;
-#endif
- logfile = optarg;
- break;
- case '?':
- default:
- usage (commit_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- /* numeric specified revision means we ignore sticky tags... */
- if (saved_tag && isdigit ((unsigned char) *saved_tag))
- {
- char *p = saved_tag + strlen (saved_tag);
- aflag = 1;
- /* strip trailing dots and leading zeros */
- while (*--p == '.') ;
- p[1] = '\0';
- while (saved_tag[0] == '0' && isdigit ((unsigned char) saved_tag[1]))
- ++saved_tag;
- }
-
- /* some checks related to the "-F logfile" option */
- if (logfile)
- {
- size_t size = 0, len;
-
- if (saved_message)
- error (1, 0, "cannot specify both a message and a log file");
-
- get_file (logfile, logfile, "r", &saved_message, &size, &len);
- }
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- struct find_data find_args;
-
- ign_setup ();
-
- find_args.ulist = getlist ();
- find_args.argc = 0;
- find_args.questionables = NULL;
- find_args.ignlist = NULL;
- find_args.repository = NULL;
-
- /* It is possible that only a numeric tag should set this.
- I haven't really thought about it much.
- Anyway, I suspect that setting it unnecessarily only causes
- a little unneeded network traffic. */
- find_args.force = force_ci || saved_tag != NULL;
-
- err = start_recursion (find_fileproc, find_filesdoneproc,
- find_dirent_proc, (DIRLEAVEPROC) NULL,
- (void *)&find_args,
- argc, argv, local, W_LOCAL, 0, CVS_LOCK_NONE,
- (char *) NULL, 0, (char *) NULL);
- if (err)
- error (1, 0, "correct above errors first!");
-
- if (find_args.argc == 0)
- {
- /* Nothing to commit. Exit now without contacting the
- server (note that this means that we won't print "?
- foo" for files which merit it, because we don't know
- what is in the CVSROOT/cvsignore file). */
- dellist (&find_args.ulist);
- return 0;
- }
-
- /* Now we keep track of which files we actually are going to
- operate on, and only work with those files in the future.
- This saves time--we don't want to search the file system
- of the working directory twice. */
- if (size_overflow_p (xtimes (find_args.argc, sizeof (char **))))
- {
- find_args.argc = 0;
- return 0;
- }
- find_args.argv = xmalloc (xtimes (find_args.argc, sizeof (char **)));
- find_args.argc = 0;
- walklist (find_args.ulist, copy_ulist, &find_args);
-
- /* Do this before calling do_editor; don't ask for a log
- message if we can't talk to the server. But do it after we
- have made the checks that we can locally (to more quickly
- catch syntax errors, the case where no files are modified,
- added or removed, etc.).
-
- On the other hand, calling start_server before do_editor
- means that we chew up server resources the whole time that
- the user has the editor open (hours or days if the user
- forgets about it), which seems dubious. */
- start_server ();
-
- /*
- * We do this once, not once for each directory as in normal CVS.
- * The protocol is designed this way. This is a feature.
- */
- if (use_editor)
- do_editor (".", &saved_message, (char *)NULL, find_args.ulist);
-
- /* We always send some sort of message, even if empty. */
- option_with_arg ("-m", saved_message ? saved_message : "");
-
- /* OK, now process all the questionable files we have been saving
- up. */
- {
- struct question *p;
- struct question *q;
-
- p = find_args.questionables;
- while (p != NULL)
- {
- if (ign_inhibit_server || !supported_request ("Questionable"))
- {
- cvs_output ("? ", 2);
- if (p->dir[0] != '\0')
- {
- cvs_output (p->dir, 0);
- cvs_output ("/", 1);
- }
- cvs_output (p->file, 0);
- cvs_output ("\n", 1);
- }
- else
- {
- send_to_server ("Directory ", 0);
- send_to_server (p->dir[0] == '\0' ? "." : p->dir, 0);
- send_to_server ("\012", 1);
- send_to_server (p->repos, 0);
- send_to_server ("\012", 1);
-
- send_to_server ("Questionable ", 0);
- send_to_server (p->file, 0);
- send_to_server ("\012", 1);
- }
- free (p->dir);
- free (p->repos);
- free (p->file);
- q = p->next;
- free (p);
- p = q;
- }
- }
-
- if (local)
- send_arg("-l");
- if (force_ci)
- send_arg("-f");
- option_with_arg ("-r", saved_tag);
- send_arg ("--");
-
- /* FIXME: This whole find_args.force/SEND_FORCE business is a
- kludge. It would seem to be a server bug that we have to
- say that files are modified when they are not. This makes
- "cvs commit -r 2" across a whole bunch of files a very slow
- operation (and it isn't documented in cvsclient.texi). I
- haven't looked at the server code carefully enough to be
- _sure_ why this is needed, but if it is because the "ci"
- program, which we used to call, wanted the file to exist,
- then it would be relatively simple to fix in the server. */
- send_files (find_args.argc, find_args.argv, local, 0,
- find_args.force ? SEND_FORCE : 0);
-
- /* Sending only the names of the files which were modified, added,
- or removed means that the server will only do an up-to-date
- check on those files. This is different from local CVS and
- previous versions of client/server CVS, but it probably is a Good
- Thing, or at least Not Such A Bad Thing. */
- send_file_names (find_args.argc, find_args.argv, 0);
- free (find_args.argv);
- dellist (&find_args.ulist);
-
- send_to_server ("ci\012", 0);
- err = get_responses_and_close ();
- if (err != 0 && use_editor && saved_message != NULL)
- {
- /* If there was an error, don't nuke the user's carefully
- constructed prose. This is something of a kludge; a better
- solution is probably more along the lines of #150 in TODO
- (doing a second up-to-date check before accepting the
- log message has also been suggested, but that seems kind of
- iffy because the real up-to-date check could still fail,
- another error could occur, &c. Also, a second check would
- slow things down). */
-
- char *fname;
- FILE *fp;
-
- fp = cvs_temp_file (&fname);
- if (fp == NULL)
- error (1, 0, "cannot create temporary file %s",
- fname ? fname : "(null)");
- if (fwrite (saved_message, 1, strlen (saved_message), fp)
- != strlen (saved_message))
- error (1, errno, "cannot write temporary file %s", fname);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close temporary file %s", fname);
- error (0, 0, "saving log message in %s", fname);
- free (fname);
- }
- return err;
- }
-#endif
-
- if (saved_tag != NULL)
- tag_check_valid (saved_tag, argc, argv, local, aflag, "");
-
- /* XXX - this is not the perfect check for this */
- if (argc <= 0)
- write_dirtag = saved_tag;
-
- wrap_setup ();
-
- lock_tree_for_write (argc, argv, local, W_LOCAL, aflag);
-
- /*
- * Set up the master update list and hard link list
- */
- mulist = getlist ();
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- if (preserve_perms)
- {
- hardlist = getlist ();
-
- /*
- * We need to save the working directory so that
- * check_fileproc can construct a full pathname for each file.
- */
- working_dir = xgetwd();
- }
-#endif
-
- /*
- * Run the recursion processor to verify the files are all up-to-date
- */
- err = start_recursion (check_fileproc, check_filesdoneproc,
- check_direntproc, (DIRLEAVEPROC) NULL, NULL, argc,
- argv, local, W_LOCAL, aflag, CVS_LOCK_NONE,
- (char *) NULL, 1, (char *) NULL);
- if (err)
- {
- Lock_Cleanup ();
- error (1, 0, "correct above errors first!");
- }
-
- /*
- * Run the recursion processor to commit the files
- */
- write_dirnonbranch = 0;
- if (noexec == 0)
- err = start_recursion (commit_fileproc, commit_filesdoneproc,
- commit_direntproc, commit_dirleaveproc, NULL,
- argc, argv, local, W_LOCAL, aflag, CVS_LOCK_NONE,
- (char *) NULL, 1, (char *) NULL);
-
- /*
- * Unlock all the dirs and clean up
- */
- Lock_Cleanup ();
- dellist (&mulist);
-
- if (server_active)
- return err;
-
- /* see if we need to sleep before returning to avoid time-stamp races */
- if (last_register_time)
- {
- sleep_past (last_register_time);
- }
-
- return err;
-}
-
-
-
-/* This routine determines the status of a given file and retrieves
- the version information that is associated with that file. */
-
-static
-Ctype
-classify_file_internal (finfo, vers)
- struct file_info *finfo;
- Vers_TS **vers;
-{
- int save_noexec, save_quiet, save_really_quiet;
- Ctype status;
-
- /* FIXME: Do we need to save quiet as well as really_quiet? Last
- time I glanced at Classify_File I only saw it looking at really_quiet
- not quiet. */
- save_noexec = noexec;
- save_quiet = quiet;
- save_really_quiet = really_quiet;
- noexec = quiet = really_quiet = 1;
-
- /* handle specified numeric revision specially */
- if (saved_tag && isdigit ((unsigned char) *saved_tag))
- {
- /* If the tag is for the trunk, make sure we're at the head */
- if (numdots (saved_tag) < 2)
- {
- status = Classify_File (finfo, (char *) NULL, (char *) NULL,
- (char *) NULL, 1, aflag, vers, 0);
- if (status == T_UPTODATE || status == T_MODIFIED ||
- status == T_ADDED)
- {
- Ctype xstatus;
-
- freevers_ts (vers);
- xstatus = Classify_File (finfo, saved_tag, (char *) NULL,
- (char *) NULL, 1, aflag, vers, 0);
- if (xstatus == T_REMOVE_ENTRY)
- status = T_MODIFIED;
- else if (status == T_MODIFIED && xstatus == T_CONFLICT)
- status = T_MODIFIED;
- else
- status = xstatus;
- }
- }
- else
- {
- char *xtag, *cp;
-
- /*
- * The revision is off the main trunk; make sure we're
- * up-to-date with the head of the specified branch.
- */
- xtag = xstrdup (saved_tag);
- if ((numdots (xtag) & 1) != 0)
- {
- cp = strrchr (xtag, '.');
- *cp = '\0';
- }
- status = Classify_File (finfo, xtag, (char *) NULL,
- (char *) NULL, 1, aflag, vers, 0);
- if ((status == T_REMOVE_ENTRY || status == T_CONFLICT)
- && (cp = strrchr (xtag, '.')) != NULL)
- {
- /* pluck one more dot off the revision */
- *cp = '\0';
- freevers_ts (vers);
- status = Classify_File (finfo, xtag, (char *) NULL,
- (char *) NULL, 1, aflag, vers, 0);
- if (status == T_UPTODATE || status == T_REMOVE_ENTRY)
- status = T_MODIFIED;
- }
- /* now, muck with vers to make the tag correct */
- free ((*vers)->tag);
- (*vers)->tag = xstrdup (saved_tag);
- free (xtag);
- }
- }
- else
- status = Classify_File (finfo, saved_tag, (char *) NULL, (char *) NULL,
- 1, 0, vers, 0);
- noexec = save_noexec;
- quiet = save_quiet;
- really_quiet = save_really_quiet;
-
- return status;
-}
-
-
-
-/*
- * Check to see if a file is ok to commit and make sure all files are
- * up-to-date
- */
-/* ARGSUSED */
-static int
-check_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- Ctype status;
- const char *xdir;
- Node *p;
- List *ulist, *cilist;
- Vers_TS *vers;
- struct commit_info *ci;
- struct logfile_info *li;
-
- size_t cvsroot_len = strlen (current_parsed_root->directory);
-
- if (!finfo->repository)
- {
- error (0, 0, "nothing known about `%s'", finfo->fullname);
- return 1;
- }
-
- if (strncmp (finfo->repository, current_parsed_root->directory,
- cvsroot_len) == 0
- && ISDIRSEP (finfo->repository[cvsroot_len])
- && strncmp (finfo->repository + cvsroot_len + 1,
- CVSROOTADM,
- sizeof (CVSROOTADM) - 1) == 0
- && ISDIRSEP (finfo->repository[cvsroot_len + sizeof (CVSROOTADM)])
- && strcmp (finfo->repository + cvsroot_len + sizeof (CVSROOTADM) + 1,
- CVSNULLREPOS) == 0
- )
- error (1, 0, "cannot check in to %s", finfo->repository);
-
- status = classify_file_internal (finfo, &vers);
-
- /*
- * If the force-commit option is enabled, and the file in question
- * appears to be up-to-date, just make it look modified so that
- * it will be committed.
- */
- if (force_ci && status == T_UPTODATE)
- status = T_MODIFIED;
-
- switch (status)
- {
- case T_CHECKOUT:
- case T_PATCH:
- case T_NEEDS_MERGE:
- case T_REMOVE_ENTRY:
- error (0, 0, "Up-to-date check failed for `%s'", finfo->fullname);
- freevers_ts (&vers);
- return 1;
- case T_CONFLICT:
- case T_MODIFIED:
- case T_ADDED:
- case T_REMOVED:
- /*
- * some quick sanity checks; if no numeric -r option specified:
- * - can't have a sticky date
- * - can't have a sticky tag that is not a branch
- * Also,
- * - if status is T_REMOVED, file must not exist and its entry
- * can't have a numeric sticky tag.
- * - if status is T_ADDED, rcs file must not exist unless on
- * a branch or head is dead
- * - if status is T_ADDED, can't have a non-trunk numeric rev
- * - if status is T_MODIFIED and a Conflict marker exists, don't
- * allow the commit if timestamp is identical or if we find
- * an RCS_MERGE_PAT in the file.
- */
- if (!saved_tag || !isdigit ((unsigned char) *saved_tag))
- {
- if (vers->date)
- {
- error (0, 0,
- "cannot commit with sticky date for file `%s'",
- finfo->fullname);
- freevers_ts (&vers);
- return 1;
- }
- if (status == T_MODIFIED && vers->tag &&
- !RCS_isbranch (finfo->rcs, vers->tag))
- {
- error (0, 0,
- "sticky tag `%s' for file `%s' is not a branch",
- vers->tag, finfo->fullname);
- freevers_ts (&vers);
- return 1;
- }
- }
- if (status == T_CONFLICT && !force_ci)
- {
- error (0, 0,
- "file `%s' had a conflict and has not been modified",
- finfo->fullname);
- freevers_ts (&vers);
- return 1;
- }
- if (status == T_MODIFIED && !force_ci && file_has_markers (finfo))
- {
- /* Make this a warning, not an error, because we have
- no way of knowing whether the "conflict indicators"
- are really from a conflict or whether they are part
- of the document itself (cvs.texinfo and sanity.sh in
- CVS itself, for example, tend to want to have strings
- like ">>>>>>>" at the start of a line). Making people
- kludge this the way they need to kludge keyword
- expansion seems undesirable. And it is worse than
- keyword expansion, because there is no -ko
- analogue. */
- error (0, 0,
- "\
-warning: file `%s' seems to still contain conflict indicators",
- finfo->fullname);
- }
-
- if (status == T_REMOVED)
- {
- if (vers->ts_user != NULL)
- {
- error (0, 0,
- "`%s' should be removed and is still there (or is"
- " back again)", finfo->fullname);
- freevers_ts (&vers);
- return 1;
- }
-
- if (vers->tag && isdigit ((unsigned char) *vers->tag))
- {
- /* Remove also tries to forbid this, but we should check
- here. I'm only _sure_ about somewhat obscure cases
- (hacking the Entries file, using an old version of
- CVS for the remove and a new one for the commit), but
- there might be other cases. */
- error (0, 0,
- "cannot remove file `%s' which has a numeric sticky"
- " tag of `%s'", finfo->fullname, vers->tag);
- freevers_ts (&vers);
- return 1;
- }
- }
- if (status == T_ADDED)
- {
- if (vers->tag == NULL)
- {
- if (finfo->rcs != NULL &&
- !RCS_isdead (finfo->rcs, finfo->rcs->head))
- {
- error (0, 0,
- "cannot add file `%s' when RCS file `%s' already exists",
- finfo->fullname, finfo->rcs->path);
- freevers_ts (&vers);
- return 1;
- }
- }
- else if (isdigit ((unsigned char) *vers->tag) &&
- numdots (vers->tag) > 1)
- {
- error (0, 0,
- "cannot add file `%s' with revision `%s'; must be on trunk",
- finfo->fullname, vers->tag);
- freevers_ts (&vers);
- return 1;
- }
- }
-
- /* done with consistency checks; now, to get on with the commit */
- if (finfo->update_dir[0] == '\0')
- xdir = ".";
- else
- xdir = finfo->update_dir;
- if ((p = findnode (mulist, xdir)) != NULL)
- {
- ulist = ((struct master_lists *) p->data)->ulist;
- cilist = ((struct master_lists *) p->data)->cilist;
- }
- else
- {
- struct master_lists *ml;
-
- ulist = getlist ();
- cilist = getlist ();
- p = getnode ();
- p->key = xstrdup (xdir);
- p->type = UPDATE;
- ml = (struct master_lists *)
- xmalloc (sizeof (struct master_lists));
- ml->ulist = ulist;
- ml->cilist = cilist;
- p->data = ml;
- p->delproc = masterlist_delproc;
- (void) addnode (mulist, p);
- }
-
- /* first do ulist, then cilist */
- p = getnode ();
- p->key = xstrdup (finfo->file);
- p->type = UPDATE;
- p->delproc = update_delproc;
- li = ((struct logfile_info *)
- xmalloc (sizeof (struct logfile_info)));
- li->type = status;
- li->tag = xstrdup (vers->tag);
- li->rev_old = xstrdup (vers->vn_rcs);
- li->rev_new = NULL;
- p->data = li;
- (void) addnode (ulist, p);
-
- p = getnode ();
- p->key = xstrdup (finfo->file);
- p->type = UPDATE;
- p->delproc = ci_delproc;
- ci = (struct commit_info *) xmalloc (sizeof (struct commit_info));
- ci->status = status;
- if (vers->tag)
- if (isdigit ((unsigned char) *vers->tag))
- ci->rev = xstrdup (vers->tag);
- else
- ci->rev = RCS_whatbranch (finfo->rcs, vers->tag);
- else
- ci->rev = (char *) NULL;
- ci->tag = xstrdup (vers->tag);
- ci->options = xstrdup(vers->options);
- p->data = ci;
- (void) addnode (cilist, p);
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- if (preserve_perms)
- {
- /* Add this file to hardlist, indexed on its inode. When
- we are done, we can find out what files are hardlinked
- to a given file by looking up its inode in hardlist. */
- char *fullpath;
- Node *linkp;
- struct hardlink_info *hlinfo;
-
- /* Get the full pathname of the current file. */
- fullpath = xmalloc (strlen(working_dir) +
- strlen(finfo->fullname) + 2);
- sprintf (fullpath, "%s/%s", working_dir, finfo->fullname);
-
- /* To permit following links in subdirectories, files
- are keyed on finfo->fullname, not on finfo->name. */
- linkp = lookup_file_by_inode (fullpath);
-
- /* If linkp is NULL, the file doesn't exist... maybe
- we're doing a remove operation? */
- if (linkp != NULL)
- {
- /* Create a new hardlink_info node, which will record
- the current file's status and the links listed in its
- `hardlinks' delta field. We will append this
- hardlink_info node to the appropriate hardlist entry. */
- hlinfo = (struct hardlink_info *)
- xmalloc (sizeof (struct hardlink_info));
- hlinfo->status = status;
- linkp->data = hlinfo;
- }
- }
-#endif
-
- break;
- case T_UNKNOWN:
- error (0, 0, "nothing known about `%s'", finfo->fullname);
- freevers_ts (&vers);
- return 1;
- case T_UPTODATE:
- break;
- default:
- error (0, 0, "CVS internal error: unknown status %d", status);
- break;
- }
-
- freevers_ts (&vers);
- return 0;
-}
-
-
-
-/*
- * By default, return the code that tells do_recursion to examine all
- * directories
- */
-/* ARGSUSED */
-static Dtype
-check_direntproc (callerdat, dir, repos, update_dir, entries)
- void *callerdat;
- const char *dir;
- const char *repos;
- const char *update_dir;
- List *entries;
-{
- if (!isdir (dir))
- return R_SKIP_ALL;
-
- if (!quiet)
- error (0, 0, "Examining %s", update_dir);
-
- return R_PROCESS;
-}
-
-
-
-/*
- * Walklist proc to run pre-commit checks
- */
-static int
-precommit_list_proc (p, closure)
- Node *p;
- void *closure;
-{
- struct logfile_info *li = p->data;
- if (li->type == T_ADDED
- || li->type == T_MODIFIED
- || li->type == T_REMOVED)
- {
- run_arg (p->key);
- }
- return 0;
-}
-
-
-
-/*
- * Callback proc for pre-commit checking
- */
-static int
-precommit_proc (repository, filter)
- const char *repository;
- const char *filter;
-{
- /* see if the filter is there, only if it's a full path */
- if (isabsolute (filter))
- {
- char *s, *cp;
-
- s = xstrdup (filter);
- for (cp = s; *cp; cp++)
- if (isspace ((unsigned char) *cp))
- {
- *cp = '\0';
- break;
- }
- if (!isfile (s))
- {
- error (0, errno, "cannot find pre-commit filter `%s'", s);
- free (s);
- return 1; /* so it fails! */
- }
- free (s);
- }
-
- run_setup (filter);
- run_arg (repository);
- (void) walklist (saved_ulist, precommit_list_proc, NULL);
- return run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY);
-}
-
-
-
-/*
- * Run the pre-commit checks for the dir
- */
-/* ARGSUSED */
-static int
-check_filesdoneproc (callerdat, err, repos, update_dir, entries)
- void *callerdat;
- int err;
- const char *repos;
- const char *update_dir;
- List *entries;
-{
- int n;
- Node *p;
-
- /* find the update list for this dir */
- p = findnode (mulist, update_dir);
- if (p != NULL)
- saved_ulist = ((struct master_lists *) p->data)->ulist;
- else
- saved_ulist = (List *) NULL;
-
- /* skip the checks if there's nothing to do */
- if (saved_ulist == NULL || saved_ulist->list->next == saved_ulist->list)
- return err;
-
- /* run any pre-commit checks */
- if ((n = Parse_Info (CVSROOTADM_COMMITINFO, repos, precommit_proc, 1)) > 0)
- {
- error (0, 0, "Pre-commit check failed");
- err += n;
- }
-
- return err;
-}
-
-
-
-/*
- * Do the work of committing a file
- */
-static int maxrev;
-static char *sbranch;
-
-/* ARGSUSED */
-static int
-commit_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- Node *p;
- int err = 0;
- List *ulist, *cilist;
- struct commit_info *ci;
-
- /* Keep track of whether write_dirtag is a branch tag.
- Note that if it is a branch tag in some files and a nonbranch tag
- in others, treat it as a nonbranch tag. It is possible that case
- should elicit a warning or an error. */
- if (write_dirtag != NULL
- && finfo->rcs != NULL)
- {
- char *rev = RCS_getversion (finfo->rcs, write_dirtag, NULL, 1, NULL);
- if (rev != NULL
- && !RCS_nodeisbranch (finfo->rcs, write_dirtag))
- write_dirnonbranch = 1;
- if (rev != NULL)
- free (rev);
- }
-
- if (finfo->update_dir[0] == '\0')
- p = findnode (mulist, ".");
- else
- p = findnode (mulist, finfo->update_dir);
-
- /*
- * if p is null, there were file type command line args which were
- * all up-to-date so nothing really needs to be done
- */
- if (p == NULL)
- return 0;
- ulist = ((struct master_lists *) p->data)->ulist;
- cilist = ((struct master_lists *) p->data)->cilist;
-
- /*
- * At this point, we should have the commit message unless we were called
- * with files as args from the command line. In that latter case, we
- * need to get the commit message ourselves
- */
- if (!got_message)
- {
- got_message = 1;
- if (!server_active && use_editor)
- do_editor (finfo->update_dir, &saved_message,
- finfo->repository, ulist);
- do_verify (&saved_message, finfo->repository);
- }
-
- p = findnode (cilist, finfo->file);
- if (p == NULL)
- return 0;
-
- ci = p->data;
- if (ci->status == T_MODIFIED)
- {
- if (finfo->rcs == NULL)
- error (1, 0, "internal error: no parsed RCS file");
- if (lock_RCS (finfo->file, finfo->rcs, ci->rev,
- finfo->repository) != 0)
- {
- unlockrcs (finfo->rcs);
- err = 1;
- goto out;
- }
- }
- else if (ci->status == T_ADDED)
- {
- if (checkaddfile (finfo->file, finfo->repository, ci->tag, ci->options,
- &finfo->rcs) != 0)
- {
- if (finfo->rcs != NULL)
- fixaddfile (finfo->rcs->path);
- err = 1;
- goto out;
- }
-
- /* adding files with a tag, now means adding them on a branch.
- Since the branch test was done in check_fileproc for
- modified files, we need to stub it in again here. */
-
- if (ci->tag
-
- /* If numeric, it is on the trunk; check_fileproc enforced
- this. */
- && !isdigit ((unsigned char) ci->tag[0]))
- {
- if (finfo->rcs == NULL)
- error (1, 0, "internal error: no parsed RCS file");
- if (ci->rev)
- free (ci->rev);
- ci->rev = RCS_whatbranch (finfo->rcs, ci->tag);
- err = Checkin ('A', finfo, ci->rev,
- ci->tag, ci->options, saved_message);
- if (err != 0)
- {
- unlockrcs (finfo->rcs);
- fixbranch (finfo->rcs, sbranch);
- }
-
- (void) time (&last_register_time);
-
- ci->status = T_UPTODATE;
- }
- }
-
- /*
- * Add the file for real
- */
- if (ci->status == T_ADDED)
- {
- char *xrev = (char *) NULL;
-
- if (ci->rev == NULL)
- {
- /* find the max major rev number in this directory */
- maxrev = 0;
- (void) walklist (finfo->entries, findmaxrev, NULL);
- if (finfo->rcs->head) {
- /* resurrecting: include dead revision */
- int thisrev = atoi (finfo->rcs->head);
- if (thisrev > maxrev)
- maxrev = thisrev;
- }
- if (maxrev == 0)
- maxrev = 1;
- xrev = xmalloc (20);
- (void) sprintf (xrev, "%d", maxrev);
- }
-
- /* XXX - an added file with symbolic -r should add tag as well */
- err = finaladd (finfo, ci->rev ? ci->rev : xrev, ci->tag, ci->options);
- if (xrev)
- free (xrev);
- }
- else if (ci->status == T_MODIFIED)
- {
- err = Checkin ('M', finfo, ci->rev, ci->tag,
- ci->options, saved_message);
-
- (void) time (&last_register_time);
-
- if (err != 0)
- {
- unlockrcs (finfo->rcs);
- fixbranch (finfo->rcs, sbranch);
- }
- }
- else if (ci->status == T_REMOVED)
- {
- err = remove_file (finfo, ci->tag, saved_message);
-#ifdef SERVER_SUPPORT
- if (server_active) {
- server_scratch_entry_only ();
- server_updated (finfo,
- NULL,
-
- /* Doesn't matter, it won't get checked. */
- SERVER_UPDATED,
-
- (mode_t) -1,
- (unsigned char *) NULL,
- (struct buffer *) NULL);
- }
-#endif
- }
-
- /* Clearly this is right for T_MODIFIED. I haven't thought so much
- about T_ADDED or T_REMOVED. */
- notify_do ('C', finfo->file, getcaller (), NULL, NULL, finfo->repository);
-
-out:
- if (err != 0)
- {
- /* on failure, remove the file from ulist */
- p = findnode (ulist, finfo->file);
- if (p)
- delnode (p);
- }
- else
- {
- /* On success, retrieve the new version number of the file and
- copy it into the log information (see logmsg.c
- (logfile_write) for more details). We should only update
- the version number for files that have been added or
- modified but not removed since classify_file_internal
- will return the version number of a file even after it has
- been removed from the archive, which is not the behavior we
- want for our commitlog messages; we want the old version
- number and then "NONE." */
-
- if (ci->status != T_REMOVED)
- {
- p = findnode (ulist, finfo->file);
- if (p)
- {
- Vers_TS *vers;
- struct logfile_info *li;
-
- (void) classify_file_internal (finfo, &vers);
- li = p->data;
- li->rev_new = xstrdup (vers->vn_rcs);
- freevers_ts (&vers);
- }
- }
- }
- if (SIG_inCrSect ())
- SIG_endCrSect ();
-
- return err;
-}
-
-
-
-/*
- * Log the commit and clean up the update list
- */
-/* ARGSUSED */
-static int
-commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
- void *callerdat;
- int err;
- const char *repository;
- const char *update_dir;
- List *entries;
-{
- Node *p;
- List *ulist;
-
- assert (repository);
-
- p = findnode (mulist, update_dir);
- if (p == NULL)
- return err;
-
- ulist = ((struct master_lists *) p->data)->ulist;
-
- got_message = 0;
-
- Update_Logfile (repository, saved_message, (FILE *) 0, ulist);
-
- /* Build the administrative files if necessary. */
- {
- const char *p;
-
- if (strncmp (current_parsed_root->directory, repository,
- strlen (current_parsed_root->directory)) != 0)
- error (0, 0,
- "internal error: repository (%s) doesn't begin with root (%s)",
- repository, current_parsed_root->directory);
- p = repository + strlen (current_parsed_root->directory);
- if (*p == '/')
- ++p;
- if (strcmp ("CVSROOT", p) == 0
- /* Check for subdirectories because people may want to create
- subdirectories and list files therein in checkoutlist. */
- || strncmp ("CVSROOT/", p, strlen ("CVSROOT/")) == 0
- )
- {
- /* "Database" might a little bit grandiose and/or vague,
- but "checked-out copies of administrative files, unless
- in the case of modules and you are using ndbm in which
- case modules.{pag,dir,db}" is verbose and excessively
- focused on how the database is implemented. */
-
- /* mkmodules requires the absolute name of the CVSROOT directory.
- Remove anything after the `CVSROOT' component -- this is
- necessary when committing in a subdirectory of CVSROOT. */
- char *admin_dir = xstrdup (repository);
- int cvsrootlen = strlen ("CVSROOT");
- assert (admin_dir[p - repository + cvsrootlen] == '\0'
- || admin_dir[p - repository + cvsrootlen] == '/');
- admin_dir[p - repository + cvsrootlen] = '\0';
-
- cvs_output (program_name, 0);
- cvs_output (" ", 1);
- cvs_output (cvs_cmd_name, 0);
- cvs_output (": Rebuilding administrative file database\n", 0);
- mkmodules (admin_dir);
- free (admin_dir);
- }
- }
-
- return err;
-}
-
-
-
-/*
- * Get the log message for a dir
- */
-/* ARGSUSED */
-static Dtype
-commit_direntproc (callerdat, dir, repos, update_dir, entries)
- void *callerdat;
- const char *dir;
- const char *repos;
- const char *update_dir;
- List *entries;
-{
- Node *p;
- List *ulist;
- char *real_repos;
-
- if (!isdir (dir))
- return R_SKIP_ALL;
-
- /* find the update list for this dir */
- p = findnode (mulist, update_dir);
- if (p != NULL)
- ulist = ((struct master_lists *) p->data)->ulist;
- else
- ulist = (List *) NULL;
-
- /* skip the files as an optimization */
- if (ulist == NULL || ulist->list->next == ulist->list)
- return R_SKIP_FILES;
-
- /* get commit message */
- real_repos = Name_Repository (dir, update_dir);
- got_message = 1;
- if (!server_active && use_editor)
- do_editor (update_dir, &saved_message, real_repos, ulist);
- do_verify (&saved_message, real_repos);
- free (real_repos);
- return R_PROCESS;
-}
-
-
-
-/*
- * Process the post-commit proc if necessary
- */
-/* ARGSUSED */
-static int
-commit_dirleaveproc (callerdat, dir, err, update_dir, entries)
- void *callerdat;
- const char *dir;
- int err;
- const char *update_dir;
- List *entries;
-{
- /* update the per-directory tag info */
- /* FIXME? Why? The "commit examples" node of cvs.texinfo briefly
- mentions commit -r being sticky, but apparently in the context of
- this being a confusing feature! */
- if (err == 0 && write_dirtag != NULL)
- {
- char *repos = Name_Repository (NULL, update_dir);
- WriteTag (NULL, write_dirtag, NULL, write_dirnonbranch,
- update_dir, repos);
- free (repos);
- }
-
- return err;
-}
-
-
-
-/*
- * find the maximum major rev number in an entries file
- */
-static int
-findmaxrev (p, closure)
- Node *p;
- void *closure;
-{
- int thisrev;
- Entnode *entdata = p->data;
-
- if (entdata->type != ENT_FILE)
- return 0;
- thisrev = atoi (entdata->version);
- if (thisrev > maxrev)
- maxrev = thisrev;
- return 0;
-}
-
-/*
- * Actually remove a file by moving it to the attic
- * XXX - if removing a ,v file that is a relative symbolic link to
- * another ,v file, we probably should add a ".." component to the
- * link to keep it relative after we move it into the attic.
-
- Return value is 0 on success, or >0 on error (in which case we have
- printed an error message). */
-static int
-remove_file (finfo, tag, message)
- struct file_info *finfo;
- char *tag;
- char *message;
-{
- int retcode;
-
- int branch;
- int lockflag;
- char *corev;
- char *rev;
- char *prev_rev;
- char *old_path;
-
- corev = NULL;
- rev = NULL;
- prev_rev = NULL;
-
- retcode = 0;
-
- if (finfo->rcs == NULL)
- error (1, 0, "internal error: no parsed RCS file");
-
- branch = 0;
- if (tag && !(branch = RCS_nodeisbranch (finfo->rcs, tag)))
- {
- /* a symbolic tag is specified; just remove the tag from the file */
- if ((retcode = RCS_deltag (finfo->rcs, tag)) != 0)
- {
- if (!quiet)
- error (0, retcode == -1 ? errno : 0,
- "failed to remove tag `%s' from `%s'", tag,
- finfo->fullname);
- return 1;
- }
- RCS_rewrite (finfo->rcs, NULL, NULL);
- Scratch_Entry (finfo->entries, finfo->file);
- return 0;
- }
-
- /* we are removing the file from either the head or a branch */
- /* commit a new, dead revision. */
-
- /* Print message indicating that file is going to be removed. */
- cvs_output ("Removing ", 0);
- cvs_output (finfo->fullname, 0);
- cvs_output (";\n", 0);
-
- rev = NULL;
- lockflag = 1;
- if (branch)
- {
- char *branchname;
-
- rev = RCS_whatbranch (finfo->rcs, tag);
- if (rev == NULL)
- {
- error (0, 0, "cannot find branch \"%s\".", tag);
- return 1;
- }
-
- branchname = RCS_getbranch (finfo->rcs, rev, 1);
- if (branchname == NULL)
- {
- /* no revision exists on this branch. use the previous
- revision but do not lock. */
- corev = RCS_gettag (finfo->rcs, tag, 1, (int *) NULL);
- prev_rev = xstrdup (corev);
- lockflag = 0;
- } else
- {
- corev = xstrdup (rev);
- prev_rev = xstrdup (branchname);
- free (branchname);
- }
-
- } else /* Not a branch */
- {
- /* Get current head revision of file. */
- prev_rev = RCS_head (finfo->rcs);
- }
-
- /* if removing without a tag or a branch, then make sure the default
- branch is the trunk. */
- if (!tag && !branch)
- {
- if (RCS_setbranch (finfo->rcs, NULL) != 0)
- {
- error (0, 0, "cannot change branch to default for %s",
- finfo->fullname);
- return 1;
- }
- RCS_rewrite (finfo->rcs, NULL, NULL);
- }
-
- /* check something out. Generally this is the head. If we have a
- particular rev, then name it. */
- retcode = RCS_checkout (finfo->rcs, finfo->file, rev ? corev : NULL,
- (char *) NULL, (char *) NULL, RUN_TTY,
- (RCSCHECKOUTPROC) NULL, (void *) NULL);
- if (retcode != 0)
- {
- error (0, 0,
- "failed to check out `%s'", finfo->fullname);
- return 1;
- }
-
- /* Except when we are creating a branch, lock the revision so that
- we can check in the new revision. */
- if (lockflag)
- {
- if (RCS_lock (finfo->rcs, rev ? corev : NULL, 1) == 0)
- RCS_rewrite (finfo->rcs, NULL, NULL);
- }
-
- if (corev != NULL)
- free (corev);
-
- retcode = RCS_checkin (finfo->rcs, finfo->file, message, rev, 0,
- RCS_FLAGS_DEAD | RCS_FLAGS_QUIET);
- if (retcode != 0)
- {
- if (!quiet)
- error (0, retcode == -1 ? errno : 0,
- "failed to commit dead revision for `%s'", finfo->fullname);
- if (prev_rev != NULL)
- free (prev_rev);
- return 1;
- }
- /* At this point, the file has been committed as removed. We should
- probably tell the history file about it */
- corev = rev ? RCS_getbranch (finfo->rcs, rev, 1) : RCS_head (finfo->rcs);
- history_write ('R', NULL, corev, finfo->file, finfo->repository);
- free (corev);
-
- if (rev != NULL)
- free (rev);
-
- old_path = xstrdup (finfo->rcs->path);
- if (!branch)
- RCS_setattic (finfo->rcs, 1);
-
- /* Print message that file was removed. */
- cvs_output (old_path, 0);
- cvs_output (" <-- ", 0);
- cvs_output (finfo->file, 0);
- cvs_output ("\nnew revision: delete; previous revision: ", 0);
- cvs_output (prev_rev, 0);
- cvs_output ("\ndone\n", 0);
- free(prev_rev);
-
- free (old_path);
-
- Scratch_Entry (finfo->entries, finfo->file);
- return 0;
-}
-
-
-
-/*
- * Do the actual checkin for added files
- */
-static int
-finaladd (finfo, rev, tag, options)
- struct file_info *finfo;
- char *rev;
- char *tag;
- char *options;
-{
- int ret;
-
- ret = Checkin ('A', finfo, rev, tag, options, saved_message);
- if (ret == 0)
- {
- char *tmp = xmalloc (strlen (finfo->file) + sizeof (CVSADM)
- + sizeof (CVSEXT_LOG) + 10);
- (void) sprintf (tmp, "%s/%s%s", CVSADM, finfo->file, CVSEXT_LOG);
- if (unlink_file (tmp) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", tmp);
- free (tmp);
- }
- else if (finfo->rcs != NULL)
- fixaddfile (finfo->rcs->path);
-
- (void) time (&last_register_time);
-
- return ret;
-}
-
-
-
-/*
- * Unlock an rcs file
- */
-static void
-unlockrcs (rcs)
- RCSNode *rcs;
-{
- int retcode;
-
- if ((retcode = RCS_unlock (rcs, NULL, 1)) != 0)
- error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
- "could not unlock %s", rcs->path);
- else
- RCS_rewrite (rcs, NULL, NULL);
-}
-
-
-
-/*
- * remove a partially added file. if we can parse it, leave it alone.
- *
- * FIXME: Every caller that calls this function can access finfo->rcs (the
- * parsed RCSNode data), so we should be able to detect that the file needs
- * to be removed without reparsing the file as we do below.
- */
-static void
-fixaddfile (rcs)
- const char *rcs;
-{
- RCSNode *rcsfile;
- int save_really_quiet;
-
- save_really_quiet = really_quiet;
- really_quiet = 1;
- if ((rcsfile = RCS_parsercsfile (rcs)) == NULL)
- {
- if (unlink_file (rcs) < 0)
- error (0, errno, "cannot remove %s", rcs);
- }
- else
- freercsnode (&rcsfile);
- really_quiet = save_really_quiet;
-}
-
-
-
-/*
- * put the branch back on an rcs file
- */
-static void
-fixbranch (rcs, branch)
- RCSNode *rcs;
- char *branch;
-{
- int retcode;
-
- if (branch != NULL)
- {
- if ((retcode = RCS_setbranch (rcs, branch)) != 0)
- error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
- "cannot restore branch to %s for %s", branch, rcs->path);
- RCS_rewrite (rcs, NULL, NULL);
- }
-}
-
-
-
-/*
- * do the initial part of a file add for the named file. if adding
- * with a tag, put the file in the Attic and point the symbolic tag
- * at the committed revision.
- *
- * INPUTS
- * file The name of the file in the workspace.
- * repository The repository directory to expect to find FILE,v in.
- * tag The name or rev num of the branch being added to, if any.
- * options Any RCS keyword expansion options specified by the user.
- * rcsnode A pointer to the pre-parsed RCSNode for this file, if the file
- * exists in the repository. If this is NULL, assume the file
- * does not yet exist.
- *
- * RETURNS
- * 0 on success.
- * 1 on errors, after printing any appropriate error messages.
- *
- * ERRORS
- * This function will return an error when any of the following functions do:
- * add_rcs_file
- * RCS_setattic
- * lock_RCS
- * RCS_checkin
- * RCS_parse (called to verify the newly created archive file)
- * RCS_settag
- */
-
-static int
-checkaddfile (file, repository, tag, options, rcsnode)
- const char *file;
- const char *repository;
- const char *tag;
- const char *options;
- RCSNode **rcsnode;
-{
- RCSNode *rcs;
- char *fname;
- int newfile = 0; /* Set to 1 if we created a new RCS archive. */
- int retval = 1;
- int adding_on_branch;
-
- assert (rcsnode != NULL);
-
- /* Callers expect to be able to use either "" or NULL to mean the
- default keyword expansion. */
- if (options != NULL && options[0] == '\0')
- options = NULL;
- if (options != NULL)
- assert (options[0] == '-' && options[1] == 'k');
-
- /* If numeric, it is on the trunk; check_fileproc enforced
- this. */
- adding_on_branch = tag != NULL && !isdigit ((unsigned char) tag[0]);
-
- if (*rcsnode == NULL)
- {
- char *rcsname;
- char *desc = NULL;
- size_t descalloc = 0;
- size_t desclen = 0;
- const char *opt;
-
- if ( adding_on_branch )
- {
- mode_t omask;
- rcsname = xmalloc (strlen (repository)
- + sizeof (CVSATTIC)
- + strlen (file)
- + sizeof (RCSEXT)
- + 3);
- (void) sprintf (rcsname, "%s/%s", repository, CVSATTIC);
- omask = umask ( cvsumask );
- if (CVS_MKDIR (rcsname, 0777 ) != 0 && errno != EEXIST)
- error (1, errno, "cannot make directory `%s'", rcsname);
- (void) umask ( omask );
- (void) sprintf (rcsname,
- "%s/%s/%s%s",
- repository,
- CVSATTIC,
- file,
- RCSEXT);
- }
- else
- {
- rcsname = xmalloc (strlen (repository)
- + strlen (file)
- + sizeof (RCSEXT)
- + 2);
- (void) sprintf (rcsname,
- "%s/%s%s",
- repository,
- file,
- RCSEXT);
- }
-
- /* this is the first time we have ever seen this file; create
- an RCS file. */
- fname = xmalloc (strlen (file) + sizeof (CVSADM)
- + sizeof (CVSEXT_LOG) + 10);
- (void) sprintf (fname, "%s/%s%s", CVSADM, file, CVSEXT_LOG);
- /* If the file does not exist, no big deal. In particular, the
- server does not (yet at least) create CVSEXT_LOG files. */
- if (isfile (fname))
- /* FIXME: Should be including update_dir in the appropriate
- place here. */
- get_file (fname, fname, "r", &desc, &descalloc, &desclen);
- free (fname);
-
- /* From reading the RCS 5.7 source, "rcs -i" adds a newline to the
- end of the log message if the message is nonempty.
- Do it. RCS also deletes certain whitespace, in cleanlogmsg,
- which we don't try to do here. */
- if (desclen > 0)
- {
- expand_string (&desc, &descalloc, desclen + 1);
- desc[desclen++] = '\012';
- }
-
- /* Set RCS keyword expansion options. */
- if (options != NULL)
- opt = options + 2;
- else
- opt = NULL;
-
- /* This message is an artifact of the time when this
- was implemented via "rcs -i". It should be revised at
- some point (does the "initial revision" in the message from
- RCS_checkin indicate that this is a new file? Or does the
- "RCS file" message serve some function?). */
- cvs_output ("RCS file: ", 0);
- cvs_output (rcsname, 0);
- cvs_output ("\ndone\n", 0);
-
- if (add_rcs_file (NULL, rcsname, file, NULL, opt,
- NULL, NULL, 0, NULL,
- desc, desclen, NULL) != 0)
- {
- if (rcsname != NULL)
- free (rcsname);
- goto out;
- }
- rcs = RCS_parsercsfile (rcsname);
- newfile = 1;
- if (rcsname != NULL)
- free (rcsname);
- if (desc != NULL)
- free (desc);
- *rcsnode = rcs;
- }
- else
- {
- /* file has existed in the past. Prepare to resurrect. */
- char *rev;
- char *oldexpand;
-
- rcs = *rcsnode;
-
- oldexpand = RCS_getexpand (rcs);
- if ((oldexpand != NULL
- && options != NULL
- && strcmp (options + 2, oldexpand) != 0)
- || (oldexpand == NULL && options != NULL))
- {
- /* We tell the user about this, because it means that the
- old revisions will no longer retrieve the way that they
- used to. */
- error (0, 0, "changing keyword expansion mode to %s", options);
- RCS_setexpand (rcs, options + 2);
- }
-
- if (!adding_on_branch)
- {
- /* We are adding on the trunk, so move the file out of the
- Attic. */
- if (!(rcs->flags & INATTIC))
- {
- error (0, 0, "warning: expected %s to be in Attic",
- rcs->path);
- }
-
- /* Begin a critical section around the code that spans the
- first commit on the trunk of a file that's already been
- committed on a branch. */
- SIG_beginCrSect ();
-
- if (RCS_setattic (rcs, 0))
- {
- goto out;
- }
- }
-
- rev = RCS_getversion (rcs, tag, NULL, 1, (int *) NULL);
- /* and lock it */
- if (lock_RCS (file, rcs, rev, repository))
- {
- error (0, 0, "cannot lock revision %s in `%s'.",
- rev ? rev : tag ? tag : "HEAD", rcs->path);
- if (rev != NULL)
- free (rev);
- goto out;
- }
-
- if (rev != NULL)
- free (rev);
- }
-
- /* when adding a file for the first time, and using a tag, we need
- to create a dead revision on the trunk. */
- if (adding_on_branch)
- {
- if (newfile)
- {
- char *tmp;
- FILE *fp;
- int retcode;
-
- /* move the new file out of the way. */
- fname = xmalloc (strlen (file) + sizeof (CVSADM)
- + sizeof (CVSPREFIX) + 10);
- (void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
- rename_file (file, fname);
-
- /* Create empty FILE. Can't use copy_file with a DEVNULL
- argument -- copy_file now ignores device files. */
- fp = fopen (file, "w");
- if (fp == NULL)
- error (1, errno, "cannot open %s for writing", file);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", file);
-
- tmp = xmalloc (strlen (file) + strlen (tag) + 80);
- /* commit a dead revision. */
- (void) sprintf (tmp, "file %s was initially added on branch %s.",
- file, tag);
- retcode = RCS_checkin (rcs, NULL, tmp, NULL, 0,
- RCS_FLAGS_DEAD | RCS_FLAGS_QUIET);
- free (tmp);
- if (retcode != 0)
- {
- error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
- "could not create initial dead revision %s", rcs->path);
- free (fname);
- goto out;
- }
-
- /* put the new file back where it was */
- rename_file (fname, file);
- free (fname);
-
- /* double-check that the file was written correctly */
- freercsnode (&rcs);
- rcs = RCS_parse (file, repository);
- if (rcs == NULL)
- {
- error (0, 0, "could not read %s in %s", file, repository);
- goto out;
- }
- *rcsnode = rcs;
-
- /* and lock it once again. */
- if (lock_RCS (file, rcs, NULL, repository))
- {
- error (0, 0, "cannot lock initial revision in `%s'.",
- rcs->path);
- goto out;
- }
- }
-
- /* when adding with a tag, we need to stub a branch, if it
- doesn't already exist. */
- if (!RCS_nodeisbranch (rcs, tag))
- {
- /* branch does not exist. Stub it. */
- char *head;
- char *magicrev;
- int retcode;
- time_t headtime = -1;
- char *revnum, *tmp;
- FILE *fp;
- time_t t = -1;
- struct tm *ct;
-
- fixbranch (rcs, sbranch);
-
- head = RCS_getversion (rcs, NULL, NULL, 0, (int *) NULL);
- if (!head)
- error (1, 0, "No head revision in archive file `%s'.",
- rcs->path);
- magicrev = RCS_magicrev (rcs, head);
-
- /* If this is not a new branch, then we will want a dead
- version created before this one. */
- if (!newfile)
- headtime = RCS_getrevtime (rcs, head, 0, 0);
-
- retcode = RCS_settag (rcs, tag, magicrev);
- RCS_rewrite (rcs, NULL, NULL);
-
- free (head);
- free (magicrev);
-
- if (retcode != 0)
- {
- error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
- "could not stub branch %s for %s", tag, rcs->path);
- goto out;
- }
- /* We need to add a dead version here to avoid -rtag -Dtime
- checkout problems between when the head version was
- created and now. */
- if (!newfile && headtime != -1)
- {
- /* move the new file out of the way. */
- fname = xmalloc (strlen (file) + sizeof (CVSADM)
- + sizeof (CVSPREFIX) + 10);
- (void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
- rename_file (file, fname);
-
- /* Create empty FILE. Can't use copy_file with a DEVNULL
- argument -- copy_file now ignores device files. */
- fp = fopen (file, "w");
- if (fp == NULL)
- error (1, errno, "cannot open %s for writing", file);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", file);
-
- /* As we will be hacking the delta date, put the time
- this was added into the log message. */
- t = time(NULL);
- ct = gmtime(&t);
- tmp = xmalloc (strlen (file) + strlen (tag) + 80);
-
- (void) sprintf (tmp,
- "file %s was added on branch %s on %d-%02d-%02d %02d:%02d:%02d +0000",
- file, tag,
- ct->tm_year + (ct->tm_year < 100 ? 0 : 1900),
- ct->tm_mon + 1, ct->tm_mday,
- ct->tm_hour, ct->tm_min, ct->tm_sec);
-
- /* commit a dead revision. */
- revnum = RCS_whatbranch (rcs, tag);
- retcode = RCS_checkin (rcs, NULL, tmp, revnum, headtime,
- RCS_FLAGS_DEAD |
- RCS_FLAGS_QUIET |
- RCS_FLAGS_USETIME);
- free (revnum);
- free (tmp);
-
- if (retcode != 0)
- {
- error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
- "could not created dead stub %s for %s", tag,
- rcs->path);
- goto out;
- }
-
- /* put the new file back where it was */
- rename_file (fname, file);
- free (fname);
-
- /* double-check that the file was written correctly */
- freercsnode (&rcs);
- rcs = RCS_parse (file, repository);
- if (rcs == NULL)
- {
- error (0, 0, "could not read %s", rcs->path);
- goto out;
- }
- *rcsnode = rcs;
- }
- }
- else
- {
- /* lock the branch. (stubbed branches need not be locked.) */
- if (lock_RCS (file, rcs, NULL, repository))
- {
- error (0, 0, "cannot lock head revision in `%s'.", rcs->path);
- goto out;
- }
- }
-
- if (*rcsnode != rcs)
- {
- freercsnode(rcsnode);
- *rcsnode = rcs;
- }
- }
-
- fileattr_newfile (file);
-
- /* At this point, we used to set the file mode of the RCS file
- based on the mode of the file in the working directory. If we
- are creating the RCS file for the first time, add_rcs_file does
- this already. If we are re-adding the file, then perhaps it is
- consistent to preserve the old file mode, just as we preserve
- the old keyword expansion mode.
-
- If we decide that we should change the modes, then we can't do
- it here anyhow. At this point, the RCS file may be owned by
- somebody else, so a chmod will fail. We need to instead do the
- chmod after rewriting it.
-
- FIXME: In general, I think the file mode (and the keyword
- expansion mode) should be associated with a particular revision
- of the file, so that it is possible to have different revisions
- of a file have different modes. */
-
- retval = 0;
-
- out:
- if (retval != 0 && SIG_inCrSect ())
- SIG_endCrSect ();
- return retval;
-}
-
-
-
-/*
- * Attempt to place a lock on the RCS file; returns 0 if it could and 1 if it
- * couldn't. If the RCS file currently has a branch as the head, we must
- * move the head back to the trunk before locking the file, and be sure to
- * put the branch back as the head if there are any errors.
- */
-static int
-lock_RCS (user, rcs, rev, repository)
- const char *user;
- RCSNode *rcs;
- const char *rev;
- const char *repository;
-{
- char *branch = NULL;
- int err = 0;
-
- /*
- * For a specified, numeric revision of the form "1" or "1.1", (or when
- * no revision is specified ""), definitely move the branch to the trunk
- * before locking the RCS file.
- *
- * The assumption is that if there is more than one revision on the trunk,
- * the head points to the trunk, not a branch... and as such, it's not
- * necessary to move the head in this case.
- */
- if (rev == NULL
- || (rev && isdigit ((unsigned char) *rev) && numdots (rev) < 2))
- {
- branch = xstrdup (rcs->branch);
- if (branch != NULL)
- {
- if (RCS_setbranch (rcs, NULL) != 0)
- {
- error (0, 0, "cannot change branch to default for %s",
- rcs->path);
- if (branch)
- free (branch);
- return 1;
- }
- }
- err = RCS_lock (rcs, NULL, 1);
- }
- else
- {
- RCS_lock (rcs, rev, 1);
- }
-
- /* We used to call RCS_rewrite here, and that might seem
- appropriate in order to write out the locked revision
- information. However, such a call would actually serve no
- purpose. CVS locks will prevent any interference from other
- CVS processes. The comment above rcs_internal_lockfile
- explains that it is already unsafe to use RCS and CVS
- simultaneously. It follows that writing out the locked
- revision information here would add no additional security.
-
- If we ever do care about it, the proper fix is to create the
- RCS lock file before calling this function, and maintain it
- until the checkin is complete.
-
- The call to RCS_lock is still required at present, since in
- some cases RCS_checkin will determine which revision to check
- in by looking for a lock. FIXME: This is rather roundabout,
- and a more straightforward approach would probably be easier to
- understand. */
-
- if (err == 0)
- {
- if (sbranch != NULL)
- free (sbranch);
- sbranch = branch;
- return 0;
- }
-
- /* try to restore the branch if we can on error */
- if (branch != NULL)
- fixbranch (rcs, branch);
-
- if (branch)
- free (branch);
- return 1;
-}
-
-
-
-/*
- * free an UPDATE node's data
- */
-void
-update_delproc (p)
- Node *p;
-{
- struct logfile_info *li = p->data;
-
- if (li->tag)
- free (li->tag);
- if (li->rev_old)
- free (li->rev_old);
- if (li->rev_new)
- free (li->rev_new);
- free (li);
-}
-
-/*
- * Free the commit_info structure in p.
- */
-static void
-ci_delproc (p)
- Node *p;
-{
- struct commit_info *ci = p->data;
-
- if (ci->rev)
- free (ci->rev);
- if (ci->tag)
- free (ci->tag);
- if (ci->options)
- free (ci->options);
- free (ci);
-}
-
-/*
- * Free the commit_info structure in p.
- */
-static void
-masterlist_delproc (p)
- Node *p;
-{
- struct master_lists *ml = p->data;
-
- dellist (&ml->ulist);
- dellist (&ml->cilist);
- free (ml);
-}
diff --git a/contrib/cvs/src/create_adm.c b/contrib/cvs/src/create_adm.c
deleted file mode 100644
index ccf744f3ea93..000000000000
--- a/contrib/cvs/src/create_adm.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Create Administration.
- *
- * Creates a CVS administration directory based on the argument repository; the
- * "Entries" file is prefilled from the "initrecord" argument.
- */
-
-#include "cvs.h"
-
-/* update_dir includes dir as its last component.
-
- Return value is 0 for success, or 1 if we printed a warning message.
- Note that many errors are still fatal; particularly for unlikely errors
- a fatal error is probably better than a warning which might be missed
- or after which CVS might do something non-useful. If WARN is zero, then
- don't print warnings; all errors are fatal then. */
-
-int
-Create_Admin (dir, update_dir, repository, tag, date, nonbranch, warn,
- dotemplate)
- const char *dir;
- const char *update_dir;
- const char *repository;
- const char *tag;
- const char *date;
- int nonbranch;
- int warn;
- int dotemplate;
-{
- FILE *fout;
- char *cp;
- char *reposcopy;
- char *tmp;
-
- if (trace)
- {
- fprintf (stderr, "%s-> Create_Admin (%s, %s, %s, %s, %s, %d, %d, %d)\n",
- CLIENT_SERVER_STR,
- dir, update_dir, repository, tag ? tag : "",
- date ? date : "", nonbranch, warn, dotemplate);
- }
-
- if (noexec)
- return 0;
-
- tmp = xmalloc (strlen (dir) + 100);
- (void) sprintf (tmp, "%s/%s", dir, CVSADM);
- if (isfile (tmp))
- error (1, 0, "there is a version in %s already", update_dir);
-
- if (CVS_MKDIR (tmp, 0777) < 0)
- {
- /* We want to print out the entire update_dir, since a lot of
- our code calls this function with dir == "." or dir ==
- NULL. I hope that gives enough information in cases like
- absolute pathnames; printing out xgetwd or something would
- be way too verbose in the common cases. */
-
- if (warn)
- {
- /* The reason that this is a warning, rather than silently
- just skipping creating the directory, is that we don't want
- CVS's behavior to vary subtly based on factors (like directory
- permissions) which are not made clear to the user. With
- the warning at least we let them know what is going on. */
- error (0, errno, "warning: cannot make directory %s in %s",
- CVSADM, update_dir);
- free (tmp);
- return 1;
- }
- else
- error (1, errno, "cannot make directory %s in %s",
- CVSADM, update_dir);
- }
-
- /* record the current cvs root for later use */
-
- Create_Root (dir, current_parsed_root->original);
- if (dir != NULL)
- (void) sprintf (tmp, "%s/%s", dir, CVSADM_REP);
- else
- (void) strcpy (tmp, CVSADM_REP);
- fout = CVS_FOPEN (tmp, "w+");
- if (fout == NULL)
- {
- if (update_dir[0] == '\0')
- error (1, errno, "cannot open %s", tmp);
- else
- error (1, errno, "cannot open %s/%s", update_dir, CVSADM_REP);
- }
- reposcopy = xstrdup (repository);
- Sanitize_Repository_Name (reposcopy);
-
- /* The top level of the repository is a special case -- we need to
- write it with an extra dot at the end. This trailing `.' stuff
- rubs me the wrong way -- on the other hand, I don't want to
- spend the time making sure all of the code can handle it if we
- don't do it. */
-
- if (strcmp (reposcopy, current_parsed_root->directory) == 0)
- {
- reposcopy = xrealloc (reposcopy, strlen (reposcopy) + 3);
- strcat (reposcopy, "/.");
- }
-
- cp = reposcopy;
-
- /*
- * If the Repository file is to hold a relative path, try to strip off
- * the leading CVSroot argument.
- */
- {
- char *path = xmalloc (strlen (current_parsed_root->directory) + 2);
-
- (void) sprintf (path, "%s/", current_parsed_root->directory);
- if (strncmp (cp, path, strlen (path)) == 0)
- cp += strlen (path);
- free (path);
- }
-
- if (fprintf (fout, "%s\n", cp) < 0)
- {
- if (update_dir[0] == '\0')
- error (1, errno, "write to %s failed", tmp);
- else
- error (1, errno, "write to %s/%s failed", update_dir, CVSADM_REP);
- }
- if (fclose (fout) == EOF)
- {
- if (update_dir[0] == '\0')
- error (1, errno, "cannot close %s", tmp);
- else
- error (1, errno, "cannot close %s/%s", update_dir, CVSADM_REP);
- }
-
- /* now, do the Entries file */
- if (dir != NULL)
- (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENT);
- else
- (void) strcpy (tmp, CVSADM_ENT);
- fout = CVS_FOPEN (tmp, "w+");
- if (fout == NULL)
- {
- if (update_dir[0] == '\0')
- error (1, errno, "cannot open %s", tmp);
- else
- error (1, errno, "cannot open %s/%s", update_dir, CVSADM_ENT);
- }
- if (fclose (fout) == EOF)
- {
- if (update_dir[0] == '\0')
- error (1, errno, "cannot close %s", tmp);
- else
- error (1, errno, "cannot close %s/%s", update_dir, CVSADM_ENT);
- }
-
- /* Create a new CVS/Tag file */
- WriteTag (dir, tag, date, nonbranch, update_dir, repository);
-
-#ifdef SERVER_SUPPORT
- if (server_active && dotemplate)
- {
- server_template (update_dir, repository);
- }
-
- if (trace)
- {
- fprintf (stderr, "%c<- Create_Admin\n",
- (server_active) ? 'S' : ' ');
- }
-#endif
-
- free (reposcopy);
- free (tmp);
- return 0;
-}
diff --git a/contrib/cvs/src/cvs.h b/contrib/cvs/src/cvs.h
deleted file mode 100644
index 4b7d9f5f63e9..000000000000
--- a/contrib/cvs/src/cvs.h
+++ /dev/null
@@ -1,945 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS kit.
- */
-
-/*
- * basic information used in all source files
- *
- * $FreeBSD$
- */
-
-
-#ifdef HAVE_CONFIG_H
-# include <config.h> /* this is stuff found via autoconf */
-#endif /* CONFIG_H */
-
-/* Changed from if __STDC__ to ifdef __STDC__ because of Sun's acc compiler */
-
-#ifdef __STDC__
-#define PTR void *
-#else
-#define PTR char *
-#endif
-
-/* Add prototype support. */
-#ifndef PROTO
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define PROTO(ARGS) ARGS
-#else
-#define PROTO(ARGS) ()
-#endif
-#endif
-
-#include <stdio.h>
-
-/* Under OS/2, <stdio.h> doesn't define popen()/pclose(). */
-#ifdef USE_OWN_POPEN
-#include "popen.h"
-#endif
-
-/* Begin GNULIB headers. */
-#include "xsize.h"
-/* End GNULIB headers. */
-
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#else
-extern void exit ();
-extern char *getenv();
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#include <strings.h>
-#endif
-
-#ifdef SERVER_SUPPORT
-/* If the system doesn't provide strerror, it won't be declared in
- string.h. */
-char *strerror ();
-#endif
-
-#ifdef HAVE_FNMATCH
-# include <fnmatch.h> /* This is supposed to be available on Posix systems */
-#else /* HAVE_FNMATCH */
-# include "fnmatch.h" /* Our substitute */
-#endif /* HAVE_FNMATCH */
-
-#include <ctype.h>
-#include <pwd.h>
-#include <signal.h>
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#else
-#ifndef errno
-extern int errno;
-#endif /* !errno */
-#endif /* HAVE_ERRNO_H */
-
-#include "system.h"
-
-#include "hash.h"
-#include "stack.h"
-
-#include "root.h"
-
-#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
-# include "client.h"
-#endif
-
-#ifdef MY_NDBM
-#include "myndbm.h"
-#else
-#include <ndbm.h>
-#endif /* MY_NDBM */
-
-#include "regex.h"
-#include "getopt.h"
-#include "wait.h"
-
-#include "rcs.h"
-
-
-/* This actually gets set in system.h. Note that the _ONLY_ reason for
- this is if various system calls (getwd, getcwd, readlink) require/want
- us to use it. All other parts of CVS allocate pathname buffers
- dynamically, and we want to keep it that way. */
-#ifndef PATH_MAX
-#ifdef MAXPATHLEN
-#define PATH_MAX MAXPATHLEN+2
-#else
-#define PATH_MAX 1024+2
-#endif
-#endif /* PATH_MAX */
-
-/* Definitions for the CVS Administrative directory and the files it contains.
- Here as #define's to make changing the names a simple task. */
-
-#ifdef USE_VMS_FILENAMES
-#define CVSADM "CVS"
-#define CVSADM_ENT "CVS/Entries."
-#define CVSADM_ENTBAK "CVS/Entries.Backup"
-#define CVSADM_ENTLOG "CVS/Entries.Log"
-#define CVSADM_ENTSTAT "CVS/Entries.Static"
-#define CVSADM_REP "CVS/Repository."
-#define CVSADM_ROOT "CVS/Root."
-#define CVSADM_TAG "CVS/Tag."
-#define CVSADM_NOTIFY "CVS/Notify."
-#define CVSADM_NOTIFYTMP "CVS/Notify.tmp"
-#define CVSADM_BASE "CVS/Base"
-#define CVSADM_BASEREV "CVS/Baserev."
-#define CVSADM_BASEREVTMP "CVS/Baserev.tmp"
-#define CVSADM_TEMPLATE "CVS/Template."
-#else /* USE_VMS_FILENAMES */
-#define CVSADM "CVS"
-#define CVSADM_ENT "CVS/Entries"
-#define CVSADM_ENTBAK "CVS/Entries.Backup"
-#define CVSADM_ENTLOG "CVS/Entries.Log"
-#define CVSADM_ENTSTAT "CVS/Entries.Static"
-#define CVSADM_REP "CVS/Repository"
-#define CVSADM_ROOT "CVS/Root"
-#define CVSADM_TAG "CVS/Tag"
-#define CVSADM_NOTIFY "CVS/Notify"
-#define CVSADM_NOTIFYTMP "CVS/Notify.tmp"
-/* A directory in which we store base versions of files we currently are
- editing with "cvs edit". */
-#define CVSADM_BASE "CVS/Base"
-#define CVSADM_BASEREV "CVS/Baserev"
-#define CVSADM_BASEREVTMP "CVS/Baserev.tmp"
-/* File which contains the template for use in log messages. */
-#define CVSADM_TEMPLATE "CVS/Template"
-#endif /* USE_VMS_FILENAMES */
-
-/* This is the special directory which we use to store various extra
- per-directory information in the repository. It must be the same as
- CVSADM to avoid creating a new reserved directory name which users cannot
- use, but is a separate #define because if anyone changes it (which I don't
- recommend), one needs to deal with old, unconverted, repositories.
-
- See fileattr.h for details about file attributes, the only thing stored
- in CVSREP currently. */
-#define CVSREP "CVS"
-
-/*
- * Definitions for the CVSROOT Administrative directory and the files it
- * contains. This directory is created as a sub-directory of the $CVSROOT
- * environment variable, and holds global administration information for the
- * entire source repository beginning at $CVSROOT.
- */
-#define CVSROOTADM "CVSROOT"
-#define CVSROOTADM_MODULES "modules"
-#define CVSROOTADM_LOGINFO "loginfo"
-#define CVSROOTADM_RCSINFO "rcsinfo"
-#define CVSROOTADM_COMMITINFO "commitinfo"
-#define CVSROOTADM_TAGINFO "taginfo"
-#define CVSROOTADM_EDITINFO "editinfo"
-#define CVSROOTADM_VERIFYMSG "verifymsg"
-#define CVSROOTADM_HISTORY "history"
-#define CVSROOTADM_VALTAGS "val-tags"
-#define CVSROOTADM_IGNORE "cvsignore"
-#define CVSROOTADM_CHECKOUTLIST "checkoutlist"
-#define CVSROOTADM_WRAPPER "cvswrappers"
-#define CVSROOTADM_NOTIFY "notify"
-#define CVSROOTADM_USERS "users"
-#define CVSROOTADM_READERS "readers"
-#define CVSROOTADM_WRITERS "writers"
-#define CVSROOTADM_PASSWD "passwd"
-#define CVSROOTADM_CONFIG "config"
-#define CVSROOTADM_OPTIONS "options"
-
-#define CVSNULLREPOS "Emptydir" /* an empty directory */
-
-/* Other CVS file names */
-
-/* Files go in the attic if the head main branch revision is dead,
- otherwise they go in the regular repository directories. The whole
- concept of having an attic is sort of a relic from before death
- support but on the other hand, it probably does help the speed of
- some operations (such as main branch checkouts and updates). */
-#define CVSATTIC "Attic"
-
-#define CVSLCK "#cvs.lock"
-#define CVSHISTORYLCK "#cvs.history.lock"
-#define CVSVALTAGSLCK "#cvs.val-tags.lock"
-#define CVSRFL "#cvs.rfl"
-#define CVSWFL "#cvs.wfl"
-#define CVSRFLPAT "#cvs.rfl.*" /* wildcard expr to match read locks */
-#define CVSEXT_LOG ",t"
-#define CVSPREFIX ",,"
-#define CVSDOTIGNORE ".cvsignore"
-#define CVSDOTWRAPPER ".cvswrappers"
-
-/* Command attributes -- see function lookup_command_attribute(). */
-#define CVS_CMD_IGNORE_ADMROOT 1
-
-/* Set if CVS needs to create a CVS/Root file upon completion of this
- command. The name may be slightly confusing, because the flag
- isn't really as general purpose as it seems (it is not set for cvs
- release). */
-
-#define CVS_CMD_USES_WORK_DIR 2
-
-#define CVS_CMD_MODIFIES_REPOSITORY 4
-
-/* miscellaneous CVS defines */
-
-/* This is the string which is at the start of the non-log-message lines
- that we put up for the user when they edit the log message. */
-#define CVSEDITPREFIX "CVS: "
-/* Number of characters in CVSEDITPREFIX to compare when deciding to strip
- off those lines. We don't check for the space, to accomodate users who
- have editors which strip trailing spaces. */
-#define CVSEDITPREFIXLEN 4
-
-#define CVSLCKAGE (60*60) /* 1-hour old lock files cleaned up */
-#define CVSLCKSLEEP 30 /* wait 30 seconds before retrying */
-#define CVSBRANCH "1.1.1" /* RCS branch used for vendor srcs */
-
-#ifdef USE_VMS_FILENAMES
-#define BAKPREFIX "_$"
-#define DEVNULL "NLA0:"
-#else /* USE_VMS_FILENAMES */
-#define BAKPREFIX ".#" /* when rcsmerge'ing */
-#ifndef DEVNULL
-#define DEVNULL "/dev/null"
-#endif
-#endif /* USE_VMS_FILENAMES */
-
-/*
- * Special tags. -rHEAD refers to the head of an RCS file, regardless of any
- * sticky tags. -rBASE refers to the current revision the user has checked
- * out This mimics the behaviour of RCS.
- */
-#define TAG_HEAD "HEAD"
-#define TAG_BASE "BASE"
-
-/* Environment variable used by CVS */
-#define CVSREAD_ENV "CVSREAD" /* make files read-only */
-#define CVSREAD_DFLT 0 /* writable files by default */
-
-#define CVSREADONLYFS_ENV "CVSREADONLYFS" /* repository is read-only */
-
-#define TMPDIR_ENV "TMPDIR" /* Temporary directory */
-
-#define EDITOR1_ENV "CVSEDITOR" /* which editor to use */
-#define EDITOR2_ENV "VISUAL" /* which editor to use */
-#define EDITOR3_ENV "EDITOR" /* which editor to use */
-
-#define CVSROOT_ENV "CVSROOT" /* source directory root */
-/* Define CVSROOT_DFLT to a fallback value for CVSROOT.
- *
-#undef CVSROOT_DFL
- */
-
-#define IGNORE_ENV "CVSIGNORE" /* More files to ignore */
-#define WRAPPER_ENV "CVSWRAPPERS" /* name of the wrapper file */
-
-#define CVSUMASK_ENV "CVSUMASK" /* Effective umask for repository */
-
-/*
- * If the beginning of the Repository matches the following string, strip it
- * so that the output to the logfile does not contain a full pathname.
- *
- * If the CVSROOT environment variable is set, it overrides this define.
- */
-#define REPOS_STRIP "/master/"
-
-/* Large enough to hold DATEFORM. Not an arbitrary limit as long as
- it is used for that purpose, and not to hold a string from the
- command line, the client, etc. */
-#define MAXDATELEN 50
-
-/* The type of an entnode. */
-enum ent_type
-{
- ENT_FILE, ENT_SUBDIR
-};
-
-/* structure of a entry record */
-struct entnode
-{
- enum ent_type type;
- char *user;
- char *version;
-
- /* Timestamp, or "" if none (never NULL). */
- char *timestamp;
-
- /* Keyword expansion options, or "" if none (never NULL). */
- char *options;
-
- char *tag;
- char *date;
- char *conflict;
-};
-typedef struct entnode Entnode;
-
-/* The type of request that is being done in do_module() */
-enum mtype
-{
- CHECKOUT, TAG, PATCH, EXPORT, MISC
-};
-
-/*
- * structure used for list-private storage by Entries_Open() and
- * Version_TS() and Find_Directories().
- */
-struct stickydirtag
-{
- /* These fields pass sticky tag information from Entries_Open() to
- Version_TS(). */
- int aflag;
- char *tag;
- char *date;
- int nonbranch;
-
- /* This field is set by Entries_Open() if there was subdirectory
- information; Find_Directories() uses it to see whether it needs
- to scan the directory itself. */
- int subdirs;
-};
-
-/* Flags for find_{names,dirs} routines */
-#define W_LOCAL 0x01 /* look for files locally */
-#define W_REPOS 0x02 /* look for files in the repository */
-#define W_ATTIC 0x04 /* look for files in the attic */
-
-/* Flags for return values of direnter procs for the recursion processor */
-enum direnter_type
-{
- R_PROCESS = 1, /* process files and maybe dirs */
- R_SKIP_FILES, /* don't process files in this dir */
- R_SKIP_DIRS, /* don't process sub-dirs */
- R_SKIP_ALL /* don't process files or dirs */
-};
-#ifdef ENUMS_CAN_BE_TROUBLE
-typedef int Dtype;
-#else
-typedef enum direnter_type Dtype;
-#endif
-
-/* Recursion processor lock types */
-#define CVS_LOCK_NONE 0
-#define CVS_LOCK_READ 1
-#define CVS_LOCK_WRITE 2
-
-extern const char *program_name, *program_path, *cvs_cmd_name;
-extern char *Tmpdir, *Editor;
-extern int cvsadmin_root;
-extern char *CurDir;
-extern int really_quiet, quiet;
-extern int use_editor;
-extern int cvswrite;
-extern mode_t cvsumask;
-extern char *RCS_citag;
-
-
-
-/* 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. */
-extern char *CVSroot_cmdline;
-
-/* These variables keep track of all of the CVSROOT directories that
- have been seen by the client and the current one of those selected. */
-extern List *root_directories;
-extern cvsroot_t *current_parsed_root;
-
-extern char *emptydir_name PROTO ((void));
-extern int safe_location PROTO ((char *));
-
-extern int trace; /* Show all commands */
-extern int noexec; /* Don't modify disk anywhere */
-extern int readonlyfs; /* fail on all write locks; succeed all read locks */
-extern int logoff; /* Don't write history entry */
-extern int require_real_user; /* skip CVSROOT/passwd, /etc/passwd users only*/
-
-extern int top_level_admin;
-
-
-#define LOGMSG_REREAD_NEVER 0 /* do_verify - never reread message */
-#define LOGMSG_REREAD_ALWAYS 1 /* do_verify - always reread message */
-#define LOGMSG_REREAD_STAT 2 /* do_verify - reread message if changed */
-extern int RereadLogAfterVerify;
-
-#ifdef CLIENT_SUPPORT
-extern List *dirs_sent_to_server; /* used to decide which "Argument
- xxx" commands to send to each
- server in multiroot mode. */
-#endif
-
-extern char hostname[];
-
-/* Externs that are included directly in the CVS sources */
-
-int RCS_merge PROTO((RCSNode *, const char *, const char *, const char *,
- const char *, const char *));
-/* Flags used by RCS_* functions. See the description of the individual
- functions for which flags mean what for each function. */
-#define RCS_FLAGS_FORCE 1
-#define RCS_FLAGS_DEAD 2
-#define RCS_FLAGS_QUIET 4
-#define RCS_FLAGS_MODTIME 8
-#define RCS_FLAGS_KEEPFILE 16
-#define RCS_FLAGS_USETIME 32
-
-extern int RCS_exec_rcsdiff PROTO ((RCSNode *rcsfile, int diff_argc,
- char *const *diff_argv,
- const char *options,
- const char *rev1, const char *rev1_cache,
- const char *rev2, const char *label1,
- const char *label2, const char *workfile));
-extern int diff_exec PROTO ((const char *file1, const char *file2,
- const char *label1, const char *label2,
- int diff_argc, char *const *diff_argv,
- const char *out));
-
-
-#include "error.h"
-
-DBM *open_module PROTO((void));
-FILE *open_file PROTO((const char *, const char *));
-List *Find_Directories PROTO((char *repository, int which, List *entries));
-void Entries_Close PROTO((List *entries));
-List *Entries_Open PROTO ((int aflag, char *update_dir));
-void Subdirs_Known PROTO((List *entries));
-void Subdir_Register PROTO((List *, const char *, const char *));
-void Subdir_Deregister PROTO((List *, const char *, const char *));
-
-char *Make_Date PROTO((char *rawdate));
-char *date_from_time_t PROTO ((time_t));
-void date_to_internet PROTO ((char *, const char *));
-void date_to_tm PROTO ((struct tm *, const char *));
-void tm_to_internet PROTO ((char *, const struct tm *));
-
-char *Name_Repository PROTO((const char *dir, const char *update_dir));
-const char *Short_Repository PROTO((const char *repository));
-void Sanitize_Repository_Name PROTO((char *repository));
-
-char *previous_rev PROTO ((RCSNode *rcs, const char *rev));
-char *gca PROTO ((const char *rev1, const char *rev2));
-extern void check_numeric PROTO ((const char *, int, char **));
-char *getcaller PROTO ((void));
-char *time_stamp PROTO ((const char *file));
-
-void *xmalloc PROTO((size_t bytes));
-void *xrealloc PROTO((void *ptr, size_t bytes));
-void expand_string PROTO ((char **, size_t *, size_t));
-void xrealloc_and_strcat PROTO ((char **, size_t *, const char *));
-char *xstrdup PROTO((const char *str));
-int strip_trailing_newlines PROTO((char *str));
-int pathname_levels PROTO ((const char *path));
-
-typedef int (*CALLPROC) PROTO((const char *repository, const char *value));
-int Parse_Info PROTO((const char *infofile, const char *repository,
- CALLPROC callproc, int all));
-extern int parse_config PROTO ((char *));
-
-typedef RETSIGTYPE (*SIGCLEANUPPROC) PROTO(());
-int SIG_register PROTO((int sig, SIGCLEANUPPROC sigcleanup));
-int isdir PROTO((const char *file));
-int isfile PROTO((const char *file));
-int islink PROTO((const char *file));
-int isdevice PROTO ((const char *));
-int isreadable PROTO((const char *file));
-int iswritable PROTO((const char *file));
-int isaccessible PROTO((const char *file, const int mode));
-int isabsolute PROTO((const char *filename));
-#ifdef HAVE_READLINK
-char *xreadlink PROTO((const char *link));
-#endif
-char *xresolvepath PROTO((const char *path));
-const char *last_component PROTO((const char *path));
-char *get_homedir PROTO ((void));
-char *strcat_filename_onto_homedir PROTO ((const char *, const char *));
-char *cvs_temp_name PROTO ((void));
-FILE *cvs_temp_file PROTO ((char **filename));
-void parseopts PROTO ((const char *root));
-
-int numdots PROTO((const char *s));
-char *increment_revnum PROTO ((const char *));
-int compare_revnums PROTO ((const char *, const char *));
-int unlink_file PROTO((const char *f));
-int unlink_file_dir PROTO((const char *f));
-
-
-
-/* This is the structure that the recursion processor passes to the
- fileproc to tell it about a particular file. */
-struct file_info
-{
- /* Name of the file, without any directory component. */
- const char *file;
-
- /* Name of the directory we are in, relative to the directory in
- which this command was issued. We have cd'd to this directory
- (either in the working directory or in the repository, depending
- on which sort of recursion we are doing). If we are in the directory
- in which the command was issued, this is "". */
- const char *update_dir;
-
- /* update_dir and file put together, with a slash between them as
- necessary. This is the proper way to refer to the file in user
- messages. */
- const char *fullname;
-
- /* Name of the directory corresponding to the repository which contains
- this file. */
- const char *repository;
-
- /* The pre-parsed entries for this directory. */
- List *entries;
-
- RCSNode *rcs;
-};
-
-
-
-int update PROTO((int argc, char *argv[]));
-/* The only place this is currently used outside of update.c is add.c.
- * Restricting its use to update.c seems to be in the best interest of
- * modularity, but I can't think of a good way to get an update of a
- * resurrected file done and print the fact otherwise.
- */
-void write_letter PROTO ((struct file_info *finfo, int letter));
-int xcmp PROTO((const char *file1, const char *file2));
-int yesno PROTO((void));
-void *valloc PROTO((size_t bytes));
-time_t get_date PROTO((char *date, struct timeb *now));
-extern int Create_Admin PROTO ((const char *dir, const char *update_dir,
- const char *repository, const char *tag,
- const char *date,
- int nonbranch, int warn, int dotemplate));
-extern int expand_at_signs PROTO ((const char *, off_t, FILE *));
-
-/* Locking subsystem (implemented in lock.c). */
-
-int Reader_Lock PROTO((char *xrepository));
-void Lock_Cleanup PROTO((void));
-
-/* Writelock an entire subtree, well the part specified by ARGC, ARGV, LOCAL,
- and AFLAG, anyway. */
-void lock_tree_for_write PROTO ((int argc, char **argv, int local, int which,
- int aflag));
-
-/* See lock.c for description. */
-extern void lock_dir_for_write PROTO ((char *));
-
-/* Get a write lock for the history file. */
-int history_lock PROTO ((const char *));
-void clear_history_lock PROTO ((void));
-
-/* Get a write lock for the val-tags file. */
-int val_tags_lock PROTO ((const char *));
-void clear_val_tags_lock PROTO ((void));
-
-/* LockDir setting from CVSROOT/config. */
-extern char *lock_dir;
-
-void Scratch_Entry PROTO((List * list, const char *fname));
-void ParseTag PROTO((char **tagp, char **datep, int *nonbranchp));
-void WriteTag PROTO ((const char *dir, const char *tag, const char *date,
- int nonbranch, const char *update_dir,
- const char *repository));
-void WriteTemplate PROTO ((const char *dir, const char *update_dir));
-void cat_module PROTO((int status));
-void check_entries PROTO((char *dir));
-void close_module PROTO((DBM * db));
-void copy_file PROTO((const char *from, const char *to));
-void fperrmsg PROTO((FILE * fp, int status, int errnum, char *message,...));
-void free_names PROTO((int *pargc, char *argv[]));
-
-extern int ign_name PROTO ((char *name));
-void ign_add PROTO((char *ign, int hold));
-void ign_add_file PROTO((char *file, int hold));
-void ign_setup PROTO((void));
-void ign_dir_add PROTO((char *name));
-int ignore_directory PROTO((const char *name));
-typedef void (*Ignore_proc) PROTO ((const char *, const char *));
-extern void ignore_files PROTO ((List *, List *, const char *, Ignore_proc));
-extern int ign_inhibit_server;
-
-#include "update.h"
-
-void line2argv PROTO ((int *pargc, char ***argv, char *line, char *sepchars));
-void make_directories PROTO((const char *name));
-void make_directory PROTO((const char *name));
-extern int mkdir_if_needed PROTO ((const char *name));
-void rename_file PROTO((const char *from, const char *to));
-/* Expand wildcards in each element of (ARGC,ARGV). This is according to the
- files which exist in the current directory, and accordingly to OS-specific
- conventions regarding wildcard syntax. It might be desirable to change the
- former in the future (e.g. "cvs status *.h" including files which don't exist
- in the working directory). The result is placed in *PARGC and *PARGV;
- the *PARGV array itself and all the strings it contains are newly
- malloc'd. It is OK to call it with PARGC == &ARGC or PARGV == &ARGV. */
-extern void expand_wild PROTO ((int argc, char **argv,
- int *pargc, char ***pargv));
-
-#ifdef SERVER_SUPPORT
-extern int cvs_casecmp PROTO ((const char *, const char *));
-#endif
-
-void strip_trailing_slashes PROTO((char *path));
-void update_delproc PROTO((Node * p));
-void usage PROTO((const char *const *cpp));
-void xchmod PROTO((const char *fname, int writable));
-char *xgetwd PROTO((void));
-List *Find_Names PROTO((char *repository, int which, int aflag,
- List **optentries));
-void Register PROTO((List * list, const char *fname, const char *vn,
- const char *ts, const char *options, const char *tag,
- const char *date, const char *ts_conflict));
-void Update_Logfile PROTO((const char *repository, const char *xmessage,
- FILE * xlogfp, List * xchanges));
-void do_editor PROTO((const char *dir, char **messagep,
- const char *repository, List * changes));
-
-void do_verify PROTO((char **messagep, const char *repository));
-
-typedef int (*CALLBACKPROC) PROTO((int argc, char *argv[], char *where,
- char *mwhere, char *mfile, int shorten, int local_specified,
- char *omodule, char *msg));
-
-typedef int (*FILEPROC) PROTO ((void *callerdat, struct file_info *finfo));
-typedef int (*FILESDONEPROC) PROTO ((void *callerdat, int err,
- const char *repository,
- const char *update_dir,
- List *entries));
-typedef Dtype (*DIRENTPROC) PROTO ((void *callerdat, const char *dir,
- const char *repos, const char *update_dir,
- List *entries));
-typedef int (*DIRLEAVEPROC) PROTO ((void *callerdat, const char *dir, int err,
- const char *update_dir, List *entries));
-
-extern int mkmodules PROTO ((char *dir));
-extern int init PROTO ((int argc, char **argv));
-
-int do_module PROTO((DBM * db, char *mname, enum mtype m_type, char *msg,
- CALLBACKPROC callback_proc, char *where, int shorten,
- int local_specified, int run_module_prog, int build_dirs,
- char *extra_arg));
-void history_write PROTO((int type, const char *update_dir, const char *revs,
- const char *name, const char *repository));
-int start_recursion PROTO((FILEPROC fileproc, FILESDONEPROC filesdoneproc,
- DIRENTPROC direntproc, DIRLEAVEPROC dirleaveproc,
- void *callerdat,
- int argc, char *argv[], int local, int which,
- int aflag, int locktype, char *update_preload,
- int dosrcs, char *repository));
-void SIG_beginCrSect PROTO((void));
-void SIG_endCrSect PROTO((void));
-int SIG_inCrSect PROTO((void));
-void read_cvsrc PROTO((int *argc, char ***argv, const char *cmdname));
-
-char *make_message_rcslegal PROTO((const char *message));
-extern int file_has_markers PROTO ((const struct file_info *));
-extern void get_file PROTO ((const char *, const char *, const char *,
- char **, size_t *, size_t *));
-extern char *shell_escape PROTO((char *buf, const char *str));
-char *backup_file PROTO((const char *file, const char *suffix));
-extern void resolve_symlink PROTO ((char **filename));
-void sleep_past PROTO ((time_t desttime));
-
-/* flags for run_exec(), the fast system() for CVS */
-#define RUN_NORMAL 0x0000 /* no special behaviour */
-#define RUN_COMBINED 0x0001 /* stdout is duped to stderr */
-#define RUN_REALLY 0x0002 /* do the exec, even if noexec is on */
-#define RUN_STDOUT_APPEND 0x0004 /* append to stdout, don't truncate */
-#define RUN_STDERR_APPEND 0x0008 /* append to stderr, don't truncate */
-#define RUN_SIGIGNORE 0x0010 /* ignore interrupts for command */
-#define RUN_TTY (char *)0 /* for the benefit of lint */
-
-void run_add_arg_p PROTO ((int *, size_t *, char ***, const char *s));
-void run_arg_free_p PROTO ((int, char **));
-void run_arg PROTO((const char *s));
-void run_print PROTO((FILE * fp));
-void run_setup PROTO ((const char *prog));
-int run_exec PROTO((const char *stin, const char *stout, const char *sterr,
- int flags));
-
-/* other similar-minded stuff from run.c. */
-FILE *run_popen PROTO((const char *, const char *));
-int piped_child PROTO((const char **, int *, int *, int));
-void close_on_exec PROTO((int));
-
-pid_t waitpid PROTO((pid_t, int *, int));
-
-/*
- * a struct vers_ts contains all the information about a file including the
- * user and rcs file names, and the version checked out and the head.
- *
- * this is usually obtained from a call to Version_TS which takes a
- * tag argument for the RCS file if desired
- */
-struct vers_ts
-{
- /* rcs version user file derives from, from CVS/Entries.
- It can have the following special values:
-
- NULL = file is not mentioned in Entries (this is also used for a
- directory).
- "" = ILLEGAL! The comment used to say that it meant "no user file"
- but as far as I know CVS didn't actually use it that way.
- Note that according to cvs.texinfo, "" is not legal in the
- Entries file.
- 0 = user file is new
- -vers = user file to be removed. */
- char *vn_user;
-
- /* Numeric revision number corresponding to ->vn_tag (->vn_tag
- will often be symbolic). */
- char *vn_rcs;
- /* If ->tag is a simple tag in the RCS file--a tag which really
- exists which is not a magic revision--and if ->date is NULL,
- then this is a copy of ->tag. Otherwise, it is a copy of
- ->vn_rcs. */
- char *vn_tag;
-
- /* This is the timestamp from stating the file in the working directory.
- It is NULL if there is no file in the working directory. It is
- "Is-modified" if we know the file is modified but don't have its
- contents. */
- char *ts_user;
- /* Timestamp from CVS/Entries. For the server, ts_user and ts_rcs
- are computed in a slightly different way, but the fact remains that
- if they are equal the file in the working directory is unmodified
- and if they differ it is modified. */
- char *ts_rcs;
-
- /* Options from CVS/Entries (keyword expansion), malloc'd. If none,
- then it is an empty string (never NULL). */
- char *options;
-
- /* If non-NULL, there was a conflict (or merely a merge? See merge_file)
- and the time stamp in this field is the time stamp of the working
- directory file which was created with the conflict markers in it.
- This is from CVS/Entries. */
- char *ts_conflict;
-
- /* Tag specified on the command line, or if none, tag stored in
- CVS/Entries. */
- char *tag;
- /* Date specified on the command line, or if none, date stored in
- CVS/Entries. */
- char *date;
- /* If this is 1, then tag is not a branch tag. If this is 0, then
- tag may or may not be a branch tag. */
- int nonbranch;
-
- /* Pointer to entries file node */
- Entnode *entdata;
-
- /* Pointer to parsed src file info */
- RCSNode *srcfile;
-};
-typedef struct vers_ts Vers_TS;
-
-Vers_TS *Version_TS PROTO ((struct file_info *finfo, char *options, char *tag,
- char *date, int force_tag_match,
- int set_time));
-void freevers_ts PROTO ((Vers_TS ** versp));
-
-/* Miscellaneous CVS infrastructure which layers on top of the recursion
- processor (for example, needs struct file_info). */
-
-int Checkin PROTO ((int type, struct file_info *finfo, char *rev,
- char *tag, char *options, char *message));
-int No_Difference PROTO ((struct file_info *finfo, Vers_TS *vers));
-/* TODO: can the finfo argument to special_file_mismatch be changed? -twp */
-int special_file_mismatch PROTO ((struct file_info *finfo,
- char *rev1, char *rev2));
-
-/* CVSADM_BASEREV stuff, from entries.c. */
-extern char *base_get PROTO ((struct file_info *));
-extern void base_register PROTO ((struct file_info *, char *));
-extern void base_deregister PROTO ((struct file_info *));
-
-/*
- * defines for Classify_File() to determine the current state of a file.
- * These are also used as types in the data field for the list we make for
- * Update_Logfile in commit, import, and add.
- */
-enum classify_type
-{
- T_UNKNOWN = 1, /* no old-style analog existed */
- T_CONFLICT, /* C (conflict) list */
- T_NEEDS_MERGE, /* G (needs merging) list */
- T_MODIFIED, /* M (needs checked in) list */
- T_CHECKOUT, /* O (needs checkout) list */
- T_ADDED, /* A (added file) list */
- T_REMOVED, /* R (removed file) list */
- T_REMOVE_ENTRY, /* W (removed entry) list */
- T_UPTODATE, /* File is up-to-date */
- T_PATCH, /* P Like C, but can patch */
- T_TITLE /* title for node type */
-};
-typedef enum classify_type Ctype;
-
-Ctype Classify_File PROTO
- ((struct file_info *finfo, char *tag, char *date, char *options,
- int force_tag_match, int aflag, Vers_TS **versp, int pipeout));
-
-/*
- * structure used for list nodes passed to Update_Logfile() and
- * do_editor().
- */
-struct logfile_info
-{
- enum classify_type type;
- char *tag;
- char *rev_old; /* rev number before a commit/modify,
- NULL for add or import */
- char *rev_new; /* rev number after a commit/modify,
- add, or import, NULL for remove */
-};
-
-/* Wrappers. */
-
-typedef enum { WRAP_MERGE, WRAP_COPY } WrapMergeMethod;
-typedef enum {
- /* -t and -f wrapper options. Treating directories as single files. */
- WRAP_TOCVS,
- WRAP_FROMCVS,
- /* -k wrapper option. Default keyword expansion options. */
- WRAP_RCSOPTION
-} WrapMergeHas;
-
-void wrap_setup PROTO((void));
-int wrap_name_has PROTO((const char *name,WrapMergeHas has));
-char *wrap_rcsoption PROTO ((const char *fileName, int asFlag));
-char *wrap_tocvs_process_file PROTO((const char *fileName));
-int wrap_merge_is_copy PROTO((const char *fileName));
-void wrap_fromcvs_process_file PROTO ((const char *fileName));
-void wrap_add_file PROTO((const char *file,int temp));
-void wrap_add PROTO((char *line,int temp));
-void wrap_send PROTO ((void));
-#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
-void wrap_unparse_rcs_options PROTO ((char **, int));
-#endif /* SERVER_SUPPORT || CLIENT_SUPPORT */
-
-/* Pathname expansion */
-char *expand_path PROTO((const char *name, const char *file, int line));
-
-/* User variables. */
-extern List *variable_list;
-
-extern void variable_set PROTO ((char *nameval));
-
-int watch PROTO ((int argc, char **argv));
-int edit PROTO ((int argc, char **argv));
-int unedit PROTO ((int argc, char **argv));
-int editors PROTO ((int argc, char **argv));
-int watchers PROTO ((int argc, char **argv));
-extern int annotate PROTO ((int argc, char **argv));
-extern int add PROTO ((int argc, char **argv));
-extern int admin PROTO ((int argc, char **argv));
-extern int checkout PROTO ((int argc, char **argv));
-extern int commit PROTO ((int argc, char **argv));
-extern int diff PROTO ((int argc, char **argv));
-extern int history PROTO ((int argc, char **argv));
-extern int import PROTO ((int argc, char **argv));
-extern int cvslog PROTO ((int argc, char **argv));
-#ifdef AUTH_CLIENT_SUPPORT
-/* Some systems (namely Mac OS X) have conflicting definitions for these
- * functions. Avoid them.
- */
-#ifdef HAVE_LOGIN
-# define login cvs_login
-#endif /* HAVE_LOGIN */
-#ifdef HAVE_LOGOUT
-# define logout cvs_logout
-#endif /* HAVE_LOGOUT */
-extern int login PROTO((int argc, char **argv));
-extern int logout PROTO((int argc, char **argv));
-#endif /* AUTH_CLIENT_SUPPORT */
-extern int patch PROTO((int argc, char **argv));
-extern int release PROTO((int argc, char **argv));
-extern int cvsremove PROTO((int argc, char **argv));
-extern int rtag PROTO((int argc, char **argv));
-extern int cvsstatus PROTO((int argc, char **argv));
-extern int cvstag PROTO((int argc, char **argv));
-extern int version PROTO((int argc, char **argv));
-
-extern unsigned long int lookup_command_attribute PROTO((char *));
-
-#if defined(AUTH_CLIENT_SUPPORT) || defined(AUTH_SERVER_SUPPORT)
-char *scramble PROTO ((char *str));
-char *descramble PROTO ((char *str));
-#endif /* AUTH_CLIENT_SUPPORT || AUTH_SERVER_SUPPORT */
-
-#ifdef AUTH_CLIENT_SUPPORT
-char *get_cvs_password PROTO((void));
-void free_cvs_password PROTO((char *str));
-int get_cvs_port_number PROTO((const cvsroot_t *root));
-char *normalize_cvsroot PROTO((const cvsroot_t *root));
-#endif /* AUTH_CLIENT_SUPPORT */
-
-extern void tag_check_valid PROTO ((char *, int, char **, int, int, char *));
-extern void tag_check_valid_join PROTO ((char *, int, char **, int, int,
- char *));
-
-#include "server.h"
-
-/* From server.c and documented there. */
-extern void cvs_output PROTO ((const char *, size_t));
-extern void cvs_output_binary PROTO ((char *, size_t));
-extern void cvs_outerr PROTO ((const char *, size_t));
-extern void cvs_flusherr PROTO ((void));
-extern void cvs_flushout PROTO ((void));
-extern void cvs_output_tagged PROTO ((const char *, const char *));
diff --git a/contrib/cvs/src/cvsbug.in b/contrib/cvs/src/cvsbug.in
deleted file mode 100755
index 07de1512249e..000000000000
--- a/contrib/cvs/src/cvsbug.in
+++ /dev/null
@@ -1,525 +0,0 @@
-#! /bin/sh
-# Submit a problem report to a GNATS site.
-# Copyright (C) 1993 Free Software Foundation, Inc.
-# Contributed by Brendan Kehoe (brendan@cygnus.com), based on a
-# version written by Heinz G. Seidl (hgs@ide.com).
-#
-# This file is part of GNU GNATS.
-# Modified by Berliner for CVS.
-#
-# GNU GNATS is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# GNU GNATS is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# The version of this send-pr.
-VERSION=3.2
-
-# The submitter-id for your site.
-SUBMITTER=net
-
-## # Where the GNATS directory lives, if at all.
-## [ -z "$GNATS_ROOT" ] &&
-## GNATS_ROOT=/usr/local/lib/gnats/gnats-db
-
-# The default mail address for PR submissions.
-GNATS_ADDR=@PACKAGE_BUGREPORT@
-
-## # Where the gnats category tree lives.
-## DATADIR=/usr/local/lib
-
-## # If we've been moved around, try using GCC_EXEC_PREFIX.
-## [ ! -d $DATADIR/gnats -a -d "$GCC_EXEC_PREFIX" ] && DATADIR=${GCC_EXEC_PREFIX}..
-
-# The default release for this host.
-DEFAULT_RELEASE="@VERSION@"
-
-# The default organization.
-DEFAULT_ORGANIZATION="net"
-
-## # The default site to look for.
-## GNATS_SITE=unknown
-
-## # Newer config information?
-## [ -f ${GNATS_ROOT}/gnats-adm/config ] && . ${GNATS_ROOT}/gnats-adm/config
-
-# Hack mktemp on systems that don't have it.
-@MKTEMP_SH_FUNCTION@
-MKTEMP="@MKTEMP@"
-
-# What mailer to use. This must come after the config file, since it is
-# host-dependent.
-SENDMAIL="@SENDMAIL@"
-MAIL_AGENT="$SENDMAIL -oi -t"
-MAILER=`echo $MAIL_AGENT | sed -e 's, .*,,'`
-if [ ! -f "$MAILER" ] ; then
- echo "$COMMAND: Cannot find mail program \"$MAILER\"."
- echo "$COMMAND: Please fix the MAIL_AGENT entry in the $COMMAND file."
- exit 1
-fi
-
-if test "`echo -n foo`" = foo ; then
- ECHON=bsd
-elif test "`echo 'foo\c'`" = foo ; then
- ECHON=sysv
-else
- ECHON=none
-fi
-
-if [ $ECHON = bsd ] ; then
- ECHON1="echo -n"
- ECHON2=
-elif [ $ECHON = sysv ] ; then
- ECHON1=echo
- ECHON2='\c'
-else
- ECHON1=echo
- ECHON2=
-fi
-
-#
-
-[ -z "$TMPDIR" ] && TMPDIR=/tmp
-
-TEMP="`$MKTEMP $TMPDIR/p.XXXXXX`"
-BAD="`$MKTEMP $TMPDIR/pbad.XXXXXX`"
-REF="`$MKTEMP $TMPDIR/pf.XXXXXX`"
-
-if [ -z "$LOGNAME" -a -n "$USER" ]; then
- LOGNAME=$USER
-fi
-
-FROM="$LOGNAME"
-REPLY_TO="$LOGNAME"
-
-# Find out the name of the originator of this PR.
-if [ -n "$NAME" ]; then
- ORIGINATOR="$NAME"
-elif [ -f $HOME/.fullname ]; then
- ORIGINATOR="`sed -e '1q' $HOME/.fullname`"
-elif [ -f /bin/domainname ]; then
- if [ "`/bin/domainname`" != "" -a -f /usr/bin/ypcat ]; then
- # Must use temp file due to incompatibilities in quoting behavior
- # and to protect shell metacharacters in the expansion of $LOGNAME
- /usr/bin/ypcat passwd 2>/dev/null | cat - /etc/passwd | grep "^$LOGNAME:" |
- cut -f5 -d':' | sed -e 's/,.*//' > $TEMP
- ORIGINATOR="`cat $TEMP`"
- fi
-fi
-
-if [ "$ORIGINATOR" = "" ]; then
- grep "^$LOGNAME:" /etc/passwd | cut -f5 -d':' | sed -e 's/,.*//' > $TEMP
- ORIGINATOR="`cat $TEMP`"
-fi
-
-if [ -n "$ORGANIZATION" ]; then
- if [ -f "$ORGANIZATION" ]; then
- ORGANIZATION="`cat $ORGANIZATION`"
- fi
-else
- if [ -n "$DEFAULT_ORGANIZATION" ]; then
- ORGANIZATION="$DEFAULT_ORGANIZATION"
- elif [ -f $HOME/.organization ]; then
- ORGANIZATION="`cat $HOME/.organization`"
- elif [ -f $HOME/.signature ]; then
- ORGANIZATION="`cat $HOME/.signature`"
- fi
-fi
-
-# If they don't have a preferred editor set, then use
-if [ -z "$VISUAL" ]; then
- if [ -z "$EDITOR" ]; then
- EDIT=vi
- else
- EDIT="$EDITOR"
- fi
-else
- EDIT="$VISUAL"
-fi
-
-# Find out some information.
-SYSTEM=`( [ -f /bin/uname ] && /bin/uname -a ) || \
- ( [ -f /usr/bin/uname ] && /usr/bin/uname -a ) || echo ""`
-ARCH=`[ -f /bin/arch ] && /bin/arch`
-MACHINE=`[ -f /bin/machine ] && /bin/machine`
-
-COMMAND=`echo $0 | sed -e 's,.*/,,'`
-## USAGE="Usage: $COMMAND [-PVL] [-t address] [-f filename] [--request-id]
-USAGE="Usage: $COMMAND [-PVL]
-[--version]"
-REMOVE=
-BATCH=
-
-while [ $# -gt 0 ]; do
- case "$1" in
- -r) ;; # Ignore for backward compat.
-## -t | --to) if [ $# -eq 1 ]; then echo "$USAGE"; exit 1; fi
-## shift ; GNATS_ADDR="$1"
-## EXPLICIT_GNATS_ADDR=true
-## ;;
-## -f | --file) if [ $# -eq 1 ]; then echo "$USAGE"; exit 1; fi
-## shift ; IN_FILE="$1"
-## if [ "$IN_FILE" != "-" -a ! -r "$IN_FILE" ]; then
-## echo "$COMMAND: cannot read $IN_FILE"
-## exit 1
-## fi
-## ;;
- -b | --batch) BATCH=true ;;
- -p | -P | --print) PRINT=true ;;
- -L | --list) FORMAT=norm ;;
- -l | -CL | --lisp) FORMAT=lisp ;;
-## --request-id) REQUEST_ID=true ;;
- -h | --help) echo "$USAGE"; exit 0 ;;
- -V | --version) echo "$VERSION"; exit 0 ;;
- -*) echo "$USAGE" ; exit 1 ;;
- *) echo "$USAGE" ; exit 1
-## if [ -z "$USER_GNATS_SITE" ]; then
-## if [ ! -r "$DATADIR/gnats/$1" ]; then
-## echo "$COMMAND: the GNATS site $1 does not have a categories list."
-## exit 1
-## else
-## # The site name is the alias they'll have to have created.
-## USER_GNATS_SITE=$1
-## fi
-## else
-## echo "$USAGE" ; exit 1
-## fi
- ;;
- esac
- shift
-done
-
-if [ -n "$USER_GNATS_SITE" ]; then
- GNATS_SITE=$USER_GNATS_SITE
- GNATS_ADDR=$USER_GNATS_SITE-gnats
-fi
-
-if [ "$SUBMITTER" = "unknown" -a -z "$REQUEST_ID" -a -z "$IN_FILE" ]; then
- cat << '__EOF__'
-It seems that send-pr is not installed with your unique submitter-id.
-You need to run
-
- install-sid YOUR-SID
-
-where YOUR-SID is the identification code you received with `send-pr'.
-`send-pr' will automatically insert this value into the template field
-`>Submitter-Id'. If you've downloaded `send-pr' from the Net, use `net'
-for this value. If you do not know your id, run `send-pr --request-id' to
-get one from your support site.
-__EOF__
- exit 1
-fi
-
-## if [ -r "$DATADIR/gnats/$GNATS_SITE" ]; then
-## CATEGORIES=`grep -v '^#' $DATADIR/gnats/$GNATS_SITE | sort`
-## else
-## echo "$COMMAND: could not read $DATADIR/gnats/$GNATS_SITE for categories list."
-## exit 1
-## fi
-CATEGORIES="contrib cvs doc pcl-cvs portability"
-
-if [ -z "$CATEGORIES" ]; then
- echo "$COMMAND: the categories list for $GNATS_SITE was empty!"
- exit 1
-fi
-
-case "$FORMAT" in
- lisp) echo "$CATEGORIES" | \
- awk 'BEGIN {printf "( "}
- {printf "(\"%s\") ",$0}
- END {printf ")\n"}'
- exit 0
- ;;
- norm) l=`echo "$CATEGORIES" | \
- awk 'BEGIN {max = 0; }
- { if (length($0) > max) { max = length($0); } }
- END {print max + 1;}'`
- c=`expr 70 / $l`
- if [ $c -eq 0 ]; then c=1; fi
- echo "$CATEGORIES" | \
- awk 'BEGIN {print "Known categories:"; i = 0 }
- { printf ("%-'$l'.'$l's", $0); if ((++i % '$c') == 0) { print "" } }
- END { print ""; }'
- exit 0
- ;;
-esac
-
-ORIGINATOR_C='<name of the PR author (one line)>'
-ORGANIZATION_C='<organization of PR author (multiple lines)>'
-CONFIDENTIAL_C='<[ yes | no ] (one line)>'
-SYNOPSIS_C='<synopsis of the problem (one line)>'
-SEVERITY_C='<[ non-critical | serious | critical ] (one line)>'
-PRIORITY_C='<[ low | medium | high ] (one line)>'
-CATEGORY_C='<name of the product (one line)>'
-CLASS_C='<[ sw-bug | doc-bug | change-request | support ] (one line)>'
-RELEASE_C='<release number or tag (one line)>'
-ENVIRONMENT_C='<machine, os, target, libraries (multiple lines)>'
-DESCRIPTION_C='<precise description of the problem (multiple lines)>'
-HOW_TO_REPEAT_C='<code/input/activities to reproduce the problem (multiple lines)>'
-FIX_C='<how to correct or work around the problem, if known (multiple lines)>'
-
-# Catch some signals. ($xs kludge needed by Sun /bin/sh)
-xs=0
-trap 'rm -f $REF $TEMP; exit $xs' 0
-trap 'echo "$COMMAND: Aborting ..."; rm -f $REF $TEMP; xs=1; exit' 1 2 3 13 15
-
-# If they told us to use a specific file, then do so.
-if [ -n "$IN_FILE" ]; then
- if [ "$IN_FILE" = "-" ]; then
- # The PR is coming from the standard input.
- if [ -n "$EXPLICIT_GNATS_ADDR" ]; then
- sed -e "s;^[Tt][Oo]:.*;To: $GNATS_ADDR;" > $TEMP
- else
- cat > $TEMP
- fi
- else
- # Use the file they named.
- if [ -n "$EXPLICIT_GNATS_ADDR" ]; then
- sed -e "s;^[Tt][Oo]:.*;To: $GNATS_ADDR;" $IN_FILE > $TEMP
- else
- cat $IN_FILE > $TEMP
- fi
- fi
-else
-
- if [ -n "$PR_FORM" -a -z "$PRINT_INTERN" ]; then
- # If their PR_FORM points to a bogus entry, then bail.
- if [ ! -f "$PR_FORM" -o ! -r "$PR_FORM" -o ! -s "$PR_FORM" ]; then
- echo "$COMMAND: can't seem to read your template file (\`$PR_FORM'), ignoring PR_FORM"
- sleep 1
- PRINT_INTERN=bad_prform
- fi
- fi
-
- if [ -n "$PR_FORM" -a -z "$PRINT_INTERN" ]; then
- cp $PR_FORM $TEMP ||
- ( echo "$COMMAND: could not copy $PR_FORM" ; xs=1; exit )
- else
- for file in $TEMP $REF ; do
- cat > $file << '__EOF__'
-SEND-PR: -*- send-pr -*-
-SEND-PR: Lines starting with `SEND-PR' will be removed automatically, as
-SEND-PR: will all comments (text enclosed in `<' and `>').
-SEND-PR:
-SEND-PR: Choose from the following categories:
-SEND-PR:
-__EOF__
-
- # Format the categories so they fit onto lines.
- l=`echo "$CATEGORIES" | \
- awk 'BEGIN {max = 0; }
- { if (length($0) > max) { max = length($0); } }
- END {print max + 1;}'`
- c=`expr 61 / $l`
- if [ $c -eq 0 ]; then c=1; fi
- echo "$CATEGORIES" | \
- awk 'BEGIN {printf "SEND-PR: "; i = 0 }
- { printf ("%-'$l'.'$l's", $0);
- if ((++i % '$c') == 0) { printf "\nSEND-PR: " } }
- END { printf "\nSEND-PR:\n"; }' >> $file
-
- cat >> $file << __EOF__
-To: $GNATS_ADDR
-Subject:
-From: $FROM
-Reply-To: $REPLY_TO
-X-send-pr-version: $VERSION
-
-
->Submitter-Id: $SUBMITTER
->Originator: $ORIGINATOR
->Organization:
-${ORGANIZATION-$ORGANIZATION_C}
->Confidential: $CONFIDENTIAL_C
->Synopsis: $SYNOPSIS_C
->Severity: $SEVERITY_C
->Priority: $PRIORITY_C
->Category: $CATEGORY_C
->Class: $CLASS_C
->Release: ${DEFAULT_RELEASE-$RELEASE_C}
->Environment:
- $ENVIRONMENT_C
-`[ -n "$SYSTEM" ] && echo System: $SYSTEM`
-`[ -n "$ARCH" ] && echo Architecture: $ARCH`
-`[ -n "$MACHINE" ] && echo Machine: $MACHINE`
->Description:
- $DESCRIPTION_C
->How-To-Repeat:
- $HOW_TO_REPEAT_C
->Fix:
- $FIX_C
-__EOF__
- done
- fi
-
- if [ "$PRINT" = true -o "$PRINT_INTERN" = true ]; then
- cat $TEMP
- xs=0; exit
- fi
-
- chmod u+w $TEMP
- if [ -z "$REQUEST_ID" ]; then
- eval $EDIT $TEMP
- else
- ed -s $TEMP << '__EOF__'
-/^Subject/s/^Subject:.*/Subject: request for a customer id/
-/^>Category/s/^>Category:.*/>Category: send-pr/
-w
-q
-__EOF__
- fi
-
- if cmp -s $REF $TEMP ; then
- echo "$COMMAND: problem report not filled out, therefore not sent"
- xs=1; exit
- fi
-fi
-
-#
-# Check the enumeration fields
-
-# This is a "sed-subroutine" with one keyword parameter
-# (with workaround for Sun sed bug)
-#
-SED_CMD='
-/$PATTERN/{
-s|||
-s|<.*>||
-s|^[ ]*||
-s|[ ]*$||
-p
-q
-}'
-
-
-while [ -z "$REQUEST_ID" ]; do
- CNT=0
-
- # 1) Confidential
- #
- PATTERN=">Confidential:"
- CONFIDENTIAL=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
- case "$CONFIDENTIAL" in
- ""|yes|no) CNT=`expr $CNT + 1` ;;
- *) echo "$COMMAND: \`$CONFIDENTIAL' is not a valid value for \`Confidential'." ;;
- esac
- #
- # 2) Severity
- #
- PATTERN=">Severity:"
- SEVERITY=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
- case "$SEVERITY" in
- ""|non-critical|serious|critical) CNT=`expr $CNT + 1` ;;
- *) echo "$COMMAND: \`$SEVERITY' is not a valid value for \`Severity'."
- esac
- #
- # 3) Priority
- #
- PATTERN=">Priority:"
- PRIORITY=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
- case "$PRIORITY" in
- ""|low|medium|high) CNT=`expr $CNT + 1` ;;
- *) echo "$COMMAND: \`$PRIORITY' is not a valid value for \`Priority'."
- esac
- #
- # 4) Category
- #
- PATTERN=">Category:"
- CATEGORY=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
- FOUND=
- for C in $CATEGORIES
- do
- if [ "$C" = "$CATEGORY" ]; then FOUND=true ; break ; fi
- done
- if [ -n "$FOUND" ]; then
- CNT=`expr $CNT + 1`
- else
- if [ -z "$CATEGORY" ]; then
- echo "$COMMAND: you must include a Category: field in your report."
- else
- echo "$COMMAND: \`$CATEGORY' is not a known category."
- fi
- fi
- #
- # 5) Class
- #
- PATTERN=">Class:"
- CLASS=`eval sed -n -e "\"$SED_CMD\"" $TEMP`
- case "$CLASS" in
- ""|sw-bug|doc-bug|change-request|support) CNT=`expr $CNT + 1` ;;
- *) echo "$COMMAND: \`$CLASS' is not a valid value for \`Class'."
- esac
-
- [ $CNT -lt 5 -a -z "$BATCH" ] &&
- echo "Errors were found with the problem report."
-
- while true; do
- if [ -z "$BATCH" ]; then
- $ECHON1 "a)bort, e)dit or s)end? $ECHON2"
- read input
- else
- if [ $CNT -eq 5 ]; then
- input=s
- else
- input=a
- fi
- fi
- case "$input" in
- a*)
- if [ -z "$BATCH" ]; then
- echo "$COMMAND: the problem report remains in $BAD and is not sent."
- mv $TEMP $BAD
- else
- echo "$COMMAND: the problem report is not sent."
- fi
- xs=1; exit
- ;;
- e*)
- eval $EDIT $TEMP
- continue 2
- ;;
- s*)
- break 2
- ;;
- esac
- done
-done
-#
-# Remove comments and send the problem report
-# (we have to use patterns, where the comment contains regex chars)
-#
-# /^>Originator:/s;$ORIGINATOR;;
-sed -e "
-/^SEND-PR:/d
-/^>Organization:/,/^>[A-Za-z-]*:/s;$ORGANIZATION_C;;
-/^>Confidential:/s;<.*>;;
-/^>Synopsis:/s;$SYNOPSIS_C;;
-/^>Severity:/s;<.*>;;
-/^>Priority:/s;<.*>;;
-/^>Category:/s;$CATEGORY_C;;
-/^>Class:/s;<.*>;;
-/^>Release:/,/^>[A-Za-z-]*:/s;$RELEASE_C;;
-/^>Environment:/,/^>[A-Za-z-]*:/s;$ENVIRONMENT_C;;
-/^>Description:/,/^>[A-Za-z-]*:/s;$DESCRIPTION_C;;
-/^>How-To-Repeat:/,/^>[A-Za-z-]*:/s;$HOW_TO_REPEAT_C;;
-/^>Fix:/,/^>[A-Za-z-]*:/s;$FIX_C;;
-" $TEMP > $REF
-
-if $MAIL_AGENT < $REF; then
- echo "$COMMAND: problem report sent"
- xs=0; exit
-else
- echo "$COMMAND: mysterious mail failure."
- if [ -z "$BATCH" ]; then
- echo "$COMMAND: the problem report remains in $BAD and is not sent."
- mv $REF $BAD
- else
- echo "$COMMAND: the problem report is not sent."
- fi
- xs=1; exit
-fi
diff --git a/contrib/cvs/src/cvsrc.c b/contrib/cvs/src/cvsrc.c
deleted file mode 100644
index 60de909b5886..000000000000
--- a/contrib/cvs/src/cvsrc.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1993 david d zuhn
- *
- * Written by david d `zoo' zuhn while at Cygnus Support
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- */
-
-
-#include "cvs.h"
-#include "getline.h"
-
-/* this file is to be found in the user's home directory */
-
-#ifndef CVSRC_FILENAME
-#define CVSRC_FILENAME ".cvsrc"
-#endif
-char cvsrc[] = CVSRC_FILENAME;
-
-#define GROW 10
-
-extern char *strtok ();
-
-/* Read cvsrc, processing options matching CMDNAME ("cvs" for global
- options, and update *ARGC and *ARGV accordingly. */
-
-void
-read_cvsrc (argc, argv, cmdname)
- int *argc;
- char ***argv;
- const char *cmdname;
-{
- char *homedir;
- char *homeinit;
- FILE *cvsrcfile;
-
- char *line;
- int line_length;
- size_t line_chars_allocated;
-
- char *optstart;
-
- int command_len;
- int found = 0;
-
- int i;
-
- int new_argc;
- int max_new_argv;
- char **new_argv;
-
- /* old_argc and old_argv hold the values returned from the
- previous invocation of read_cvsrc and are used to free the
- allocated memory. The first invocation of read_cvsrc gets argv
- from the system, this memory must not be free'd. */
- static int old_argc = 0;
- static char **old_argv = NULL;
-
- /* don't do anything if argc is -1, since that implies "help" mode */
- if (*argc == -1)
- return;
-
- /* 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;
-
- homeinit = strcat_filename_onto_homedir (homedir, cvsrc);
-
- /* if it can't be read, there's no point to continuing */
-
- if (!isreadable (homeinit))
- {
- free (homeinit);
- return;
- }
-
- /* now scan the file until we find the line for the command in question */
-
- line = NULL;
- line_chars_allocated = 0;
- command_len = strlen (cmdname);
- cvsrcfile = open_file (homeinit, "r");
- while ((line_length = getline (&line, &line_chars_allocated, cvsrcfile))
- >= 0)
- {
- /* skip over comment lines */
- if (line[0] == '#')
- continue;
-
- /* stop if we match the current command */
- if (!strncmp (line, cmdname, command_len)
- && isspace ((unsigned char) *(line + command_len)))
- {
- found = 1;
- break;
- }
- }
-
- if (line_length < 0 && !feof (cvsrcfile))
- error (0, errno, "cannot read %s", homeinit);
-
- fclose (cvsrcfile);
-
- /* setup the new options list */
-
- new_argc = 1;
- max_new_argv = (*argc) + GROW;
- new_argv = (char **) xmalloc (max_new_argv * sizeof (char*));
- new_argv[0] = xstrdup ((*argv)[0]);
-
- if (found)
- {
- /* skip over command in the options line */
- for (optstart = strtok (line + command_len, "\t \n\r");
- optstart;
- optstart = strtok (NULL, "\t \n\r"))
- {
- new_argv [new_argc++] = xstrdup (optstart);
-
- if (new_argc >= max_new_argv)
- {
- max_new_argv += GROW;
- new_argv = (char **) xrealloc (new_argv, max_new_argv * sizeof (char*));
- }
- }
- }
-
- if (line != NULL)
- free (line);
-
- /* now copy the remaining arguments */
-
- if (new_argc + *argc > max_new_argv)
- {
- max_new_argv = new_argc + *argc;
- new_argv = (char **) xrealloc (new_argv, max_new_argv * sizeof (char*));
- }
- for (i=1; i < *argc; i++)
- {
- new_argv [new_argc++] = xstrdup ((*argv)[i]);
- }
-
- if (old_argv != NULL)
- {
- /* Free the memory which was allocated in the previous
- read_cvsrc call. */
- free_names (&old_argc, old_argv);
- }
-
- old_argc = *argc = new_argc;
- old_argv = *argv = new_argv;
-
- free (homeinit);
- return;
-}
diff --git a/contrib/cvs/src/diff.c b/contrib/cvs/src/diff.c
deleted file mode 100644
index 8a61f9a2e00a..000000000000
--- a/contrib/cvs/src/diff.c
+++ /dev/null
@@ -1,1178 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Difference
- *
- * Run diff against versions in the repository. Options that are specified are
- * passed on directly to "rcsdiff".
- *
- * Without any file arguments, runs diff against all the currently modified
- * files.
- *
- * $FreeBSD$
- */
-
-#include <assert.h>
-#include "cvs.h"
-
-enum diff_file
-{
- DIFF_ERROR,
- DIFF_ADDED,
- DIFF_REMOVED,
- DIFF_DIFFERENT,
- DIFF_SAME
-};
-
-static Dtype diff_dirproc PROTO ((void *callerdat, const char *dir,
- const char *pos_repos,
- const char *update_dir,
- List *entries));
-static int diff_filesdoneproc PROTO ((void *callerdat, int err,
- const char *repos,
- const char *update_dir,
- List *entries));
-static int diff_dirleaveproc PROTO ((void *callerdat, const char *dir,
- int err, const char *update_dir,
- List *entries));
-static enum diff_file diff_file_nodiff PROTO(( struct file_info *finfo,
- Vers_TS *vers,
- enum diff_file,
- char **rev1_cache ));
-static int diff_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-static void diff_mark_errors PROTO((int err));
-
-
-/* Global variables. Would be cleaner if we just put this stuff in a
- struct like log.c does. */
-
-/* Command line tags, from -r option. Points into argv. */
-static char *diff_rev1, *diff_rev2;
-/* Command line dates, from -D option. Malloc'd. */
-static char *diff_date1, *diff_date2;
-static char *diff_join1, *diff_join2;
-static char *use_rev1, *use_rev2;
-static int have_rev1_label, have_rev2_label;
-
-/* Revision of the user file, if it is unchanged from something in the
- repository and we want to use that fact. */
-static char *user_file_rev;
-
-static char *options;
-static char **diff_argv;
-static int diff_argc;
-static size_t diff_arg_allocated;
-static int diff_errors;
-static int empty_files = 0;
-
-static const char *const diff_usage[] =
-{
- "Usage: %s %s [-lR] [-k kopt] [format_options]\n",
- " [[-r rev1 | -D date1] [-r rev2 | -D date2]] [files...] \n",
- "\t-l\tLocal directory only, not recursive\n",
- "\t-R\tProcess directories recursively.\n",
- "\t-k kopt\tSpecify keyword expansion mode.\n",
- "\t-D d1\tDiff revision for date against working file.\n",
- "\t-D d2\tDiff rev1/date1 against date2.\n",
- "\t-r rev1\tDiff revision for rev1 against working file.\n",
- "\t-r rev2\tDiff rev1/date1 against rev2.\n",
- "\nformat_options:\n",
- " -i --ignore-case Consider upper- and lower-case to be the same.\n",
- " -w --ignore-all-space Ignore all white space.\n",
- " -b --ignore-space-change Ignore changes in the amount of white space.\n",
- " -B --ignore-blank-lines Ignore changes whose lines are all blank.\n",
- " -I RE --ignore-matching-lines=RE Ignore changes whose lines all match RE.\n",
- " --binary Read and write data in binary mode.\n",
- " -a --text Treat all files as text.\n\n",
- " -c -C NUM --context[=NUM] Output NUM (default 2) lines of copied context.\n",
- " -u -U NUM --unified[=NUM] Output NUM (default 2) lines of unified context.\n",
- " -NUM Use NUM context lines.\n",
- " -L LABEL --label LABEL Use LABEL instead of file name.\n",
- " -p --show-c-function Show which C function each change is in.\n",
- " -F RE --show-function-line=RE Show the most recent line matching RE.\n",
- " --brief Output only whether files differ.\n",
- " -e --ed Output an ed script.\n",
- " -f --forward-ed Output something like an ed script in forward order.\n",
- " -n --rcs Output an RCS format diff.\n",
- " -y --side-by-side Output in two columns.\n",
- " -W NUM --width=NUM Output at most NUM (default 130) characters per line.\n",
- " --left-column Output only the left column of common lines.\n",
- " --suppress-common-lines Do not output common lines.\n",
- " --ifdef=NAME Output merged file to show `#ifdef NAME' diffs.\n",
- " --GTYPE-group-format=GFMT Similar, but format GTYPE input groups with GFMT.\n",
- " --line-format=LFMT Similar, but format all input lines with LFMT.\n",
- " --LTYPE-line-format=LFMT Similar, but format LTYPE input lines with LFMT.\n",
- " LTYPE is `old', `new', or `unchanged'. GTYPE is LTYPE or `changed'.\n",
- " GFMT may contain:\n",
- " %%< lines from FILE1\n",
- " %%> lines from FILE2\n",
- " %%= lines common to FILE1 and FILE2\n",
- " %%[-][WIDTH][.[PREC]]{doxX}LETTER printf-style spec for LETTER\n",
- " LETTERs are as follows for new group, lower case for old group:\n",
- " F first line number\n",
- " L last line number\n",
- " N number of lines = L-F+1\n",
- " E F-1\n",
- " M L+1\n",
- " LFMT may contain:\n",
- " %%L contents of line\n",
- " %%l contents of line, excluding any trailing newline\n",
- " %%[-][WIDTH][.[PREC]]{doxX}n printf-style spec for input line number\n",
- " Either GFMT or LFMT may contain:\n",
- " %%%% %%\n",
- " %%c'C' the single character C\n",
- " %%c'\\OOO' the character with octal code OOO\n\n",
- " -t --expand-tabs Expand tabs to spaces in output.\n",
- " -T --initial-tab Make tabs line up by prepending a tab.\n\n",
- " -N --new-file Treat absent files as empty.\n",
- " -s --report-identical-files Report when two files are the same.\n",
- " --horizon-lines=NUM Keep NUM lines of the common prefix and suffix.\n",
- " -d --minimal Try hard to find a smaller set of changes.\n",
- " -H --speed-large-files Assume large files and many scattered small changes.\n",
- "\n(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-/* I copied this array directly out of diff.c in diffutils 2.7, after
- removing the following entries, none of which seem relevant to use
- with CVS:
- --help
- --version (-v)
- --recursive (-r)
- --unidirectional-new-file (-P)
- --starting-file (-S)
- --exclude (-x)
- --exclude-from (-X)
- --sdiff-merge-assist
- --paginate (-l) (doesn't work with library callbacks)
-
- I changed the options which take optional arguments (--context and
- --unified) to return a number rather than a letter, so that the
- optional argument could be handled more easily. I changed the
- --brief and --ifdef options to return numbers, since -q and -D mean
- something else to cvs diff.
-
- The numbers 129- that appear in the fourth element of some entries
- tell the big switch in `diff' how to process those options. -- Ian
-
- The following options, which diff lists as "An alias, no longer
- recommended" have been removed: --file-label --entire-new-file
- --ascii --print. */
-
-static struct option const longopts[] =
-{
- {"ignore-blank-lines", 0, 0, 'B'},
- {"context", 2, 0, 143},
- {"ifdef", 1, 0, 131},
- {"show-function-line", 1, 0, 'F'},
- {"speed-large-files", 0, 0, 'H'},
- {"ignore-matching-lines", 1, 0, 'I'},
- {"label", 1, 0, 'L'},
- {"new-file", 0, 0, 'N'},
- {"initial-tab", 0, 0, 'T'},
- {"width", 1, 0, 'W'},
- {"text", 0, 0, 'a'},
- {"ignore-space-change", 0, 0, 'b'},
- {"minimal", 0, 0, 'd'},
- {"ed", 0, 0, 'e'},
- {"forward-ed", 0, 0, 'f'},
- {"ignore-case", 0, 0, 'i'},
- {"rcs", 0, 0, 'n'},
- {"show-c-function", 0, 0, 'p'},
-
- /* This is a potentially very useful option, except the output is so
- silly. It would be much better for it to look like "cvs rdiff -s"
- which displays all the same info, minus quite a few lines of
- extraneous garbage. */
- {"brief", 0, 0, 145},
-
- {"report-identical-files", 0, 0, 's'},
- {"expand-tabs", 0, 0, 't'},
- {"ignore-all-space", 0, 0, 'w'},
- {"side-by-side", 0, 0, 'y'},
- {"unified", 2, 0, 146},
- {"left-column", 0, 0, 129},
- {"suppress-common-lines", 0, 0, 130},
- {"old-line-format", 1, 0, 132},
- {"new-line-format", 1, 0, 133},
- {"unchanged-line-format", 1, 0, 134},
- {"line-format", 1, 0, 135},
- {"old-group-format", 1, 0, 136},
- {"new-group-format", 1, 0, 137},
- {"unchanged-group-format", 1, 0, 138},
- {"changed-group-format", 1, 0, 139},
- {"horizon-lines", 1, 0, 140},
- {"binary", 0, 0, 142},
- {0, 0, 0, 0}
-};
-
-
-
-/* Add one of OPT or LONGOPT, and ARGUMENT, when present, to global DIFF_ARGV.
- *
- * INPUTS
- * opt A character option representation.
- * longopt A long option name.
- * argument Optional option argument.
- *
- * GLOBALS
- * diff_argc The number of arguments in DIFF_ARGV.
- * diff_argv Array of argument strings.
- * diff_arg_allocated Allocated length of DIFF_ARGV.
- *
- * NOTES
- * Behavior when both OPT & LONGOPT are provided is undefined.
- *
- * RETURNS
- * Nothing.
- */
-static void
-add_diff_args (char opt, const char *longopt, const char *argument)
-{
- char *tmp;
-
- /* Add opt or longopt to diff_arv. */
- assert (opt || (longopt && *longopt));
- assert (!(opt && (longopt && *longopt)));
- if (opt)
- {
- tmp = xmalloc (3);
- sprintf (tmp, "-%c", opt);
- }
- else
- {
- tmp = xmalloc (3 + strlen (longopt));
- sprintf (tmp, "--%s", longopt);
- }
- run_add_arg_p (&diff_argc, &diff_arg_allocated, &diff_argv, tmp);
- free (tmp);
-
- /* When present, add ARGUMENT to DIFF_ARGV. */
- if (argument)
- run_add_arg_p (&diff_argc, &diff_arg_allocated, &diff_argv, argument);
-}
-
-
-
-/* CVS 1.9 and similar versions seemed to have pretty weird handling
- of -y and -T. In the cases where it called rcsdiff,
- they would have the meanings mentioned below. In the cases where it
- called diff, they would have the meanings mentioned in "longopts".
- Noone seems to have missed them, so I think the right thing to do is
- just to remove the options altogether (which I have done).
-
- In the case of -z and -q, "cvs diff" did not accept them even back
- when we called rcsdiff (at least, it hasn't accepted them
- recently).
-
- In comparing rcsdiff to the new CVS implementation, I noticed that
- the following rcsdiff flags are not handled by CVS diff:
-
- -y: perform diff even when the requested revisions are the
- same revision number
- -q: run quietly
- -T: preserve modification time on the RCS file
- -z: specify timezone for use in file labels
-
- I think these are not really relevant. -y is undocumented even in
- RCS 5.7, and seems like a minor change at best. According to RCS
- documentation, -T only applies when a RCS file has been modified
- because of lock changes; doesn't CVS sidestep RCS's entire lock
- structure? -z seems to be unsupported by CVS diff, and has a
- different meaning as a global option anyway. (Adding it could be
- a feature, but if it is left out for now, it should not break
- anything.) For the purposes of producing output, CVS diff appears
- mostly to ignore -q. Maybe this should be fixed, but I think it's
- a larger issue than the changes included here. */
-
-int
-diff (argc, argv)
- int argc;
- char **argv;
-{
- int c, err = 0;
- int local = 0;
- int which;
- int option_index;
-
- if (argc == -1)
- usage (diff_usage);
-
- have_rev1_label = have_rev2_label = 0;
-
- /*
- * Note that we catch all the valid arguments here, so that we can
- * intercept the -r arguments for doing revision diffs; and -l/-R for a
- * non-recursive/recursive diff.
- */
-
- /* Clean out our global variables (multiroot can call us multiple
- times and the server can too, if the client sends several
- diff commands). */
- if (diff_argc)
- {
- run_arg_free_p (diff_argc, diff_argv);
- diff_argc = 0;
- }
- diff_rev1 = NULL;
- diff_rev2 = NULL;
- diff_date1 = NULL;
- diff_date2 = NULL;
- diff_join1 = NULL;
- diff_join2 = NULL;
-
- optind = 0;
- /* FIXME: This should really be allocating an argv to be passed to diff
- * later rather than strcatting onto the opts variable. We have some
- * handling routines that can already handle most of the argc/argv
- * maintenance for us and currently, if anyone were to attempt to pass a
- * quoted string in here, it would be split on spaces and tabs on its way
- * to diff.
- */
- while ((c = getopt_long (argc, argv,
- "+abcdefhilnpstuwy0123456789BHNRTC:D:F:I:L:U:W:k:r:j:",
- longopts, &option_index)) != -1)
- {
- switch (c)
- {
- case 'y':
- add_diff_args (0, "side-by-side", NULL);
- break;
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
- case 'h': case 'i': case 'n': case 'p': case 's': case 't':
- case 'u': case 'w':
- case '0': case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- case 'B': case 'H': case 'T':
- add_diff_args (c, NULL, NULL);
- break;
- case 'L':
- if (have_rev1_label++)
- if (have_rev2_label++)
- {
- error (0, 0, "extra -L arguments ignored");
- break;
- }
- /* Fall through. */
- case 'C': case 'F': case 'I': case 'U': case 'W':
- add_diff_args (c, NULL, optarg);
- break;
- case 129: case 130: case 131: case 132: case 133: case 134:
- case 135: case 136: case 137: case 138: case 139: case 140:
- case 141: case 142: case 143: case 145: case 146:
- add_diff_args (0, longopts[option_index].name,
- longopts[option_index].has_arg ? optarg : NULL);
- break;
- case 'R':
- local = 0;
- break;
- case 'l':
- local = 1;
- break;
- case 'k':
- if (options)
- free (options);
- options = RCS_check_kflag (optarg);
- break;
- case 'j':
- {
- char *ptr;
- char *cpy = strdup(optarg);
-
- if ((ptr = strchr(optarg, ':')) != NULL)
- *ptr++ = 0;
- if (diff_rev2 != NULL || diff_date2 != NULL)
- error (1, 0,
- "no more than two revisions/dates can be specified");
- if (diff_rev1 != NULL || diff_date1 != NULL) {
- diff_join2 = cpy;
- diff_rev2 = optarg;
- diff_date2 = ptr ? Make_Date(ptr) : NULL;
- } else {
- diff_join1 = cpy;
- diff_rev1 = optarg;
- diff_date1 = ptr ? Make_Date(ptr) : NULL;
- }
- }
- break;
- case 'r':
- if (diff_rev2 != NULL || diff_date2 != NULL)
- error (1, 0,
- "no more than two revisions/dates can be specified");
- if (diff_rev1 != NULL || diff_date1 != NULL)
- diff_rev2 = optarg;
- else
- diff_rev1 = optarg;
- break;
- case 'D':
- if (diff_rev2 != NULL || diff_date2 != NULL)
- error (1, 0,
- "no more than two revisions/dates can be specified");
- if (diff_rev1 != NULL || diff_date1 != NULL)
- diff_date2 = Make_Date (optarg);
- else
- diff_date1 = Make_Date (optarg);
- break;
- case 'N':
- empty_files = 1;
- break;
- case '?':
- default:
- usage (diff_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- /* make sure options is non-null */
- if (!options)
- options = xstrdup ("");
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote) {
- /* We're the client side. Fire up the remote server. */
- start_server ();
-
- ign_setup ();
-
- if (local)
- send_arg("-l");
- if (empty_files)
- send_arg("-N");
- send_options (diff_argc, diff_argv);
- if (options[0] != '\0')
- send_arg (options);
- if (diff_join1)
- option_with_arg ("-j", diff_join1);
- else if (diff_rev1)
- option_with_arg ("-r", diff_rev1);
- else if (diff_date1)
- client_senddate (diff_date1);
-
- if (diff_join2)
- option_with_arg ("-j", diff_join2);
- else if (diff_rev2)
- option_with_arg ("-r", diff_rev2);
- else if (diff_date2)
- client_senddate (diff_date2);
- send_arg ("--");
-
- /* Send the current files unless diffing two revs from the archive */
- if (diff_rev2 == NULL && diff_date2 == NULL)
- send_files (argc, argv, local, 0, 0);
- else
- send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
-
- send_file_names (argc, argv, SEND_EXPAND_WILD);
-
- send_to_server ("diff\012", 0);
- err = get_responses_and_close ();
- } else
-#endif
- { /* FreeBSD addition - warning idention not changed til matching-} */
- if (diff_rev1 != NULL)
- tag_check_valid (diff_rev1, argc, argv, local, 0, "");
- if (diff_rev2 != NULL)
- tag_check_valid (diff_rev2, argc, argv, local, 0, "");
-
- which = W_LOCAL;
- if (diff_rev1 != NULL || diff_date1 != NULL)
- which |= W_REPOS | W_ATTIC;
-
- wrap_setup ();
-
- /* start the recursion processor */
- err = start_recursion (diff_fileproc, diff_filesdoneproc, diff_dirproc,
- diff_dirleaveproc, NULL, argc, argv, local,
- which, 0, CVS_LOCK_READ, (char *) NULL, 1,
- (char *) NULL);
- } /* FreeBSD addition */
-
- /* clean up */
- free (options);
- options = NULL;
-
- if (diff_date1 != NULL)
- free (diff_date1);
- if (diff_date2 != NULL)
- free (diff_date2);
- if (diff_join1 != NULL)
- free (diff_join1);
- if (diff_join2 != NULL)
- free (diff_join2);
-
- return (err);
-}
-
-/*
- * Do a file diff
- */
-/* ARGSUSED */
-static int
-diff_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- int status, err = 2; /* 2 == trouble, like rcsdiff */
- Vers_TS *vers;
- enum diff_file empty_file = DIFF_DIFFERENT;
- char *tmp = NULL;
- char *tocvsPath = NULL;
- char *fname = NULL;
- char *label1;
- char *label2;
- char *rev1_cache = NULL;
-
- user_file_rev = 0;
- vers = Version_TS (finfo, NULL, NULL, NULL, 1, 0);
-
- if (diff_rev2 != NULL || diff_date2 != NULL)
- {
- /* Skip all the following checks regarding the user file; we're
- not using it. */
- }
- else if (vers->vn_user == NULL)
- {
- /* The file does not exist in the working directory. */
- if ((diff_rev1 != NULL || diff_date1 != NULL)
- && vers->srcfile != NULL)
- {
- /* The file does exist in the repository. */
- if (empty_files)
- empty_file = DIFF_REMOVED;
- else
- {
- int exists;
-
- exists = 0;
- /* special handling for TAG_HEAD */
- if (diff_rev1 && strcmp (diff_rev1, TAG_HEAD) == 0)
- {
- char *head =
- (vers->vn_rcs == NULL
- ? NULL
- : RCS_branch_head (vers->srcfile, vers->vn_rcs));
- exists = head != NULL && !RCS_isdead(vers->srcfile, head);
- if (head != NULL)
- free (head);
- }
- else
- {
- Vers_TS *xvers;
-
- xvers = Version_TS (finfo, NULL, diff_rev1, diff_date1,
- 1, 0);
- exists = xvers->vn_rcs != NULL && !RCS_isdead(xvers->srcfile, xvers->vn_rcs);
- freevers_ts (&xvers);
- }
- if (exists)
- error (0, 0,
- "%s no longer exists, no comparison available",
- finfo->fullname);
- goto out;
- }
- }
- else
- {
- error (0, 0, "I know nothing about %s", finfo->fullname);
- goto out;
- }
- }
- else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
- {
- /* The file was added locally. */
- int exists = 0;
-
- if (vers->srcfile != NULL)
- {
- /* The file does exist in the repository. */
-
- if ((diff_rev1 != NULL || diff_date1 != NULL))
- {
- /* special handling for TAG_HEAD */
- if (diff_rev1 && strcmp (diff_rev1, TAG_HEAD) == 0)
- {
- char *head =
- (vers->vn_rcs == NULL
- ? NULL
- : RCS_branch_head (vers->srcfile, vers->vn_rcs));
- exists = head != NULL && !RCS_isdead(vers->srcfile, head);
- if (head != NULL)
- free (head);
- }
- else
- {
- Vers_TS *xvers;
-
- xvers = Version_TS (finfo, NULL, diff_rev1, diff_date1,
- 1, 0);
- exists = xvers->vn_rcs != NULL
- && !RCS_isdead (xvers->srcfile, xvers->vn_rcs);
- freevers_ts (&xvers);
- }
- }
- else
- {
- /* The file was added locally, but an RCS archive exists. Our
- * base revision must be dead.
- */
- /* No need to set, exists = 0, here. That's the default. */
- }
- }
- if (!exists)
- {
- /* If we got here, then either the RCS archive does not exist or
- * the relevant revision is dead.
- */
- if (empty_files)
- empty_file = DIFF_ADDED;
- else
- {
- error (0, 0, "%s is a new entry, no comparison available",
- finfo->fullname);
- goto out;
- }
- }
- }
- else if (vers->vn_user[0] == '-')
- {
- if (empty_files)
- empty_file = DIFF_REMOVED;
- else
- {
- error (0, 0, "%s was removed, no comparison available",
- finfo->fullname);
- goto out;
- }
- }
- else
- {
- if (vers->vn_rcs == NULL && vers->srcfile == NULL)
- {
- error (0, 0, "cannot find revision control file for %s",
- finfo->fullname);
- goto out;
- }
- else
- {
- if (vers->ts_user == NULL)
- {
- error (0, 0, "cannot find %s", finfo->fullname);
- goto out;
- }
- else if (!strcmp (vers->ts_user, vers->ts_rcs))
- {
- /* The user file matches some revision in the repository
- Diff against the repository (for remote CVS, we might not
- have a copy of the user file around). */
- user_file_rev = vers->vn_user;
- }
- }
- }
-
- empty_file = diff_file_nodiff( finfo, vers, empty_file, &rev1_cache );
- if( empty_file == DIFF_SAME )
- {
- /* In the server case, would be nice to send a "Checked-in"
- response, so that the client can rewrite its timestamp.
- server_checked_in by itself isn't the right thing (it
- needs a server_register), but I'm not sure what is.
- It isn't clear to me how "cvs status" handles this (that
- is, for a client which sends Modified not Is-modified to
- "cvs status"), but it does. */
- err = 0;
- goto out;
- }
- else if( empty_file == DIFF_ERROR )
- goto out;
-
- /* Output an "Index:" line for patch to use */
- cvs_output ("Index: ", 0);
- cvs_output (finfo->fullname, 0);
- cvs_output ("\n", 1);
-
- tocvsPath = wrap_tocvs_process_file(finfo->file);
- if( tocvsPath != NULL )
- {
- /* Backup the current version of the file to CVS/,,filename */
- fname = xmalloc (strlen (finfo->file)
- + sizeof CVSADM
- + sizeof CVSPREFIX
- + 10);
- sprintf(fname,"%s/%s%s",CVSADM, CVSPREFIX, finfo->file);
- if (unlink_file_dir (fname) < 0)
- if (! existence_error (errno))
- error (1, errno, "cannot remove %s", fname);
- rename_file (finfo->file, fname);
- /* Copy the wrapped file to the current directory then go to work */
- copy_file (tocvsPath, finfo->file);
- }
-
- /* Set up file labels appropriate for compatibility with the Larry Wall
- * implementation of patch if the user didn't specify. This is irrelevant
- * according to the POSIX.2 specification.
- */
- label1 = NULL;
- label2 = NULL;
- if (!have_rev1_label)
- {
- if (empty_file == DIFF_ADDED)
- label1 =
- make_file_label (DEVNULL, NULL, NULL);
- else
- label1 =
- make_file_label (finfo->fullname, use_rev1,
- vers ? vers->srcfile : NULL);
- }
-
- if (!have_rev2_label)
- {
- if (empty_file == DIFF_REMOVED)
- label2 =
- make_file_label (DEVNULL, NULL, NULL);
- else
- label2 =
- make_file_label (finfo->fullname, use_rev2,
- vers ? vers->srcfile : NULL);
- }
-
- if (empty_file == DIFF_ADDED || empty_file == DIFF_REMOVED)
- {
- /* This is fullname, not file, possibly despite the POSIX.2
- * specification, because that's the way all the Larry Wall
- * implementations of patch (are there other implementations?) want
- * things and the POSIX.2 spec appears to leave room for this.
- */
- cvs_output ("\
-===================================================================\n\
-RCS file: ", 0);
- cvs_output (finfo->fullname, 0);
- cvs_output ("\n", 1);
-
- cvs_output ("diff -N ", 0);
- cvs_output (finfo->fullname, 0);
- cvs_output ("\n", 1);
-
- if (empty_file == DIFF_ADDED)
- {
- if (use_rev2 == NULL)
- status = diff_exec (DEVNULL, finfo->file, label1, label2,
- diff_argc, diff_argv, RUN_TTY);
- else
- {
- int retcode;
-
- tmp = cvs_temp_name ();
- retcode = RCS_checkout (vers->srcfile, (char *) NULL,
- use_rev2, (char *) NULL,
- (*options
- ? options
- : vers->options),
- tmp, (RCSCHECKOUTPROC) NULL,
- (void *) NULL);
- if( retcode != 0 )
- goto out;
-
- status = diff_exec (DEVNULL, tmp, label1, label2,
- diff_argc, diff_argv, RUN_TTY);
- }
- }
- else
- {
- int retcode;
-
- tmp = cvs_temp_name ();
- retcode = RCS_checkout (vers->srcfile, (char *) NULL,
- use_rev1, (char *) NULL,
- *options ? options : vers->options,
- tmp, (RCSCHECKOUTPROC) NULL,
- (void *) NULL);
- if (retcode != 0)
- goto out;
-
- status = diff_exec (tmp, DEVNULL, label1, label2,
- diff_argc, diff_argv, RUN_TTY);
- }
- }
- else
- {
- status = RCS_exec_rcsdiff (vers->srcfile, diff_argc, diff_argv,
- *options ? options : vers->options,
- use_rev1, rev1_cache, use_rev2,
- label1, label2, finfo->file);
-
- }
-
- if (label1) free (label1);
- if (label2) free (label2);
-
- switch (status)
- {
- case -1: /* fork failed */
- error (1, errno, "fork failed while diffing %s",
- vers->srcfile->path);
- case 0: /* everything ok */
- err = 0;
- break;
- default: /* other error */
- err = status;
- break;
- }
-
-out:
- if( tocvsPath != NULL )
- {
- if (unlink_file_dir (finfo->file) < 0)
- if (! existence_error (errno))
- error (1, errno, "cannot remove %s", finfo->file);
-
- rename_file (fname, finfo->file);
- if (unlink_file (tocvsPath) < 0)
- error (1, errno, "cannot remove %s", tocvsPath);
- free (fname);
- }
-
- /* Call CVS_UNLINK() rather than unlink_file() below to avoid the check
- * for noexec.
- */
- if( tmp != NULL )
- {
- if (CVS_UNLINK(tmp) < 0)
- error (0, errno, "cannot remove %s", tmp);
- free (tmp);
- }
- if( rev1_cache != NULL )
- {
- if( CVS_UNLINK( rev1_cache ) < 0 )
- error( 0, errno, "cannot remove %s", rev1_cache );
- free( rev1_cache );
- }
-
- freevers_ts (&vers);
- diff_mark_errors (err);
- return err;
-}
-
-/*
- * Remember the exit status for each file.
- */
-static void
-diff_mark_errors (err)
- int err;
-{
- if (err > diff_errors)
- diff_errors = err;
-}
-
-/*
- * Print a warm fuzzy message when we enter a dir
- *
- * Don't try to diff directories that don't exist! -- DW
- */
-/* ARGSUSED */
-static Dtype
-diff_dirproc (callerdat, dir, pos_repos, update_dir, entries)
- void *callerdat;
- const char *dir;
- const char *pos_repos;
- const char *update_dir;
- List *entries;
-{
- /* XXX - check for dirs we don't want to process??? */
-
- /* YES ... for instance dirs that don't exist!!! -- DW */
- if (!isdir (dir))
- return (R_SKIP_ALL);
-
- if (!quiet)
- error (0, 0, "Diffing %s", update_dir);
- return (R_PROCESS);
-}
-
-/*
- * Concoct the proper exit status - done with files
- */
-/* ARGSUSED */
-static int
-diff_filesdoneproc (callerdat, err, repos, update_dir, entries)
- void *callerdat;
- int err;
- const char *repos;
- const char *update_dir;
- List *entries;
-{
- return (diff_errors);
-}
-
-/*
- * Concoct the proper exit status - leaving directories
- */
-/* ARGSUSED */
-static int
-diff_dirleaveproc (callerdat, dir, err, update_dir, entries)
- void *callerdat;
- const char *dir;
- int err;
- const char *update_dir;
- List *entries;
-{
- return (diff_errors);
-}
-
-/*
- * verify that a file is different
- */
-static enum diff_file
-diff_file_nodiff( finfo, vers, empty_file, rev1_cache )
- struct file_info *finfo;
- Vers_TS *vers;
- enum diff_file empty_file;
- char **rev1_cache; /* Cache the content of rev1 if we have to look
- * it up.
- */
-{
- Vers_TS *xvers;
- int retcode;
-
- /* free up any old use_rev* variables and reset 'em */
- if (use_rev1)
- free (use_rev1);
- if (use_rev2)
- free (use_rev2);
- use_rev1 = use_rev2 = (char *) NULL;
-
- if (diff_rev1 || diff_date1)
- {
- /* special handling for TAG_HEAD */
- if (diff_rev1 && strcmp (diff_rev1, TAG_HEAD) == 0)
- {
- if (vers->vn_rcs != NULL && vers->srcfile != NULL)
- use_rev1 = RCS_branch_head (vers->srcfile, vers->vn_rcs);
- }
- else
- {
- xvers = Version_TS (finfo, NULL, diff_rev1, diff_date1, 1, 0);
- if (xvers->vn_rcs != NULL)
- use_rev1 = xstrdup (xvers->vn_rcs);
- freevers_ts (&xvers);
- }
- }
- if (diff_rev2 || diff_date2)
- {
- /* special handling for TAG_HEAD */
- if (diff_rev2 && strcmp (diff_rev2, TAG_HEAD) == 0)
- {
- if (vers->vn_rcs != NULL && vers->srcfile != NULL)
- use_rev2 = RCS_branch_head (vers->srcfile, vers->vn_rcs);
- }
- else
- {
- xvers = Version_TS (finfo, NULL, diff_rev2, diff_date2, 1, 0);
- if (xvers->vn_rcs != NULL)
- use_rev2 = xstrdup (xvers->vn_rcs);
- freevers_ts (&xvers);
- }
-
- if( use_rev1 == NULL || RCS_isdead( vers->srcfile, use_rev1 ) )
- {
- /* The first revision does not exist. If EMPTY_FILES is
- true, treat this as an added file. Otherwise, warn
- about the missing tag. */
- if( use_rev2 == NULL || RCS_isdead( vers->srcfile, use_rev2 ) )
- /* At least in the case where DIFF_REV1 and DIFF_REV2
- * are both numeric (and non-existant (NULL), as opposed to
- * dead?), we should be returning some kind of error (see
- * basicb-8a0 in testsuite). The symbolic case may be more
- * complicated.
- */
- return DIFF_SAME;
- if( empty_files )
- return DIFF_ADDED;
- if( use_rev1 != NULL )
- {
- if (diff_rev1)
- {
- error( 0, 0,
- "Tag %s refers to a dead (removed) revision in file `%s'.",
- diff_rev1, finfo->fullname );
- }
- else
- {
- error( 0, 0,
- "Date %s refers to a dead (removed) revision in file `%s'.",
- diff_date1, finfo->fullname );
- }
- error( 0, 0,
- "No comparison available. Pass `-N' to `%s diff'?",
- program_name );
- }
- else if (diff_rev1)
- error (0, 0, "tag %s is not in file %s", diff_rev1,
- finfo->fullname);
- else
- error (0, 0, "no revision for date %s in file %s",
- diff_date1, finfo->fullname);
- return DIFF_ERROR;
- }
-
- assert( use_rev1 != NULL );
- if( use_rev2 == NULL || RCS_isdead( vers->srcfile, use_rev2 ) )
- {
- /* The second revision does not exist. If EMPTY_FILES is
- true, treat this as a removed file. Otherwise warn
- about the missing tag. */
- if (empty_files)
- return DIFF_REMOVED;
- if( use_rev2 != NULL )
- {
- if (diff_rev2)
- {
- error( 0, 0,
- "Tag %s refers to a dead (removed) revision in file `%s'.",
- diff_rev2, finfo->fullname );
- }
- else
- {
- error( 0, 0,
- "Date %s refers to a dead (removed) revision in file `%s'.",
- diff_date2, finfo->fullname );
- }
- error( 0, 0,
- "No comparison available. Pass `-N' to `%s diff'?",
- program_name );
- }
- else if (diff_rev2)
- error (0, 0, "tag %s is not in file %s", diff_rev2,
- finfo->fullname);
- else
- error (0, 0, "no revision for date %s in file %s",
- diff_date2, finfo->fullname);
- return DIFF_ERROR;
- }
- /* Now, see if we really need to do the diff. We can't assume that the
- * files are different when the revs are.
- */
- assert( use_rev2 != NULL );
- if( strcmp (use_rev1, use_rev2) == 0 )
- return DIFF_SAME;
- /* else fall through and do the diff */
- }
-
- /* If we had a r1/d1 & r2/d2, then at this point we must have a C3P0...
- * err... ok, then both rev1 & rev2 must have resolved to an existing,
- * live version due to if statement we just closed.
- */
- assert (!(diff_rev2 || diff_date2) || (use_rev1 && use_rev2));
-
- if ((diff_rev1 || diff_date1) &&
- (use_rev1 == NULL || RCS_isdead (vers->srcfile, use_rev1)))
- {
- /* The first revision does not exist, and no second revision
- was given. */
- if (empty_files)
- {
- if (empty_file == DIFF_REMOVED)
- return DIFF_SAME;
- if( user_file_rev && use_rev2 == NULL )
- use_rev2 = xstrdup( user_file_rev );
- return DIFF_ADDED;
- }
- if( use_rev1 != NULL )
- {
- if (diff_rev1)
- {
- error( 0, 0,
- "Tag %s refers to a dead (removed) revision in file `%s'.",
- diff_rev1, finfo->fullname );
- }
- else
- {
- error( 0, 0,
- "Date %s refers to a dead (removed) revision in file `%s'.",
- diff_date1, finfo->fullname );
- }
- error( 0, 0,
- "No comparison available. Pass `-N' to `%s diff'?",
- program_name );
- }
- else if ( diff_rev1 )
- error( 0, 0, "tag %s is not in file %s", diff_rev1,
- finfo->fullname );
- else
- error( 0, 0, "no revision for date %s in file %s",
- diff_date1, finfo->fullname );
- return DIFF_ERROR;
- }
-
- assert( !diff_rev1 || use_rev1 );
-
- if (user_file_rev)
- {
- /* drop user_file_rev into first unused use_rev */
- if (!use_rev1)
- use_rev1 = xstrdup (user_file_rev);
- else if (!use_rev2)
- use_rev2 = xstrdup (user_file_rev);
- /* and if not, it wasn't needed anyhow */
- user_file_rev = NULL;
- }
-
- /* Now, see if we really need to do the diff. We can't assume that the
- * files are different when the revs are.
- */
- if( use_rev1 && use_rev2)
- {
- if (strcmp (use_rev1, use_rev2) == 0)
- return DIFF_SAME;
- /* Fall through and do the diff. */
- }
- /* Don't want to do the timestamp check with both use_rev1 & use_rev2 set.
- * The timestamp check is just for the default case of diffing the
- * workspace file against its base revision.
- */
- else if( use_rev1 == NULL
- || ( vers->vn_user != NULL
- && strcmp( use_rev1, vers->vn_user ) == 0 ) )
- {
- if (empty_file == DIFF_DIFFERENT
- && vers->ts_user != NULL
- && strcmp (vers->ts_rcs, vers->ts_user) == 0
- && (!(*options) || strcmp (options, vers->options) == 0))
- {
- return DIFF_SAME;
- }
- if (use_rev1 == NULL
- && (vers->vn_user[0] != '0' || vers->vn_user[1] != '\0'))
- {
- if (vers->vn_user[0] == '-')
- use_rev1 = xstrdup (vers->vn_user + 1);
- else
- use_rev1 = xstrdup (vers->vn_user);
- }
- }
-
- /* If we already know that the file is being added or removed,
- then we don't want to do an actual file comparison here. */
- if (empty_file != DIFF_DIFFERENT)
- return empty_file;
-
- /*
- * Run a quick cmp to see if we should bother with a full diff.
- */
-
- retcode = RCS_cmp_file( vers->srcfile, use_rev1, rev1_cache,
- use_rev2, *options ? options : vers->options,
- finfo->file );
-
- return retcode == 0 ? DIFF_SAME : DIFF_DIFFERENT;
-}
diff --git a/contrib/cvs/src/edit.c b/contrib/cvs/src/edit.c
deleted file mode 100644
index 4e0cf1e037ee..000000000000
--- a/contrib/cvs/src/edit.c
+++ /dev/null
@@ -1,1164 +0,0 @@
-/* Implementation for "cvs edit", "cvs watch on", and related commands
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-#include "cvs.h"
-#include "getline.h"
-#include "watch.h"
-#include "edit.h"
-#include "fileattr.h"
-
-static int watch_onoff PROTO ((int, char **));
-
-static int setting_default;
-static int turning_on;
-
-static int setting_tedit;
-static int setting_tunedit;
-static int setting_tcommit;
-
-static int onoff_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-
-static int
-onoff_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- char *watched = fileattr_get0 (finfo->file, "_watched");
- fileattr_set (finfo->file, "_watched", turning_on ? "" : NULL);
- if (watched != NULL)
- free (watched);
- return 0;
-}
-
-
-
-static int onoff_filesdoneproc PROTO ((void *, int, const char *, const char *,
- List *));
-
-static int
-onoff_filesdoneproc (callerdat, err, repository, update_dir, entries)
- void *callerdat;
- int err;
- const char *repository;
- const char *update_dir;
- List *entries;
-{
- if (setting_default)
- {
- char *watched = fileattr_get0 (NULL, "_watched");
- fileattr_set (NULL, "_watched", turning_on ? "" : NULL);
- if (watched != NULL)
- free (watched);
- }
- return err;
-}
-
-static int
-watch_onoff (argc, argv)
- int argc;
- char **argv;
-{
- int c;
- int local = 0;
- int err;
-
- optind = 0;
- while ((c = getopt (argc, argv, "+lR")) != -1)
- {
- switch (c)
- {
- case 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case '?':
- default:
- usage (watch_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- start_server ();
-
- ign_setup ();
-
- if (local)
- send_arg ("-l");
- send_arg ("--");
- 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 ();
- }
-#endif /* CLIENT_SUPPORT */
-
- setting_default = (argc <= 0);
-
- lock_tree_for_write (argc, argv, local, W_LOCAL, 0);
-
- err = start_recursion (onoff_fileproc, onoff_filesdoneproc,
- (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
- argc, argv, local, W_LOCAL, 0, CVS_LOCK_NONE,
- (char *) NULL, 0, (char *) NULL);
-
- Lock_Cleanup ();
- return err;
-}
-
-int
-watch_on (argc, argv)
- int argc;
- char **argv;
-{
- turning_on = 1;
- return watch_onoff (argc, argv);
-}
-
-int
-watch_off (argc, argv)
- int argc;
- char **argv;
-{
- turning_on = 0;
- return watch_onoff (argc, argv);
-}
-
-static int dummy_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-
-static int
-dummy_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- /* This is a pretty hideous hack, but the gist of it is that recurse.c
- won't call cvs_notify_check unless there is a fileproc, so we
- can't just pass NULL for fileproc. */
- return 0;
-}
-
-static int ncheck_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-
-/* Check for and process notifications. Local only. I think that doing
- this as a fileproc is the only way to catch all the
- cases (e.g. foo/bar.c), even though that means checking over and over
- for the same CVSADM_NOTIFY file which we removed the first time we
- processed the directory. */
-
-static int
-ncheck_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- int notif_type;
- char *filename;
- char *val;
- char *cp;
- char *watches;
-
- FILE *fp;
- char *line = NULL;
- size_t line_len = 0;
-
- /* We send notifications even if noexec. I'm not sure which behavior
- is most sensible. */
-
- fp = CVS_FOPEN (CVSADM_NOTIFY, "r");
- if (fp == NULL)
- {
- if (!existence_error (errno))
- error (0, errno, "cannot open %s", CVSADM_NOTIFY);
- return 0;
- }
-
- while (getline (&line, &line_len, fp) > 0)
- {
- notif_type = line[0];
- if (notif_type == '\0')
- continue;
- filename = line + 1;
- cp = strchr (filename, '\t');
- if (cp == NULL)
- continue;
- *cp++ = '\0';
- val = cp;
- cp = strchr (val, '\t');
- if (cp == NULL)
- continue;
- *cp++ = '+';
- cp = strchr (cp, '\t');
- if (cp == NULL)
- continue;
- *cp++ = '+';
- cp = strchr (cp, '\t');
- if (cp == NULL)
- continue;
- *cp++ = '\0';
- watches = cp;
- cp = strchr (cp, '\n');
- if (cp == NULL)
- continue;
- *cp = '\0';
-
- notify_do (notif_type, filename, getcaller (), val, watches,
- finfo->repository);
- }
- free (line);
-
- if (ferror (fp))
- error (0, errno, "cannot read %s", CVSADM_NOTIFY);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", CVSADM_NOTIFY);
-
- if ( CVS_UNLINK (CVSADM_NOTIFY) < 0)
- error (0, errno, "cannot remove %s", CVSADM_NOTIFY);
-
- return 0;
-}
-
-static int send_notifications PROTO ((int, char **, int));
-
-/* Look through the CVSADM_NOTIFY file and process each item there
- accordingly. */
-static int
-send_notifications (argc, argv, local)
- int argc;
- char **argv;
- int local;
-{
- int err = 0;
-
-#ifdef CLIENT_SUPPORT
- /* OK, we've done everything which needs to happen on the client side.
- Now we can try to contact the server; if we fail, then the
- notifications stay in CVSADM_NOTIFY to be sent next time. */
- if (current_parsed_root->isremote)
- {
- if (strcmp (cvs_cmd_name, "release") != 0)
- {
- start_server ();
- ign_setup ();
- }
-
- err += start_recursion (dummy_fileproc, (FILESDONEPROC) NULL,
- (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
- argc, argv, local, W_LOCAL, 0, 0, (char *)NULL,
- 0, (char *) NULL);
-
- send_to_server ("noop\012", 0);
- if (strcmp (cvs_cmd_name, "release") == 0)
- err += get_server_responses ();
- else
- err += get_responses_and_close ();
- }
- else
-#endif
- {
- /* Local. */
-
- lock_tree_for_write (argc, argv, local, W_LOCAL, 0);
- err += start_recursion (ncheck_fileproc, (FILESDONEPROC) NULL,
- (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
- argc, argv, local, W_LOCAL, 0, 0, (char *)NULL,
- 0, (char *) NULL);
- Lock_Cleanup ();
- }
- return err;
-}
-
-static int edit_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-
-static int
-edit_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- FILE *fp;
- time_t now;
- char *ascnow;
- char *basefilename;
-
- if (noexec)
- return 0;
-
- /* This is a somewhat screwy way to check for this, because it
- doesn't help errors other than the nonexistence of the file
- (e.g. permissions problems). It might be better to rearrange
- the code so that CVSADM_NOTIFY gets written only after the
- various actions succeed (but what if only some of them
- succeed). */
- if (!isfile (finfo->file))
- {
- error (0, 0, "no such file %s; ignored", finfo->fullname);
- return 0;
- }
-
- fp = open_file (CVSADM_NOTIFY, "a");
-
- (void) time (&now);
- ascnow = asctime (gmtime (&now));
- ascnow[24] = '\0';
- /* Fix non-standard format. */
- if (ascnow[8] == '0') ascnow[8] = ' ';
- fprintf (fp, "E%s\t%s GMT\t%s\t%s\t", finfo->file,
- ascnow, hostname, CurDir);
- if (setting_tedit)
- fprintf (fp, "E");
- if (setting_tunedit)
- fprintf (fp, "U");
- if (setting_tcommit)
- fprintf (fp, "C");
- fprintf (fp, "\n");
-
- if (fclose (fp) < 0)
- {
- if (finfo->update_dir[0] == '\0')
- error (0, errno, "cannot close %s", CVSADM_NOTIFY);
- else
- error (0, errno, "cannot close %s/%s", finfo->update_dir,
- CVSADM_NOTIFY);
- }
-
- xchmod (finfo->file, 1);
-
- /* Now stash the file away in CVSADM so that unedit can revert even if
- it can't communicate with the server. We stash away a writable
- copy so that if the user removes the working file, then restores it
- with "cvs update" (which clears _editors but does not update
- CVSADM_BASE), then a future "cvs edit" can still win. */
- /* Could save a system call by only calling mkdir_if_needed if
- trying to create the output file fails. But copy_file isn't
- set up to facilitate that. */
- mkdir_if_needed (CVSADM_BASE);
- basefilename = xmalloc (10 + sizeof CVSADM_BASE + strlen (finfo->file));
- strcpy (basefilename, CVSADM_BASE);
- strcat (basefilename, "/");
- strcat (basefilename, finfo->file);
- copy_file (finfo->file, basefilename);
- free (basefilename);
-
- {
- Node *node;
-
- node = findnode_fn (finfo->entries, finfo->file);
- if (node != NULL)
- base_register (finfo, ((Entnode *) node->data)->version);
- }
-
- return 0;
-}
-
-static const char *const edit_usage[] =
-{
- "Usage: %s %s [-lR] [-a <action>]... [<file>]...\n",
- "-l\tLocal directory only, not recursive.\n",
- "-R\tProcess directories recursively (default).\n",
- "-a\tSpecify action to register for temporary watch, one of:\n",
- " \t`edit', `unedit', `commit', `all', or `none' (defaults to `all').\n",
- "(Specify the --help global option for a list of other help options.)\n",
- NULL
-};
-
-int
-edit (argc, argv)
- int argc;
- char **argv;
-{
- int local = 0;
- int c;
- int err;
- int a_omitted;
-
- if (argc == -1)
- usage (edit_usage);
-
- a_omitted = 1;
- setting_tedit = 0;
- setting_tunedit = 0;
- setting_tcommit = 0;
- optind = 0;
- while ((c = getopt (argc, argv, "+lRa:")) != -1)
- {
- switch (c)
- {
- case 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case 'a':
- a_omitted = 0;
- if (strcmp (optarg, "edit") == 0)
- setting_tedit = 1;
- else if (strcmp (optarg, "unedit") == 0)
- setting_tunedit = 1;
- else if (strcmp (optarg, "commit") == 0)
- setting_tcommit = 1;
- else if (strcmp (optarg, "all") == 0)
- {
- setting_tedit = 1;
- setting_tunedit = 1;
- setting_tcommit = 1;
- }
- else if (strcmp (optarg, "none") == 0)
- {
- setting_tedit = 0;
- setting_tunedit = 0;
- setting_tcommit = 0;
- }
- else
- usage (edit_usage);
- break;
- case '?':
- default:
- usage (edit_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- if (a_omitted)
- {
- setting_tedit = 1;
- setting_tunedit = 1;
- setting_tcommit = 1;
- }
-
- if (strpbrk (hostname, "+,>;=\t\n") != NULL)
- error (1, 0,
- "host name (%s) contains an invalid character (+,>;=\\t\\n)",
- hostname);
- if (strpbrk (CurDir, "+,>;=\t\n") != NULL)
- error (1, 0,
-"current directory (%s) contains an invalid character (+,>;=\\t\\n)",
- CurDir);
-
- /* No need to readlock since we aren't doing anything to the
- repository. */
- err = start_recursion (edit_fileproc, (FILESDONEPROC) NULL,
- (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
- argc, argv, local, W_LOCAL, 0, 0, (char *) NULL,
- 0, (char *) NULL);
-
- err += send_notifications (argc, argv, local);
-
- return err;
-}
-
-static int unedit_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-
-static int
-unedit_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- FILE *fp;
- time_t now;
- char *ascnow;
- char *basefilename;
-
- if (noexec)
- return 0;
-
- basefilename = xmalloc (10 + sizeof CVSADM_BASE + strlen (finfo->file));
- strcpy (basefilename, CVSADM_BASE);
- strcat (basefilename, "/");
- strcat (basefilename, finfo->file);
- if (!isfile (basefilename))
- {
- /* This file apparently was never cvs edit'd (e.g. we are uneditting
- a directory where only some of the files were cvs edit'd. */
- free (basefilename);
- return 0;
- }
-
- if (xcmp (finfo->file, basefilename) != 0)
- {
- printf ("%s has been modified; revert changes? ", finfo->fullname);
- if (!yesno ())
- {
- /* "no". */
- free (basefilename);
- return 0;
- }
- }
- rename_file (basefilename, finfo->file);
- free (basefilename);
-
- fp = open_file (CVSADM_NOTIFY, "a");
-
- (void) time (&now);
- ascnow = asctime (gmtime (&now));
- ascnow[24] = '\0';
- /* Fix non-standard format. */
- if (ascnow[8] == '0') ascnow[8] = ' ';
- fprintf (fp, "U%s\t%s GMT\t%s\t%s\t\n", finfo->file,
- ascnow, hostname, CurDir);
-
- if (fclose (fp) < 0)
- {
- if (finfo->update_dir[0] == '\0')
- error (0, errno, "cannot close %s", CVSADM_NOTIFY);
- else
- error (0, errno, "cannot close %s/%s", finfo->update_dir,
- CVSADM_NOTIFY);
- }
-
- /* Now update the revision number in CVS/Entries from CVS/Baserev.
- The basic idea here is that we are reverting to the revision
- that the user edited. If we wanted "cvs update" to update
- CVS/Base as we go along (so that an unedit could revert to the
- current repository revision), we would need:
-
- update (or all send_files?) (client) needs to send revision in
- new Entry-base request. update (server/local) needs to check
- revision against repository and send new Update-base response
- (like Update-existing in that the file already exists. While
- we are at it, might try to clean up the syntax by having the
- mode only in a "Mode" response, not in the Update-base itself). */
- {
- char *baserev;
- Node *node;
- Entnode *entdata;
-
- baserev = base_get (finfo);
- node = findnode_fn (finfo->entries, finfo->file);
- /* The case where node is NULL probably should be an error or
- something, but I don't want to think about it too hard right
- now. */
- if (node != NULL)
- {
- entdata = node->data;
- if (baserev == NULL)
- {
- /* This can only happen if the CVS/Baserev file got
- corrupted. We suspect it might be possible if the
- user interrupts CVS, although I haven't verified
- that. */
- error (0, 0, "%s not mentioned in %s", finfo->fullname,
- CVSADM_BASEREV);
-
- /* Since we don't know what revision the file derives from,
- keeping it around would be asking for trouble. */
- if (unlink_file (finfo->file) < 0)
- error (0, errno, "cannot remove %s", finfo->fullname);
-
- /* This is cheesy, in a sense; why shouldn't we do the
- update for the user? However, doing that would require
- contacting the server, so maybe this is OK. */
- error (0, 0, "run update to complete the unedit");
- return 0;
- }
- Register (finfo->entries, finfo->file, baserev, entdata->timestamp,
- entdata->options, entdata->tag, entdata->date,
- entdata->conflict);
- }
- free (baserev);
- base_deregister (finfo);
- }
-
- xchmod (finfo->file, 0);
- return 0;
-}
-
-static const char *const unedit_usage[] =
-{
- "Usage: %s %s [-lR] [<file>]...\n",
- "-l\tLocal directory only, not recursive.\n",
- "-R\tProcess directories recursively (default).\n",
- "(Specify the --help global option for a list of other help options.)\n",
- NULL
-};
-
-int
-unedit (argc, argv)
- int argc;
- char **argv;
-{
- int local = 0;
- int c;
- int err;
-
- if (argc == -1)
- usage (unedit_usage);
-
- optind = 0;
- while ((c = getopt (argc, argv, "+lR")) != -1)
- {
- switch (c)
- {
- case 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case '?':
- default:
- usage (unedit_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- /* No need to readlock since we aren't doing anything to the
- repository. */
- err = start_recursion (unedit_fileproc, (FILESDONEPROC) NULL,
- (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
- argc, argv, local, W_LOCAL, 0, 0, (char *)NULL,
- 0, (char *) NULL);
-
- err += send_notifications (argc, argv, local);
-
- return err;
-}
-
-void
-mark_up_to_date (file)
- const char *file;
-{
- char *base;
-
- /* The file is up to date, so we better get rid of an out of
- date file in CVSADM_BASE. */
- base = xmalloc (strlen (file) + 80);
- strcpy (base, CVSADM_BASE);
- strcat (base, "/");
- strcat (base, file);
- if (unlink_file (base) < 0 && ! existence_error (errno))
- error (0, errno, "cannot remove %s", file);
- free (base);
-}
-
-
-
-void
-editor_set (filename, editor, val)
- const char *filename;
- const char *editor;
- const char *val;
-{
- char *edlist;
- char *newlist;
-
- edlist = fileattr_get0 (filename, "_editors");
- newlist = fileattr_modify (edlist, editor, val, '>', ',');
- /* If the attributes is unchanged, don't rewrite the attribute file. */
- if (!((edlist == NULL && newlist == NULL)
- || (edlist != NULL
- && newlist != NULL
- && strcmp (edlist, newlist) == 0)))
- fileattr_set (filename, "_editors", newlist);
- if (edlist != NULL)
- free (edlist);
- if (newlist != NULL)
- free (newlist);
-}
-
-struct notify_proc_args {
- /* What kind of notification, "edit", "tedit", etc. */
- const char *type;
- /* User who is running the command which causes notification. */
- const char *who;
- /* User to be notified. */
- const char *notifyee;
- /* File. */
- const char *file;
-};
-
-
-
-/* Pass as a static until we get around to fixing Parse_Info to pass along
- a void * where we can stash it. */
-static struct notify_proc_args *notify_args;
-
-
-
-static int notify_proc PROTO ((const char *repository, const char *filter));
-
-static int
-notify_proc (repository, filter)
- const char *repository;
- const char *filter;
-{
- FILE *pipefp;
- char *prog;
- char *expanded_prog;
- const char *p;
- char *q;
- const char *srepos;
- struct notify_proc_args *args = notify_args;
-
- srepos = Short_Repository (repository);
- prog = xmalloc (strlen (filter) + strlen (args->notifyee) + 1);
- /* Copy FILTER to PROG, replacing the first occurrence of %s with
- the notifyee. We only allocated enough memory for one %s, and I doubt
- there is a need for more. */
- for (p = filter, q = prog; *p != '\0'; ++p)
- {
- if (p[0] == '%')
- {
- if (p[1] == 's')
- {
- strcpy (q, args->notifyee);
- q += strlen (q);
- strcpy (q, p + 2);
- q += strlen (q);
- break;
- }
- else
- continue;
- }
- *q++ = *p;
- }
- *q = '\0';
-
- /* FIXME: why are we calling expand_proc? Didn't we already
- expand it in Parse_Info, before passing it to notify_proc? */
- expanded_prog = expand_path (prog, "notify", 0);
- if (!expanded_prog)
- {
- free (prog);
- return 1;
- }
-
- pipefp = run_popen (expanded_prog, "w");
- if (pipefp == NULL)
- {
- error (0, errno, "cannot write entry to notify filter: %s", prog);
- free (prog);
- free (expanded_prog);
- return 1;
- }
-
- fprintf (pipefp, "%s %s\n---\n", srepos, args->file);
- fprintf (pipefp, "Triggered %s watch on %s\n", args->type, repository);
- fprintf (pipefp, "By %s\n", args->who);
-
- /* Lots more potentially useful information we could add here; see
- logfile_write for inspiration. */
-
- free (prog);
- free (expanded_prog);
- 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;
- const char *filename;
- const char *who;
- const char *val;
- const char *watches;
- const char *repository;
-{
- static struct addremove_args blank;
- struct addremove_args args;
- char *watchers;
- char *p;
- char *endp;
- char *nextp;
-
- /* Initialize fields to 0, NULL, or 0.0. */
- args = blank;
- 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':
- case 'C':
- editor_set (filename, who, NULL);
- break;
- default:
- return;
- }
-
- watchers = fileattr_get0 (filename, "_watchers");
- p = watchers;
- while (p != NULL)
- {
- char *q;
- char *endq;
- char *nextq;
- char *notif;
-
- endp = strchr (p, '>');
- if (endp == NULL)
- break;
- nextp = strchr (p, ',');
-
- if ((size_t)(endp - p) == strlen (who) && strncmp (who, p, endp - p) == 0)
- {
- /* Don't notify user of their own changes. Would perhaps
- be better to check whether it is the same working
- directory, not the same user, but that is hairy. */
- p = nextp == NULL ? nextp : nextp + 1;
- continue;
- }
-
- /* Now we point q at a string which looks like
- "edit+unedit+commit,"... and walk down it. */
- q = endp + 1;
- notif = NULL;
- while (q != NULL)
- {
- endq = strchr (q, '+');
- if (endq == NULL || (nextp != NULL && endq > nextp))
- {
- if (nextp == NULL)
- endq = q + strlen (q);
- else
- endq = nextp;
- nextq = NULL;
- }
- else
- nextq = endq + 1;
-
- /* If there is a temporary and a regular watch, send a single
- notification, for the regular watch. */
- if (type == 'E' && endq - q == 4 && strncmp ("edit", q, 4) == 0)
- {
- notif = "edit";
- }
- else if (type == 'U'
- && endq - q == 6 && strncmp ("unedit", q, 6) == 0)
- {
- notif = "unedit";
- }
- else if (type == 'C'
- && endq - q == 6 && strncmp ("commit", q, 6) == 0)
- {
- notif = "commit";
- }
- else if (type == 'E'
- && endq - q == 5 && strncmp ("tedit", q, 5) == 0)
- {
- if (notif == NULL)
- notif = "temporary edit";
- }
- else if (type == 'U'
- && endq - q == 7 && strncmp ("tunedit", q, 7) == 0)
- {
- if (notif == NULL)
- notif = "temporary unedit";
- }
- else if (type == 'C'
- && endq - q == 7 && strncmp ("tcommit", q, 7) == 0)
- {
- if (notif == NULL)
- notif = "temporary commit";
- }
- q = nextq;
- }
- if (nextp != NULL)
- ++nextp;
-
- if (notif != NULL)
- {
- struct notify_proc_args args;
- size_t len = endp - p;
- FILE *fp;
- char *usersname;
- char *line = NULL;
- size_t line_len = 0;
-
- args.notifyee = NULL;
- usersname = xmalloc (strlen (current_parsed_root->directory)
- + sizeof CVSROOTADM
- + sizeof CVSROOTADM_USERS
- + 20);
- strcpy (usersname, current_parsed_root->directory);
- strcat (usersname, "/");
- strcat (usersname, CVSROOTADM);
- strcat (usersname, "/");
- strcat (usersname, CVSROOTADM_USERS);
- fp = CVS_FOPEN (usersname, "r");
- if (fp == NULL && !existence_error (errno))
- error (0, errno, "cannot read %s", usersname);
- if (fp != NULL)
- {
- while (getline (&line, &line_len, fp) >= 0)
- {
- if (strncmp (line, p, len) == 0
- && line[len] == ':')
- {
- char *cp;
- args.notifyee = xstrdup (line + len + 1);
-
- /* 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;
- }
- }
- if (ferror (fp))
- error (0, errno, "cannot read %s", usersname);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", usersname);
- }
- free (usersname);
- if (line != NULL)
- free (line);
-
- if (args.notifyee == NULL)
- {
- char *tmp;
- tmp = xmalloc (endp - p + 1);
- strncpy (tmp, p, endp - p);
- tmp[endp - p] = '\0';
- args.notifyee = tmp;
- }
-
- notify_args = &args;
- args.type = notif;
- args.who = who;
- args.file = filename;
-
- (void) Parse_Info (CVSROOTADM_NOTIFY, repository, notify_proc, 1);
-
- /* It's okay to cast out the const for the free() below since we
- * just allocated this a few lines above. The const was for
- * everybody else.
- */
- free ((char *)args.notifyee);
- }
-
- p = nextp;
- }
- if (watchers != NULL)
- free (watchers);
-
- switch (type)
- {
- case 'E':
- if (*watches == 'E')
- {
- args.add_tedit = 1;
- ++watches;
- }
- if (*watches == 'U')
- {
- args.add_tunedit = 1;
- ++watches;
- }
- if (*watches == 'C')
- {
- args.add_tcommit = 1;
- }
- watch_modify_watchers (filename, &args);
- break;
- case 'U':
- case 'C':
- args.remove_temp = 1;
- watch_modify_watchers (filename, &args);
- break;
- }
-}
-
-#ifdef CLIENT_SUPPORT
-/* Check and send notifications. This is only for the client. */
-void
-cvs_notify_check (repository, update_dir)
- const char *repository;
- const char *update_dir;
-{
- FILE *fp;
- char *line = NULL;
- size_t line_len = 0;
-
- if (! server_started)
- /* We are in the midst of a command which is not to talk to
- the server (e.g. the first phase of a cvs edit). Just chill
- out, we'll catch the notifications on the flip side. */
- return;
-
- /* We send notifications even if noexec. I'm not sure which behavior
- is most sensible. */
-
- fp = CVS_FOPEN (CVSADM_NOTIFY, "r");
- if (fp == NULL)
- {
- if (!existence_error (errno))
- error (0, errno, "cannot open %s", CVSADM_NOTIFY);
- return;
- }
- while (getline (&line, &line_len, fp) > 0)
- {
- int notif_type;
- char *filename;
- char *val;
- char *cp;
-
- notif_type = line[0];
- if (notif_type == '\0')
- continue;
- filename = line + 1;
- cp = strchr (filename, '\t');
- if (cp == NULL)
- continue;
- *cp++ = '\0';
- val = cp;
-
- client_notify (repository, update_dir, filename, notif_type, val);
- }
- if (line)
- free (line);
- if (ferror (fp))
- error (0, errno, "cannot read %s", CVSADM_NOTIFY);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", CVSADM_NOTIFY);
-
- /* Leave the CVSADM_NOTIFY file there, until the server tells us it
- has dealt with it. */
-}
-#endif /* CLIENT_SUPPORT */
-
-
-static const char *const editors_usage[] =
-{
- "Usage: %s %s [-lR] [<file>]...\n",
- "-l\tProcess this directory only (not recursive).\n",
- "-R\tProcess directories recursively (default).\n",
- "(Specify the --help global option for a list of other help options.)\n",
- NULL
-};
-
-static int editors_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-
-static int
-editors_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- char *them;
- char *p;
-
- them = fileattr_get0 (finfo->file, "_editors");
- if (them == NULL)
- return 0;
-
- cvs_output (finfo->fullname, 0);
-
- p = them;
- while (1)
- {
- cvs_output ("\t", 1);
- while (*p != '>' && *p != '\0')
- cvs_output (p++, 1);
- if (*p == '\0')
- {
- /* Only happens if attribute is misformed. */
- cvs_output ("\n", 1);
- break;
- }
- ++p;
- cvs_output ("\t", 1);
- while (1)
- {
- while (*p != '+' && *p != ',' && *p != '\0')
- cvs_output (p++, 1);
- if (*p == '\0')
- {
- cvs_output ("\n", 1);
- goto out;
- }
- if (*p == ',')
- {
- ++p;
- break;
- }
- ++p;
- cvs_output ("\t", 1);
- }
- cvs_output ("\n", 1);
- }
- out:;
- free (them);
- return 0;
-}
-
-int
-editors (argc, argv)
- int argc;
- char **argv;
-{
- int local = 0;
- int c;
-
- if (argc == -1)
- usage (editors_usage);
-
- optind = 0;
- while ((c = getopt (argc, argv, "+lR")) != -1)
- {
- switch (c)
- {
- case 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case '?':
- default:
- usage (editors_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- start_server ();
- ign_setup ();
-
- if (local)
- send_arg ("-l");
- send_arg ("--");
- 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 ();
- }
-#endif /* CLIENT_SUPPORT */
-
- return start_recursion (editors_fileproc, (FILESDONEPROC) NULL,
- (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
- argc, argv, local, W_LOCAL, 0, 1, (char *) NULL,
- 0, (char *) NULL);
-}
diff --git a/contrib/cvs/src/edit.h b/contrib/cvs/src/edit.h
deleted file mode 100644
index 9b20180429e7..000000000000
--- a/contrib/cvs/src/edit.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Interface to "cvs edit", "cvs watch on", and related features
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-extern int watch_on PROTO ((int argc, char **argv));
-extern int watch_off PROTO ((int argc, char **argv));
-
-#ifdef CLIENT_SUPPORT
-/* Check to see if any notifications are sitting around in need of being
- sent. These are the notifications stored in CVSADM_NOTIFY (edit,unedit);
- commit calls notify_do directly. */
-extern void cvs_notify_check PROTO ((const char *repository,
- const char *update_dir));
-#endif /* CLIENT_SUPPORT */
-
-/* Issue a notification for file FILENAME. TYPE is 'E' for edit, 'U'
- for unedit, and 'C' for commit. WHO is the user currently running.
- For TYPE 'E', VAL is the time+host+directory data which goes in
- _editors, and WATCHES is zero or more of E,U,C, in that order, to specify
- what kinds of temporary watches to set. */
-extern void notify_do PROTO ((int type, const char *filename, const char *who,
- const char *val, const char *watches,
- const char *repository));
-
-/* Set attributes to reflect the fact that EDITOR is editing FILENAME.
- VAL is time+host+directory, or NULL if we are to say that EDITOR is
- *not* editing FILENAME. */
-extern void editor_set PROTO ((const char *filename, const char *editor,
- const char *val));
-
-/* Take note of the fact that FILE is up to date (this munges CVS/Base;
- processing of CVS/Entries is done separately). */
-extern void mark_up_to_date PROTO ((const char *file));
diff --git a/contrib/cvs/src/entries.c b/contrib/cvs/src/entries.c
deleted file mode 100644
index 9592c3c637ad..000000000000
--- a/contrib/cvs/src/entries.c
+++ /dev/null
@@ -1,1263 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Entries file to Files file
- *
- * Creates the file Files containing the names that comprise the project, from
- * the Entries file.
- */
-
-/*
- * $FreeBSD$
- */
-#include "cvs.h"
-#include "getline.h"
-
-static Node *AddEntryNode PROTO((List * list, Entnode *entnode));
-
-static Entnode *fgetentent PROTO((FILE *, char *, int *));
-static int fputentent PROTO((FILE *, Entnode *));
-
-static Entnode *subdir_record PROTO((int, const char *, const char *));
-
-static FILE *entfile;
-static char *entfilename; /* for error messages */
-
-
-
-/*
- * Construct an Entnode
- */
-static Entnode *Entnode_Create PROTO ((enum ent_type, const char *,
- const char *, const char *,
- const char *, const char *,
- const char *, const char *));
-
-static Entnode *
-Entnode_Create(type, user, vn, ts, options, tag, date, ts_conflict)
- enum ent_type type;
- const char *user;
- const char *vn;
- const char *ts;
- const char *options;
- const char *tag;
- const char *date;
- const char *ts_conflict;
-{
- Entnode *ent;
-
- /* Note that timestamp and options must be non-NULL */
- ent = (Entnode *) xmalloc (sizeof (Entnode));
- ent->type = type;
- ent->user = xstrdup (user);
- ent->version = xstrdup (vn);
- ent->timestamp = xstrdup (ts ? ts : "");
- ent->options = xstrdup (options ? options : "");
- ent->tag = xstrdup (tag);
- ent->date = xstrdup (date);
- ent->conflict = xstrdup (ts_conflict);
-
- return ent;
-}
-
-/*
- * Destruct an Entnode
- */
-static void Entnode_Destroy PROTO ((Entnode *));
-
-static void
-Entnode_Destroy (ent)
- Entnode *ent;
-{
- free (ent->user);
- free (ent->version);
- free (ent->timestamp);
- free (ent->options);
- if (ent->tag)
- free (ent->tag);
- if (ent->date)
- free (ent->date);
- if (ent->conflict)
- free (ent->conflict);
- free (ent);
-}
-
-/*
- * Write out the line associated with a node of an entries file
- */
-static int write_ent_proc PROTO ((Node *, void *));
-static int
-write_ent_proc (node, closure)
- Node *node;
- void *closure;
-{
- Entnode *entnode = node->data;
-
- if (closure != NULL && entnode->type != ENT_FILE)
- *(int *) closure = 1;
-
- if (fputentent(entfile, entnode))
- error (1, errno, "cannot write %s", entfilename);
-
- return (0);
-}
-
-/*
- * write out the current entries file given a list, making a backup copy
- * first of course
- */
-static void
-write_entries (list)
- List *list;
-{
- int sawdir;
-
- sawdir = 0;
-
- /* open the new one and walk the list writing entries */
- entfilename = CVSADM_ENTBAK;
- entfile = CVS_FOPEN (entfilename, "w+");
- if (entfile == NULL)
- {
- /* Make this a warning, not an error. For example, one user might
- have checked out a working directory which, for whatever reason,
- contains an Entries.Log file. A second user, without write access
- to that working directory, might want to do a "cvs log". The
- problem rewriting Entries shouldn't affect the ability of "cvs log"
- to work, although the warning is probably a good idea so that
- whether Entries gets rewritten is not an inexplicable process. */
- /* FIXME: should be including update_dir in message. */
- error (0, errno, "cannot rewrite %s", entfilename);
-
- /* Now just return. We leave the Entries.Log file around. As far
- as I know, there is never any data lying around in 'list' that
- is not in Entries.Log at this time (if there is an error writing
- Entries.Log that is a separate problem). */
- return;
- }
-
- (void) walklist (list, write_ent_proc, (void *) &sawdir);
- if (! sawdir)
- {
- struct stickydirtag *sdtp;
-
- /* We didn't write out any directories. Check the list
- private data to see whether subdirectory information is
- known. If it is, we need to write out an empty D line. */
- sdtp = list->list->data;
- if (sdtp == NULL || sdtp->subdirs)
- if (fprintf (entfile, "D\n") < 0)
- error (1, errno, "cannot write %s", entfilename);
- }
- if (fclose (entfile) == EOF)
- error (1, errno, "error closing %s", entfilename);
-
- /* now, atomically (on systems that support it) rename it */
- rename_file (entfilename, CVSADM_ENT);
-
- /* now, remove the log file */
- if (unlink_file (CVSADM_ENTLOG) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", CVSADM_ENTLOG);
-}
-
-
-
-/*
- * Removes the argument file from the Entries file if necessary.
- */
-void
-Scratch_Entry (list, fname)
- List *list;
- const char *fname;
-{
- Node *node;
-
- if (trace)
- (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)
- {
- if (!noexec)
- {
- entfilename = CVSADM_ENTLOG;
- entfile = open_file (entfilename, "a");
-
- if (fprintf (entfile, "R ") < 0)
- error (1, errno, "cannot write %s", entfilename);
-
- write_ent_proc (node, NULL);
-
- if (fclose (entfile) == EOF)
- error (1, errno, "error closing %s", entfilename);
- }
-
- delnode (node); /* delete the node */
-
-#ifdef SERVER_SUPPORT
- if (server_active)
- server_scratch (fname);
-#endif
- }
-}
-
-
-
-/*
- * Enters the given file name/version/time-stamp into the Entries file,
- * removing the old entry first, if necessary.
- */
-void
-Register (list, fname, vn, ts, options, tag, date, ts_conflict)
- List *list;
- const char *fname;
- const char *vn;
- const char *ts;
- const char *options;
- const char *tag;
- const char *date;
- const char *ts_conflict;
-{
- Entnode *entnode;
- Node *node;
-
-#ifdef SERVER_SUPPORT
- if (server_active)
- {
- server_register (fname, vn, ts, options, tag, date, ts_conflict);
- }
-#endif
-
- if (trace)
- {
- (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 : "");
- }
-
- entnode = Entnode_Create (ENT_FILE, fname, vn, ts, options, tag, date,
- ts_conflict);
- node = AddEntryNode (list, entnode);
-
- if (!noexec)
- {
- entfilename = CVSADM_ENTLOG;
- 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);
-
- write_ent_proc (node, NULL);
-
- if (fclose (entfile) == EOF)
- error (1, errno, "error closing %s", entfilename);
- }
-}
-
-/*
- * Node delete procedure for list-private sticky dir tag/date info
- */
-static void
-freesdt (p)
- Node *p;
-{
- struct stickydirtag *sdtp = p->data;
-
- if (sdtp->tag)
- free (sdtp->tag);
- if (sdtp->date)
- free (sdtp->date);
- free ((char *) sdtp);
-}
-
-/* Return the next real Entries line. On end of file, returns NULL.
- On error, prints an error message and returns NULL. */
-
-static Entnode *
-fgetentent(fpin, cmd, sawdir)
- FILE *fpin;
- char *cmd;
- int *sawdir;
-{
- Entnode *ent;
- char *line;
- size_t line_chars_allocated;
- register char *cp;
- enum ent_type type;
- char *l, *user, *vn, *ts, *options;
- char *tag_or_date, *tag, *date, *ts_conflict;
- int line_length;
-
- line = NULL;
- line_chars_allocated = 0;
-
- ent = NULL;
- while ((line_length = getline (&line, &line_chars_allocated, fpin)) > 0)
- {
- l = line;
-
- /* If CMD is not NULL, we are reading an Entries.Log file.
- Each line in the Entries.Log file starts with a single
- character command followed by a space. For backward
- compatibility, the absence of a space indicates an add
- command. */
- if (cmd != NULL)
- {
- if (l[1] != ' ')
- *cmd = 'A';
- else
- {
- *cmd = l[0];
- l += 2;
- }
- }
-
- type = ENT_FILE;
-
- if (l[0] == 'D')
- {
- type = ENT_SUBDIR;
- *sawdir = 1;
- ++l;
- /* An empty D line is permitted; it is a signal that this
- Entries file lists all known subdirectories. */
- }
-
- if (l[0] != '/')
- continue;
-
- user = l + 1;
- if ((cp = strchr (user, '/')) == NULL)
- continue;
- *cp++ = '\0';
- vn = cp;
- if ((cp = strchr (vn, '/')) == NULL)
- continue;
- *cp++ = '\0';
- ts = cp;
- if ((cp = strchr (ts, '/')) == NULL)
- continue;
- *cp++ = '\0';
- options = cp;
- if ((cp = strchr (options, '/')) == NULL)
- continue;
- *cp++ = '\0';
- tag_or_date = cp;
- if ((cp = strchr (tag_or_date, '\n')) == NULL)
- continue;
- *cp = '\0';
- tag = (char *) NULL;
- date = (char *) NULL;
- if (*tag_or_date == 'T')
- tag = tag_or_date + 1;
- else if (*tag_or_date == 'D')
- date = tag_or_date + 1;
-
- if ((ts_conflict = strchr (ts, '+')))
- *ts_conflict++ = '\0';
-
- /*
- * XXX - Convert timestamp from old format to new format.
- *
- * If the timestamp doesn't match the file's current
- * mtime, we'd have to generate a string that doesn't
- * match anyways, so cheat and base it on the existing
- * string; it doesn't have to match the same mod time.
- *
- * For an unmodified file, write the correct timestamp.
- */
- {
- struct stat sb;
- if (strlen (ts) > 30 && CVS_STAT (user, &sb) == 0)
- {
- char *c = ctime (&sb.st_mtime);
- /* Fix non-standard format. */
- if (c[8] == '0') c[8] = ' ';
-
- if (!strncmp (ts + 25, c, 24))
- ts = time_stamp (user);
- else
- {
- ts += 24;
- ts[0] = '*';
- }
- }
- }
-
- ent = Entnode_Create (type, user, vn, ts, options, tag, date,
- ts_conflict);
- break;
- }
-
- if (line_length < 0 && !feof (fpin))
- error (0, errno, "cannot read entries file");
-
- free (line);
- return ent;
-}
-
-static int
-fputentent(fp, p)
- FILE *fp;
- Entnode *p;
-{
- switch (p->type)
- {
- case ENT_FILE:
- break;
- case ENT_SUBDIR:
- if (fprintf (fp, "D") < 0)
- return 1;
- break;
- }
-
- if (fprintf (fp, "/%s/%s/%s", p->user, p->version, p->timestamp) < 0)
- return 1;
- if (p->conflict)
- {
- if (fprintf (fp, "+%s", p->conflict) < 0)
- return 1;
- }
- if (fprintf (fp, "/%s/", p->options) < 0)
- return 1;
-
- if (p->tag)
- {
- if (fprintf (fp, "T%s\n", p->tag) < 0)
- return 1;
- }
- else if (p->date)
- {
- if (fprintf (fp, "D%s\n", p->date) < 0)
- return 1;
- }
- else
- {
- if (fprintf (fp, "\n") < 0)
- return 1;
- }
-
- return 0;
-}
-
-
-/* Read the entries file into a list, hashing on the file name.
-
- UPDATE_DIR is the name of the current directory, for use in error
- messages, or NULL if not known (that is, noone has gotten around
- to updating the caller to pass in the information). */
-List *
-Entries_Open (aflag, update_dir)
- int aflag;
- char *update_dir;
-{
- List *entries;
- struct stickydirtag *sdtp = NULL;
- Entnode *ent;
- char *dirtag, *dirdate;
- int dirnonbranch;
- int do_rewrite = 0;
- FILE *fpin;
- int sawdir;
-
- /* get a fresh list... */
- entries = getlist ();
-
- /*
- * Parse the CVS/Tag file, to get any default tag/date settings. Use
- * list-private storage to tuck them away for Version_TS().
- */
- ParseTag (&dirtag, &dirdate, &dirnonbranch);
- if (aflag || dirtag || dirdate)
- {
- sdtp = (struct stickydirtag *) xmalloc (sizeof (*sdtp));
- memset ((char *) sdtp, 0, sizeof (*sdtp));
- sdtp->aflag = aflag;
- sdtp->tag = xstrdup (dirtag);
- sdtp->date = xstrdup (dirdate);
- sdtp->nonbranch = dirnonbranch;
-
- /* feed it into the list-private area */
- entries->list->data = sdtp;
- entries->list->delproc = freesdt;
- }
-
- sawdir = 0;
-
- fpin = CVS_FOPEN (CVSADM_ENT, "r");
- if (fpin == NULL)
- {
- if (update_dir != NULL)
- error (0, 0, "in directory %s:", update_dir);
- error (0, errno, "cannot open %s for reading", CVSADM_ENT);
- }
- else
- {
- while ((ent = fgetentent (fpin, (char *) NULL, &sawdir)) != NULL)
- {
- (void) AddEntryNode (entries, ent);
- }
-
- 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");
- if (fpin != NULL)
- {
- char cmd;
- Node *node;
-
- while ((ent = fgetentent (fpin, &cmd, &sawdir)) != NULL)
- {
- switch (cmd)
- {
- case 'A':
- (void) AddEntryNode (entries, ent);
- break;
- case 'R':
- node = findnode_fn (entries, ent->user);
- if (node != NULL)
- delnode (node);
- Entnode_Destroy (ent);
- break;
- default:
- /* Ignore unrecognized commands. */
- Entnode_Destroy (ent);
- break;
- }
- }
- do_rewrite = 1;
- 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
- information is known. Nonexistent list private data is taken
- to mean that it is known. */
- if (sdtp != NULL)
- sdtp->subdirs = sawdir;
- else if (! sawdir)
- {
- sdtp = (struct stickydirtag *) xmalloc (sizeof (*sdtp));
- memset ((char *) sdtp, 0, sizeof (*sdtp));
- sdtp->subdirs = 0;
- entries->list->data = sdtp;
- entries->list->delproc = freesdt;
- }
-
- if (do_rewrite && !noexec)
- write_entries (entries);
-
- /* clean up and return */
- if (dirtag)
- free (dirtag);
- if (dirdate)
- free (dirdate);
- return (entries);
-}
-
-void
-Entries_Close(list)
- List *list;
-{
- if (list)
- {
- if (!noexec)
- {
- if (isfile (CVSADM_ENTLOG))
- write_entries (list);
- }
- dellist(&list);
- }
-}
-
-
-/*
- * Free up the memory associated with the data section of an ENTRIES type
- * node
- */
-static void
-Entries_delproc (node)
- Node *node;
-{
- Entnode *p = node->data;
-
- Entnode_Destroy(p);
-}
-
-/*
- * Get an Entries file list node, initialize it, and add it to the specified
- * list
- */
-static Node *
-AddEntryNode (list, entdata)
- List *list;
- Entnode *entdata;
-{
- Node *p;
-
- /* was it already there? */
- if ((p = findnode_fn (list, entdata->user)) != NULL)
- {
- /* take it out */
- delnode (p);
- }
-
- /* get a node and fill in the regular stuff */
- p = getnode ();
- p->type = ENTRIES;
- p->delproc = Entries_delproc;
-
- /* this one gets a key of the name for hashing */
- /* FIXME This results in duplicated data --- the hash package shouldn't
- assume that the key is dynamically allocated. The user's free proc
- should be responsible for freeing the key. */
- p->key = xstrdup (entdata->user);
- p->data = entdata;
-
- /* put the node into the list */
- addnode (list, p);
- return (p);
-}
-
-static char *root_template;
-
-static int
-get_root_template(const char *repository, const char *path)
-{
- if (root_template) {
- if (strcmp(path, root_template) == 0)
- return(0);
- free(root_template);
- }
- if ((root_template = strdup(path)) == NULL)
- return(-1);
- return(0);
-}
-
-/*
- * Write out/Clear the CVS/Template file.
- */
-void
-WriteTemplate (dir, update_dir)
- const char *dir;
- const char *update_dir;
-{
- char *tmp = NULL;
- struct stat st1;
- struct stat st2;
-
- if (Parse_Info(CVSROOTADM_RCSINFO, "cvs", get_root_template, 1) < 0)
- return;
-
- if (asprintf(&tmp, "%s/%s", dir, CVSADM_TEMPLATE) < 0)
- error (1, errno, "out of memory");
-
- if (stat(root_template, &st1) == 0) {
- if (stat(tmp, &st2) < 0 || st1.st_mtime != st2.st_mtime) {
- FILE *fi;
- FILE *fo;
-
- if ((fi = open_file(root_template, "r")) != NULL) {
- if ((fo = open_file(tmp, "w")) != NULL) {
- int n;
- char buf[256];
-
- while ((n = fread(buf, 1, sizeof(buf), fi)) > 0)
- fwrite(buf, 1, n, fo);
- fflush(fo);
- if (ferror(fi) || ferror(fo)) {
- fclose(fo);
- remove(tmp);
- error (1, errno, "error copying Template");
- } else {
- struct timeval times[2];
- fclose(fo);
- times[0].tv_sec = st1.st_mtime;
- times[0].tv_usec = 0;
- times[1] = times[0];
- utimes(tmp, times);
- }
- }
- fclose(fi);
- }
- }
- }
- free(tmp);
-}
-
-/*
- * Write out/Clear the CVS/Tag file.
- */
-void
-WriteTag (dir, tag, date, nonbranch, update_dir, repository)
- const char *dir;
- const char *tag;
- const char *date;
- int nonbranch;
- const char *update_dir;
- const char *repository;
-{
- FILE *fout;
- char *tmp;
-
- if (noexec)
- return;
-
- tmp = xmalloc ((dir ? strlen (dir) : 0)
- + sizeof (CVSADM_TAG)
- + 10);
- if (dir == NULL)
- (void) strcpy (tmp, CVSADM_TAG);
- else
- (void) sprintf (tmp, "%s/%s", dir, CVSADM_TAG);
-
- if (tag || date)
- {
- fout = open_file (tmp, "w+");
- if (tag)
- {
- if (nonbranch)
- {
- if (fprintf (fout, "N%s\n", tag) < 0)
- error (1, errno, "write to %s failed", tmp);
- }
- else
- {
- if (fprintf (fout, "T%s\n", tag) < 0)
- error (1, errno, "write to %s failed", tmp);
- }
- }
- else
- {
- if (fprintf (fout, "D%s\n", date) < 0)
- error (1, errno, "write to %s failed", tmp);
- }
- if (fclose (fout) == EOF)
- error (1, errno, "cannot close %s", tmp);
- }
- else
- if (unlink_file (tmp) < 0 && ! existence_error (errno))
- error (1, errno, "cannot remove %s", tmp);
- free (tmp);
-#ifdef SERVER_SUPPORT
- if (server_active)
- server_set_sticky (update_dir, repository, tag, date, nonbranch);
-#endif
-}
-
-/* Parse the CVS/Tag file for the current directory.
-
- If it contains a date, sets *DATEP to the date in a newly malloc'd
- string, *TAGP to NULL, and *NONBRANCHP to an unspecified value.
-
- If it contains a branch tag, sets *TAGP to the tag in a newly
- malloc'd string, *NONBRANCHP to 0, and *DATEP to NULL.
-
- If it contains a nonbranch tag, sets *TAGP to the tag in a newly
- malloc'd string, *NONBRANCHP to 1, and *DATEP to NULL.
-
- If it does not exist, or contains something unrecognized by this
- version of CVS, set *DATEP and *TAGP to NULL and *NONBRANCHP to
- an unspecified value.
-
- If there is an error, print an error message, set *DATEP and *TAGP
- to NULL, and return. */
-void
-ParseTag (tagp, datep, nonbranchp)
- char **tagp;
- char **datep;
- int *nonbranchp;
-{
- FILE *fp;
-
- if (tagp)
- *tagp = (char *) NULL;
- if (datep)
- *datep = (char *) NULL;
- /* Always store a value here, even in the 'D' case where the value
- is unspecified. Shuts up tools which check for references to
- uninitialized memory. */
- if (nonbranchp != NULL)
- *nonbranchp = 0;
- fp = CVS_FOPEN (CVSADM_TAG, "r");
- if (fp)
- {
- char *line;
- int line_length;
- size_t line_chars_allocated;
-
- line = NULL;
- line_chars_allocated = 0;
-
- if ((line_length = getline (&line, &line_chars_allocated, fp)) > 0)
- {
- /* Remove any trailing newline. */
- if (line[line_length - 1] == '\n')
- line[--line_length] = '\0';
- switch (*line)
- {
- case 'T':
- if (tagp != NULL)
- *tagp = xstrdup (line + 1);
- break;
- case 'D':
- if (datep != NULL)
- *datep = xstrdup (line + 1);
- break;
- case 'N':
- if (tagp != NULL)
- *tagp = xstrdup (line + 1);
- if (nonbranchp != NULL)
- *nonbranchp = 1;
- break;
- default:
- /* Silently ignore it; it may have been
- written by a future version of CVS which extends the
- syntax. */
- break;
- }
- }
-
- if (line_length < 0)
- {
- /* FIXME-update-dir: should include update_dir in messages. */
- if (feof (fp))
- error (0, 0, "cannot read %s: end of file", CVSADM_TAG);
- else
- error (0, errno, "cannot read %s", CVSADM_TAG);
- }
-
- if (fclose (fp) < 0)
- /* FIXME-update-dir: should include update_dir in message. */
- error (0, errno, "cannot close %s", CVSADM_TAG);
-
- free (line);
- }
- else if (!existence_error (errno))
- /* FIXME-update-dir: should include update_dir in message. */
- error (0, errno, "cannot open %s", CVSADM_TAG);
-}
-
-/*
- * This is called if all subdirectory information is known, but there
- * aren't any subdirectories. It records that fact in the list
- * private data.
- */
-
-void
-Subdirs_Known (entries)
- List *entries;
-{
- struct stickydirtag *sdtp = entries->list->data;
-
- /* If there is no list private data, that means that the
- subdirectory information is known. */
- if (sdtp != NULL && ! sdtp->subdirs)
- {
- FILE *fp;
-
- sdtp->subdirs = 1;
- if (!noexec)
- {
- /* Create Entries.Log so that Entries_Close will do something. */
- entfilename = CVSADM_ENTLOG;
- fp = CVS_FOPEN (entfilename, "a");
- if (fp == NULL)
- {
- int save_errno = errno;
-
- /* As in subdir_record, just silently skip the whole thing
- if there is no CVSADM directory. */
- if (! isdir (CVSADM))
- return;
- error (1, save_errno, "cannot open %s", entfilename);
- }
- else
- {
- if (fclose (fp) == EOF)
- error (1, errno, "cannot close %s", entfilename);
- }
- }
- }
-}
-
-/* Record subdirectory information. */
-
-static Entnode *
-subdir_record (cmd, parent, dir)
- int cmd;
- const char *parent;
- const char *dir;
-{
- Entnode *entnode;
-
- /* None of the information associated with a directory is
- currently meaningful. */
- entnode = Entnode_Create (ENT_SUBDIR, dir, "", "", "",
- (char *) NULL, (char *) NULL,
- (char *) NULL);
-
- if (!noexec)
- {
- if (parent == NULL)
- entfilename = CVSADM_ENTLOG;
- else
- {
- entfilename = xmalloc (strlen (parent)
- + sizeof CVSADM_ENTLOG
- + 10);
- sprintf (entfilename, "%s/%s", parent, CVSADM_ENTLOG);
- }
-
- entfile = CVS_FOPEN (entfilename, "a");
- if (entfile == NULL)
- {
- int save_errno = errno;
-
- /* It is not an error if there is no CVS administration
- directory. Permitting this case simplifies some
- calling code. */
-
- if (parent == NULL)
- {
- if (! isdir (CVSADM))
- return entnode;
- }
- else
- {
- sprintf (entfilename, "%s/%s", parent, CVSADM);
- if (! isdir (entfilename))
- {
- free (entfilename);
- entfilename = NULL;
- return entnode;
- }
- }
-
- error (1, save_errno, "cannot open %s", entfilename);
- }
-
- if (fprintf (entfile, "%c ", cmd) < 0)
- error (1, errno, "cannot write %s", entfilename);
-
- if (fputentent (entfile, entnode) != 0)
- error (1, errno, "cannot write %s", entfilename);
-
- if (fclose (entfile) == EOF)
- error (1, errno, "error closing %s", entfilename);
-
- if (parent != NULL)
- {
- free (entfilename);
- entfilename = NULL;
- }
- }
-
- return entnode;
-}
-
-/*
- * Record the addition of a new subdirectory DIR in PARENT. PARENT
- * may be NULL, which means the current directory. ENTRIES is the
- * current entries list; it may be NULL, which means that it need not
- * be updated.
- */
-
-void
-Subdir_Register (entries, parent, dir)
- List *entries;
- const char *parent;
- const char *dir;
-{
- Entnode *entnode;
-
- /* Ignore attempts to register ".". These can happen in the
- server code. */
- if (dir[0] == '.' && dir[1] == '\0')
- return;
-
- entnode = subdir_record ('A', parent, dir);
-
- if (entries != NULL && (parent == NULL || strcmp (parent, ".") == 0))
- (void) AddEntryNode (entries, entnode);
- else
- Entnode_Destroy (entnode);
-}
-
-/*
- * Record the removal of a subdirectory. The arguments are the same
- * as for Subdir_Register.
- */
-
-void
-Subdir_Deregister (entries, parent, dir)
- List *entries;
- const char *parent;
- const char *dir;
-{
- Entnode *entnode;
-
- entnode = subdir_record ('R', parent, dir);
- Entnode_Destroy (entnode);
-
- if (entries != NULL && (parent == NULL || strcmp (parent, ".") == 0))
- {
- Node *p;
-
- p = findnode_fn (entries, dir);
- if (p != NULL)
- delnode (p);
- }
-}
-
-
-
-/* OK, the following base_* code tracks the revisions of the files in
- CVS/Base. We do this in a file CVS/Baserev. Separate from
- CVS/Entries because it needs to go in separate data structures
- anyway (the name in Entries must be unique), so this seemed
- cleaner. The business of rewriting the whole file in
- base_deregister and base_register is the kind of thing we used to
- do for Entries and which turned out to be slow, which is why there
- is now the Entries.Log machinery. So maybe from that point of
- view it is a mistake to do this separately from Entries, I dunno.
-
- We also need something analogous for:
-
- 1. CVS/Template (so we can update the Template file automagically
- without the user needing to check out a new working directory).
- Updating would probably print a message (that part might be
- optional, although probably it should be visible because not all
- cvs commands would make the update happen and so it is a
- user-visible behavior). Constructing version number for template
- is a bit hairy (base it on the timestamp on the server? Or see if
- the template is in checkoutlist and if yes use its versioning and
- if no don't version it?)....
-
- 2. cvsignore (need to keep a copy in the working directory to do
- "cvs release" on the client side; see comment at src/release.c
- (release). Would also allow us to stop needing Questionable. */
-
-enum base_walk {
- /* Set the revision for FILE to *REV. */
- BASE_REGISTER,
- /* Get the revision for FILE and put it in a newly malloc'd string
- in *REV, or put NULL if not mentioned. */
- BASE_GET,
- /* Remove FILE. */
- BASE_DEREGISTER
-};
-
-static void base_walk PROTO ((enum base_walk, struct file_info *, char **));
-
-/* Read through the lines in CVS/Baserev, taking the actions as documented
- for CODE. */
-
-static void
-base_walk (code, finfo, rev)
- enum base_walk code;
- struct file_info *finfo;
- char **rev;
-{
- FILE *fp;
- char *line;
- size_t line_allocated;
- FILE *newf;
- char *baserev_fullname;
- char *baserevtmp_fullname;
-
- line = NULL;
- line_allocated = 0;
- newf = NULL;
-
- /* First compute the fullnames for the error messages. This
- computation probably should be broken out into a separate function,
- as recurse.c does it too and places like Entries_Open should be
- doing it. */
- baserev_fullname = xmalloc (sizeof (CVSADM_BASEREV)
- + strlen (finfo->update_dir)
- + 2);
- baserev_fullname[0] = '\0';
- baserevtmp_fullname = xmalloc (sizeof (CVSADM_BASEREVTMP)
- + strlen (finfo->update_dir)
- + 2);
- baserevtmp_fullname[0] = '\0';
- if (finfo->update_dir[0] != '\0')
- {
- strcat (baserev_fullname, finfo->update_dir);
- strcat (baserev_fullname, "/");
- strcat (baserevtmp_fullname, finfo->update_dir);
- strcat (baserevtmp_fullname, "/");
- }
- strcat (baserev_fullname, CVSADM_BASEREV);
- strcat (baserevtmp_fullname, CVSADM_BASEREVTMP);
-
- fp = CVS_FOPEN (CVSADM_BASEREV, "r");
- if (fp == NULL)
- {
- if (!existence_error (errno))
- {
- error (0, errno, "cannot open %s for reading", baserev_fullname);
- goto out;
- }
- }
-
- switch (code)
- {
- case BASE_REGISTER:
- case BASE_DEREGISTER:
- newf = CVS_FOPEN (CVSADM_BASEREVTMP, "w");
- if (newf == NULL)
- {
- error (0, errno, "cannot open %s for writing",
- baserevtmp_fullname);
- goto out;
- }
- break;
- case BASE_GET:
- *rev = NULL;
- break;
- }
-
- if (fp != NULL)
- {
- while (getline (&line, &line_allocated, fp) >= 0)
- {
- char *linefile;
- char *p;
- char *linerev;
-
- if (line[0] != 'B')
- /* Ignore, for future expansion. */
- continue;
-
- linefile = line + 1;
- p = strchr (linefile, '/');
- if (p == NULL)
- /* Syntax error, ignore. */
- continue;
- linerev = p + 1;
- p = strchr (linerev, '/');
- if (p == NULL)
- continue;
-
- linerev[-1] = '\0';
- if (fncmp (linefile, finfo->file) == 0)
- {
- switch (code)
- {
- case BASE_REGISTER:
- case BASE_DEREGISTER:
- /* Don't copy over the old entry, we don't want it. */
- break;
- case BASE_GET:
- *p = '\0';
- *rev = xstrdup (linerev);
- *p = '/';
- goto got_it;
- }
- }
- else
- {
- linerev[-1] = '/';
- switch (code)
- {
- case BASE_REGISTER:
- case BASE_DEREGISTER:
- if (fprintf (newf, "%s\n", line) < 0)
- error (0, errno, "error writing %s",
- baserevtmp_fullname);
- break;
- case BASE_GET:
- break;
- }
- }
- }
- if (ferror (fp))
- error (0, errno, "cannot read %s", baserev_fullname);
- }
- got_it:
-
- if (code == BASE_REGISTER)
- {
- if (fprintf (newf, "B%s/%s/\n", finfo->file, *rev) < 0)
- error (0, errno, "error writing %s",
- baserevtmp_fullname);
- }
-
- out:
-
- if (line != NULL)
- free (line);
-
- if (fp != NULL)
- {
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", baserev_fullname);
- }
- if (newf != NULL)
- {
- if (fclose (newf) < 0)
- error (0, errno, "cannot close %s", baserevtmp_fullname);
- rename_file (CVSADM_BASEREVTMP, CVSADM_BASEREV);
- }
-
- free (baserev_fullname);
- free (baserevtmp_fullname);
-}
-
-/* Return, in a newly malloc'd string, the revision for FILE in CVS/Baserev,
- or NULL if not listed. */
-
-char *
-base_get (finfo)
- struct file_info *finfo;
-{
- char *rev;
- base_walk (BASE_GET, finfo, &rev);
- return rev;
-}
-
-/* Set the revision for FILE to REV. */
-
-void
-base_register (finfo, rev)
- struct file_info *finfo;
- char *rev;
-{
- base_walk (BASE_REGISTER, finfo, &rev);
-}
-
-/* Remove FILE. */
-
-void
-base_deregister (finfo)
- struct file_info *finfo;
-{
- base_walk (BASE_DEREGISTER, finfo, NULL);
-}
diff --git a/contrib/cvs/src/error.c b/contrib/cvs/src/error.c
deleted file mode 100644
index 129ba9bdcf2b..000000000000
--- a/contrib/cvs/src/error.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/* error.c -- error handler for noninteractive utilities
- Copyright (C) 1990-1992 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-/* David MacKenzie */
-/* Brian Berliner added support for CVS */
-
-#include "cvs.h"
-
-#include <stdio.h>
-
-/* If non-zero, error will use the CVS protocol to stdout to report error
- messages. This will only be set in the CVS server parent process;
- most other code is run via do_cvs_command, which forks off a child
- process and packages up its stderr in the protocol. */
-int error_use_protocol;
-
-#ifdef HAVE_VPRINTF
-
-#ifdef __STDC__
-#include <stdarg.h>
-#define VA_START(args, lastarg) va_start(args, lastarg)
-#else /* ! __STDC__ */
-#include <varargs.h>
-#define VA_START(args, lastarg) va_start(args)
-#endif /* __STDC__ */
-
-#else /* ! HAVE_VPRINTF */
-
-#ifdef HAVE_DOPRNT
-#define va_alist args
-#define va_dcl int args;
-#else /* ! HAVE_DOPRNT */
-#define va_alist a1, a2, a3, a4, a5, a6, a7, a8
-#define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
-#endif /* HAVE_DOPRNT */
-
-#endif /* HAVE_VPRINTF */
-
-#if STDC_HEADERS
-#include <stdlib.h>
-#include <string.h>
-#else /* ! STDC_HEADERS */
-#ifdef __STDC__
-void exit(int status);
-#else /* ! __STDC__ */
-void exit ();
-#endif /* __STDC__ */
-#endif /* STDC_HEADERS */
-
-#ifndef strerror
-extern char *strerror ();
-#endif
-
-void
-error_exit PROTO ((void))
-{
- rcs_cleanup ();
- Lock_Cleanup ();
-#ifdef SERVER_SUPPORT
- if (server_active)
- server_cleanup (0);
-#endif
-#ifdef SYSTEM_CLEANUP
- /* Hook for OS-specific behavior, for example socket subsystems on
- NT and OS2 or dealing with windows and arguments on Mac. */
- SYSTEM_CLEANUP ();
-#endif
- exit (EXIT_FAILURE);
-}
-
-/* Print the program name and error message MESSAGE, which is a printf-style
- 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.
-
- I think this is largely cleaned up to the point where it does the right
- thing for the server, whether the normal server_active (child process)
- case or the error_use_protocol (parent process) case. The one exception
- is that STATUS nonzero for error_use_protocol probably doesn't work yet;
- in that case still need to use the pending_error machinery in server.c.
-
- error() does not molest errno; some code (e.g. Entries_Open) depends
- on being able to say something like:
- error (0, 0, "foo");
- error (0, errno, "bar");
-
- */
-
-/* VARARGS */
-void
-#if defined (__STDC__)
-error (int status, int errnum, const char *message, ...)
-#else
-error (status, errnum, message, va_alist)
- int status;
- int errnum;
- const char *message;
- va_dcl
-#endif
-{
- int save_errno = errno;
-
- if (message[0] != '\0')
- {
- va_list args;
- const char *p;
- char *q;
- char *str;
- int num;
- long lnum;
- unsigned int unum;
- unsigned long ulnum;
- int ch;
- char buf[100];
-
- cvs_outerr (program_name, 0);
- if (cvs_cmd_name && *cvs_cmd_name)
- {
- cvs_outerr (" ", 1);
- if (status != 0)
- cvs_outerr ("[", 1);
- cvs_outerr (cvs_cmd_name, 0);
- if (status != 0)
- cvs_outerr (" aborted]", 0);
- }
- cvs_outerr (": ", 2);
-
- VA_START (args, message);
- p = message;
- while ((q = strchr (p, '%')) != NULL)
- {
- static const char msg[] =
- "\ninternal error: bad % in error()\n";
- if (q - p > 0)
- cvs_outerr (p, q - p);
-
- switch (q[1])
- {
- 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 'l':
- if (q[2] == 'd')
- {
- lnum = va_arg (args, long);
- sprintf (buf, "%ld", lnum);
- }
- else if (q[2] == 'u')
- {
- ulnum = va_arg (args, unsigned long);
- sprintf (buf, "%lu", ulnum);
- }
- else goto bad;
- cvs_outerr (buf, strlen (buf));
- q++;
- 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:
- bad:
- 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 (p, strlen (p));
- out:
- va_end (args);
-
- if (errnum != 0)
- {
- cvs_outerr (": ", 2);
- cvs_outerr (strerror (errnum), 0);
- }
- cvs_outerr ("\n", 1);
- }
-
- if (status)
- error_exit ();
- errno = save_errno;
-}
-
-/* Print the program name and error message MESSAGE, which is a printf-style
- format string with optional args to the file specified by FP.
- If ERRNUM is nonzero, print its corresponding system error message.
- Exit with status EXIT_FAILURE if STATUS is nonzero. */
-/* VARARGS */
-void
-#if defined (HAVE_VPRINTF) && defined (__STDC__)
-fperrmsg (FILE *fp, int status, int errnum, char *message, ...)
-#else
-fperrmsg (fp, status, errnum, message, va_alist)
- FILE *fp;
- int status;
- int errnum;
- char *message;
- va_dcl
-#endif
-{
-#ifdef HAVE_VPRINTF
- va_list args;
-#endif
-
- fprintf (fp, "%s: ", program_name);
-#ifdef HAVE_VPRINTF
- VA_START (args, message);
- vfprintf (fp, message, args);
- va_end (args);
-#else
-#ifdef HAVE_DOPRNT
- _doprnt (message, &args, fp);
-#else
- fprintf (fp, message, a1, a2, a3, a4, a5, a6, a7, a8);
-#endif
-#endif
- if (errnum)
- fprintf (fp, ": %s", strerror (errnum));
- putc ('\n', fp);
- fflush (fp);
- if (status)
- error_exit ();
-}
diff --git a/contrib/cvs/src/error.h b/contrib/cvs/src/error.h
deleted file mode 100644
index 1c8471d54ada..000000000000
--- a/contrib/cvs/src/error.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* error.h -- declaration for error-reporting function
- Copyright (C) 1995 Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-#ifndef ERROR_H
-#define ERROR_H
-
-/* Add prototype support. Normally this is done in cvs.h, but that
- doesn't get included from lib/savecwd.c. */
-#ifndef PROTO
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define PROTO(ARGS) ARGS
-#else
-#define PROTO(ARGS) ()
-#endif
-#endif
-
-#ifndef __attribute__
-/* This feature is available in gcc versions 2.5 and later. */
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
-# define __attribute__(Spec) /* empty */
-# endif
-/* The __-protected variants of `format' and `printf' attributes
- are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
-# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
-# define __format__ format
-# define __printf__ printf
-# define __noreturn__ noreturn
-# endif
-#endif
-
-#ifdef __STDC__
-void error (int, int, const char *, ...) \
- __attribute__ ((__format__ (__printf__, 3, 4)));
-#else
-void error ();
-#endif
-
-/* Exit due to an error. Similar to error (1, 0, "message"), but call
- it in the case where the message has already been printed. */
-#ifdef __STDC__
-void error_exit (void) __attribute__ ((__noreturn__));
-#else
-void error_exit ();
-#endif
-
-/* If non-zero, error will use the CVS protocol to report error
- messages. This will only be set in the CVS server parent process;
- most other code is run via do_cvs_command, which forks off a child
- process and packages up its stderr in the protocol. */
-extern int error_use_protocol;
-
-#endif /* ERROR_H */
diff --git a/contrib/cvs/src/expand_path.c b/contrib/cvs/src/expand_path.c
deleted file mode 100644
index 1c960f343992..000000000000
--- a/contrib/cvs/src/expand_path.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/* expand_path.c -- expand environmental variables in passed in string
- *
- * Copyright (C) 1995-2005 The Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * The main routine is expand_path(), it is the routine that handles
- * the '~' character in four forms:
- * ~name
- * ~name/
- * ~/
- * ~
- * and handles environment variables contained within the pathname
- * which are defined by:
- * ${var_name} (var_name is the name of the environ variable)
- * $var_name (var_name ends w/ non-alphanumeric char other than '_')
- */
-
-#include "cvs.h"
-#include <sys/types.h>
-
-static char *expand_variable PROTO((const char *env, const char *file,
- int line));
-
-
-
-/* User variables. */
-
-List *variable_list = NULL;
-
-static void variable_delproc PROTO ((Node *));
-
-static void
-variable_delproc (node)
- Node *node;
-{
- free (node->data);
-}
-
-/* Currently used by -s option; we might want a way to set user
- variables in a file in the $CVSROOT/CVSROOT directory too. */
-
-void
-variable_set (nameval)
- char *nameval;
-{
- char *p;
- char *name;
- Node *node;
-
- p = nameval;
- while (isalnum ((unsigned char) *p) || *p == '_')
- ++p;
- if (*p != '=')
- error (1, 0, "illegal character in user variable name in %s", nameval);
- if (p == nameval)
- error (1, 0, "empty user variable name in %s", nameval);
- name = xmalloc (p - nameval + 1);
- strncpy (name, nameval, p - nameval);
- name[p - nameval] = '\0';
- /* Make p point to the value. */
- ++p;
- if (strchr (p, '\012') != NULL)
- error (1, 0, "linefeed in user variable value in %s", nameval);
-
- if (variable_list == NULL)
- variable_list = getlist ();
-
- node = findnode (variable_list, name);
- if (node == NULL)
- {
- node = getnode ();
- node->type = VARIABLE;
- node->delproc = variable_delproc;
- node->key = name;
- node->data = xstrdup (p);
- (void) addnode (variable_list, node);
- }
- else
- {
- /* Replace the old value. For example, this means that -s
- options on the command line override ones from .cvsrc. */
- free (node->data);
- node->data = xstrdup (p);
- free (name);
- }
-}
-
-
-
-/* This routine will expand the pathname to account for ~ and $
- characters as described above. Returns a pointer to a newly
- malloc'd string. If an error occurs, an error message is printed
- via error() and NULL is returned. FILE and LINE are the filename
- and linenumber to include in the error message. FILE must point
- to something; LINE can be zero to indicate the line number is not
- known. */
-char *
-expand_path (name, file, line)
- const char *name;
- const char *file;
- int line;
-{
- size_t s, d, p;
- char *e;
-
- char *mybuf = NULL;
- size_t mybuf_size = 0;
- char *buf = NULL;
- size_t buf_size = 0;
-
- char *result;
-
- /* Sorry this routine is so ugly; it is a head-on collision
- between the `traditional' unix *d++ style and the need to
- dynamically allocate. It would be much cleaner (and probably
- faster, not that this is a bottleneck for CVS) with more use of
- strcpy & friends, but I haven't taken the effort to rewrite it
- thusly. */
-
- /* First copy from NAME to MYBUF, expanding $<foo> as we go. */
- s = d = 0;
- while (name[s] != '\0')
- {
- if (name[s] == '$')
- {
- p = d;
- if (name[++s] == '{')
- {
- while (name[++s] != '}' && name[s] != '\0')
- {
- expand_string (&mybuf, &mybuf_size, p + 1);
- mybuf[p++] = name[s];
- }
- if (name[s] != '\0') ++s;
- }
- else
- {
- while (isalnum ((unsigned char) name[s]) || name[s] == '_')
- {
- expand_string (&mybuf, &mybuf_size, p + 1);
- mybuf[p++] = name[s++];
- }
- }
- expand_string (&mybuf, &mybuf_size, p + 1);
- mybuf[p] = '\0';
- e = expand_variable (mybuf + d, file, line);
-
- if (e)
- {
- p = strlen(e);
- expand_string (&mybuf, &mybuf_size, d + p);
- memcpy(mybuf + d, e, p);
- d += p;
- }
- else
- /* expand_variable has already printed an error message. */
- goto error_exit;
- }
- else
- {
- expand_string (&mybuf, &mybuf_size, d + 1);
- mybuf[d++] = name[s++];
- }
- }
- expand_string (&mybuf, &mybuf_size, d + 1);
- mybuf[d++] = '\0';
-
- /* Then copy from MYBUF to BUF, expanding ~. */
- s = d = 0;
- /* If you don't want ~username ~/ to be expanded simply remove
- * This entire if statement including the else portion
- */
- if (mybuf[s] == '~')
- {
- p = d;
- while (mybuf[++s] != '/' && mybuf[s] != '\0')
- {
- expand_string (&buf, &buf_size, p + 1);
- buf[p++] = name[s];
- }
- expand_string (&buf, &buf_size, p + 1);
- buf[p] = '\0';
-
- if (p == d)
- e = get_homedir ();
- else
- {
-#ifdef GETPWNAM_MISSING
- if (line != 0)
- error (0, 0,
- "%s:%d:tilde expansion not supported on this system",
- file, line);
- else
- error (0, 0, "%s:tilde expansion not supported on this system",
- file);
- goto error_exit;
-#else
- struct passwd *ps;
- ps = getpwnam (buf + d);
- if (ps == NULL)
- {
- if (line != 0)
- error (0, 0, "%s:%d: no such user %s",
- file, line, buf + d);
- else
- error (0, 0, "%s: no such user %s", file, buf + d);
- goto error_exit;
- }
- e = ps->pw_dir;
-#endif
- }
- if (e == NULL)
- error (1, 0, "cannot find home directory");
-
- p = strlen(e);
- expand_string (&buf, &buf_size, d + p);
- memcpy(buf + d, e, p);
- d += p;
- }
- /* Kill up to here */
- p = strlen(mybuf + s) + 1;
- expand_string (&buf, &buf_size, d + p);
- memcpy(buf + d, mybuf + s, p);
-
- /* OK, buf contains the value we want to return. Clean up and return
- it. */
- free (mybuf);
- /* Save a little memory with xstrdup; buf will tend to allocate
- more than it needs to. */
- result = xstrdup (buf);
- free (buf);
- return result;
-
- error_exit:
- if (mybuf != NULL)
- free (mybuf);
- if (buf != NULL)
- free (buf);
- return NULL;
-}
-
-static char *
-expand_variable (name, file, line)
- const char *name;
- const char *file;
- int line;
-{
- if (strcmp (name, CVSROOT_ENV) == 0)
- return current_parsed_root->directory;
- else if (strcmp (name, "RCSBIN") == 0)
- {
- error (0, 0, "RCSBIN internal variable is no longer supported");
- return NULL;
- }
- else if (strcmp (name, EDITOR1_ENV) == 0)
- return Editor;
- else if (strcmp (name, EDITOR2_ENV) == 0)
- return Editor;
- else if (strcmp (name, EDITOR3_ENV) == 0)
- return Editor;
- else if (strcmp (name, "USER") == 0)
- return getcaller ();
- else if (isalpha ((unsigned char) name[0]))
- {
- /* These names are reserved for future versions of CVS,
- so that is why it is an error. */
- if (line != 0)
- error (0, 0, "%s:%d: no such internal variable $%s",
- file, line, name);
- else
- error (0, 0, "%s: no such internal variable $%s",
- file, name);
- return NULL;
- }
- else if (name[0] == '=')
- {
- Node *node;
- /* Crazy syntax for a user variable. But we want
- *something* that lets the user name a user variable
- anything he wants, without interference from
- (existing or future) internal variables. */
- node = findnode (variable_list, name + 1);
- if (node == NULL)
- {
- if (line != 0)
- error (0, 0, "%s:%d: no such user variable ${%s}",
- file, line, name);
- else
- error (0, 0, "%s: no such user variable ${%s}",
- file, name);
- return NULL;
- }
- return node->data;
- }
- else
- {
- /* It is an unrecognized character. We return an error to
- reserve these for future versions of CVS; it is plausible
- that various crazy syntaxes might be invented for inserting
- information about revisions, branches, etc. */
- if (line != 0)
- error (0, 0, "%s:%d: unrecognized variable syntax %s",
- file, line, name);
- else
- error (0, 0, "%s: unrecognized variable syntax %s",
- file, name);
- return NULL;
- }
-}
diff --git a/contrib/cvs/src/fileattr.c b/contrib/cvs/src/fileattr.c
deleted file mode 100644
index ca6bd0eb478b..000000000000
--- a/contrib/cvs/src/fileattr.c
+++ /dev/null
@@ -1,656 +0,0 @@
-/* Implementation for file attribute munging features.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-#include "cvs.h"
-#include "getline.h"
-#include "fileattr.h"
-#include <assert.h>
-
-static void fileattr_read PROTO ((void));
-static int writeattr_proc PROTO ((Node *, void *));
-
-/* Where to look for CVSREP_FILEATTR. */
-static char *fileattr_stored_repos;
-
-/* The in-memory attributes. */
-static List *attrlist;
-static char *fileattr_default_attrs;
-/* We have already tried to read attributes and failed in this directory
- (for example, there is no CVSREP_FILEATTR file). */
-static int attr_read_attempted;
-
-/* Have the in-memory attributes been modified since we read them? */
-static int attrs_modified;
-
-/* More in-memory attributes: linked list of unrecognized
- fileattr lines. We pass these on unchanged. */
-struct unrecog {
- char *line;
- struct unrecog *next;
-};
-static struct unrecog *unrecog_head;
-
-/* Note that if noone calls fileattr_get, this is very cheap. No stat(),
- no open(), no nothing. */
-void
-fileattr_startdir (repos)
- const char *repos;
-{
- assert (fileattr_stored_repos == NULL);
- fileattr_stored_repos = xstrdup (repos);
- assert (attrlist == NULL);
- attr_read_attempted = 0;
- assert (unrecog_head == NULL);
-}
-
-static void
-fileattr_delproc (node)
- Node *node;
-{
- assert (node->data != NULL);
- free (node->data);
- node->data = NULL;
-}
-
-/* Read all the attributes for the current directory into memory. */
-static void
-fileattr_read ()
-{
- char *fname;
- FILE *fp;
- char *line = NULL;
- size_t line_len = 0;
-
- /* If there are no attributes, don't waste time repeatedly looking
- for the CVSREP_FILEATTR file. */
- if (attr_read_attempted)
- return;
-
- /* If NULL was passed to fileattr_startdir, then it isn't kosher to look
- at attributes. */
- assert (fileattr_stored_repos != NULL);
-
- fname = xmalloc (strlen (fileattr_stored_repos)
- + 1
- + sizeof (CVSREP_FILEATTR)
- + 1);
-
- strcpy (fname, fileattr_stored_repos);
- strcat (fname, "/");
- strcat (fname, CVSREP_FILEATTR);
-
- attr_read_attempted = 1;
- fp = CVS_FOPEN (fname, FOPEN_BINARY_READ);
- if (fp == NULL)
- {
- if (!existence_error (errno))
- error (0, errno, "cannot read %s", fname);
- free (fname);
- return;
- }
- attrlist = getlist ();
- while (1) {
- int nread;
- nread = getline (&line, &line_len, fp);
- if (nread < 0)
- break;
- /* Remove trailing newline. */
- line[nread - 1] = '\0';
- if (line[0] == 'F')
- {
- char *p;
- Node *newnode;
-
- p = strchr (line, '\t');
- if (p == NULL)
- error (1, 0,
- "file attribute database corruption: tab missing in %s",
- fname);
- *p++ = '\0';
- newnode = getnode ();
- newnode->type = FILEATTR;
- newnode->delproc = fileattr_delproc;
- newnode->key = xstrdup (line + 1);
- newnode->data = xstrdup (p);
- if (addnode (attrlist, newnode) != 0)
- /* If the same filename appears twice in the file, discard
- any line other than the first for that filename. This
- is the way that CVS has behaved since file attributes
- were first introduced. */
- freenode (newnode);
- }
- else if (line[0] == 'D')
- {
- char *p;
- /* Currently nothing to skip here, but for future expansion,
- ignore anything located here. */
- p = strchr (line, '\t');
- if (p == NULL)
- error (1, 0,
- "file attribute database corruption: tab missing in %s",
- fname);
- ++p;
- if (fileattr_default_attrs) free (fileattr_default_attrs);
- fileattr_default_attrs = xstrdup (p);
- }
- else
- {
- /* Unrecognized type, we want to just preserve the line without
- changing it, for future expansion. */
- struct unrecog *new;
-
- new = (struct unrecog *) xmalloc (sizeof (struct unrecog));
- new->line = xstrdup (line);
- new->next = unrecog_head;
- unrecog_head = new;
- }
- }
- if (ferror (fp))
- error (0, errno, "cannot read %s", fname);
- if (line != NULL)
- free (line);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", fname);
- attrs_modified = 0;
- free (fname);
-}
-
-char *
-fileattr_get (filename, attrname)
- const char *filename;
- const char *attrname;
-{
- Node *node;
- size_t attrname_len = strlen (attrname);
- char *p;
-
- if (attrlist == NULL)
- fileattr_read ();
- if (attrlist == NULL)
- /* Either nothing has any attributes, or fileattr_read already printed
- an error message. */
- return NULL;
-
- if (filename == NULL)
- p = fileattr_default_attrs;
- else
- {
- node = findnode (attrlist, filename);
- if (node == NULL)
- /* A file not mentioned has no attributes. */
- return NULL;
- p = node->data;
- }
- while (p)
- {
- if (strncmp (attrname, p, attrname_len) == 0
- && p[attrname_len] == '=')
- {
- /* Found it. */
- return p + attrname_len + 1;
- }
- p = strchr (p, ';');
- if (p == NULL)
- break;
- ++p;
- }
- /* The file doesn't have this attribute. */
- return NULL;
-}
-
-char *
-fileattr_get0 (filename, attrname)
- const char *filename;
- const char *attrname;
-{
- char *cp;
- char *cpend;
- char *retval;
-
- cp = fileattr_get (filename, attrname);
- if (cp == NULL)
- return NULL;
- cpend = strchr (cp, ';');
- if (cpend == NULL)
- cpend = cp + strlen (cp);
- retval = xmalloc (cpend - cp + 1);
- strncpy (retval, cp, cpend - cp);
- retval[cpend - cp] = '\0';
- return retval;
-}
-
-char *
-fileattr_modify (list, attrname, attrval, namevalsep, entsep)
- char *list;
- const char *attrname;
- const char *attrval;
- int namevalsep;
- int entsep;
-{
- char *retval;
- char *rp;
- size_t attrname_len = strlen (attrname);
-
- /* Portion of list before the attribute to be replaced. */
- char *pre;
- char *preend;
- /* Portion of list after the attribute to be replaced. */
- char *post;
-
- char *p;
- char *p2;
-
- p = list;
- pre = list;
- preend = NULL;
- /* post is NULL unless set otherwise. */
- post = NULL;
- p2 = NULL;
- if (list != NULL)
- {
- while (1) {
- p2 = strchr (p, entsep);
- if (p2 == NULL)
- {
- p2 = p + strlen (p);
- if (preend == NULL)
- preend = p2;
- }
- else
- ++p2;
- if (strncmp (attrname, p, attrname_len) == 0
- && p[attrname_len] == namevalsep)
- {
- /* Found it. */
- preend = p;
- if (preend > list)
- /* Don't include the preceding entsep. */
- --preend;
-
- post = p2;
- }
- if (p2[0] == '\0')
- break;
- p = p2;
- }
- }
- if (post == NULL)
- post = p2;
-
- if (preend == pre && attrval == NULL && post == p2)
- return NULL;
-
- retval = xmalloc ((preend - pre)
- + 1
- + (attrval == NULL ? 0 : (attrname_len + 1
- + strlen (attrval)))
- + 1
- + (p2 - post)
- + 1);
- if (preend != pre)
- {
- strncpy (retval, pre, preend - pre);
- rp = retval + (preend - pre);
- if (attrval != NULL)
- *rp++ = entsep;
- *rp = '\0';
- }
- else
- retval[0] = '\0';
- if (attrval != NULL)
- {
- strcat (retval, attrname);
- rp = retval + strlen (retval);
- *rp++ = namevalsep;
- strcpy (rp, attrval);
- }
- if (post != p2)
- {
- rp = retval + strlen (retval);
- if (preend != pre || attrval != NULL)
- *rp++ = entsep;
- strncpy (rp, post, p2 - post);
- rp += p2 - post;
- *rp = '\0';
- }
- return retval;
-}
-
-void
-fileattr_set (filename, attrname, attrval)
- const char *filename;
- const char *attrname;
- const char *attrval;
-{
- Node *node;
- char *p;
-
- if (filename == NULL)
- {
- p = fileattr_modify (fileattr_default_attrs, attrname, attrval,
- '=', ';');
- if (fileattr_default_attrs != NULL)
- free (fileattr_default_attrs);
- fileattr_default_attrs = p;
- attrs_modified = 1;
- return;
- }
- if (attrlist == NULL)
- fileattr_read ();
- if (attrlist == NULL)
- {
- /* Not sure this is a graceful way to handle things
- in the case where fileattr_read was unable to read the file. */
- /* No attributes existed previously. */
- attrlist = getlist ();
- }
-
- node = findnode (attrlist, filename);
- if (node == NULL)
- {
- if (attrval == NULL)
- /* Attempt to remove an attribute which wasn't there. */
- return;
-
- /* First attribute for this file. */
- node = getnode ();
- node->type = FILEATTR;
- node->delproc = fileattr_delproc;
- node->key = xstrdup (filename);
- node->data = xmalloc (strlen (attrname) + 1 + strlen (attrval) + 1);
- strcpy (node->data, attrname);
- strcat (node->data, "=");
- strcat (node->data, attrval);
- addnode (attrlist, node);
- }
-
- p = fileattr_modify (node->data, attrname, attrval, '=', ';');
- if (p == NULL)
- delnode (node);
- else
- {
- free (node->data);
- node->data = p;
- }
-
- attrs_modified = 1;
-}
-
-char *
-fileattr_getall (filename)
- const char *filename;
-{
- Node *node;
- char *p;
-
- if (attrlist == NULL)
- fileattr_read ();
- if (attrlist == NULL)
- /* Either nothing has any attributes, or fileattr_read already printed
- an error message. */
- return NULL;
-
- if (filename == NULL)
- p = fileattr_default_attrs;
- else
- {
- node = findnode (attrlist, filename);
- if (node == NULL)
- /* A file not mentioned has no attributes. */
- return NULL;
- p = node->data;
- }
- return xstrdup (p);
-}
-
-void
-fileattr_setall (filename, attrs)
- const char *filename;
- const char *attrs;
-{
- Node *node;
-
- if (filename == NULL)
- {
- if (fileattr_default_attrs != NULL)
- free (fileattr_default_attrs);
- fileattr_default_attrs = xstrdup (attrs);
- attrs_modified = 1;
- return;
- }
- if (attrlist == NULL)
- fileattr_read ();
- if (attrlist == NULL)
- {
- /* Not sure this is a graceful way to handle things
- in the case where fileattr_read was unable to read the file. */
- /* No attributes existed previously. */
- attrlist = getlist ();
- }
-
- node = findnode (attrlist, filename);
- if (node == NULL)
- {
- /* The file had no attributes. Add them if we have any to add. */
- if (attrs != NULL)
- {
- node = getnode ();
- node->type = FILEATTR;
- node->delproc = fileattr_delproc;
- node->key = xstrdup (filename);
- node->data = xstrdup (attrs);
- addnode (attrlist, node);
- }
- }
- else
- {
- if (attrs == NULL)
- delnode (node);
- else
- {
- free (node->data);
- node->data = xstrdup (attrs);
- }
- }
-
- attrs_modified = 1;
-}
-
-void
-fileattr_newfile (filename)
- const char *filename;
-{
- Node *node;
-
- if (attrlist == NULL)
- fileattr_read ();
-
- if (fileattr_default_attrs == NULL)
- return;
-
- if (attrlist == NULL)
- {
- /* Not sure this is a graceful way to handle things
- in the case where fileattr_read was unable to read the file. */
- /* No attributes existed previously. */
- attrlist = getlist ();
- }
-
- node = getnode ();
- node->type = FILEATTR;
- node->delproc = fileattr_delproc;
- node->key = xstrdup (filename);
- node->data = xstrdup (fileattr_default_attrs);
- addnode (attrlist, node);
- attrs_modified = 1;
-}
-
-static int
-writeattr_proc (node, data)
- Node *node;
- void *data;
-{
- FILE *fp = (FILE *)data;
- fputs ("F", fp);
- fputs (node->key, fp);
- fputs ("\t", fp);
- fputs (node->data, fp);
- fputs ("\012", fp);
- return 0;
-}
-
-void
-fileattr_write ()
-{
- FILE *fp;
- char *fname;
- mode_t omask;
- struct unrecog *p;
-
- if (!attrs_modified)
- return;
-
- if (noexec)
- return;
-
- /* If NULL was passed to fileattr_startdir, then it isn't kosher to set
- attributes. */
- assert (fileattr_stored_repos != NULL);
-
- fname = xmalloc (strlen (fileattr_stored_repos)
- + 1
- + sizeof (CVSREP_FILEATTR)
- + 1);
-
- strcpy (fname, fileattr_stored_repos);
- strcat (fname, "/");
- strcat (fname, CVSREP_FILEATTR);
-
- if (list_isempty (attrlist)
- && fileattr_default_attrs == NULL
- && unrecog_head == NULL)
- {
- /* There are no attributes. */
- if (unlink_file (fname) < 0)
- {
- if (!existence_error (errno))
- {
- error (0, errno, "cannot remove %s", fname);
- }
- }
-
- /* Now remove CVSREP directory, if empty. The main reason we bother
- is that CVS 1.6 and earlier will choke if a CVSREP directory
- exists, so provide the user a graceful way to remove it. */
- strcpy (fname, fileattr_stored_repos);
- strcat (fname, "/");
- strcat (fname, CVSREP);
- if (CVS_RMDIR (fname) < 0)
- {
- if (errno != ENOTEMPTY
-
- /* Don't know why we would be here if there is no CVSREP
- directory, but it seemed to be happening anyway, so
- check for it. */
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", fname);
- }
-
- free (fname);
- return;
- }
-
- omask = umask (cvsumask);
- fp = CVS_FOPEN (fname, FOPEN_BINARY_WRITE);
- if (fp == NULL)
- {
- if (existence_error (errno))
- {
- /* Maybe the CVSREP directory doesn't exist. Try creating it. */
- char *repname;
-
- repname = xmalloc (strlen (fileattr_stored_repos)
- + 1
- + sizeof (CVSREP)
- + 1);
- strcpy (repname, fileattr_stored_repos);
- strcat (repname, "/");
- strcat (repname, CVSREP);
-
- if (CVS_MKDIR (repname, 0777) < 0 && errno != EEXIST)
- {
- error (0, errno, "cannot make directory %s", repname);
- (void) umask (omask);
- free (fname);
- free (repname);
- return;
- }
- free (repname);
-
- fp = CVS_FOPEN (fname, FOPEN_BINARY_WRITE);
- }
- if (fp == NULL)
- {
- error (0, errno, "cannot write %s", fname);
- (void) umask (omask);
- free (fname);
- return;
- }
- }
- (void) umask (omask);
-
- /* First write the "F" attributes. */
- walklist (attrlist, writeattr_proc, fp);
-
- /* Then the "D" attribute. */
- if (fileattr_default_attrs != NULL)
- {
- fputs ("D\t", fp);
- fputs (fileattr_default_attrs, fp);
- fputs ("\012", fp);
- }
-
- /* Then any other attributes. */
- for (p = unrecog_head; p != NULL; p = p->next)
- {
- fputs (p->line, fp);
- fputs ("\012", fp);
- }
-
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", fname);
- attrs_modified = 0;
- free (fname);
-}
-
-void
-fileattr_free ()
-{
- /* Note that attrs_modified will ordinarily be zero, but there are
- a few cases in which fileattr_write will fail to zero it (if
- noexec is set, or error conditions). This probably is the way
- it should be. */
- dellist (&attrlist);
- if (fileattr_stored_repos != NULL)
- free (fileattr_stored_repos);
- fileattr_stored_repos = NULL;
- if (fileattr_default_attrs != NULL)
- free (fileattr_default_attrs);
- fileattr_default_attrs = NULL;
- while (unrecog_head)
- {
- struct unrecog *p = unrecog_head;
- unrecog_head = p->next;
- free (p->line);
- free (p);
- }
-}
diff --git a/contrib/cvs/src/fileattr.h b/contrib/cvs/src/fileattr.h
deleted file mode 100644
index 507807c147d2..000000000000
--- a/contrib/cvs/src/fileattr.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Declarations for file attribute munging features.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-#ifndef FILEATTR_H
-
-/* 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.
-
- ENT-TYPE is 'D', and FILENAME empty, for default attributes.
-
- 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.
-
- 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
- (or will be, once we add commands to manipulate user-defined attributes).
-
- Builtin attributes:
-
- _watched: Present means the file is watched and should be checked out
- read-only.
-
- _watchers: Users with watches for this file. Value is
- WATCHER > TYPE { , WATCHER > TYPE }
- where WATCHER is a username, and TYPE is edit,unedit,commit separated by
- + (or nothing if none; there is no "none" or "all" keyword).
-
- _editors: Users editing this file. Value is
- EDITOR > VAL { , EDITOR > VAL }
- where EDITOR is a username, and VAL is TIME+HOSTNAME+PATHNAME, where
- TIME is when the "cvs edit" command happened,
- and HOSTNAME and PATHNAME are for the working directory. */
-
-#define CVSREP_FILEATTR "CVS/fileattr"
-
-/* Prepare for a new directory with repository REPOS. If REPOS is NULL,
- then prepare for a "non-directory"; the caller can call fileattr_write
- and fileattr_free, but must not call fileattr_get or fileattr_set. */
-extern void fileattr_startdir PROTO ((const char *repos));
-
-/* Get the attribute ATTRNAME for file FILENAME. The return value
- points into memory managed by the fileattr_* routines, should not
- be altered by the caller, and is only good until the next call to
- fileattr_clear or fileattr_set. It points to the value, terminated
- by '\0' or ';'. Return NULL if said file lacks said attribute.
- If FILENAME is NULL, return default attributes (attributes for
- files created in the future). */
-extern char *fileattr_get PROTO ((const char *filename, const char *attrname));
-
-/* Like fileattr_get, but return a pointer to a newly malloc'd string
- terminated by '\0' (or NULL if said file lacks said attribute). */
-extern char *fileattr_get0 PROTO ((const char *filename,
- const char *attrname));
-
-/* This is just a string manipulation function; it does not manipulate
- file attributes as such.
-
- LIST is in the format
-
- ATTRNAME NAMEVALSEP ATTRVAL {ENTSEP ATTRNAME NAMEVALSEP ATTRVAL}
-
- And we want to put in an attribute with name NAME and value VAL,
- replacing the already-present attribute with name NAME if there is
- one. Or if VAL is NULL remove attribute NAME. Return a new
- malloc'd list; don't muck with the one passed in. If we are removing
- the last attribute return NULL. LIST can be NULL to mean that we
- started out without any attributes.
-
- Examples:
-
- fileattr_modify ("abc=def", "xxx", "val", '=', ';')) => "abc=def;xxx=val"
- fileattr_modify ("abc=def", "abc", "val", '=', ';')) => "abc=val"
- fileattr_modify ("abc=v1;def=v2", "abc", "val", '=', ';'))
- => "abc=val;def=v2"
- fileattr_modify ("abc=v1;def=v2", "def", "val", '=', ';'))
- => "abc=v1;def=val"
- fileattr_modify ("abc=v1;def=v2", "xxx", "val", '=', ';'))
- => "abc=v1;def=v2;xxx=val"
- fileattr_modify ("abc=v1;def=v2;ghi=v3", "def", "val", '=', ';'))
- => "abc=v1;def=val;ghi=v3"
-*/
-
-extern char *fileattr_modify PROTO ((char *list, const char *attrname,
- const char *attrval, int namevalsep,
- int entsep));
-
-/* Set attribute ATTRNAME for file FILENAME to ATTRVAL. If ATTRVAL is NULL,
- the attribute is removed. Changes are not written to disk until the
- next call to fileattr_write. If FILENAME is NULL, set attributes for
- files created in the future. If ATTRVAL is NULL, remove that attribute. */
-extern void fileattr_set PROTO ((const char *filename, const char *attrname,
- const char *attrval));
-
-/* Get all the attributes for file FILENAME. They are returned as malloc'd
- data in an unspecified format which is guaranteed only to be good for
- passing to fileattr_setall, or NULL if no attributes. If FILENAME is
- NULL, get default attributes. */
-extern char *fileattr_getall PROTO ((const char *filename));
-
-/* Set the attributes for file FILENAME to ATTRS, overwriting all previous
- attributes for that file. ATTRS was obtained from a previous call to
- fileattr_getall (malloc'd data or NULL). */
-extern void fileattr_setall PROTO ((const char *filename, const char *attrs));
-
-/* Set the attributes for file FILENAME in whatever manner is appropriate
- for a newly created file. */
-extern void fileattr_newfile PROTO ((const char *filename));
-
-/* Write out all modified attributes. */
-extern void fileattr_write PROTO ((void));
-
-/* Free all memory allocated by fileattr_*. */
-extern void fileattr_free PROTO ((void));
-
-#define FILEATTR_H 1
-#endif /* fileattr.h */
diff --git a/contrib/cvs/src/filesubr.c b/contrib/cvs/src/filesubr.c
deleted file mode 100644
index 1e1f90101522..000000000000
--- a/contrib/cvs/src/filesubr.c
+++ /dev/null
@@ -1,1100 +0,0 @@
-/* filesubr.c --- subroutines for dealing with files
- Jim Blandy <jimb@cyclic.com>
-
- This file is part of GNU CVS.
-
- GNU CVS is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-/* These functions were moved out of subr.c because they need different
- definitions under operating systems (like, say, Windows NT) with different
- file system semantics. */
-
-#include <assert.h>
-#include "cvs.h"
-
-#include "xsize.h"
-
-static int deep_remove_dir PROTO((const char *path));
-
-/*
- * Copies "from" to "to".
- */
-void
-copy_file (from, to)
- const char *from;
- const char *to;
-{
- struct stat sb;
- struct utimbuf t;
- int fdin, fdout;
-
- if (trace)
- (void) fprintf (stderr, "%s-> copy(%s,%s)\n",
- CLIENT_SERVER_STR, from, to);
- if (noexec)
- return;
-
- /* If the file to be copied is a link or a device, then just create
- the new link or device appropriately. */
- if (islink (from))
- {
- char *source = xreadlink (from);
- symlink (source, to);
- free (source);
- return;
- }
-
- if (isdevice (from))
- {
-#if defined(HAVE_MKNOD) && defined(HAVE_STRUCT_STAT_ST_RDEV)
- if (stat (from, &sb) < 0)
- error (1, errno, "cannot stat %s", from);
- mknod (to, sb.st_mode, sb.st_rdev);
-#else
- error (1, 0, "cannot copy device files on this system (%s)", from);
-#endif
- }
- else
- {
- /* Not a link or a device... probably a regular file. */
- if ((fdin = open (from, O_RDONLY)) < 0)
- error (1, errno, "cannot open %s for copying", from);
- if (fstat (fdin, &sb) < 0)
- error (1, errno, "cannot fstat %s", from);
- if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0)
- error (1, errno, "cannot create %s for copying", to);
- if (sb.st_size > 0)
- {
- char buf[BUFSIZ];
- int n;
-
- for (;;)
- {
- n = read (fdin, buf, sizeof(buf));
- if (n == -1)
- {
-#ifdef EINTR
- if (errno == EINTR)
- continue;
-#endif
- error (1, errno, "cannot read file %s for copying", from);
- }
- else if (n == 0)
- break;
-
- if (write(fdout, buf, n) != n) {
- error (1, errno, "cannot write file %s for copying", to);
- }
- }
-
-#ifdef HAVE_FSYNC
- if (fsync (fdout))
- error (1, errno, "cannot fsync file %s after copying", to);
-#endif
- }
-
- if (close (fdin) < 0)
- error (0, errno, "cannot close %s", from);
- if (close (fdout) < 0)
- error (1, errno, "cannot close %s", to);
- }
-
- /* preserve last access & modification times */
- memset ((char *) &t, 0, sizeof (t));
- t.actime = sb.st_atime;
- t.modtime = sb.st_mtime;
- (void) utime (to, &t);
-}
-
-/* FIXME-krp: these functions would benefit from caching the char * &
- stat buf. */
-
-/*
- * Returns non-zero if the argument file is a directory, or is a symbolic
- * link which points to a directory.
- */
-int
-isdir (file)
- const char *file;
-{
- struct stat sb;
-
- if (stat (file, &sb) < 0)
- return (0);
- return (S_ISDIR (sb.st_mode));
-}
-
-/*
- * Returns non-zero if the argument file is a symbolic link.
- */
-int
-islink (file)
- const char *file;
-{
-#ifdef S_ISLNK
- struct stat sb;
-
- if (CVS_LSTAT (file, &sb) < 0)
- return (0);
- return (S_ISLNK (sb.st_mode));
-#else
- return (0);
-#endif
-}
-
-/*
- * Returns non-zero if the argument file is a block or
- * character special device.
- */
-int
-isdevice (file)
- const char *file;
-{
- struct stat sb;
-
- if (CVS_LSTAT (file, &sb) < 0)
- return (0);
-#ifdef S_ISBLK
- if (S_ISBLK (sb.st_mode))
- return 1;
-#endif
-#ifdef S_ISCHR
- if (S_ISCHR (sb.st_mode))
- return 1;
-#endif
- return 0;
-}
-
-/*
- * Returns non-zero if the argument file exists.
- */
-int
-isfile (file)
- const char *file;
-{
- return isaccessible(file, F_OK);
-}
-
-/*
- * Returns non-zero if the argument file is readable.
- */
-int
-isreadable (file)
- const char *file;
-{
- return isaccessible(file, R_OK);
-}
-
-/*
- * Returns non-zero if the argument file is writable.
- */
-int
-iswritable (file)
- const char *file;
-{
- return isaccessible(file, W_OK);
-}
-
-/*
- * Returns non-zero if the argument file is accessable according to
- * mode. If compiled with SETXID_SUPPORT also works if cvs has setxid
- * bits set.
- */
-int
-isaccessible (file, mode)
- const char *file;
- const int mode;
-{
-#ifdef SETXID_SUPPORT
- struct stat sb;
- int umask = 0;
- int gmask = 0;
- int omask = 0;
- int uid, mask;
-
- if (stat(file, &sb) == -1)
- return 0;
- if (mode == F_OK)
- return 1;
-
- uid = geteuid();
- if (uid == 0) /* superuser */
- {
- if (!(mode & X_OK) || (sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
- return 1;
-
- errno = EACCES;
- return 0;
- }
-
- if (mode & R_OK)
- {
- umask |= S_IRUSR;
- gmask |= S_IRGRP;
- omask |= S_IROTH;
- }
- if (mode & W_OK)
- {
- umask |= S_IWUSR;
- gmask |= S_IWGRP;
- omask |= S_IWOTH;
- }
- if (mode & X_OK)
- {
- umask |= S_IXUSR;
- gmask |= S_IXGRP;
- omask |= S_IXOTH;
- }
-
- mask = sb.st_uid == uid ? umask : sb.st_gid == getegid() ? gmask : omask;
- if ((sb.st_mode & mask) == mask)
- return 1;
- errno = EACCES;
- return 0;
-#else
- return access(file, mode) == 0;
-#endif
-}
-
-/*
- * Open a file and die if it fails
- */
-FILE *
-open_file (name, mode)
- const char *name;
- const char *mode;
-{
- FILE *fp;
-
- if ((fp = fopen (name, mode)) == NULL)
- error (1, errno, "cannot open %s", name);
- return (fp);
-}
-
-/*
- * Make a directory and die if it fails
- */
-void
-make_directory (name)
- const char *name;
-{
- struct stat sb;
-
- if (stat (name, &sb) == 0 && (!S_ISDIR (sb.st_mode)))
- error (0, 0, "%s already exists but is not a directory", name);
- if (!noexec && mkdir (name, 0777) < 0)
- error (1, errno, "cannot make directory %s", name);
-}
-
-/*
- * Make a path to the argument directory, printing a message if something
- * goes wrong.
- */
-void
-make_directories (name)
- const char *name;
-{
- char *cp;
-
- if (noexec)
- return;
-
- if (mkdir (name, 0777) == 0 || errno == EEXIST)
- return;
- if (! existence_error (errno))
- {
- error (0, errno, "cannot make path to %s", name);
- return;
- }
- if ((cp = strrchr (name, '/')) == NULL)
- return;
- *cp = '\0';
- make_directories (name);
- *cp++ = '/';
- if (*cp == '\0')
- return;
- (void) mkdir (name, 0777);
-}
-
-/* Create directory NAME if it does not already exist; fatal error for
- other errors. Returns 0 if directory was created; 1 if it already
- existed. */
-int
-mkdir_if_needed (name)
- const char *name;
-{
- if (mkdir (name, 0777) < 0)
- {
- int save_errno = errno;
- if (save_errno != EEXIST && !isdir (name))
- error (1, save_errno, "cannot make directory %s", name);
- return 1;
- }
- return 0;
-}
-
-/*
- * Change the mode of a file, either adding write permissions, or removing
- * all write permissions. Either change honors the current umask setting.
- *
- * Don't do anything if PreservePermissions is set to `yes'. This may
- * have unexpected consequences for some uses of xchmod.
- */
-void
-xchmod (fname, writable)
- const char *fname;
- int writable;
-{
- struct stat sb;
- mode_t mode, oumask;
-
- if (preserve_perms)
- return;
-
- if (stat (fname, &sb) < 0)
- {
- if (!noexec)
- error (0, errno, "cannot stat %s", fname);
- return;
- }
- oumask = umask (0);
- (void) umask (oumask);
- if (writable)
- {
- mode = sb.st_mode | (~oumask
- & (((sb.st_mode & S_IRUSR) ? S_IWUSR : 0)
- | ((sb.st_mode & S_IRGRP) ? S_IWGRP : 0)
- | ((sb.st_mode & S_IROTH) ? S_IWOTH : 0)));
- }
- else
- {
- mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH) & ~oumask;
- }
-
- if (trace)
- (void) fprintf (stderr, "%s-> chmod(%s,%o)\n",
- CLIENT_SERVER_STR, fname,
- (unsigned int) mode);
- if (noexec)
- return;
-
- if (chmod (fname, mode) < 0)
- error (0, errno, "cannot change mode of file %s", fname);
-}
-
-/*
- * Rename a file and die if it fails
- */
-void
-rename_file (from, to)
- const char *from;
- const char *to;
-{
- if (trace)
- (void) fprintf (stderr, "%s-> rename(%s,%s)\n",
- CLIENT_SERVER_STR, from, to);
- if (noexec)
- return;
-
- if (rename (from, to) < 0)
- error (1, errno, "cannot rename file %s to %s", from, to);
-}
-
-/*
- * unlink a file, if possible.
- */
-int
-unlink_file (f)
- const char *f;
-{
- if (trace)
- (void) fprintf (stderr, "%s-> unlink_file(%s)\n",
- CLIENT_SERVER_STR, f);
- if (noexec)
- return (0);
-
- return (CVS_UNLINK (f));
-}
-
-/*
- * Unlink a file or dir, if possible. If it is a directory do a deep
- * removal of all of the files in the directory. Return -1 on error
- * (in which case errno is set).
- */
-int
-unlink_file_dir (f)
- const char *f;
-{
- struct stat sb;
-
- /* This is called by the server parent process in contexts where
- it is not OK to send output (e.g. after we sent "ok" to the
- client). */
- if (trace && !server_active)
- (void) fprintf (stderr, "-> unlink_file_dir(%s)\n", f);
-
- if (noexec)
- return (0);
-
- /* For at least some unices, if root tries to unlink() a directory,
- instead of doing something rational like returning EISDIR,
- the system will gleefully go ahead and corrupt the filesystem.
- So we first call stat() to see if it is OK to call unlink(). This
- doesn't quite work--if someone creates a directory between the
- call to stat() and the call to unlink(), we'll still corrupt
- the filesystem. Where is the Unix Haters Handbook when you need
- it? */
- if (stat (f, &sb) < 0)
- {
- if (existence_error (errno))
- {
- /* The file or directory doesn't exist anyhow. */
- return -1;
- }
- }
- else if (S_ISDIR (sb.st_mode))
- return deep_remove_dir (f);
-
- return CVS_UNLINK (f);
-}
-
-/* Remove a directory and everything it contains. Returns 0 for
- * success, -1 for failure (in which case errno is set).
- */
-
-static int
-deep_remove_dir (path)
- const char *path;
-{
- DIR *dirp;
- struct dirent *dp;
-
- if (rmdir (path) != 0)
- {
- if (errno == ENOTEMPTY
- || errno == EEXIST
- /* Ugly workaround for ugly AIX 4.1 (and 3.2) header bug
- (it defines ENOTEMPTY and EEXIST to 17 but actually
- returns 87). */
- || (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87))
- {
- if ((dirp = CVS_OPENDIR (path)) == NULL)
- /* If unable to open the directory return
- * an error
- */
- return -1;
-
- errno = 0;
- while ((dp = CVS_READDIR (dirp)) != NULL)
- {
- char *buf;
-
- if (strcmp (dp->d_name, ".") == 0 ||
- strcmp (dp->d_name, "..") == 0)
- continue;
-
- buf = xmalloc (strlen (path) + strlen (dp->d_name) + 5);
- sprintf (buf, "%s/%s", path, dp->d_name);
-
- /* See comment in unlink_file_dir explanation of why we use
- isdir instead of just calling unlink and checking the
- status. */
- if (isdir(buf))
- {
- if (deep_remove_dir(buf))
- {
- CVS_CLOSEDIR(dirp);
- free (buf);
- return -1;
- }
- }
- else
- {
- if (CVS_UNLINK (buf) != 0)
- {
- CVS_CLOSEDIR(dirp);
- free (buf);
- return -1;
- }
- }
- free (buf);
-
- errno = 0;
- }
- if (errno != 0)
- {
- int save_errno = errno;
- CVS_CLOSEDIR (dirp);
- errno = save_errno;
- return -1;
- }
- CVS_CLOSEDIR (dirp);
- return rmdir (path);
- }
- else
- return -1;
- }
-
- /* Was able to remove the directory return 0 */
- return 0;
-}
-
-/* Read NCHARS bytes from descriptor FD into BUF.
- Return the number of characters successfully read.
- The number returned is always NCHARS unless end-of-file or error. */
-static size_t
-block_read (fd, buf, nchars)
- int fd;
- char *buf;
- size_t nchars;
-{
- char *bp = buf;
- size_t nread;
-
- do
- {
- nread = read (fd, bp, nchars);
- if (nread == (size_t)-1)
- {
-#ifdef EINTR
- if (errno == EINTR)
- continue;
-#endif
- return (size_t)-1;
- }
-
- if (nread == 0)
- break;
-
- bp += nread;
- nchars -= nread;
- } while (nchars != 0);
-
- return bp - buf;
-}
-
-
-/*
- * Compare "file1" to "file2". Return non-zero if they don't compare exactly.
- * If FILE1 and FILE2 are special files, compare their salient characteristics
- * (i.e. major/minor device numbers, links, etc.
- */
-int
-xcmp (file1, file2)
- const char *file1;
- const char *file2;
-{
- char *buf1, *buf2;
- struct stat sb1, sb2;
- int fd1, fd2;
- int ret;
-
- if (CVS_LSTAT (file1, &sb1) < 0)
- error (1, errno, "cannot lstat %s", file1);
- if (CVS_LSTAT (file2, &sb2) < 0)
- error (1, errno, "cannot lstat %s", file2);
-
- /* If FILE1 and FILE2 are not the same file type, they are unequal. */
- if ((sb1.st_mode & S_IFMT) != (sb2.st_mode & S_IFMT))
- return 1;
-
- /* If FILE1 and FILE2 are symlinks, they are equal if they point to
- the same thing. */
-#ifdef S_ISLNK
- if (S_ISLNK (sb1.st_mode) && S_ISLNK (sb2.st_mode))
- {
- int result;
- buf1 = xreadlink (file1);
- buf2 = xreadlink (file2);
- result = (strcmp (buf1, buf2) == 0);
- free (buf1);
- free (buf2);
- return result;
- }
-#endif
-
- /* If FILE1 and FILE2 are devices, they are equal if their device
- numbers match. */
- if (S_ISBLK (sb1.st_mode) || S_ISCHR (sb1.st_mode))
- {
-#ifdef HAVE_STRUCT_STAT_ST_RDEV
- if (sb1.st_rdev == sb2.st_rdev)
- return 0;
- else
- return 1;
-#else
- error (1, 0, "cannot compare device files on this system (%s and %s)",
- file1, file2);
-#endif
- }
-
- if ((fd1 = open (file1, O_RDONLY)) < 0)
- error (1, errno, "cannot open file %s for comparing", file1);
- if ((fd2 = open (file2, O_RDONLY)) < 0)
- error (1, errno, "cannot open file %s for comparing", file2);
-
- /* A generic file compare routine might compare st_dev & st_ino here
- to see if the two files being compared are actually the same file.
- But that won't happen in CVS, so we won't bother. */
-
- if (sb1.st_size != sb2.st_size)
- ret = 1;
- else if (sb1.st_size == 0)
- ret = 0;
- else
- {
- /* FIXME: compute the optimal buffer size by computing the least
- common multiple of the files st_blocks field */
- size_t buf_size = 8 * 1024;
- size_t read1;
- size_t read2;
-
- buf1 = xmalloc (buf_size);
- buf2 = xmalloc (buf_size);
-
- do
- {
- read1 = block_read (fd1, buf1, buf_size);
- if (read1 == (size_t)-1)
- error (1, errno, "cannot read file %s for comparing", file1);
-
- read2 = block_read (fd2, buf2, buf_size);
- if (read2 == (size_t)-1)
- error (1, errno, "cannot read file %s for comparing", file2);
-
- /* assert (read1 == read2); */
-
- ret = memcmp(buf1, buf2, read1);
- } while (ret == 0 && read1 == buf_size);
-
- free (buf1);
- free (buf2);
- }
-
- (void) close (fd1);
- (void) close (fd2);
- return (ret);
-}
-
-/* Generate a unique temporary filename. Returns a pointer to a newly
- * malloc'd string containing the name. Returns successfully or not at
- * all.
- *
- * THIS FUNCTION IS DEPRECATED!!! USE cvs_temp_file INSTEAD!!!
- *
- * and yes, I know about the way the rcs commands use temp files. I think
- * they should be converted too but I don't have time to look into it right
- * now.
- */
-char *
-cvs_temp_name ()
-{
- char *fn;
- FILE *fp;
-
- fp = cvs_temp_file (&fn);
- if (fp == NULL)
- error (1, errno, "Failed to create temporary file %s",
- fn ? fn : "(null)");
- if (fclose (fp) == EOF)
- error (0, errno, "Failed to close temporary file %s", fn);
- return fn;
-}
-
-/* Generate a unique temporary filename and return an open file stream
- * to the truncated file by that name
- *
- * INPUTS
- * filename where to place the pointer to the newly allocated file
- * name string
- *
- * OUTPUTS
- * filename dereferenced, will point to the newly allocated file
- * name string. This value is undefined if the function
- * returns an error.
- *
- * RETURNS
- * An open file pointer to a read/write mode empty temporary file with the
- * unique file name or NULL on failure.
- *
- * ERRORS
- * on error, errno will be set to some value either by CVS_FOPEN or
- * whatever system function is called to generate the temporary file name
- */
-/* There are at least four functions for generating temporary
- * filenames. We use mkstemp (BSD 4.3) if possible, else tempnam (SVID 3),
- * else mktemp (BSD 4.3), and as last resort tmpnam (POSIX). Reason is that
- * mkstemp, tempnam, and mktemp both allow to specify the directory in which
- * the temporary file will be created.
- *
- * And the _correct_ way to use the deprecated functions probably involves
- * opening file descriptors using O_EXCL & O_CREAT and even doing the annoying
- * NFS locking thing, but until I hear of more problems, I'm not going to
- * bother.
- */
-FILE *
-cvs_temp_file (filename)
- char **filename;
-{
- char *fn;
- FILE *fp;
-
- /* FIXME - I'd like to be returning NULL here in noexec mode, but I think
- * some of the rcs & diff functions which rely on a temp file run in
- * noexec mode too.
- */
-
- assert (filename != NULL);
-
-#ifdef HAVE_MKSTEMP
-
- {
- int fd;
-
- fn = xmalloc (strlen (Tmpdir) + 11);
- sprintf (fn, "%s/%s", Tmpdir, "cvsXXXXXX" );
- fd = mkstemp (fn);
-
- /* a NULL return will be interpreted by callers as an error and
- * errno should still be set
- */
- if (fd == -1) fp = NULL;
- else if ((fp = CVS_FDOPEN (fd, "w+")) == NULL)
- {
- /* Attempt to close and unlink the file since mkstemp returned
- * sucessfully and we believe it's been created and opened.
- */
- int save_errno = errno;
- if (close (fd))
- error (0, errno, "Failed to close temporary file %s", fn);
- if (CVS_UNLINK (fn))
- error (0, errno, "Failed to unlink temporary file %s", fn);
- errno = save_errno;
- }
-
- if (fp == NULL)
- {
- free (fn);
- fn = NULL;
- }
- /* mkstemp is defined to open mode 0600 using glibc 2.0.7+ */
- /* FIXME - configure can probably tell us which version of glibc we are
- * linking to and not chmod for 2.0.7+
- */
- else chmod (fn, 0600);
-
- }
-
-#elif HAVE_TEMPNAM
-
- /* tempnam has been deprecated due to under-specification */
-
- fn = tempnam (Tmpdir, "cvs");
- if (fn == NULL) fp = NULL;
- else if ((fp = CVS_FOPEN (fn, "w+")) == NULL)
- {
- free (fn);
- fn = NULL;
- }
- else chmod (fn, 0600);
-
- /* tempnam returns a pointer to a newly malloc'd string, so there's
- * no need for a xstrdup
- */
-
-#elif HAVE_MKTEMP
-
- /* mktemp has been deprecated due to the BSD 4.3 specification specifying
- * that XXXXXX will be replaced by a PID and a letter, creating only 26
- * possibilities, a security risk, and a race condition.
- */
-
- {
- char *ifn;
-
- ifn = xmalloc (strlen (Tmpdir) + 11);
- sprintf (ifn, "%s/%s", Tmpdir, "cvsXXXXXX" );
- fn = mktemp (ifn);
-
- if (fn == NULL) fp = NULL;
- else fp = CVS_FOPEN (fn, "w+");
-
- if (fp == NULL) free (ifn);
- else chmod (fn, 0600);
-
- }
-
-#else /* use tmpnam if all else fails */
-
- /* tmpnam is deprecated */
-
- {
- char ifn[L_tmpnam + 1];
-
- fn = tmpnam (ifn);
-
- if (fn == NULL) fp = NULL;
- else if ((fp = CVS_FOPEN (ifn, "w+")) != NULL)
- {
- fn = xstrdup (ifn);
- chmod (fn, 0600);
- }
-
- }
-
-#endif
-
- *filename = fn;
- if (fn == NULL && fp != NULL)
- {
- fclose (fp);
- fp = NULL;
- }
- return fp;
-}
-
-
-
-#ifdef HAVE_READLINK
-/* char *
- * xreadlink ( const char *link )
- *
- * Like the X/OPEN and 4.4BSD readlink() function, but allocates and returns
- * its own buf.
- *
- * INPUTS
- * link The original path.
- *
- * RETURNS
- * The resolution of the final symbolic link in the path.
- *
- * ERRORS
- * This function exits with a fatal error if it fails to read the link for
- * any reason.
- */
-#define MAXSIZE (SIZE_MAX < SSIZE_MAX ? SIZE_MAX : SSIZE_MAX)
-
-char *
-xreadlink (link)
- const char *link;
-{
- char *file = NULL;
- size_t buflen = BUFSIZ;
-
- /* Get the name of the file to which `from' is linked. */
- while (1)
- {
- ssize_t r;
- size_t link_name_len;
-
- file = xrealloc (file, buflen);
- r = readlink (link, file, buflen);
- link_name_len = r;
-
- if (r < 0
-#ifdef ERANGE
- /* AIX 4 and HP-UX report ERANGE if the buffer is too small. */
- && errno != ERANGE
-#endif
- )
- error (1, errno, "cannot readlink %s", link);
-
- /* If there is space for the NUL byte, set it and return. */
- if (r >= 0 && link_name_len < buflen)
- {
- file[link_name_len] = '\0';
- return file;
- }
-
- if (buflen <= MAXSIZE / 2)
- buflen *= 2;
- else if (buflen < MAXSIZE)
- buflen = MAXSIZE;
- else
- /* Our buffer cannot grow any bigger. */
- error (1, ENAMETOOLONG, "cannot readlink %s", link);
- }
-}
-#endif /* HAVE_READLINK */
-
-
-
-/* char *
- * xresolvepath ( const char *path )
- *
- * Like xreadlink(), but resolve all links in a path.
- *
- * INPUTS
- * path The original path.
- *
- * RETURNS
- * The path with any symbolic links expanded.
- *
- * ERRORS
- * This function exits with a fatal error if it fails to read the link for
- * any reason.
- */
-char *
-xresolvepath ( path )
- const char *path;
-{
- char *hardpath;
- char *owd;
-
- assert ( isdir ( path ) );
-
- /* FIXME - If HAVE_READLINK is defined, we should probably walk the path
- * bit by bit calling xreadlink().
- */
-
- owd = xgetwd();
- if ( CVS_CHDIR ( path ) < 0)
- error ( 1, errno, "cannot chdir to %s", path );
- if ( ( hardpath = xgetwd() ) == NULL )
- error (1, errno, "cannot getwd in %s", path);
- if ( CVS_CHDIR ( owd ) < 0)
- error ( 1, errno, "cannot chdir to %s", owd );
- free (owd);
- return hardpath;
-}
-
-
-
-/* Return a pointer into PATH's last component. */
-const char *
-last_component (path)
- const char *path;
-{
- const char *last = strrchr (path, '/');
-
- assert (path);
- if (last && (last != path))
- return last + 1;
- else
- return path;
-}
-
-/* Return the home directory. Returns a pointer to storage
- managed by this function or its callees (currently getenv).
- This function will return the same thing every time it is
- called. Returns NULL if there is no home directory.
-
- Note that for a pserver server, this may return root's home
- directory. What typically happens is that upon being started from
- inetd, before switching users, the code in cvsrc.c calls
- get_homedir which remembers root's home directory in the static
- variable. Then the switch happens and get_homedir might return a
- directory that we don't even have read or execute permissions for
- (which is bad, when various parts of CVS try to read there). One
- fix would be to make the value returned by get_homedir only good
- until the next call (which would free the old value). Another fix
- would be to just always malloc our answer, and let the caller free
- it (that is best, because some day we may need to be reentrant).
-
- The workaround is to put -f in inetd.conf which means that
- get_homedir won't get called until after the switch in user ID.
-
- The whole concept of a "home directory" on the server is pretty
- iffy, although I suppose some people probably are relying on it for
- .cvsrc and such, in the cases where it works. */
-char *
-get_homedir ()
-{
- static char *home = NULL;
- char *env;
- struct passwd *pw;
-
- if (home != NULL)
- return home;
-
- if (!server_active && (env = getenv ("HOME")) != NULL)
- home = env;
- else if ((pw = (struct passwd *) getpwuid (getuid ()))
- && pw->pw_dir)
- home = xstrdup (pw->pw_dir);
- else
- return 0;
-
- return home;
-}
-
-/* Compose a path to a file in the home directory. This is necessary because
- * of different behavior on UNIX and VMS. See the notes in vms/filesubr.c.
- *
- * A more clean solution would be something more along the lines of a
- * "join a directory to a filename" kind of thing which was not specific to
- * the homedir. This should aid portability between UNIX, Mac, Windows, VMS,
- * and possibly others. This is already handled by Perl - it might be
- * interesting to see how much of the code was written in C since Perl is under
- * the GPL and the Artistic license - we might be able to use it.
- */
-char *
-strcat_filename_onto_homedir (dir, file)
- const char *dir;
- const char *file;
-{
- char *path = xmalloc (strlen (dir) + 1 + strlen(file) + 1);
- sprintf (path, "%s/%s", dir, file);
- return path;
-}
-
-/* See cvs.h for description. On unix this does nothing, because the
- shell expands the wildcards. */
-void
-expand_wild (argc, argv, pargc, pargv)
- int argc;
- char **argv;
- int *pargc;
- char ***pargv;
-{
- int i;
- assert (argv || !argc);
- if (size_overflow_p (xtimes (argc, sizeof (char *)))) {
- *pargc = 0;
- *pargv = NULL;
- error (0, 0, "expand_wild: too many arguments");
- return;
- }
- *pargc = argc;
- *pargv = xmalloc (xtimes (argc, sizeof (char *)));
- for (i = 0; i < argc; ++i)
- (*pargv)[i] = xstrdup (argv[i]);
-}
-
-
-
-#ifdef SERVER_SUPPORT
-/* Case-insensitive string compare. I know that some systems
- have such a routine, but I'm not sure I see any reasons for
- dealing with the hair of figuring out whether they do (I haven't
- looked into whether this is a performance bottleneck; I would guess
- not). */
-int
-cvs_casecmp (str1, str2)
- const char *str1;
- const char *str2;
-{
- const char *p;
- const char *q;
- int pqdiff;
-
- p = str1;
- q = str2;
- while ((pqdiff = tolower (*p) - tolower (*q)) == 0)
- {
- if (*p == '\0')
- return 0;
- ++p;
- ++q;
- }
- return pqdiff;
-}
-#endif /* SERVER_SUPPORT */
diff --git a/contrib/cvs/src/find_names.c b/contrib/cvs/src/find_names.c
deleted file mode 100644
index 5bfd8957ef15..000000000000
--- a/contrib/cvs/src/find_names.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Find Names
- *
- * Finds all the pertinent file names, both from the administration and from the
- * repository
- *
- * Find Dirs
- *
- * Finds all pertinent sub-directories of the checked out instantiation and the
- * repository (and optionally the attic)
- */
-
-#include "cvs.h"
-
-static int find_dirs PROTO((char *dir, List * list, int checkadm,
- List *entries));
-static int find_rcs PROTO((char *dir, List * list));
-static int add_subdir_proc PROTO((Node *, void *));
-static int register_subdir_proc PROTO((Node *, void *));
-
-/*
- * add the key from entry on entries list to the files list
- */
-static int add_entries_proc PROTO((Node *, void *));
-static int
-add_entries_proc (node, closure)
- Node *node;
- void *closure;
-{
- Node *fnode;
- List *filelist = closure;
- Entnode *entnode = node->data;
-
- if (entnode->type != ENT_FILE)
- return (0);
-
- fnode = getnode ();
- fnode->type = FILES;
- fnode->key = xstrdup (node->key);
- if (addnode (filelist, fnode) != 0)
- freenode (fnode);
- 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;
- int which;
- int aflag;
- List **optentries;
-{
- List *entries;
- List *files;
-
- /* make a list for the files */
- files = getlist ();
-
- /* look at entries (if necessary) */
- if (which & W_LOCAL)
- {
- /* parse the entries file (if it exists) */
- entries = Entries_Open (aflag, NULL);
- if (entries != NULL)
- {
- /* walk the entries file adding elements to the files list */
- (void) walklist (entries, add_entries_proc, files);
-
- /* if our caller wanted the entries list, return it; else free it */
- if (optentries != NULL)
- *optentries = entries;
- else
- Entries_Close (entries);
- }
- }
-
- if ((which & W_REPOS) && repository && !isreadable (CVSADM_ENTSTAT))
- {
- /* search the repository */
- if (find_rcs (repository, files) != 0)
- {
- error (0, errno, "cannot open directory %s", repository);
- goto error_exit;
- }
-
- /* search the attic too */
- if (which & W_ATTIC)
- {
- char *dir;
- dir = xmalloc (strlen (repository) + sizeof (CVSATTIC) + 10);
- (void) sprintf (dir, "%s/%s", repository, CVSATTIC);
- 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);
- }
- }
-
- /* sort the list into alphabetical order and return it */
- sortlist (files, fsortcmp);
- return (files);
- error_exit:
- dellist (&files);
- return NULL;
-}
-
-/*
- * Add an entry from the subdirs list to the directories list. This
- * is called via walklist.
- */
-
-static int
-add_subdir_proc (p, closure)
- Node *p;
- void *closure;
-{
- List *dirlist = closure;
- Entnode *entnode = p->data;
- Node *dnode;
-
- if (entnode->type != ENT_SUBDIR)
- return 0;
-
- dnode = getnode ();
- dnode->type = DIRS;
- dnode->key = xstrdup (entnode->user);
- if (addnode (dirlist, dnode) != 0)
- freenode (dnode);
- return 0;
-}
-
-/*
- * Register a subdirectory. This is called via walklist.
- */
-
-/*ARGSUSED*/
-static int
-register_subdir_proc (p, closure)
- Node *p;
- void *closure;
-{
- List *entries = (List *) closure;
-
- Subdir_Register (entries, (char *) NULL, p->key);
- return 0;
-}
-
-/*
- * create a list of directories to traverse from the current directory
- */
-List *
-Find_Directories (repository, which, entries)
- char *repository;
- int which;
- List *entries;
-{
- List *dirlist;
-
- /* make a list for the directories */
- dirlist = getlist ();
-
- /* find the local ones */
- if (which & W_LOCAL)
- {
- List *tmpentries;
- struct stickydirtag *sdtp;
-
- /* Look through the Entries file. */
-
- if (entries != NULL)
- tmpentries = entries;
- else if (isfile (CVSADM_ENT))
- tmpentries = Entries_Open (0, NULL);
- else
- tmpentries = NULL;
-
- if (tmpentries != NULL)
- sdtp = tmpentries->list->data;
-
- /* If we do have an entries list, then if sdtp is NULL, or if
- sdtp->subdirs is nonzero, all subdirectory information is
- recorded in the entries list. */
- if (tmpentries != NULL && (sdtp == NULL || sdtp->subdirs))
- walklist (tmpentries, add_subdir_proc, (void *) dirlist);
- else
- {
- /* This is an old working directory, in which subdirectory
- information is not recorded in the Entries file. Find
- the subdirectories the hard way, and, if possible, add
- it to the Entries file for next time. */
-
- /* FIXME-maybe: find_dirs is bogus for this usage because
- it skips CVSATTIC and CVSLCK directories--those names
- should be special only in the repository. However, in
- the interests of not perturbing this code, we probably
- should leave well enough alone unless we want to write
- a sanity.sh test case (which would operate by manually
- hacking on the CVS/Entries file). */
-
- if (find_dirs (".", dirlist, 1, tmpentries) != 0)
- error (1, errno, "cannot open current directory");
- if (tmpentries != NULL)
- {
- if (! list_isempty (dirlist))
- walklist (dirlist, register_subdir_proc,
- (void *) tmpentries);
- else
- Subdirs_Known (tmpentries);
- }
- }
-
- if (entries == NULL && tmpentries != NULL)
- Entries_Close (tmpentries);
- }
-
- /* look for sub-dirs in the repository */
- if ((which & W_REPOS) && repository)
- {
- /* search the repository */
- if (find_dirs (repository, dirlist, 0, entries) != 0)
- error (1, errno, "cannot open directory %s", repository);
-
- /* We don't need to look in the attic because directories
- never go in the attic. In the future, there hopefully will
- be a better mechanism for detecting whether a directory in
- the repository is alive or dead; it may or may not involve
- moving directories to the attic. */
- }
-
- /* sort the list into alphabetical order and return it */
- sortlist (dirlist, fsortcmp);
- return (dirlist);
-}
-
-/*
- * 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, 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)
- char *dir;
- List *list;
-{
- Node *p;
- struct dirent *dp;
- DIR *dirp;
-
- /* set up to read the dir */
- if ((dirp = CVS_OPENDIR (dir)) == NULL)
- return (1);
-
- /* read the dir, grabbing the ,v files */
- errno = 0;
- while ((dp = CVS_READDIR (dirp)) != NULL)
- {
- if (CVS_FNMATCH (RCSPAT, dp->d_name, 0) == 0)
- {
- char *comma;
-
- comma = strrchr (dp->d_name, ','); /* strip the ,v */
- *comma = '\0';
- p = getnode ();
- p->type = FILES;
- p->key = xstrdup (dp->d_name);
- if (addnode (list, p) != 0)
- freenode (p);
- }
- errno = 0;
- }
- if (errno != 0)
- {
- int save_errno = errno;
- (void) CVS_CLOSEDIR (dirp);
- errno = save_errno;
- return 1;
- }
- (void) CVS_CLOSEDIR (dirp);
- return (0);
-}
-
-/*
- * Finds all the subdirectories of the argument dir and adds them to
- * 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, in which case errno is set to indicate the error.
- */
-static int
-find_dirs (dir, list, checkadm, entries)
- char *dir;
- List *list;
- int checkadm;
- List *entries;
-{
- Node *p;
- char *tmp = NULL;
- size_t tmp_size = 0;
- struct dirent *dp;
- DIR *dirp;
- int skip_emptydir = 0;
-
- /* First figure out whether we need to skip directories named
- Emptydir. Except in the CVSNULLREPOS case, Emptydir is just
- a normal directory name. */
- if (isabsolute (dir)
- && strncmp (dir, current_parsed_root->directory, strlen (current_parsed_root->directory)) == 0
- && ISDIRSEP (dir[strlen (current_parsed_root->directory)])
- && strcmp (dir + strlen (current_parsed_root->directory) + 1, CVSROOTADM) == 0)
- skip_emptydir = 1;
-
- /* set up to read the dir */
- if ((dirp = CVS_OPENDIR (dir)) == NULL)
- return (1);
-
- /* read the dir, grabbing sub-dirs */
- errno = 0;
- while ((dp = CVS_READDIR (dirp)) != NULL)
- {
- if (strcmp (dp->d_name, ".") == 0 ||
- strcmp (dp->d_name, "..") == 0 ||
- strcmp (dp->d_name, CVSATTIC) == 0 ||
- strcmp (dp->d_name, CVSLCK) == 0 ||
- strcmp (dp->d_name, CVSREP) == 0)
- 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)
- goto do_it_again;
-
- if (skip_emptydir
- && strcmp (dp->d_name, CVSNULLREPOS) == 0)
- goto do_it_again;
-
-#ifdef DT_DIR
- if (dp->d_type != DT_DIR)
- {
- if (dp->d_type != DT_UNKNOWN && dp->d_type != DT_LNK)
- goto do_it_again;
-#endif
- /* don't bother stating ,v files */
- if (CVS_FNMATCH (RCSPAT, dp->d_name, 0) == 0)
- 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))
- goto do_it_again;
-
-#ifdef DT_DIR
- }
-#endif
-
- /* check for administration directories (if needed) */
- if (checkadm)
- {
- /* blow off symbolic links to dirs in local dir */
-#ifdef DT_DIR
- if (dp->d_type != DT_DIR)
- {
- /* we're either unknown or a symlink at this point */
- if (dp->d_type == DT_LNK)
- goto do_it_again;
-#endif
- /* Note that we only get here if we already set tmp
- above. */
- if (islink (tmp))
- goto do_it_again;
-#ifdef DT_DIR
- }
-#endif
-
- /* check for new style */
- expand_string (&tmp,
- &tmp_size,
- (strlen (dir) + strlen (dp->d_name)
- + sizeof (CVSADM) + 10));
- (void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, CVSADM);
- if (!isdir (tmp))
- goto do_it_again;
- }
-
- /* put it in the list */
- p = getnode ();
- p->type = DIRS;
- 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) CVS_CLOSEDIR (dirp);
- errno = save_errno;
- return 1;
- }
- (void) CVS_CLOSEDIR (dirp);
- if (tmp != NULL)
- free (tmp);
- return (0);
-}
diff --git a/contrib/cvs/src/hardlink.c b/contrib/cvs/src/hardlink.c
deleted file mode 100644
index ed050334fada..000000000000
--- a/contrib/cvs/src/hardlink.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/* This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-/* Collect and manage hardlink info associated with a particular file. */
-
-#include "cvs.h"
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
-# include "hardlink.h"
-
-/* The structure currently used to manage hardlink info is a list.
- Therefore, most of the functions which manipulate hardlink data
- are walklist procedures. This is not a very efficient implementation;
- if someone decides to use a real hash table (for instance), then
- much of this code can be rewritten to be a little less arcane.
-
- Each element of `hardlist' represents an inode. It is keyed on the
- inode number, and points to a list of files. This is to make it
- easy to find out what files are linked to a given file FOO: find
- FOO's inode, look it up in hardlist, and retrieve the list of files
- associated with that inode.
-
- Each file node, in turn, is represented by a `hardlink_info' struct,
- which includes `status' and `links' fields. The `status' field should
- be used by a procedure like commit_fileproc or update_fileproc to
- record each file's status; that way, after all file links have been
- recorded, CVS can check the linkage of files which are in doubt
- (i.e. T_NEEDS_MERGE files).
-
- TODO: a diagram of an example hardlist would help here. */
-
-/* TODO: change this to something with a marginal degree of
- efficiency, like maybe a hash table. Yeah. */
-
-List *hardlist; /* Record hardlink information for working files */
-char *working_dir; /* The top-level working directory, used for
- constructing full pathnames. */
-
-/* Return a pointer to FILEPATH's node in the hardlist. This means
- looking up its inode, retrieving the list of files linked to that
- inode, and then looking up FILE in that list. If the file doesn't
- seem to exist, return NULL. */
-Node *
-lookup_file_by_inode (filepath)
- const char *filepath;
-{
- char *inodestr, *file;
- struct stat sb;
- Node *hp, *p;
-
- /* Get file's basename, so that we can stat it. */
- file = strrchr (filepath, '/');
- if (file)
- ++file;
- else
- file = (char *) filepath;
-
- /* inodestr contains the hexadecimal representation of an
- inode, so it requires two bytes of text to represent
- each byte of the inode number. */
- inodestr = (char *) xmalloc (2*sizeof(ino_t) + 1);
- if (stat (file, &sb) < 0)
- {
- 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
- link information, so return without changing hardlist. */
- free (inodestr);
- return NULL;
- }
- error (1, errno, "cannot stat %s", file);
- }
-
- sprintf (inodestr, "%lx", (unsigned long) sb.st_ino);
-
- /* Find out if this inode is already in the hardlist, adding
- a new entry to the list if not. */
- hp = findnode (hardlist, inodestr);
- if (hp == NULL)
- {
- hp = getnode ();
- hp->type = NT_UNKNOWN;
- hp->key = inodestr;
- hp->data = getlist();
- hp->delproc = dellist;
- (void) addnode (hardlist, hp);
- }
- else
- {
- free (inodestr);
- }
-
- p = findnode (hp->data, filepath);
- if (p == NULL)
- {
- p = getnode();
- p->type = NT_UNKNOWN;
- p->key = xstrdup (filepath);
- p->data = NULL;
- (void) addnode (hp->data, p);
- }
-
- return p;
-}
-
-/* After a file has been checked out, add a node for it to the hardlist
- (if necessary) and mark it as checked out. */
-void
-update_hardlink_info (file)
- const char *file;
-{
- char *path;
- Node *n;
- struct hardlink_info *hlinfo;
-
- if (file[0] == '/')
- {
- path = xstrdup (file);
- }
- else
- {
- /* file is a relative pathname; assume it's from the current
- working directory. */
- char *dir = xgetwd();
- path = xmalloc (strlen(dir) + strlen(file) + 2);
- sprintf (path, "%s/%s", dir, file);
- free (dir);
- }
-
- n = lookup_file_by_inode (path);
- if (n == NULL)
- {
- /* Something is *really* wrong if the file doesn't exist here;
- update_hardlink_info should be called only when a file has
- just been checked out to a working directory. */
- error (1, 0, "lost hardlink info for %s", file);
- }
-
- if (n->data == NULL)
- n->data = xmalloc (sizeof (struct hardlink_info));
- hlinfo = n->data;
- hlinfo->status = T_UPTODATE;
- hlinfo->checked_out = 1;
-}
-
-/* Return a List with all the files known to be linked to FILE in
- the working directory. Used by special_file_mismatch, to determine
- whether it is safe to merge two files.
-
- FIXME: What is the memory allocation for the return value? We seem
- to sometimes allocate a new list (getlist() call below) and sometimes
- return an existing list (where we return n->data). */
-List *
-list_linked_files_on_disk (file)
- char *file;
-{
- char *inodestr, *path;
- struct stat sb;
- Node *n;
-
- /* If hardlist is NULL, we have not been doing an operation that
- would permit us to know anything about the file's hardlinks
- (cvs update, cvs commit, etc). Return an empty list. */
- if (hardlist == NULL)
- return getlist();
-
- /* Get the full pathname of file (assuming the working directory) */
- if (file[0] == '/')
- path = xstrdup (file);
- else
- {
- char *dir = xgetwd();
- path = (char *) xmalloc (strlen(dir) + strlen(file) + 2);
- sprintf (path, "%s/%s", dir, file);
- free (dir);
- }
-
- /* We do an extra lookup_file here just to make sure that there
- is a node for `path' in the hardlist. If that were not so,
- comparing the working directory linkage against the repository
- linkage for a file would always fail. */
- (void) lookup_file_by_inode (path);
-
- if (stat (path, &sb) < 0)
- error (1, errno, "cannot stat %s", file);
- /* inodestr contains the hexadecimal representation of an
- inode, so it requires two bytes of text to represent
- each byte of the inode number. */
- inodestr = (char *) xmalloc (2*sizeof(ino_t) + 1);
- sprintf (inodestr, "%lx", (unsigned long) sb.st_ino);
-
- /* Make sure the files linked to this inode are sorted. */
- n = findnode (hardlist, inodestr);
- sortlist (n->data, fsortcmp);
-
- free (inodestr);
- return n->data;
-}
-
-/* Compare the files in the `key' fields of two lists, returning 1 if
- the lists are equivalent and 0 otherwise.
-
- Only the basenames of each file are compared. This is an awful hack
- that exists because list_linked_files_on_disk returns full paths
- and the `hardlinks' structure of a RCSVers node contains only
- basenames. That in turn is a result of the awful hack that only
- basenames are stored in the RCS file. If anyone ever solves the
- problem of correctly managing cross-directory hardlinks, this
- function (along with most functions in this file) must be fixed. */
-
-int
-compare_linkage_lists (links1, links2)
- List *links1;
- List *links2;
-{
- Node *n1, *n2;
- char *p1, *p2;
-
- sortlist (links1, fsortcmp);
- sortlist (links2, fsortcmp);
-
- n1 = links1->list->next;
- n2 = links2->list->next;
-
- while (n1 != links1->list && n2 != links2->list)
- {
- /* Get the basenames of both files. */
- p1 = strrchr (n1->key, '/');
- if (p1 == NULL)
- p1 = n1->key;
- else
- ++p1;
-
- p2 = strrchr (n2->key, '/');
- if (p2 == NULL)
- p2 = n2->key;
- else
- ++p2;
-
- /* Compare the files' basenames. */
- if (strcmp (p1, p2) != 0)
- return 0;
-
- n1 = n1->next;
- n2 = n2->next;
- }
-
- /* At this point we should be at the end of both lists; if not,
- one file has more links than the other, and return 1. */
- return (n1 == links1->list && n2 == links2->list);
-}
-
-/* Find a checked-out file in a list of filenames. Used by RCS_checkout
- when checking out a new hardlinked file, to decide whether this file
- can be linked to any others that already exist. The return value
- is not currently used. */
-
-int
-find_checkedout_proc (node, data)
- Node *node;
- void *data;
-{
- Node **uptodate = (Node **) data;
- Node *link;
- char *dir = xgetwd();
- char *path;
- struct hardlink_info *hlinfo;
-
- /* If we have already found a file, don't do anything. */
- if (*uptodate != NULL)
- return 0;
-
- /* Look at this file in the hardlist and see whether the checked_out
- field is 1, meaning that it has been checked out during this CVS run. */
- path = (char *)
- xmalloc (strlen (dir) + strlen (node->key) + 2);
- sprintf (path, "%s/%s", dir, node->key);
- link = lookup_file_by_inode (path);
- free (path);
- free (dir);
-
- if (link == NULL)
- {
- /* We haven't seen this file -- maybe it hasn't been checked
- out yet at all. */
- return 0;
- }
-
- hlinfo = link->data;
- if (hlinfo->checked_out)
- {
- /* This file has been checked out recently, so it's safe to
- link to it. */
- *uptodate = link;
- }
-
- return 0;
-}
-#endif /* PRESERVE_PERMISSIONS_SUPPORT */
diff --git a/contrib/cvs/src/hardlink.h b/contrib/cvs/src/hardlink.h
deleted file mode 100644
index b2279683fe69..000000000000
--- a/contrib/cvs/src/hardlink.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-/* Data type definitions and declarations for hardlink management. */
-
-/* This file should be #included in CVS source files after cvs.h
- since it relies on types and macros defined there. */
-
-/* The `checked_out' member of a hardlink_info struct is used only
- when files are being checked out or updated. It is used only when
- hardlinked files are being checked out. */
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
-struct hardlink_info
-{
- Ctype status; /* as returned from Classify_File() */
- int checked_out; /* has this file been checked out lately? */
-};
-
-extern List *hardlist;
-extern char *working_dir;
-
-Node *lookup_file_by_inode PROTO ((const char *));
-void update_hardlink_info PROTO ((const char *));
-List *list_linked_files_on_disk PROTO ((char *));
-int compare_linkage_lists PROTO ((List *, List *));
-int find_checkedout_proc PROTO ((Node *, void *));
-#endif /* PRESERVE_PERMISSIONS_SUPPORT */
diff --git a/contrib/cvs/src/hash.c b/contrib/cvs/src/hash.c
deleted file mode 100644
index d9bc12cc3c13..000000000000
--- a/contrib/cvs/src/hash.c
+++ /dev/null
@@ -1,528 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Polk's hash list manager. So cool.
- */
-
-#include "cvs.h"
-#include <assert.h>
-
-/* Global caches. The idea is that we maintain a linked list of "free"d
- nodes or lists, and get new items from there. It has been suggested
- to use an obstack instead, but off the top of my head, I'm not sure
- that would gain enough to be worth worrying about. */
-static List *listcache = NULL;
-static Node *nodecache = NULL;
-
-static void freenode_mem PROTO((Node * p));
-
-/* hash function */
-static int
-hashp (key)
- const char *key;
-{
- unsigned int h = 0;
- unsigned int g;
-
- assert(key != NULL);
-
- while (*key != 0)
- {
- unsigned int c = *key++;
- /* The FOLD_FN_CHAR is so that findnode_fn works. */
- h = (h << 4) + FOLD_FN_CHAR (c);
- if ((g = h & 0xf0000000) != 0)
- h = (h ^ (g >> 24)) ^ g;
- }
-
- return (h % HASHSIZE);
-}
-
-/*
- * create a new list (or get an old one from the cache)
- */
-List *
-getlist ()
-{
- int i;
- List *list;
- Node *node;
-
- if (listcache != NULL)
- {
- /* get a list from the cache and clear it */
- list = listcache;
- listcache = listcache->next;
- list->next = (List *) NULL;
- for (i = 0; i < HASHSIZE; i++)
- list->hasharray[i] = (Node *) NULL;
- }
- else
- {
- /* make a new list from scratch */
- list = (List *) xmalloc (sizeof (List));
- memset ((char *) list, 0, sizeof (List));
- node = getnode ();
- list->list = node;
- node->type = HEADER;
- node->next = node->prev = node;
- }
- return (list);
-}
-
-/*
- * free up a list
- */
-void
-dellist (listp)
- List **listp;
-{
- int i;
- Node *p;
-
- if (*listp == (List *) NULL)
- return;
-
- p = (*listp)->list;
-
- /* free each node in the list (except header) */
- while (p->next != p)
- delnode (p->next);
-
- /* free any list-private data, without freeing the actual header */
- freenode_mem (p);
-
- /* free up the header nodes for hash lists (if any) */
- for (i = 0; i < HASHSIZE; i++)
- {
- if ((p = (*listp)->hasharray[i]) != (Node *) NULL)
- {
- /* put the nodes into the cache */
-#ifndef NOCACHE
- p->type = NT_UNKNOWN;
- p->next = nodecache;
- nodecache = p;
-#else
- /* If NOCACHE is defined we turn off the cache. This can make
- it easier to tools to determine where items were allocated
- and freed, for tracking down memory leaks and the like. */
- free (p);
-#endif
- }
- }
-
- /* put it on the cache */
-#ifndef NOCACHE
- (*listp)->next = listcache;
- listcache = *listp;
-#else
- free ((*listp)->list);
- free (*listp);
-#endif
- *listp = (List *) NULL;
-}
-
-/*
- * get a new list node
- */
-Node *
-getnode ()
-{
- Node *p;
-
- if (nodecache != (Node *) NULL)
- {
- /* get one from the cache */
- p = nodecache;
- nodecache = p->next;
- }
- else
- {
- /* make a new one */
- p = (Node *) xmalloc (sizeof (Node));
- }
-
- /* always make it clean */
- memset ((char *) p, 0, sizeof (Node));
- p->type = NT_UNKNOWN;
-
- return (p);
-}
-
-/*
- * remove a node from it's list (maybe hash list too) and free it
- */
-void
-delnode (p)
- Node *p;
-{
- if (p == (Node *) NULL)
- return;
-
- /* take it out of the list */
- p->next->prev = p->prev;
- p->prev->next = p->next;
-
- /* if it was hashed, remove it from there too */
- if (p->hashnext != (Node *) NULL)
- {
- p->hashnext->hashprev = p->hashprev;
- p->hashprev->hashnext = p->hashnext;
- }
-
- /* free up the storage */
- freenode (p);
-}
-
-/*
- * free up the storage associated with a node
- */
-static void
-freenode_mem (p)
- Node *p;
-{
- if (p->delproc != (void (*) ()) NULL)
- p->delproc (p); /* call the specified delproc */
- else
- {
- if (p->data != NULL) /* otherwise free() it if necessary */
- free (p->data);
- }
- if (p->key != NULL) /* free the key if necessary */
- free (p->key);
-
- /* to be safe, re-initialize these */
- p->key = p->data = NULL;
- p->delproc = (void (*) ()) NULL;
-}
-
-/*
- * free up the storage associated with a node and recycle it
- */
-void
-freenode (p)
- Node *p;
-{
- /* first free the memory */
- freenode_mem (p);
-
- /* then put it in the cache */
-#ifndef NOCACHE
- p->type = NT_UNKNOWN;
- p->next = nodecache;
- nodecache = p;
-#else
- free (p);
-#endif
-}
-
-/*
- * Link item P into list LIST before item MARKER. If P->KEY is non-NULL and
- * that key is already in the hash table, return -1 without modifying any
- * parameter.
- *
- * return 0 on success
- */
-int
-insert_before (list, marker, p)
- List *list;
- Node *marker;
- Node *p;
-{
- if (p->key != NULL) /* hash it too? */
- {
- int hashval;
- Node *q;
-
- hashval = hashp (p->key);
- if (list->hasharray[hashval] == NULL) /* make a header for list? */
- {
- q = getnode ();
- q->type = HEADER;
- list->hasharray[hashval] = q->hashnext = q->hashprev = q;
- }
-
- /* put it into the hash list if it's not already there */
- for (q = list->hasharray[hashval]->hashnext;
- q != list->hasharray[hashval]; q = q->hashnext)
- {
- if (strcmp (p->key, q->key) == 0)
- return (-1);
- }
- q = list->hasharray[hashval];
- p->hashprev = q->hashprev;
- p->hashnext = q;
- p->hashprev->hashnext = p;
- q->hashprev = p;
- }
-
- p->next = marker;
- p->prev = marker->prev;
- marker->prev->next = p;
- marker->prev = p;
-
- return (0);
-}
-
-/*
- * insert item p at end of list "list" (maybe hash it too) if hashing and it
- * already exists, return -1 and don't actually put it in the list
- *
- * return 0 on success
- */
-int
-addnode (list, p)
- List *list;
- Node *p;
-{
- return insert_before (list, list->list, p);
-}
-
-/*
- * Like addnode, but insert p at the front of `list'. This bogosity is
- * necessary to preserve last-to-first output order for some RCS functions.
- */
-int
-addnode_at_front (list, p)
- List *list;
- Node *p;
-{
- return insert_before (list, list->list->next, p);
-}
-
-/* Look up an entry in hash list table and return a pointer to the
- node. Return NULL if not found. Abort with a fatal error for
- errors. */
-Node *
-findnode (list, key)
- List *list;
- const char *key;
-{
- Node *head, *p;
-
- /* This probably should be "assert (list != NULL)" (or if not we
- should document the current behavior), but only if we check all
- the callers to see if any are relying on this behavior. */
- if ((list == (List *) NULL))
- return ((Node *) NULL);
-
- assert (key != NULL);
-
- head = list->hasharray[hashp (key)];
- if (head == (Node *) NULL)
- /* Not found. */
- return ((Node *) NULL);
-
- for (p = head->hashnext; p != head; p = p->hashnext)
- if (strcmp (p->key, key) == 0)
- return (p);
- return ((Node *) NULL);
-}
-
-/*
- * Like findnode, but for a filename.
- */
-Node *
-findnode_fn (list, key)
- List *list;
- const char *key;
-{
- Node *head, *p;
-
- /* This probably should be "assert (list != NULL)" (or if not we
- should document the current behavior), but only if we check all
- the callers to see if any are relying on this behavior. */
- if (list == (List *) NULL)
- return ((Node *) NULL);
-
- assert (key != NULL);
-
- head = list->hasharray[hashp (key)];
- if (head == (Node *) NULL)
- return ((Node *) NULL);
-
- for (p = head->hashnext; p != head; p = p->hashnext)
- if (fncmp (p->key, key) == 0)
- return (p);
- return ((Node *) NULL);
-}
-
-/*
- * walk a list with a specific proc
- */
-int
-walklist (list, proc, closure)
- List *list;
- int (*proc) PROTO ((Node *, void *));
- void *closure;
-{
- Node *head, *p;
- int err = 0;
-
- if (list == NULL)
- return (0);
-
- head = list->list;
- for (p = head->next; p != head; p = p->next)
- err += proc (p, closure);
- return (err);
-}
-
-int
-list_isempty (list)
- List *list;
-{
- return list == NULL || list->list->next == list->list;
-}
-
-static int (*client_comp) PROTO ((const Node *, const Node *));
-static int qsort_comp PROTO ((const void *, const void *));
-
-static int
-qsort_comp (elem1, elem2)
- const void *elem1;
- const void *elem2;
-{
- Node **node1 = (Node **) elem1;
- Node **node2 = (Node **) elem2;
- return client_comp (*node1, *node2);
-}
-
-/*
- * sort the elements of a list (in place)
- */
-void
-sortlist (list, comp)
- List *list;
- int (*comp) PROTO ((const Node *, const Node *));
-{
- Node *head, *remain, *p, **array;
- int i, n;
-
- if (list == NULL)
- return;
-
- /* save the old first element of the list */
- head = list->list;
- remain = head->next;
-
- /* count the number of nodes in the list */
- n = 0;
- for (p = remain; p != head; p = p->next)
- n++;
-
- /* allocate an array of nodes and populate it */
- array = (Node **) xmalloc (sizeof(Node *) * n);
- i = 0;
- for (p = remain; p != head; p = p->next)
- array[i++] = p;
-
- /* sort the array of nodes */
- client_comp = comp;
- qsort (array, n, sizeof(Node *), qsort_comp);
-
- /* rebuild the list from beginning to end */
- head->next = head->prev = head;
- for (i = 0; i < n; i++)
- {
- p = array[i];
- p->next = head;
- p->prev = head->prev;
- p->prev->next = p;
- head->prev = p;
- }
-
- /* release the array of nodes */
- free (array);
-}
-
-/*
- * compare two files list node (for sort)
- */
-int
-fsortcmp (p, q)
- const Node *p;
- const Node *q;
-{
- return (strcmp (p->key, q->key));
-}
-
-/* Debugging functions. Quite useful to call from within gdb. */
-
-static char *nodetypestring PROTO ((Ntype));
-
-static char *
-nodetypestring (type)
- Ntype type;
-{
- switch (type) {
- case NT_UNKNOWN: return("UNKNOWN");
- case HEADER: return("HEADER");
- case ENTRIES: return("ENTRIES");
- case FILES: return("FILES");
- case LIST: return("LIST");
- case RCSNODE: return("RCSNODE");
- case RCSVERS: return("RCSVERS");
- case DIRS: return("DIRS");
- case UPDATE: return("UPDATE");
- case LOCK: return("LOCK");
- case NDBMNODE: return("NDBMNODE");
- case FILEATTR: return("FILEATTR");
- case VARIABLE: return("VARIABLE");
- case RCSFIELD: return("RCSFIELD");
- case RCSCMPFLD: return("RCSCMPFLD");
- }
-
- return("<trash>");
-}
-
-static int printnode PROTO ((Node *, void *));
-static int
-printnode (node, closure)
- Node *node;
- void *closure;
-{
- if (node == NULL)
- {
- (void) printf("NULL node.\n");
- return(0);
- }
-
- (void) printf("Node at %p: type = %s, key = %p = \"%s\", data = %p, next = %p, prev = %p\n",
- (void *)node, nodetypestring(node->type),
- (void *)node->key, node->key, node->data,
- (void *)node->next, (void *)node->prev);
-
- return(0);
-}
-
-/* This is global, not static, so that its name is unique and to avoid
- compiler warnings about it not being used. But it is not used by CVS;
- it exists so one can call it from a debugger. */
-void printlist PROTO ((List *));
-
-void
-printlist (list)
- List *list;
-{
- if (list == NULL)
- {
- (void) printf("NULL list.\n");
- return;
- }
-
- (void) printf("List at %p: list = %p, HASHSIZE = %d, next = %p\n",
- (void *)list, (void *)list->list, HASHSIZE, (void *)list->next);
-
- (void) walklist(list, printnode, NULL);
-
- return;
-}
diff --git a/contrib/cvs/src/hash.h b/contrib/cvs/src/hash.h
deleted file mode 100644
index 77d095a4e00f..000000000000
--- a/contrib/cvs/src/hash.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- */
-
-/*
- * The number of buckets for the hash table contained in each list. This
- * should probably be prime.
- */
-#define HASHSIZE 151
-
-/*
- * Types of nodes
- */
-enum ntype
-{
- NT_UNKNOWN, HEADER, ENTRIES, FILES, LIST, RCSNODE,
- RCSVERS, DIRS, UPDATE, LOCK, NDBMNODE, FILEATTR,
- VARIABLE, RCSFIELD, RCSCMPFLD
-};
-typedef enum ntype Ntype;
-
-struct hashnode
-{
- Ntype type;
- struct hashnode *next;
- struct hashnode *prev;
- struct hashnode *hashnext;
- struct hashnode *hashprev;
- char *key;
- void *data;
- void (*delproc) ();
-};
-typedef struct hashnode Node;
-
-struct hashlist
-{
- Node *list;
- Node *hasharray[HASHSIZE];
- struct hashlist *next;
-};
-typedef struct hashlist List;
-
-List *getlist PROTO((void));
-Node *findnode PROTO((List * list, const char *key));
-Node *findnode_fn PROTO((List * list, const char *key));
-Node *getnode PROTO((void));
-int insert_before PROTO((List * list, Node * marker, Node * p));
-int addnode PROTO((List * list, Node * p));
-int addnode_at_front PROTO((List * list, Node * p));
-int walklist PROTO((List * list, int (*)(Node *n, void *closure), void *closure));
-int list_isempty PROTO ((List *list));
-void dellist PROTO((List ** listp));
-void delnode PROTO((Node * p));
-void freenode PROTO((Node * p));
-void sortlist PROTO((List * list, int (*)(const Node *, const Node *)));
-int fsortcmp PROTO((const Node * p, const Node * q));
diff --git a/contrib/cvs/src/history.c b/contrib/cvs/src/history.c
deleted file mode 100644
index 78fa0fecd4fc..000000000000
--- a/contrib/cvs/src/history.c
+++ /dev/null
@@ -1,1666 +0,0 @@
-/*
- * Copyright (C) 1994-2005 The Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-/* **************** History of Users and Module ****************
- *
- * LOGGING: Append record to "${CVSROOT}/CVSROOTADM/CVSROOTADM_HISTORY".
- *
- * On For each Tag, Add, Checkout, Commit, Update or Release command,
- * one line of text is written to a History log.
- *
- * X date | user | CurDir | special | rev(s) | argument '\n'
- *
- * where: [The spaces in the example line above are not in the history file.]
- *
- * X is a single character showing the type of event:
- * T "Tag" cmd.
- * O "Checkout" cmd.
- * E "Export" cmd.
- * F "Release" cmd.
- * W "Update" cmd - No User file, Remove from Entries file.
- * U "Update" cmd - File was checked out over User file.
- * P "Update" cmd - User file was patched.
- * G "Update" cmd - File was merged successfully.
- * C "Update" cmd - File was merged and shows overlaps.
- * M "Commit" cmd - "Modified" file.
- * A "Commit" cmd - "Added" file.
- * R "Commit" cmd - "Removed" file.
- *
- * date is a fixed length 8-char hex representation of a Unix time_t.
- * [Starting here, variable fields are delimited by '|' chars.]
- *
- * user is the username of the person who typed the command.
- *
- * CurDir The directory where the action occurred. This should be the
- * absolute path of the directory which is at the same level as
- * the "Repository" field (for W,U,P,G,C & M,A,R).
- *
- * Repository For record types [W,U,P,G,C,M,A,R] this field holds the
- * repository read from the administrative data where the
- * command was typed.
- * T "A" --> New Tag, "D" --> Delete Tag
- * Otherwise it is the Tag or Date to modify.
- * O,F,E A "" (null field)
- *
- * rev(s) Revision number or tag.
- * T The Tag to apply.
- * O,E The Tag or Date, if specified, else "" (null field).
- * F "" (null field)
- * W The Tag or Date, if specified, else "" (null field).
- * U,P The Revision checked out over the User file.
- * G,C The Revision(s) involved in merge.
- * M,A,R RCS Revision affected.
- *
- * argument The module (for [TOEF]) or file (for [WUPGCMAR]) affected.
- *
- *
- *** Report categories: "User" and "Since" modifiers apply to all reports.
- * [For "sort" ordering see the "sort_order" routine.]
- *
- * Extract list of record types
- *
- * -e, -x [TOEFWUPGCMAR]
- *
- * Extracted records are simply printed, No analysis is performed.
- * All "field" modifiers apply. -e chooses all types.
- *
- * Checked 'O'ut modules
- *
- * -o, -w
- * Checked out modules. 'F' and 'O' records are examined and if
- * the last record for a repository/file is an 'O', a line is
- * printed. "-w" forces the "working dir" to be used in the
- * comparison instead of the repository.
- *
- * Committed (Modified) files
- *
- * -c, -l, -w
- * All 'M'odified, 'A'dded and 'R'emoved records are examined.
- * "Field" modifiers apply. -l forces a sort by file within user
- * and shows only the last modifier. -w works as in Checkout.
- *
- * Warning: Be careful with what you infer from the output of
- * "cvs hi -c -l". It means the last time *you*
- * changed the file, not the list of files for which
- * you were the last changer!!!
- *
- * Module history for named modules.
- * -m module, -l
- *
- * This is special. If one or more modules are specified, the
- * module names are remembered and the files making up the
- * modules are remembered. Only records matching exactly those
- * files and repositories are shown. Sorting by "module", then
- * filename, is implied. If -l ("last modified") is specified,
- * then "update" records (types WUPCG), tag and release records
- * are ignored and the last (by date) "modified" record.
- *
- * TAG history
- *
- * -T All Tag records are displayed.
- *
- *** Modifiers.
- *
- * Since ... [All records contain a timestamp, so any report
- * category can be limited by date.]
- *
- * -D date - The "date" is parsed into a Unix "time_t" and
- * records with an earlier time stamp are ignored.
- * -r rev/tag - A "rev" begins with a digit. A "tag" does not. If
- * you use this option, every file is searched for the
- * indicated rev/tag.
- * -t tag - The "tag" is searched for in the history file and no
- * record is displayed before the tag is found. An
- * error is printed if the tag is never found.
- * -b string - Records are printed only back to the last reference
- * to the string in the "module", "file" or
- * "repository" fields.
- *
- * Field Selections [Simple comparisons on existing fields. All field
- * selections are repeatable.]
- *
- * -a - All users.
- * -u user - If no user is given and '-a' is not given, only
- * records for the user typing the command are shown.
- * ==> If -a or -u is not specified, just use "self".
- *
- * -f filematch - Only records in which the "file" field contains the
- * string "filematch" are considered.
- *
- * -p repository - Only records in which the "repository" string is a
- * prefix of the "repos" field are considered.
- *
- * -n modulename - Only records which contain "modulename" in the
- * "module" field are considered.
- *
- *
- * EXAMPLES: ("cvs history", "cvs his" or "cvs hi")
- *
- *** Checked out files for username. (default self, e.g. "dgg")
- * cvs hi [equivalent to: "cvs hi -o -u dgg"]
- * cvs hi -u user [equivalent to: "cvs hi -o -u user"]
- * cvs hi -o [equivalent to: "cvs hi -o -u dgg"]
- *
- *** Committed (modified) files from the beginning of the file.
- * cvs hi -c [-u user]
- *
- *** Committed (modified) files since Midnight, January 1, 1990:
- * cvs hi -c -D 'Jan 1 1990' [-u user]
- *
- *** Committed (modified) files since tag "TAG" was stored in the history file:
- * cvs hi -c -t TAG [-u user]
- *
- *** Committed (modified) files since tag "TAG" was placed on the files:
- * cvs hi -c -r TAG [-u user]
- *
- *** Who last committed file/repository X?
- * cvs hi -c -l -[fp] X
- *
- *** Modified files since tag/date/file/repos?
- * cvs hi -c {-r TAG | -D Date | -b string}
- *
- *** Tag history
- * cvs hi -T
- *
- *** History of file/repository/module X.
- * cvs hi -[fpn] X
- *
- *** History of user "user".
- * cvs hi -e -u user
- *
- *** Dump (eXtract) specified record types
- * cvs hi -x [TOEFWUPGCMAR]
- *
- *
- * FUTURE: J[Join], I[Import] (Not currently implemented.)
- *
- */
-
-#include "cvs.h"
-#include "history.h"
-#include "savecwd.h"
-
-static struct hrec
-{
- char *type; /* Type of record (In history record) */
- char *user; /* Username (In history record) */
- char *dir; /* "Compressed" Working dir (In history record) */
- char *repos; /* (Tag is special.) Repository (In history record) */
- char *rev; /* Revision affected (In history record) */
- char *file; /* Filename (In history record) */
- char *end; /* Ptr into repository to copy at end of workdir */
- char *mod; /* The module within which the file is contained */
- time_t date; /* Calculated from date stored in record */
- long idx; /* Index of record, for "stable" sort. */
-} *hrec_head;
-static long hrec_idx;
-
-
-static void fill_hrec PROTO((char *line, struct hrec * hr));
-static int accept_hrec PROTO((struct hrec * hr, struct hrec * lr));
-static int select_hrec PROTO((struct hrec * hr));
-static int sort_order PROTO((const PTR l, const PTR r));
-static int within PROTO((char *find, char *string));
-static void expand_modules PROTO((void));
-static void read_hrecs PROTO((char *fname));
-static void report_hrecs PROTO((void));
-static void save_file PROTO((char *dir, char *name, char *module));
-static void save_module PROTO((char *module));
-static void save_user PROTO((char *name));
-
-#define USER_INCREMENT 2
-#define FILE_INCREMENT 128
-#define MODULE_INCREMENT 5
-#define HREC_INCREMENT 128
-
-static short report_count;
-
-static short extract;
-static short extract_all;
-static short v_checkout;
-static short modified;
-static short tag_report;
-static short module_report;
-static short working;
-static short last_entry;
-static short all_users;
-
-static short user_sort;
-static short repos_sort;
-static short file_sort;
-static short module_sort;
-
-static short tz_local;
-static time_t tz_seconds_east_of_GMT;
-static char *tz_name = "+0000";
-
-char *logHistory;
-
-/* -r, -t, or -b options, malloc'd. These are "" if the option in
- question is not specified or is overridden by another option. The
- main reason for using "" rather than NULL is historical. Together
- with since_date, these are a mutually exclusive set; one overrides the
- others. */
-static char *since_rev;
-static char *since_tag;
-static char *backto;
-/* -D option, or 0 if not specified. RCS format. */
-static char * since_date;
-
-static struct hrec *last_since_tag;
-static struct hrec *last_backto;
-
-/* Record types to look for, malloc'd. Probably could be statically
- allocated, but only if we wanted to check for duplicates more than
- we do. */
-static char *rec_types;
-
-static size_t hrec_count;
-static size_t hrec_max;
-
-static char **user_list; /* Ptr to array of ptrs to user names */
-static size_t user_max; /* Number of elements allocated */
-static size_t user_count; /* Number of elements used */
-
-static struct file_list_str
-{
- char *l_file;
- char *l_module;
-} *file_list; /* Ptr to array file name structs */
-static size_t file_max; /* Number of elements allocated */
-static size_t file_count; /* Number of elements used */
-
-static char **mod_list; /* Ptr to array of ptrs to module names */
-static size_t mod_max; /* Number of elements allocated */
-static size_t mod_count; /* Number of elements used */
-
-static char *histfile; /* Ptr to the history file name */
-
-/* This is pretty unclear. First of all, separating "flags" vs.
- "options" (I think the distinction is that "options" take arguments)
- is nonstandard, and not something we do elsewhere in CVS. Second of
- all, what does "reports" mean? I think it means that you can only
- supply one of those options, but "reports" hardly has that meaning in
- a self-explanatory way. */
-static const char *const history_usg[] =
-{
- "Usage: %s %s [-report] [-flags] [-options args] [files...]\n\n",
- " Reports:\n",
- " -T Produce report on all TAGs\n",
- " -c Committed (Modified) files\n",
- " -o Checked out modules\n",
- " -m <module> Look for specified module (repeatable)\n",
- " -x [" ALL_HISTORY_REC_TYPES "] Extract by record type\n",
- " -e Everything (same as -x, but all record types)\n",
- " Flags:\n",
- " -a All users (Default is self)\n",
- " -l Last modified (committed or modified report)\n",
- " -w Working directory must match\n",
- " Options:\n",
- " -D <date> Since date (Many formats)\n",
- " -b <str> Back to record with str in module/file/repos field\n",
- " -f <file> Specified file (same as command line) (repeatable)\n",
- " -n <modulename> In module (repeatable)\n",
- " -p <repos> In repository (repeatable)\n",
- " -r <rev/tag> Since rev or tag (looks inside RCS files!)\n",
- " -t <tag> Since tag record placed in history file (by anyone).\n",
- " -u <user> For user name (repeatable)\n",
- " -z <tz> Output for time zone <tz> (e.g. -z -0700)\n",
- NULL};
-
-/* Sort routine for qsort:
- - If a user is selected at all, sort it first. User-within-file is useless.
- - If a module was selected explicitly, sort next on module.
- - Then sort by file. "File" is "repository/file" unless "working" is set,
- then it is "workdir/file". (Revision order should always track date.)
- - Always sort timestamp last.
-*/
-static int
-sort_order (l, r)
- const PTR l;
- const PTR r;
-{
- int i;
- const struct hrec *left = (const struct hrec *) l;
- const struct hrec *right = (const struct hrec *) r;
-
- if (user_sort) /* If Sort by username, compare users */
- {
- if ((i = strcmp (left->user, right->user)) != 0)
- return (i);
- }
- if (module_sort) /* If sort by modules, compare module names */
- {
- if (left->mod && right->mod)
- if ((i = strcmp (left->mod, right->mod)) != 0)
- return (i);
- }
- if (repos_sort) /* If sort by repository, compare them. */
- {
- if ((i = strcmp (left->repos, right->repos)) != 0)
- return (i);
- }
- if (file_sort) /* If sort by filename, compare files, NOT dirs. */
- {
- if ((i = strcmp (left->file, right->file)) != 0)
- return (i);
-
- if (working)
- {
- if ((i = strcmp (left->dir, right->dir)) != 0)
- return (i);
-
- if ((i = strcmp (left->end, right->end)) != 0)
- return (i);
- }
- }
-
- /*
- * By default, sort by date, time
- * XXX: This fails after 2030 when date slides into sign bit
- */
- if ((i = ((long) (left->date) - (long) (right->date))) != 0)
- return (i);
-
- /* For matching dates, keep the sort stable by using record index */
- return (left->idx - right->idx);
-}
-
-int
-history (argc, argv)
- int argc;
- char **argv;
-{
- int i, c;
- char *fname;
-
- if (argc == -1)
- usage (history_usg);
-
- since_rev = xstrdup ("");
- since_tag = xstrdup ("");
- backto = xstrdup ("");
- rec_types = xstrdup ("");
- optind = 0;
- while ((c = getopt (argc, argv, "+Tacelow?D:b:f:m:n:p:r:t:u:x:X:z:")) != -1)
- {
- switch (c)
- {
- case 'T': /* Tag list */
- report_count++;
- tag_report++;
- break;
- case 'a': /* For all usernames */
- all_users++;
- break;
- case 'c':
- report_count++;
- modified = 1;
- break;
- case 'e':
- report_count++;
- extract_all++;
- free (rec_types);
- rec_types = xstrdup (ALL_HISTORY_REC_TYPES);
- break;
- case 'l': /* Find Last file record */
- last_entry = 1;
- break;
- case 'o':
- report_count++;
- v_checkout = 1;
- break;
- case 'w': /* Match Working Dir (CurDir) fields */
- working = 1;
- break;
- case 'X': /* Undocumented debugging flag */
-#ifdef DEBUG
- histfile = optarg;
-#endif
- break;
-
- case 'D': /* Since specified date */
- if (*since_rev || *since_tag || *backto)
- {
- error (0, 0, "date overriding rev/tag/backto");
- *since_rev = *since_tag = *backto = '\0';
- }
- since_date = Make_Date (optarg);
- break;
- case 'b': /* Since specified file/Repos */
- if (since_date || *since_rev || *since_tag)
- {
- error (0, 0, "backto overriding date/rev/tag");
- *since_rev = *since_tag = '\0';
- if (since_date != NULL)
- free (since_date);
- since_date = NULL;
- }
- free (backto);
- backto = xstrdup (optarg);
- break;
- case 'f': /* For specified file */
- save_file (NULL, optarg, NULL);
- break;
- case 'm': /* Full module report */
- if (!module_report++) report_count++;
- /* fall through */
- case 'n': /* Look for specified module */
- save_module (optarg);
- break;
- case 'p': /* For specified directory */
- save_file (optarg, NULL, NULL);
- break;
- case 'r': /* Since specified Tag/Rev */
- if (since_date || *since_tag || *backto)
- {
- error (0, 0, "rev overriding date/tag/backto");
- *since_tag = *backto = '\0';
- if (since_date != NULL)
- free (since_date);
- since_date = NULL;
- }
- free (since_rev);
- since_rev = xstrdup (optarg);
- break;
- case 't': /* Since specified Tag/Rev */
- if (since_date || *since_rev || *backto)
- {
- error (0, 0, "tag overriding date/marker/file/repos");
- *since_rev = *backto = '\0';
- if (since_date != NULL)
- free (since_date);
- since_date = NULL;
- }
- free (since_tag);
- since_tag = xstrdup (optarg);
- break;
- case 'u': /* For specified username */
- save_user (optarg);
- break;
- case 'x':
- report_count++;
- extract++;
- {
- char *cp;
-
- for (cp = optarg; *cp; cp++)
- if (!strchr (ALL_HISTORY_REC_TYPES, *cp))
- error (1, 0, "%c is not a valid report type", *cp);
- }
- free (rec_types);
- rec_types = xstrdup (optarg);
- break;
- case 'z':
- tz_local =
- (optarg[0] == 'l' || optarg[0] == 'L')
- && (optarg[1] == 't' || optarg[1] == 'T')
- && !optarg[2];
- if (tz_local)
- tz_name = optarg;
- else
- {
- /*
- * Convert a known time with the given timezone to time_t.
- * Use the epoch + 23 hours, so timezones east of GMT work.
- */
- static char f[] = "1/1/1970 23:00 %s";
- char *buf = xmalloc (sizeof (f) - 2 + strlen (optarg));
- time_t t;
- sprintf (buf, f, optarg);
- t = get_date (buf, (struct timeb *) NULL);
- free (buf);
- if (t == (time_t) -1)
- error (0, 0, "%s is not a known time zone", optarg);
- else
- {
- /*
- * Convert to seconds east of GMT, removing the
- * 23-hour offset mentioned above.
- */
- tz_seconds_east_of_GMT = (time_t)23 * 60 * 60 - t;
- tz_name = optarg;
- }
- }
- break;
- case '?':
- default:
- usage (history_usg);
- break;
- }
- }
- argc -= optind;
- argv += optind;
- for (i = 0; i < argc; i++)
- save_file (NULL, argv[i], NULL);
-
-
- /* ================ Now analyze the arguments a bit */
- if (!report_count)
- v_checkout++;
- else if (report_count > 1)
- error (1, 0, "Only one report type allowed from: \"-Tcomxe\".");
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- struct file_list_str *f1;
- char **mod;
-
- /* We're the client side. Fire up the remote server. */
- start_server ();
-
- ign_setup ();
-
- if (tag_report)
- send_arg("-T");
- if (all_users)
- send_arg("-a");
- if (modified)
- send_arg("-c");
- if (last_entry)
- send_arg("-l");
- if (v_checkout)
- send_arg("-o");
- if (working)
- send_arg("-w");
- if (histfile)
- send_arg("-X");
- if (since_date)
- client_senddate (since_date);
- if (backto[0] != '\0')
- option_with_arg ("-b", backto);
- for (f1 = file_list; f1 < &file_list[file_count]; ++f1)
- {
- if (f1->l_file[0] == '*')
- option_with_arg ("-p", f1->l_file + 1);
- else
- option_with_arg ("-f", f1->l_file);
- }
- if (module_report)
- send_arg("-m");
- for (mod = mod_list; mod < &mod_list[mod_count]; ++mod)
- option_with_arg ("-n", *mod);
- if (*since_rev)
- option_with_arg ("-r", since_rev);
- if (*since_tag)
- option_with_arg ("-t", since_tag);
- for (mod = user_list; mod < &user_list[user_count]; ++mod)
- option_with_arg ("-u", *mod);
- if (extract_all)
- send_arg("-e");
- if (extract)
- option_with_arg ("-x", rec_types);
- option_with_arg ("-z", tz_name);
-
- send_to_server ("history\012", 0);
- return get_responses_and_close ();
- }
-#endif
-
- if (all_users)
- save_user ("");
-
- if (mod_list)
- expand_modules ();
-
- if (tag_report)
- {
- if (!strchr (rec_types, 'T'))
- {
- rec_types = xrealloc (rec_types, strlen (rec_types) + 5);
- (void) strcat (rec_types, "T");
- }
- }
- else if (extract || extract_all)
- {
- if (user_list)
- user_sort++;
- }
- else if (modified)
- {
- free (rec_types);
- rec_types = xstrdup ("MAR");
- /*
- * If the user has not specified a date oriented flag ("Since"), sort
- * by Repository/file before date. Default is "just" date.
- */
- if (last_entry
- || (!since_date && !*since_rev && !*since_tag && !*backto))
- {
- repos_sort++;
- file_sort++;
- /*
- * If we are not looking for last_modified and the user specified
- * one or more users to look at, sort by user before filename.
- */
- if (!last_entry && user_list)
- user_sort++;
- }
- }
- else if (module_report)
- {
- free (rec_types);
- rec_types = xstrdup (last_entry ? "OMAR" : ALL_HISTORY_REC_TYPES);
- module_sort++;
- repos_sort++;
- file_sort++;
- working = 0; /* User's workdir doesn't count here */
- }
- else
- /* Must be "checkout" or default */
- {
- free (rec_types);
- rec_types = xstrdup ("OF");
- /* See comments in "modified" above */
- if (!last_entry && user_list)
- user_sort++;
- if (last_entry
- || (!since_date && !*since_rev && !*since_tag && !*backto))
- file_sort++;
- }
-
- /* If no users were specified, use self (-a saves a universal ("") user) */
- if (!user_list)
- save_user (getcaller ());
-
- /* If we're looking back to a Tag value, must consider "Tag" records */
- if (*since_tag && !strchr (rec_types, 'T'))
- {
- rec_types = xrealloc (rec_types, strlen (rec_types) + 5);
- (void) strcat (rec_types, "T");
- }
-
- if (histfile)
- fname = xstrdup (histfile);
- else
- {
- fname = xmalloc (strlen (current_parsed_root->directory) + sizeof (CVSROOTADM)
- + sizeof (CVSROOTADM_HISTORY) + 10);
- (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
- CVSROOTADM, CVSROOTADM_HISTORY);
- }
-
- read_hrecs (fname);
- if(hrec_count>0)
- {
- qsort ((PTR) hrec_head, hrec_count,
- sizeof (struct hrec), sort_order);
- }
- report_hrecs ();
- free (fname);
- if (since_date != NULL)
- free (since_date);
- free (since_rev);
- free (since_tag);
- free (backto);
- free (rec_types);
-
- return (0);
-}
-
-void
-history_write (type, update_dir, revs, name, repository)
- int type;
- const char *update_dir;
- const char *revs;
- const char *name;
- const char *repository;
-{
- char *fname;
- char *workdir;
- char *username = getcaller ();
- int fd;
- char *line;
- char *slash = "", *cp;
- const char *cp2, *repos;
- int i;
- static char *tilde = "";
- static char *PrCurDir = NULL;
-
- if (logoff) /* History is turned off by noexec or
- * readonlyfs.
- */
- return;
- if (strchr (logHistory, type) == NULL)
- return;
- fname = xmalloc (strlen (current_parsed_root->directory)
- + sizeof (CVSROOTADM)
- + sizeof (CVSROOTADM_HISTORY) + 3);
- (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
- CVSROOTADM, CVSROOTADM_HISTORY);
-
- /* turn off history logging if the history file does not exist */
- /* FIXME: This should check for write permissions instead. This way,
- * O_CREATE could be added back into the call to open() below and
- * there would be no race condition involved in log rotation.
- *
- * Note that the new method of turning off logging would be either via
- * the CVSROOT/config file (probably the quicker method, but would need
- * to be added, or at least checked for, too) or by creating a dummy
- * history file with 0444 permissions.
- */
- if (!isfile (fname))
- {
- logoff = 1;
- goto out;
- }
-
- if (trace)
- fprintf (stderr, "%s-> fopen(%s,a)\n",
- CLIENT_SERVER_STR, fname);
- if (noexec)
- goto out;
-
- if (!history_lock (current_parsed_root->directory))
- /* history_lock() will already have printed an error on failure. */
- goto out;
-
- fd = CVS_OPEN (fname, O_WRONLY | O_APPEND | OPEN_BINARY, 0666);
- if (fd < 0)
- {
- if (! really_quiet)
- {
- error (0, errno, "warning: cannot write to history file %s",
- fname);
- }
- goto out;
- }
-
- repos = Short_Repository (repository);
-
- if (!PrCurDir)
- {
- char *pwdir;
-
- pwdir = get_homedir ();
- PrCurDir = CurDir;
- if (pwdir != NULL)
- {
- /* Assumes neither CurDir nor pwdir ends in '/' */
- i = strlen (pwdir);
- if (!strncmp (CurDir, pwdir, i))
- {
- PrCurDir += i; /* Point to '/' separator */
- tilde = "~";
- }
- else
- {
- /* Try harder to find a "homedir" */
- struct saved_cwd cwd;
- char *homedir;
-
- if (save_cwd (&cwd))
- error_exit ();
-
- if (CVS_CHDIR (pwdir) < 0 || (homedir = xgetwd ()) == NULL)
- homedir = pwdir;
-
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- free_cwd (&cwd);
-
- i = strlen (homedir);
- if (!strncmp (CurDir, homedir, i))
- {
- PrCurDir += i; /* Point to '/' separator */
- tilde = "~";
- }
-
- if (homedir != pwdir)
- free (homedir);
- }
- }
- }
-
- if (type == 'T')
- {
- repos = update_dir;
- update_dir = "";
- }
- else if (update_dir && *update_dir)
- slash = "/";
- else
- update_dir = "";
-
- workdir = xmalloc (strlen (tilde) + strlen (PrCurDir) + strlen (slash)
- + strlen (update_dir) + 10);
- (void) sprintf (workdir, "%s%s%s%s", tilde, PrCurDir, slash, update_dir);
-
- /*
- * "workdir" is the directory where the file "name" is. ("^~" == $HOME)
- * "repos" is the Repository, relative to $CVSROOT where the RCS file is.
- *
- * "$workdir/$name" is the working file name.
- * "$CVSROOT/$repos/$name,v" is the RCS file in the Repository.
- *
- * First, note that the history format was intended to save space, not
- * to be human readable.
- *
- * The working file directory ("workdir") and the Repository ("repos")
- * usually end with the same one or more directory elements. To avoid
- * duplication (and save space), the "workdir" field ends with
- * an integer offset into the "repos" field. This offset indicates the
- * beginning of the "tail" of "repos", after which all characters are
- * duplicates.
- *
- * In other words, if the "workdir" field has a '*' (a very stupid thing
- * to put in a filename) in it, then every thing following the last '*'
- * is a hex offset into "repos" of the first character from "repos" to
- * append to "workdir" to finish the pathname.
- *
- * It might be easier to look at an example:
- *
- * M273b3463|dgg|~/work*9|usr/local/cvs/examples|1.2|loginfo
- *
- * Indicates that the workdir is really "~/work/cvs/examples", saving
- * 10 characters, where "~/work*d" would save 6 characters and mean that
- * the workdir is really "~/work/examples". It will mean more on
- * directories like: usr/local/gnu/emacs/dist-19.17/lisp/term
- *
- * "workdir" is always an absolute pathname (~/xxx is an absolute path)
- * "repos" is always a relative pathname. So we can assume that we will
- * never run into the top of "workdir" -- there will always be a '/' or
- * a '~' at the head of "workdir" that is not matched by anything in
- * "repos". On the other hand, we *can* run off the top of "repos".
- *
- * Only "compress" if we save characters.
- */
-
- if (!repos)
- repos = "";
-
- cp = workdir + strlen (workdir) - 1;
- cp2 = repos + strlen (repos) - 1;
- for (i = 0; cp2 >= repos && cp > workdir && *cp == *cp2--; cp--)
- i++;
-
- if (i > 2)
- {
- i = strlen (repos) - i;
- (void) sprintf ((cp + 1), "*%x", i);
- }
-
- if (!revs)
- revs = "";
- line = xmalloc (strlen (username) + strlen (workdir) + strlen (repos)
- + strlen (revs) + strlen (name) + 100);
- sprintf (line, "%c%08lx|%s|%s|%s|%s|%s\n",
- type, (long) time ((time_t *) NULL),
- username, workdir, repos, revs, name);
-
- /* Lessen some race conditions on non-Posix-compliant hosts. */
- if (lseek (fd, (off_t) 0, SEEK_END) == -1)
- error (1, errno, "cannot seek to end of history file: %s", fname);
-
- if (write (fd, line, strlen (line)) < 0)
- error (1, errno, "cannot write to history file: %s", fname);
- free (line);
- if (close (fd) != 0)
- error (1, errno, "cannot close history file: %s", fname);
- free (workdir);
- out:
- clear_history_lock ();
- free (fname);
-}
-
-/*
- * save_user() adds a user name to the user list to select. Zero-length
- * username ("") matches any user.
- */
-static void
-save_user (name)
- char *name;
-{
- if (user_count == user_max)
- {
- user_max = xsum (user_max, USER_INCREMENT);
- if (user_count == user_max
- || size_overflow_p (xtimes (user_max, sizeof (char *))))
- {
- error (0, 0, "save_user: too many users");
- return;
- }
- user_list = xrealloc (user_list, xtimes (user_max, sizeof (char *)));
- }
- user_list[user_count++] = xstrdup (name);
-}
-
-/*
- * save_file() adds file name and associated module to the file list to select.
- *
- * If "dir" is null, store a file name as is.
- * If "name" is null, store a directory name with a '*' on the front.
- * Else, store concatenated "dir/name".
- *
- * Later, in the "select" stage:
- * - if it starts with '*', it is prefix-matched against the repository.
- * - if it has a '/' in it, it is matched against the repository/file.
- * - else it is matched against the file name.
- */
-static void
-save_file (dir, name, module)
- char *dir;
- char *name;
- char *module;
-{
- char *cp;
- struct file_list_str *fl;
-
- if (file_count == file_max)
- {
- file_max = xsum (file_max, FILE_INCREMENT);
- if (file_count == file_max
- || size_overflow_p (xtimes (file_max, sizeof (*fl))))
- {
- error (0, 0, "save_file: too many files");
- return;
- }
- file_list = xrealloc (file_list, xtimes (file_max, sizeof (*fl)));
- }
- fl = &file_list[file_count++];
- fl->l_file = cp = xmalloc (dir ? strlen (dir) : 0
- + name ? strlen (name) : 0
- + 2);
- fl->l_module = module;
-
- if (dir && *dir)
- {
- if (name && *name)
- {
- (void) strcpy (cp, dir);
- (void) strcat (cp, "/");
- (void) strcat (cp, name);
- }
- else
- {
- *cp++ = '*';
- (void) strcpy (cp, dir);
- }
- }
- else
- {
- if (name && *name)
- {
- (void) strcpy (cp, name);
- }
- else
- {
- error (0, 0, "save_file: null dir and file name");
- }
- }
-}
-
-static void
-save_module (module)
- char *module;
-{
- if (mod_count == mod_max)
- {
- mod_max = xsum (mod_max, MODULE_INCREMENT);
- if (mod_count == mod_max
- || size_overflow_p (xtimes (mod_max, sizeof (char *))))
- {
- error (0, 0, "save_module: too many modules");
- return;
- }
- mod_list = xrealloc (mod_list, xtimes (mod_max, sizeof (char *)));
- }
- mod_list[mod_count++] = xstrdup (module);
-}
-
-static void
-expand_modules ()
-{
-}
-
-/* fill_hrec
- *
- * Take a ptr to 7-part history line, ending with a newline, for example:
- *
- * M273b3463|dgg|~/work*9|usr/local/cvs/examples|1.2|loginfo
- *
- * Split it into 7 parts and drop the parts into a "struct hrec".
- * 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; line[-1] = '\0'; \
- } while (0)
-
-static void
-fill_hrec (line, hr)
- char *line;
- struct hrec *hr;
-{
- char *cp;
- int c;
-
- hr->type = hr->user = hr->dir = hr->repos = hr->rev = hr->file =
- hr->end = hr->mod = NULL;
- hr->date = -1;
- hr->idx = ++hrec_idx;
-
- while (isspace ((unsigned char) *line))
- line++;
-
- hr->type = line++;
- hr->date = strtoul (line, &cp, 16);
- if (cp == line || *cp != '|')
- return;
- line = cp + 1;
- NEXT_BAR (user);
- NEXT_BAR (dir);
- if ((cp = strrchr (hr->dir, '*')) != NULL)
- {
- *cp++ = '\0';
- hr->end = line + strtoul (cp, NULL, 16);
- }
- else
- hr->end = line - 1; /* A handy pointer to '\0' */
- NEXT_BAR (repos);
- NEXT_BAR (rev);
- if (strchr ("FOET", *(hr->type)))
- hr->mod = line;
-
- NEXT_BAR (file);
-}
-
-
-#ifndef STAT_BLOCKSIZE
-#if HAVE_STRUCT_STAT_ST_BLKSIZE
-#define STAT_BLOCKSIZE(s) (s).st_blksize
-#else
-#define STAT_BLOCKSIZE(s) (4 * 1024)
-#endif
-#endif
-
-
-/* read_hrecs's job is to read the history file and fill in all the "hrec"
- * (history record) array elements with the ones we need to print.
- *
- * Logic:
- * - Read a block from the file.
- * - Walk through the block parsing line into hr records.
- * - if the hr isn't used, free its strings, if it is, bump the hrec counter
- * - at the end of a block, copy the end of the current block to the start
- * of space for the next block, then read in the next block. If we get less
- * than the whole block, we're done.
- */
-static void
-read_hrecs (fname)
- char *fname;
-{
- unsigned char *cpstart, *cpend, *cp, *nl;
- char *hrline;
- int i;
- int fd;
- struct stat st_buf;
-
- if ((fd = CVS_OPEN (fname, O_RDONLY | OPEN_BINARY)) < 0)
- error (1, errno, "cannot open history file: %s", fname);
-
- if (fstat (fd, &st_buf) < 0)
- error (1, errno, "can't stat history file");
-
- if (!(st_buf.st_size))
- error (1, 0, "history file is empty");
-
- cpstart = xmalloc (2 * STAT_BLOCKSIZE(st_buf));
- cpstart[0] = '\0';
- cp = cpend = cpstart;
-
- hrec_max = HREC_INCREMENT;
- hrec_head = xmalloc (hrec_max * sizeof (struct hrec));
- hrec_idx = 0;
-
- for (;;)
- {
- for (nl = cp; nl < cpend && *nl != '\n'; nl++)
- if (!isprint(*nl)) *nl = ' ';
-
- if (nl >= cpend)
- {
- if (nl - cp >= STAT_BLOCKSIZE(st_buf))
- {
- error(1, 0, "history line %ld too long (> %lu)", hrec_idx + 1,
- (unsigned long) STAT_BLOCKSIZE(st_buf));
- }
- if (nl > cp)
- memmove (cpstart, cp, nl - cp);
- nl = cpstart + (nl - cp);
- cp = cpstart;
- i = read (fd, nl, STAT_BLOCKSIZE(st_buf));
- if (i > 0)
- {
- cpend = nl + i;
- *cpend = '\0';
- continue;
- }
- if (i < 0)
- error (1, errno, "error reading history file");
- if (nl == cp) break;
- error (0, 0, "warning: no newline at end of history file");
- }
- *nl = '\0';
-
- if (hrec_count == hrec_max)
- {
- struct hrec *old_head = hrec_head;
-
- hrec_max = xsum (hrec_max, HREC_INCREMENT);
- if (hrec_count == hrec_max
- || size_overflow_p (xtimes (hrec_max, sizeof (struct hrec))))
- error (1, 0, "Too many history records in history file.");
-
- hrec_head = xrealloc (hrec_head,
- xtimes (hrec_max, sizeof (struct hrec)));
- if (last_since_tag)
- last_since_tag = hrec_head + (last_since_tag - old_head);
- if (last_backto)
- last_backto = hrec_head + (last_backto - old_head);
- }
-
- /* fill_hrec dates from when history read the entire
- history file in one chunk, and then records were pulled out
- by pointing to the various parts of this big chunk. This is
- why there are ugly hacks here: I don't want to completely
- re-write the whole history stuff right now. */
-
- hrline = xstrdup ((char *)cp);
- fill_hrec (hrline, &hrec_head[hrec_count]);
- if (select_hrec (&hrec_head[hrec_count]))
- hrec_count++;
- else
- free(hrline);
-
- cp = nl + 1;
- }
- free (cpstart);
- close (fd);
-
- /* Special selection problem: If "since_tag" is set, we have saved every
- * record from the 1st occurrence of "since_tag", when we want to save
- * records since the *last* occurrence of "since_tag". So what we have
- * to do is bump hrec_head forward and reduce hrec_count accordingly.
- */
- if (last_since_tag)
- {
- hrec_count -= (last_since_tag - hrec_head);
- hrec_head = last_since_tag;
- }
-
- /* Much the same thing is necessary for the "backto" option. */
- if (last_backto)
- {
- hrec_count -= (last_backto - hrec_head);
- hrec_head = last_backto;
- }
-}
-
-/* Utility program for determining whether "find" is inside "string" */
-static int
-within (find, string)
- char *find, *string;
-{
- int c, len;
-
- if (!find || !string)
- return (0);
-
- c = *find++;
- len = strlen (find);
-
- while (*string)
- {
- if (!(string = strchr (string, c)))
- return (0);
- string++;
- if (!strncmp (find, string, len))
- return (1);
- }
- return (0);
-}
-
-/* The purpose of "select_hrec" is to apply the selection criteria based on
- * the command arguments and defaults and return a flag indicating whether
- * this record should be remembered for printing.
- */
-static int
-select_hrec (hr)
- struct hrec *hr;
-{
- char **cpp, *cp, *cp2;
- struct file_list_str *fl;
- int count;
-
- /* basic validity checking */
- if (!hr->type || !hr->user || !hr->dir || !hr->repos || !hr->rev ||
- !hr->file || !hr->end)
- {
- error (0, 0, "warning: history line %ld invalid", hr->idx);
- return (0);
- }
-
- /* "Since" checking: The argument parser guarantees that only one of the
- * following four choices is set:
- *
- * 1. If "since_date" is set, it contains the date specified on the
- * command line. hr->date fields earlier than "since_date" are ignored.
- * 2. If "since_rev" is set, it contains either an RCS "dotted" revision
- * number (which is of limited use) or a symbolic TAG. Each RCS file
- * is examined and the date on the specified revision (or the revision
- * corresponding to the TAG) in the RCS file (CVSROOT/repos/file) is
- * compared against hr->date as in 1. above.
- * 3. If "since_tag" is set, matching tag records are saved. The field
- * "last_since_tag" is set to the last one of these. Since we don't
- * know where the last one will be, all records are saved from the
- * first occurrence of the TAG. Later, at the end of "select_hrec"
- * records before the last occurrence of "since_tag" are skipped.
- * 4. If "backto" is set, all records with a module name or file name
- * matching "backto" are saved. In addition, all records with a
- * repository field with a *prefix* matching "backto" are saved.
- * The field "last_backto" is set to the last one of these. As in
- * 3. above, "select_hrec" adjusts to include the last one later on.
- */
- if (since_date)
- {
- char *ourdate = date_from_time_t (hr->date);
- count = RCS_datecmp (ourdate, since_date);
- free (ourdate);
- if (count < 0)
- return (0);
- }
- else if (*since_rev)
- {
- Vers_TS *vers;
- time_t t;
- struct file_info finfo;
-
- memset (&finfo, 0, sizeof finfo);
- finfo.file = hr->file;
- /* Not used, so don't worry about it. */
- finfo.update_dir = NULL;
- finfo.fullname = finfo.file;
- finfo.repository = hr->repos;
- finfo.entries = NULL;
- finfo.rcs = NULL;
-
- vers = Version_TS (&finfo, (char *) NULL, since_rev, (char *) NULL,
- 1, 0);
- if (vers->vn_rcs)
- {
- if ((t = RCS_getrevtime (vers->srcfile, vers->vn_rcs, (char *) 0, 0))
- != (time_t) 0)
- {
- if (hr->date < t)
- {
- freevers_ts (&vers);
- return (0);
- }
- }
- }
- freevers_ts (&vers);
- }
- else if (*since_tag)
- {
- if (*(hr->type) == 'T')
- {
- /*
- * A 'T'ag record, the "rev" field holds the tag to be set,
- * while the "repos" field holds "D"elete, "A"dd or a rev.
- */
- if (within (since_tag, hr->rev))
- {
- last_since_tag = hr;
- return (1);
- }
- else
- return (0);
- }
- if (!last_since_tag)
- return (0);
- }
- else if (*backto)
- {
- if (within (backto, hr->file) || within (backto, hr->mod) ||
- within (backto, hr->repos))
- last_backto = hr;
- else
- return (0);
- }
-
- /* User checking:
- *
- * Run down "user_list", match username ("" matches anything)
- * If "" is not there and actual username is not there, return failure.
- */
- if (user_list && hr->user)
- {
- for (cpp = user_list, count = user_count; count; cpp++, count--)
- {
- if (!**cpp)
- break; /* null user == accept */
- if (!strcmp (hr->user, *cpp)) /* found listed user */
- break;
- }
- if (!count)
- return (0); /* Not this user */
- }
-
- /* Record type checking:
- *
- * 1. If Record type is not in rec_types field, skip it.
- * 2. If mod_list is null, keep everything. Otherwise keep only modules
- * on mod_list.
- * 3. If neither a 'T', 'F' nor 'O' record, run through "file_list". If
- * file_list is null, keep everything. Otherwise, keep only files on
- * file_list, matched appropriately.
- */
- if (!strchr (rec_types, *(hr->type)))
- return (0);
- if (!strchr ("TFOE", *(hr->type))) /* Don't bother with "file" if "TFOE" */
- {
- if (file_list) /* If file_list is null, accept all */
- {
- for (fl = file_list, count = file_count; count; fl++, count--)
- {
- /* 1. If file_list entry starts with '*', skip the '*' and
- * compare it against the repository in the hrec.
- * 2. If file_list entry has a '/' in it, compare it against
- * the concatenation of the repository and file from hrec.
- * 3. Else compare the file_list entry against the hrec file.
- */
- char *cmpfile = NULL;
-
- if (*(cp = fl->l_file) == '*')
- {
- cp++;
- /* if argument to -p is a prefix of repository */
- if (!strncmp (cp, hr->repos, strlen (cp)))
- {
- hr->mod = fl->l_module;
- break;
- }
- }
- else
- {
- if (strchr (cp, '/'))
- {
- cmpfile = xmalloc (strlen (hr->repos)
- + strlen (hr->file)
- + 10);
- (void) sprintf (cmpfile, "%s/%s",
- hr->repos, hr->file);
- cp2 = cmpfile;
- }
- else
- {
- cp2 = hr->file;
- }
-
- /* if requested file is found within {repos}/file fields */
- if (within (cp, cp2))
- {
- hr->mod = fl->l_module;
- if (cmpfile != NULL)
- free (cmpfile);
- break;
- }
- if (cmpfile != NULL)
- free (cmpfile);
- }
- }
- if (!count)
- return (0); /* String specified and no match */
- }
- }
- if (mod_list)
- {
- for (cpp = mod_list, count = mod_count; count; cpp++, count--)
- {
- if (hr->mod && !strcmp (hr->mod, *cpp)) /* found module */
- break;
- }
- if (!count)
- return (0); /* Module specified & this record is not one of them. */
- }
-
- return (1); /* Select this record unless rejected above. */
-}
-
-/* The "sort_order" routine (when handed to qsort) has arranged for the
- * hrecs files to be in the right order for the report.
- *
- * Most of the "selections" are done in the select_hrec routine, but some
- * selections are more easily done after the qsort by "accept_hrec".
- */
-static void
-report_hrecs ()
-{
- struct hrec *hr, *lr;
- struct tm *tm;
- int i, count, ty;
- char *cp;
- int user_len, file_len, rev_len, mod_len, repos_len;
-
- if (*since_tag && !last_since_tag)
- {
- (void) printf ("No tag found: %s\n", since_tag);
- return;
- }
- else if (*backto && !last_backto)
- {
- (void) printf ("No module, file or repository with: %s\n", backto);
- return;
- }
- else if (hrec_count < 1)
- {
- (void) printf ("No records selected.\n");
- return;
- }
-
- user_len = file_len = rev_len = mod_len = repos_len = 0;
-
- /* Run through lists and find maximum field widths */
- hr = lr = hrec_head;
- hr++;
- for (count = hrec_count; count--; lr = hr, hr++)
- {
- char *repos;
-
- if (!count)
- hr = NULL;
- if (!accept_hrec (lr, hr))
- continue;
-
- ty = *(lr->type);
- repos = xstrdup (lr->repos);
- if ((cp = strrchr (repos, '/')) != NULL)
- {
- if (lr->mod && !strcmp (++cp, lr->mod))
- {
- (void) strcpy (cp, "*");
- }
- }
- if ((i = strlen (lr->user)) > user_len)
- user_len = i;
- if ((i = strlen (lr->file)) > file_len)
- file_len = i;
- if (ty != 'T' && (i = strlen (repos)) > repos_len)
- repos_len = i;
- if (ty != 'T' && (i = strlen (lr->rev)) > rev_len)
- rev_len = i;
- if (lr->mod && (i = strlen (lr->mod)) > mod_len)
- mod_len = i;
- free (repos);
- }
-
- /* Walk through hrec array setting "lr" (Last Record) to each element.
- * "hr" points to the record following "lr" -- It is NULL in the last
- * pass.
- *
- * There are two sections in the loop below:
- * 1. Based on the report type (e.g. extract, checkout, tag, etc.),
- * decide whether the record should be printed.
- * 2. Based on the record type, format and print the data.
- */
- for (lr = hrec_head, hr = (lr + 1); hrec_count--; lr = hr, hr++)
- {
- char *workdir;
- char *repos;
-
- if (!hrec_count)
- hr = NULL;
- if (!accept_hrec (lr, hr))
- continue;
-
- ty = *(lr->type);
- if (!tz_local)
- {
- time_t t = lr->date + tz_seconds_east_of_GMT;
- tm = gmtime (&t);
- }
- else
- tm = localtime (&(lr->date));
-
- (void) printf ("%c %04d-%02d-%02d %02d:%02d %s %-*s", ty,
- tm->tm_year+1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
- tm->tm_min, tz_name, user_len, lr->user);
-
- workdir = xmalloc (strlen (lr->dir) + strlen (lr->end) + 10);
- (void) sprintf (workdir, "%s%s", lr->dir, lr->end);
- if ((cp = strrchr (workdir, '/')) != NULL)
- {
- if (lr->mod && !strcmp (++cp, lr->mod))
- {
- (void) strcpy (cp, "*");
- }
- }
- repos = xmalloc (strlen (lr->repos) + 10);
- (void) strcpy (repos, lr->repos);
- if ((cp = strrchr (repos, '/')) != NULL)
- {
- if (lr->mod && !strcmp (++cp, lr->mod))
- {
- (void) strcpy (cp, "*");
- }
- }
-
- switch (ty)
- {
- case 'T':
- /* 'T'ag records: repository is a "tag type", rev is the tag */
- (void) printf (" %-*s [%s:%s]", mod_len, lr->mod, lr->rev,
- repos);
- if (working)
- (void) printf (" {%s}", workdir);
- break;
- case 'F':
- case 'E':
- case 'O':
- if (lr->rev && *(lr->rev))
- (void) printf (" [%s]", lr->rev);
- (void) printf (" %-*s =%s%-*s %s", repos_len, repos, lr->mod,
- mod_len + 1 - (int) strlen (lr->mod),
- "=", workdir);
- break;
- case 'W':
- case 'U':
- case 'P':
- case 'C':
- case 'G':
- case 'M':
- case 'A':
- case 'R':
- (void) printf (" %-*s %-*s %-*s =%s= %s", rev_len, lr->rev,
- file_len, lr->file, repos_len, repos,
- lr->mod ? lr->mod : "", workdir);
- break;
- default:
- (void) printf ("Hey! What is this junk? RecType[0x%2.2x]", ty);
- break;
- }
- (void) putchar ('\n');
- free (workdir);
- free (repos);
- }
-}
-
-static int
-accept_hrec (lr, hr)
- struct hrec *hr, *lr;
-{
- int ty;
-
- ty = *(lr->type);
-
- if (last_since_tag && ty == 'T')
- return (1);
-
- if (v_checkout)
- {
- if (ty != 'O')
- return (0); /* Only interested in 'O' records */
-
- /* We want to identify all the states that cause the next record
- * ("hr") to be different from the current one ("lr") and only
- * print a line at the allowed boundaries.
- */
-
- if (!hr || /* The last record */
- strcmp (hr->user, lr->user) || /* User has changed */
- strcmp (hr->mod, lr->mod) ||/* Module has changed */
- (working && /* If must match "workdir" */
- (strcmp (hr->dir, lr->dir) || /* and the 1st parts or */
- strcmp (hr->end, lr->end)))) /* the 2nd parts differ */
-
- return (1);
- }
- else if (modified)
- {
- if (!last_entry || /* Don't want only last rec */
- !hr || /* Last entry is a "last entry" */
- strcmp (hr->repos, lr->repos) || /* Repository has changed */
- strcmp (hr->file, lr->file))/* File has changed */
- return (1);
-
- if (working)
- { /* If must match "workdir" */
- if (strcmp (hr->dir, lr->dir) || /* and the 1st parts or */
- strcmp (hr->end, lr->end)) /* the 2nd parts differ */
- return (1);
- }
- }
- else if (module_report)
- {
- if (!last_entry || /* Don't want only last rec */
- !hr || /* Last entry is a "last entry" */
- strcmp (hr->mod, lr->mod) ||/* Module has changed */
- strcmp (hr->repos, lr->repos) || /* Repository has changed */
- strcmp (hr->file, lr->file))/* File has changed */
- return (1);
- }
- else
- {
- /* "extract" and "tag_report" always print selected records. */
- return (1);
- }
-
- return (0);
-}
diff --git a/contrib/cvs/src/history.h b/contrib/cvs/src/history.h
deleted file mode 100644
index dadc4214c60d..000000000000
--- a/contrib/cvs/src/history.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) 2003-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 2003-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * You may distribute under the terms of the GNU General Public License
- * as specified in the README file that comes with the CVS source
- * distribution.
- *
- * This is the header file for definitions and functions shared by history.c
- * with other portions of CVS.
- */
-
-#define ALL_HISTORY_REC_TYPES "TOEFWUPCGMAR"
diff --git a/contrib/cvs/src/ignore.c b/contrib/cvs/src/ignore.c
deleted file mode 100644
index 65b226038c5c..000000000000
--- a/contrib/cvs/src/ignore.c
+++ /dev/null
@@ -1,503 +0,0 @@
-/* This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-/*
- * .cvsignore file support contributed by David G. Grubbs <dgg@odi.com>
- */
-
-#include "cvs.h"
-#include "getline.h"
-
-/*
- * Ignore file section.
- *
- * "!" may be included any time to reset the list (i.e. ignore nothing);
- * "*" may be specified to ignore everything. It stays as the first
- * element forever, unless a "!" clears it out.
- */
-
-static char **ign_list; /* List of files to ignore in update
- * and import */
-static char **s_ign_list = NULL;
-static int ign_count; /* Number of active entries */
-static int s_ign_count = 0;
-static int ign_size; /* This many slots available (plus
- * one for a NULL) */
-static int ign_hold = -1; /* Index where first "temporary" item
- * is held */
-
-const char *ign_default = ". .. core RCSLOG tags TAGS RCS SCCS .make.state\
- .nse_depinfo #* .#* cvslog.* ,* CVS CVS.adm .del-* *.a *.olb *.o *.obj\
- *.so *.Z *~ *.old *.elc *.ln *.bak *.BAK *.orig *.rej *.exe _$* *$";
-
-#define IGN_GROW 16 /* grow the list by 16 elements at a
- * time */
-
-/* Nonzero if we have encountered an -I ! directive, which means one should
- no longer ask the server about what is in CVSROOTADM_IGNORE. */
-int ign_inhibit_server;
-
-
-
-/*
- * To the "ignore list", add the hard-coded default ignored wildcards above,
- * the wildcards found in $CVSROOT/CVSROOT/cvsignore, the wildcards found in
- * ~/.cvsignore and the wildcards found in the CVSIGNORE environment
- * variable.
- */
-void
-ign_setup ()
-{
- char *home_dir;
- char *tmp;
-
- ign_inhibit_server = 0;
-
- /* Start with default list and special case */
- tmp = xstrdup (ign_default);
- ign_add (tmp, 0);
- free (tmp);
-
- /* The client handles another way, by (after it does its own ignore file
- processing, and only if !ign_inhibit_server), letting the server
- know about the files and letting it decide whether to ignore
- them based on CVSROOOTADM_IGNORE. */
- if (!current_parsed_root->isremote)
- {
- char *file = xmalloc (strlen (current_parsed_root->directory) + sizeof (CVSROOTADM)
- + sizeof (CVSROOTADM_IGNORE) + 10);
- /* Then add entries found in repository, if it exists */
- (void) sprintf (file, "%s/%s/%s", current_parsed_root->directory,
- CVSROOTADM, CVSROOTADM_IGNORE);
- ign_add_file (file, 0);
- free (file);
- }
-
- /* 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 = strcat_filename_onto_homedir (home_dir, CVSDOTIGNORE);
- ign_add_file (file, 0);
- free (file);
- }
-
- /* Then add entries found in CVSIGNORE environment variable. */
- ign_add (getenv (IGNORE_ENV), 0);
-
- /* Later, add ignore entries found in -I arguments */
-}
-
-
-
-/*
- * Open a file and read lines, feeding each line to a line parser. Arrange
- * for keeping a temporary list of wildcards at the end, if the "hold"
- * argument is set.
- */
-void
-ign_add_file (file, hold)
- char *file;
- int hold;
-{
- FILE *fp;
- char *line = NULL;
- size_t line_allocated = 0;
-
- /* restore the saved list (if any) */
- if (s_ign_list != NULL)
- {
- int i;
-
- for (i = 0; i < s_ign_count; i++)
- ign_list[i] = s_ign_list[i];
- ign_count = s_ign_count;
- ign_list[ign_count] = NULL;
-
- s_ign_count = 0;
- free (s_ign_list);
- s_ign_list = NULL;
- }
-
- /* is this a temporary ignore file? */
- if (hold)
- {
- /* re-set if we had already done a temporary file */
- if (ign_hold >= 0)
- {
- int i;
-
- for (i = ign_hold; i < ign_count; i++)
- free (ign_list[i]);
- ign_count = ign_hold;
- ign_list[ign_count] = NULL;
- }
- else
- {
- ign_hold = ign_count;
- }
- }
-
- /* load the file */
- fp = CVS_FOPEN (file, "r");
- if (fp == NULL)
- {
- if (! existence_error (errno))
- error (0, errno, "cannot open %s", file);
- return;
- }
- while (getline (&line, &line_allocated, fp) >= 0)
- ign_add (line, hold);
- if (ferror (fp))
- error (0, errno, "cannot read %s", file);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", file);
- free (line);
-}
-
-
-
-/* Parse a line of space-separated wildcards and add them to the list. */
-void
-ign_add (ign, hold)
- char *ign;
- int hold;
-{
- if (!ign || !*ign)
- return;
-
- for (; *ign; ign++)
- {
- char *mark;
- char save;
-
- /* ignore whitespace before the token */
- if (isspace ((unsigned char) *ign))
- continue;
-
- /* If we have used up all the space, add some more. Do this before
- processing `!', since an "empty" list still contains the `CVS'
- entry. */
- if (ign_count >= ign_size)
- {
- ign_size += IGN_GROW;
- ign_list = (char **) xrealloc ((char *) ign_list,
- (ign_size + 1) * sizeof (char *));
- }
-
- /*
- * if we find a single character !, we must re-set the ignore list
- * (saving it if necessary). We also catch * as a special case in a
- * global ignore file as an optimization
- */
- if ((!*(ign+1) || isspace ((unsigned char) *(ign+1)))
- && (*ign == '!' || *ign == '*'))
- {
- if (!hold)
- {
- /* permanently reset the ignore list */
- int i;
-
- for (i = 0; i < ign_count; i++)
- free (ign_list[i]);
- ign_count = 1;
- /* Always ignore the "CVS" directory. */
- ign_list[0] = xstrdup("CVS");
- ign_list[1] = NULL;
-
- /* if we are doing a '!', continue; otherwise add the '*' */
- if (*ign == '!')
- {
- ign_inhibit_server = 1;
- continue;
- }
- }
- else if (*ign == '!')
- {
- /* temporarily reset the ignore list */
- int i;
-
- if (ign_hold >= 0)
- {
- for (i = ign_hold; i < ign_count; i++)
- free (ign_list[i]);
- ign_hold = -1;
- }
- if (s_ign_list)
- {
- /* Don't save the ignore list twice - if there are two
- * bangs in a local .cvsignore file then we don't want to
- * save the new list the first bang created.
- *
- * We still need to free the "new" ignore list.
- */
- for (i = 0; i < ign_count; i++)
- free (ign_list[i]);
- }
- else
- {
- /* Save the ignore list for later. */
- s_ign_list = xmalloc (ign_count * sizeof (char *));
- for (i = 0; i < ign_count; i++)
- s_ign_list[i] = ign_list[i];
- s_ign_count = ign_count;
- }
- ign_count = 1;
- /* Always ignore the "CVS" directory. */
- ign_list[0] = xstrdup ("CVS");
- ign_list[1] = NULL;
- continue;
- }
- }
-
- /* find the end of this token */
- for (mark = ign; *mark && !isspace ((unsigned char) *mark); mark++)
- /* do nothing */ ;
-
- save = *mark;
- *mark = '\0';
-
- ign_list[ign_count++] = xstrdup (ign);
- ign_list[ign_count] = NULL;
-
- *mark = save;
- if (save)
- ign = mark;
- else
- ign = mark - 1;
- }
-}
-
-
-
-/* Return true if the given filename should be ignored by update or import,
- * else return false.
- */
-int
-ign_name (name)
- char *name;
-{
- char **cpp = ign_list;
-
- if (cpp == NULL)
- return 0;
-
- while (*cpp)
- if (CVS_FNMATCH (*cpp++, name, 0) == 0)
- return 1;
-
- return 0;
-}
-
-
-
-/* FIXME: This list of dirs to ignore stuff seems not to be used.
- Really? send_dirent_proc and update_dirent_proc both call
- ignore_directory and do_module calls ign_dir_add. No doubt could
- use some documentation/testsuite work. */
-
-static char **dir_ign_list = NULL;
-static int dir_ign_max = 0;
-static int dir_ign_current = 0;
-
-/* Add a directory to list of dirs to ignore. */
-void
-ign_dir_add (name)
- char *name;
-{
- /* Make sure we've got the space for the entry. */
- if (dir_ign_current <= dir_ign_max)
- {
- dir_ign_max += IGN_GROW;
- dir_ign_list =
- (char **) xrealloc (dir_ign_list,
- (dir_ign_max + 1) * sizeof (char *));
- }
-
- dir_ign_list[dir_ign_current++] = xstrdup (name);
-}
-
-
-/* Return nonzero if NAME is part of the list of directories to ignore. */
-
-int
-ignore_directory (name)
- const char *name;
-{
- int i;
-
- if (!dir_ign_list)
- return 0;
-
- i = dir_ign_current;
- while (i--)
- {
- if (strncmp (name, dir_ign_list[i], strlen (dir_ign_list[i])+1) == 0)
- return 1;
- }
-
- return 0;
-}
-
-
-
-/*
- * Process the current directory, looking for files not in ILIST and
- * not on the global ignore list for this directory. If we find one,
- * call PROC passing it the name of the file and the update dir.
- * ENTRIES is the entries list, which is used to identify known
- * directories. ENTRIES may be NULL, in which case we assume that any
- * directory with a CVS administration directory is known.
- */
-void
-ignore_files (ilist, entries, update_dir, proc)
- List *ilist;
- List *entries;
- const char *update_dir;
- Ignore_proc proc;
-{
- int subdirs;
- DIR *dirp;
- struct dirent *dp;
- struct stat sb;
- char *file;
- const char *xdir;
- List *files;
- Node *p;
-
- /* Set SUBDIRS if we have subdirectory information in ENTRIES. */
- if (entries == NULL)
- subdirs = 0;
- else
- {
- struct stickydirtag *sdtp = entries->list->data;
-
- subdirs = sdtp == NULL || sdtp->subdirs;
- }
-
- /* we get called with update_dir set to "." sometimes... strip it */
- if (strcmp (update_dir, ".") == 0)
- xdir = "";
- else
- xdir = update_dir;
-
- dirp = CVS_OPENDIR (".");
- if (dirp == NULL)
- {
- error (0, errno, "cannot open current directory");
- return;
- }
-
- ign_add_file (CVSDOTIGNORE, 1);
- wrap_add_file (CVSDOTWRAPPER, 1);
-
- /* Make a list for the files. */
- files = getlist ();
-
- while (errno = 0, (dp = CVS_READDIR (dirp)) != NULL)
- {
- file = dp->d_name;
- if (strcmp (file, ".") == 0 || strcmp (file, "..") == 0)
- continue;
- if (findnode_fn (ilist, file) != NULL)
- continue;
- if (subdirs)
- {
- Node *node;
-
- node = findnode_fn (entries, file);
- if (node != NULL
- && ((Entnode *) node->data)->type == ENT_SUBDIR)
- {
- char *p;
- int dir;
-
- /* For consistency with past behaviour, we only ignore
- this directory if there is a CVS subdirectory.
- This will normally be the case, but the user may
- have messed up the working directory somehow. */
- p = xmalloc (strlen (file) + sizeof CVSADM + 10);
- sprintf (p, "%s/%s", file, CVSADM);
- dir = isdir (p);
- free (p);
- if (dir)
- continue;
- }
- }
-
- /* We could be ignoring FIFOs and other files which are neither
- regular files nor directories here. */
- if (ign_name (file))
- continue;
-
- if (
-#ifdef DT_DIR
- dp->d_type != DT_UNKNOWN ||
-#endif
- CVS_LSTAT (file, &sb) != -1)
- {
-
- if (
-#ifdef DT_DIR
- dp->d_type == DT_DIR
- || (dp->d_type == DT_UNKNOWN && S_ISDIR (sb.st_mode))
-#else
- S_ISDIR (sb.st_mode)
-#endif
- )
- {
- if (! subdirs)
- {
- char *temp;
-
- temp = xmalloc (strlen (file) + sizeof (CVSADM) + 10);
- (void) sprintf (temp, "%s/%s", file, CVSADM);
- if (isdir (temp))
- {
- free (temp);
- continue;
- }
- free (temp);
- }
- }
-#ifdef S_ISLNK
- else if (
-#ifdef DT_DIR
- dp->d_type == DT_LNK
- || (dp->d_type == DT_UNKNOWN && S_ISLNK(sb.st_mode))
-#else
- S_ISLNK (sb.st_mode)
-#endif
- )
- {
- continue;
- }
-#endif
- }
-
- p = getnode ();
- p->type = FILES;
- p->key = xstrdup (file);
- (void) addnode (files, p);
- }
- if (errno != 0)
- error (0, errno, "error reading current directory");
- (void) CVS_CLOSEDIR (dirp);
-
- sortlist (files, fsortcmp);
- for (p = files->list->next; p != files->list; p = p->next)
- (*proc) (p->key, xdir);
- dellist (&files);
-}
diff --git a/contrib/cvs/src/import.c b/contrib/cvs/src/import.c
deleted file mode 100644
index bc918e04ff7f..000000000000
--- a/contrib/cvs/src/import.c
+++ /dev/null
@@ -1,1653 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * "import" checks in the vendor release located in the current directory into
- * the CVS source repository. The CVS vendor branch support is utilized.
- *
- * At least three arguments are expected to follow the options:
- * repository Where the source belongs relative to the CVSROOT
- * VendorTag Vendor's major tag
- * VendorReleTag Tag for this particular release
- *
- * Additional arguments specify more Vendor Release Tags.
- */
-
-#include "cvs.h"
-#include "savecwd.h"
-#include <assert.h>
-
-static char *get_comment PROTO((const char *user));
-static int add_rev PROTO((char *message, RCSNode *rcs, char *vfile,
- char *vers));
-static int add_tags PROTO((RCSNode *rcs, char *vfile, char *vtag, int targc,
- char *targv[]));
-static int import_descend PROTO((char *message, char *vtag, int targc, char *targv[]));
-static int import_descend_dir PROTO((char *message, char *dir, char *vtag,
- int targc, char *targv[]));
-static int process_import_file PROTO((char *message, char *vfile, char *vtag,
- int targc, char *targv[]));
-static int update_rcs_file PROTO((char *message, char *vfile, char *vtag, int targc,
- char *targv[], int inattic));
-static void add_log PROTO((int ch, char *fname));
-
-static int repos_len;
-static char *vhead;
-static char *vbranch;
-static FILE *logfp;
-static char *repository;
-static int conflicts;
-static int use_file_modtime;
-static char *keyword_opt = NULL;
-
-static const char *const import_usage[] =
-{
- "Usage: %s %s [-d] [-k subst] [-I ign] [-m msg] [-b branch]\n",
- " [-W spec] repository vendor-tag release-tags...\n",
- "\t-d\tUse the file's modification time as the time of import.\n",
- "\t-k sub\tSet default RCS keyword substitution mode.\n",
- "\t-I ign\tMore files to ignore (! to reset).\n",
- "\t-b bra\tVendor branch id.\n",
- "\t-m msg\tLog message.\n",
- "\t-W spec\tWrappers specification line.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-int
-import (argc, argv)
- int argc;
- char **argv;
-{
- char *message = NULL;
- char *tmpfile;
- char *cp;
- int i, c, msglen, err;
- List *ulist;
- Node *p;
- struct logfile_info *li;
-
- if (argc == -1)
- usage (import_usage);
-
- ign_setup ();
- wrap_setup ();
-
- vbranch = xstrdup (CVSBRANCH);
- optind = 0;
- while ((c = getopt (argc, argv, "+Qqdb:m:I:k:W:")) != -1)
- {
- switch (c)
- {
- case 'Q':
- case 'q':
- /* The CVS 1.5 client sends these options (in addition to
- Global_option requests), so we must ignore them. */
- if (!server_active)
- error (1, 0,
- "-q or -Q must be specified before \"%s\"",
- cvs_cmd_name);
- break;
- case 'd':
- if (server_active)
- {
- /* CVS 1.10 and older clients will send this, but it
- doesn't do any good. So tell the user we can't
- cope, rather than silently losing. */
- error (0, 0,
- "warning: not setting the time of import from the file");
- error (0, 0, "due to client limitations");
- }
- use_file_modtime = 1;
- break;
- case 'b':
- free (vbranch);
- vbranch = xstrdup (optarg);
- break;
- case 'm':
-#ifdef FORCE_USE_EDITOR
- use_editor = 1;
-#else
- use_editor = 0;
-#endif
- if (message) free (message);
- message = xstrdup(optarg);
- break;
- case 'I':
- ign_add (optarg, 0);
- break;
- case 'k':
- /* RCS_check_kflag returns strings of the form -kxx. We
- only use it for validation, so we can free the value
- as soon as it is returned. */
- free (RCS_check_kflag (optarg));
- keyword_opt = optarg;
- break;
- case 'W':
- wrap_add (optarg, 0);
- break;
- case '?':
- default:
- usage (import_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc < 3)
- usage (import_usage);
-
- /* This is for handling the Checkin-time request. It might seem a
- bit odd to enable the use_file_modtime code even in the case
- where Checkin-time was not sent for a particular file. The
- effect is that we use the time of upload, rather than the time
- when we call RCS_checkin. Since those times are both during
- CVS's run, that seems OK, and it is easier to implement than
- putting the "was Checkin-time sent" flag in CVS/Entries or some
- such place. */
-
- if (server_active)
- use_file_modtime = 1;
-
- /* Don't allow "CVS" as any directory in module path.
- *
- * Could abstract this to valid_module_path, but I don't think we'll need
- * to call it from anywhere else.
- */
- /* for each "CVS" in path... */
- cp = argv[0];
- while ((cp = strstr(cp, "CVS")) != NULL)
- {
- if ( /* /^CVS/ OR m#/CVS#... */
- (cp == argv[0] || ISDIRSEP(*(cp-1)))
- /* ...AND /CVS$/ OR m#CVS/# */
- && (*(cp+3) == '\0' || ISDIRSEP(*(cp+3)))
- )
- {
- error (0, 0,
- "The word `CVS' is reserved by CVS and may not be used");
- error (1, 0, "as a directory in a path or as a file name.");
- }
- cp += 3;
- }
-
- for (i = 1; i < argc; i++) /* check the tags for validity */
- {
- int j;
-
- RCS_check_tag (argv[i]);
- for (j = 1; j < i; j++)
- if (strcmp (argv[j], argv[i]) == 0)
- error (1, 0, "tag `%s' was specified more than once", argv[i]);
- }
-
- /* XXX - this should be a module, not just a pathname */
- if (!isabsolute (argv[0]) && pathname_levels (argv[0]) == 0)
- {
- if (current_parsed_root == NULL)
- {
- error (0, 0, "missing CVSROOT environment variable\n");
- error (1, 0, "Set it or specify the '-d' option to %s.",
- program_name);
- }
- repository = xmalloc (strlen (current_parsed_root->directory)
- + strlen (argv[0])
- + 2);
- (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
- repos_len = strlen (current_parsed_root->directory);
- }
- else
- {
- /* It is somewhere between a security hole and "unexpected" to
- let the client start mucking around outside the cvsroot
- (wouldn't get the right CVSROOT configuration, &c). */
- error (1, 0, "directory %s not relative within the repository",
- argv[0]);
- }
-
- /*
- * Consistency checks on the specified vendor branch. It must be
- * composed of only numbers and dots ('.'). Also, for now we only
- * support branching to a single level, so the specified vendor branch
- * must only have two dots in it (like "1.1.1").
- */
- {
- regex_t pat;
- int ret = regcomp (&pat, "^[1-9][0-9]*\\.[1-9][0-9]*\\.[1-9][0-9]*$",
- REG_EXTENDED);
- assert (!ret);
- if (regexec (&pat, vbranch, 0, NULL, 0))
- {
- error (1, 0,
-"Only numeric branch specifications with two dots are\n"
-"supported by import, not `%s'. For example: `1.1.1'.",
- vbranch);
- }
- regfree (&pat);
- }
-
- /* Set vhead to the branch's parent. */
- vhead = xstrdup (vbranch);
- cp = strrchr (vhead, '.');
- *cp = '\0';
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- /* For rationale behind calling start_server before do_editor, see
- commit.c */
- start_server ();
- }
-#endif
-
- if (!server_active && use_editor)
- {
- do_editor ((char *) NULL, &message,
- current_parsed_root->isremote ? (char *) NULL : repository,
- (List *) NULL);
- }
- do_verify (&message, repository);
- msglen = message == NULL ? 0 : strlen (message);
- if (msglen == 0 || message[msglen - 1] != '\n')
- {
- char *nm = xmalloc (msglen + 2);
- *nm = '\0';
- if (message != NULL)
- {
- (void) strcpy (nm, message);
- free (message);
- }
- (void) strcat (nm + msglen, "\n");
- message = nm;
- }
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- int err;
-
- if (vbranch[0] != '\0')
- option_with_arg ("-b", vbranch);
- option_with_arg ("-m", message ? message : "");
- if (keyword_opt != NULL)
- option_with_arg ("-k", keyword_opt);
- /* The only ignore processing which takes place on the server side
- is the CVSROOT/cvsignore file. But if the user specified -I !,
- the documented behavior is to not process said file. */
- if (ign_inhibit_server)
- {
- send_arg ("-I");
- send_arg ("!");
- }
- wrap_send ();
-
- {
- int i;
- for (i = 0; i < argc; ++i)
- send_arg (argv[i]);
- }
-
- logfp = stdin;
- client_import_setup (repository);
- err = import_descend (message, argv[1], argc - 2, argv + 2);
- client_import_done ();
- if (message)
- free (message);
- free (repository);
- free (vbranch);
- free (vhead);
- send_to_server ("import\012", 0);
- err += get_responses_and_close ();
- return err;
- }
-#endif
-
- if (!safe_location ( NULL ))
- {
- error (1, 0, "attempt to import the repository");
- }
-
- /*
- * Make all newly created directories writable. Should really use a more
- * sophisticated security mechanism here.
- */
- (void) umask (cvsumask);
- make_directories (repository);
-
- /* Create the logfile that will be logged upon completion */
- if ((logfp = cvs_temp_file (&tmpfile)) == NULL)
- error (1, errno, "cannot create temporary file `%s'",
- tmpfile ? tmpfile : "(null)");
- /* On systems where we can unlink an open file, do so, so it will go
- away no matter how we exit. FIXME-maybe: Should be checking for
- errors but I'm not sure which error(s) we get if we are on a system
- where one can't unlink open files. */
- (void) CVS_UNLINK (tmpfile);
- (void) fprintf (logfp, "\nVendor Tag:\t%s\n", argv[1]);
- (void) fprintf (logfp, "Release Tags:\t");
- for (i = 2; i < argc; i++)
- (void) fprintf (logfp, "%s\n\t\t", argv[i]);
- (void) fprintf (logfp, "\n");
-
- /* Just Do It. */
- err = import_descend (message, argv[1], argc - 2, argv + 2);
- if (conflicts)
- {
- if (!really_quiet)
- {
- char buf[20];
-
- cvs_output_tagged ("+importmergecmd", NULL);
- cvs_output_tagged ("newline", NULL);
- sprintf (buf, "%d", conflicts);
- cvs_output_tagged ("conflicts", buf);
- cvs_output_tagged ("text", " conflicts created by this import.");
- cvs_output_tagged ("newline", NULL);
- cvs_output_tagged ("text",
- "Use the following command to help the merge:");
- cvs_output_tagged ("newline", NULL);
- cvs_output_tagged ("newline", NULL);
- cvs_output_tagged ("text", "\t");
- cvs_output_tagged ("text", program_name);
- if (CVSroot_cmdline != NULL)
- {
- cvs_output_tagged ("text", " -d ");
- cvs_output_tagged ("text", CVSroot_cmdline);
- }
- cvs_output_tagged ("text", " checkout -j");
- cvs_output_tagged ("mergetag1", "<prev_rel_tag>");
- cvs_output_tagged ("text", " -j");
- cvs_output_tagged ("mergetag2", argv[2]);
- cvs_output_tagged ("text", " ");
- cvs_output_tagged ("repository", argv[0]);
- cvs_output_tagged ("newline", NULL);
- cvs_output_tagged ("newline", NULL);
- cvs_output_tagged ("-importmergecmd", NULL);
- }
-
- /* FIXME: I'm not sure whether we need to put this information
- into the loginfo. If we do, then note that it does not
- report any required -d option. There is no particularly
- clean way to tell the server about the -d option used by
- the client. */
- (void) fprintf (logfp, "\n%d conflicts created by this import.\n",
- conflicts);
- (void) fprintf (logfp,
- "Use the following command to help the merge:\n\n");
- (void) fprintf (logfp, "\t%s checkout ", program_name);
- (void) fprintf (logfp, "-j%s:yesterday -j%s %s\n\n",
- argv[1], argv[1], argv[0]);
- }
- else
- {
- if (!really_quiet)
- cvs_output ("\nNo conflicts created by this import\n\n", 0);
- (void) fprintf (logfp, "\nNo conflicts created by this import\n\n");
- }
-
- /*
- * Write out the logfile and clean up.
- */
- ulist = getlist ();
- p = getnode ();
- p->type = UPDATE;
- p->delproc = update_delproc;
- p->key = xstrdup ("- Imported sources");
- li = (struct logfile_info *) xmalloc (sizeof (struct logfile_info));
- li->type = T_TITLE;
- li->tag = xstrdup (vbranch);
- li->rev_old = li->rev_new = NULL;
- p->data = li;
- (void) addnode (ulist, p);
- Update_Logfile (repository, message, logfp, ulist);
- dellist (&ulist);
- if (fclose (logfp) < 0)
- error (0, errno, "error closing %s", tmpfile);
-
- /* Make sure the temporary file goes away, even on systems that don't let
- you delete a file that's in use. */
- if (CVS_UNLINK (tmpfile) < 0 && !existence_error (errno))
- error (0, errno, "cannot remove %s", tmpfile);
- free (tmpfile);
-
- if (message)
- free (message);
- free (repository);
- free (vbranch);
- free (vhead);
-
- return (err);
-}
-
-/* Process all the files in ".", then descend into other directories.
- Returns 0 for success, or >0 on error (in which case a message
- will have been printed). */
-static int
-import_descend (message, vtag, targc, targv)
- char *message;
- char *vtag;
- int targc;
- char *targv[];
-{
- DIR *dirp;
- struct dirent *dp;
- int err = 0;
- List *dirlist = NULL;
-
- /* first, load up any per-directory ignore lists */
- ign_add_file (CVSDOTIGNORE, 1);
- wrap_add_file (CVSDOTWRAPPER, 1);
-
- if (!current_parsed_root->isremote)
- lock_dir_for_write (repository);
-
- if ((dirp = CVS_OPENDIR (".")) == NULL)
- {
- error (0, errno, "cannot open directory");
- err++;
- }
- else
- {
- errno = 0;
- while ((dp = CVS_READDIR (dirp)) != NULL)
- {
- if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0)
- goto one_more_time_boys;
-
- /* CVS directories are created in the temp directory by
- server.c because it doesn't special-case import. So
- don't print a message about them, regardless of -I!. */
- if (server_active && strcmp (dp->d_name, CVSADM) == 0)
- goto one_more_time_boys;
-
- if (ign_name (dp->d_name))
- {
- add_log ('I', dp->d_name);
- goto one_more_time_boys;
- }
-
- if (
-#ifdef DT_DIR
- (dp->d_type == DT_DIR
- || (dp->d_type == DT_UNKNOWN && isdir (dp->d_name)))
-#else
- isdir (dp->d_name)
-#endif
- && !wrap_name_has (dp->d_name, WRAP_TOCVS)
- )
- {
- Node *n;
-
- if (dirlist == NULL)
- dirlist = getlist();
-
- n = getnode();
- n->key = xstrdup (dp->d_name);
- addnode(dirlist, n);
- }
- else if (
-#ifdef DT_DIR
- dp->d_type == DT_LNK
- || (dp->d_type == DT_UNKNOWN && islink (dp->d_name))
-#else
- islink (dp->d_name)
-#endif
- )
- {
- add_log ('L', dp->d_name);
- err++;
- }
- else
- {
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- err += client_process_import_file (message, dp->d_name,
- vtag, targc, targv,
- repository,
- keyword_opt != NULL &&
- keyword_opt[0] == 'b',
- use_file_modtime);
- else
-#endif
- err += process_import_file (message, dp->d_name,
- vtag, targc, targv);
- }
- one_more_time_boys:
- errno = 0;
- }
- if (errno != 0)
- {
- error (0, errno, "cannot read directory");
- ++err;
- }
- (void) CVS_CLOSEDIR (dirp);
- }
-
- if (!current_parsed_root->isremote)
- Lock_Cleanup ();
-
- if (dirlist != NULL)
- {
- Node *head, *p;
-
- head = dirlist->list;
- for (p = head->next; p != head; p = p->next)
- {
- err += import_descend_dir (message, p->key, vtag, targc, targv);
- }
-
- dellist(&dirlist);
- }
-
- return (err);
-}
-
-/*
- * Process the argument import file.
- */
-static int
-process_import_file (message, vfile, vtag, targc, targv)
- char *message;
- char *vfile;
- char *vtag;
- int targc;
- char *targv[];
-{
- char *rcs;
- int inattic = 0;
-
- rcs = xmalloc (strlen (repository) + strlen (vfile) + sizeof (RCSEXT)
- + 5);
- (void) sprintf (rcs, "%s/%s%s", repository, vfile, RCSEXT);
- if (!isfile (rcs))
- {
- char *attic_name;
-
- attic_name = xmalloc (strlen (repository) + strlen (vfile) +
- sizeof (CVSATTIC) + sizeof (RCSEXT) + 10);
- (void) sprintf (attic_name, "%s/%s/%s%s", repository, CVSATTIC,
- vfile, RCSEXT);
- if (!isfile (attic_name))
- {
- int retval;
- char *free_opt = NULL;
- char *our_opt = keyword_opt;
-
- free (attic_name);
- /*
- * A new import source file; it doesn't exist as a ,v within the
- * repository nor in the Attic -- create it anew.
- */
- add_log ('N', vfile);
-
-#ifdef SERVER_SUPPORT
- /* The most reliable information on whether the file is binary
- is what the client told us. That is because if the client had
- the wrong idea about binaryness, it corrupted the file, so
- we might as well believe the client. */
- if (server_active)
- {
- Node *node;
- List *entries;
-
- /* Reading all the entries for each file is fairly silly, and
- probably slow. But I am too lazy at the moment to do
- anything else. */
- entries = Entries_Open (0, NULL);
- node = findnode_fn (entries, vfile);
- if (node != NULL)
- {
- Entnode *entdata = node->data;
-
- if (entdata->type == ENT_FILE)
- {
- assert (entdata->options[0] == '-'
- && entdata->options[1] == 'k');
- our_opt = xstrdup (entdata->options + 2);
- free_opt = our_opt;
- }
- }
- Entries_Close (entries);
- }
-#endif
-
- retval = add_rcs_file (message, rcs, vfile, vhead, our_opt,
- vbranch, vtag, targc, targv,
- NULL, 0, logfp);
- if (free_opt != NULL)
- free (free_opt);
- free (rcs);
- return retval;
- }
- free (attic_name);
- inattic = 1;
- }
-
- free (rcs);
- /*
- * an rcs file exists. have to do things the official, slow, way.
- */
- return (update_rcs_file (message, vfile, vtag, targc, targv, inattic));
-}
-
-/*
- * The RCS file exists; update it by adding the new import file to the
- * (possibly already existing) vendor branch.
- */
-static int
-update_rcs_file (message, vfile, vtag, targc, targv, inattic)
- char *message;
- char *vfile;
- char *vtag;
- int targc;
- char *targv[];
- int inattic;
-{
- Vers_TS *vers;
- int letter;
- char *tocvsPath;
- char *expand;
- struct file_info finfo;
-
- memset (&finfo, 0, sizeof finfo);
- finfo.file = vfile;
- /* Not used, so don't worry about it. */
- finfo.update_dir = NULL;
- finfo.fullname = finfo.file;
- finfo.repository = repository;
- finfo.entries = NULL;
- finfo.rcs = NULL;
- vers = Version_TS (&finfo, (char *) NULL, vbranch, (char *) NULL,
- 1, 0);
- if (vers->vn_rcs != NULL
- && !RCS_isdead(vers->srcfile, vers->vn_rcs))
- {
- int different;
-
- /*
- * The rcs file does have a revision on the vendor branch. Compare
- * this revision with the import file; if they match exactly, there
- * is no need to install the new import file as a new revision to the
- * branch. Just tag the revision with the new import tags.
- *
- * This is to try to cut down the number of "C" conflict messages for
- * locally modified import source files.
- */
- tocvsPath = wrap_tocvs_process_file (vfile);
- /* FIXME: Why don't we pass tocvsPath to RCS_cmp_file if it is
- not NULL? */
- expand = vers->srcfile->expand != NULL &&
- vers->srcfile->expand[0] == 'b' ? "-kb" : "-ko";
- different = RCS_cmp_file( vers->srcfile, vers->vn_rcs, (char **)NULL,
- (char *)NULL, expand, vfile );
- if (tocvsPath)
- if (unlink_file_dir (tocvsPath) < 0)
- error (0, errno, "cannot remove %s", tocvsPath);
-
- if (!different)
- {
- int retval = 0;
-
- /*
- * The two files are identical. Just update the tags, print the
- * "U", signifying that the file has changed, but needs no
- * attention, and we're done.
- */
- if (add_tags (vers->srcfile, vfile, vtag, targc, targv))
- retval = 1;
- add_log ('U', vfile);
- freevers_ts (&vers);
- return (retval);
- }
- }
-
- /* We may have failed to parse the RCS file; check just in case */
- if (vers->srcfile == NULL ||
- add_rev (message, vers->srcfile, vfile, vers->vn_rcs) ||
- add_tags (vers->srcfile, vfile, vtag, targc, targv))
- {
- freevers_ts (&vers);
- return (1);
- }
-
- if (vers->srcfile->branch == NULL || inattic ||
- strcmp (vers->srcfile->branch, vbranch) != 0)
- {
- conflicts++;
- letter = 'C';
- }
- else
- letter = 'U';
- add_log (letter, vfile);
-
- freevers_ts (&vers);
- return (0);
-}
-
-/*
- * Add the revision to the vendor branch
- */
-static int
-add_rev (message, rcs, vfile, vers)
- char *message;
- RCSNode *rcs;
- char *vfile;
- char *vers;
-{
- int locked, status, ierrno;
- char *tocvsPath;
-
- if (noexec)
- return (0);
-
- locked = 0;
- if (vers != NULL)
- {
- /* Before RCS_lock existed, we were directing stdout, as well as
- stderr, from the RCS command, to DEVNULL. I wouldn't guess that
- was necessary, but I don't know for sure. */
- /* Earlier versions of this function printed a `fork failed' error
- when RCS_lock returned an error code. That's not appropriate
- now that RCS_lock is librarified, but should the error text be
- preserved? */
- if (RCS_lock (rcs, vbranch, 1) != 0)
- return 1;
- locked = 1;
- RCS_rewrite (rcs, NULL, NULL);
- }
- tocvsPath = wrap_tocvs_process_file (vfile);
-
- status = RCS_checkin (rcs, tocvsPath == NULL ? vfile : tocvsPath,
- message, vbranch, 0,
- (RCS_FLAGS_QUIET | RCS_FLAGS_KEEPFILE
- | (use_file_modtime ? RCS_FLAGS_MODTIME : 0)));
- ierrno = errno;
-
- if ((tocvsPath != NULL) && (unlink_file_dir (tocvsPath) < 0))
- error (0, errno, "cannot remove %s", tocvsPath);
-
- if (status)
- {
- if (!noexec)
- {
- fperrmsg (logfp, 0, status == -1 ? ierrno : 0,
- "ERROR: Check-in of %s failed", rcs->path);
- error (0, status == -1 ? ierrno : 0,
- "ERROR: Check-in of %s failed", rcs->path);
- }
- if (locked)
- {
- (void) RCS_unlock(rcs, vbranch, 0);
- RCS_rewrite (rcs, NULL, NULL);
- }
- return (1);
- }
- return (0);
-}
-
-/*
- * Add the vendor branch tag and all the specified import release tags to the
- * RCS file. The vendor branch tag goes on the branch root (1.1.1) while the
- * vendor release tags go on the newly added leaf of the branch (1.1.1.1,
- * 1.1.1.2, ...).
- */
-static int
-add_tags (rcs, vfile, vtag, targc, targv)
- RCSNode *rcs;
- char *vfile;
- char *vtag;
- int targc;
- char *targv[];
-{
- int i, ierrno;
- Vers_TS *vers;
- int retcode = 0;
- struct file_info finfo;
-
- if (noexec)
- return (0);
-
- if ((retcode = RCS_settag(rcs, vtag, vbranch)) != 0)
- {
- ierrno = errno;
- fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
- "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
- error (0, retcode == -1 ? ierrno : 0,
- "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
- return (1);
- }
- RCS_rewrite (rcs, NULL, NULL);
-
- memset (&finfo, 0, sizeof finfo);
- finfo.file = vfile;
- /* Not used, so don't worry about it. */
- finfo.update_dir = NULL;
- finfo.fullname = finfo.file;
- finfo.repository = repository;
- finfo.entries = NULL;
- finfo.rcs = NULL;
- vers = Version_TS (&finfo, NULL, vtag, NULL, 1, 0);
- for (i = 0; i < targc; i++)
- {
- if ((retcode = RCS_settag (rcs, targv[i], vers->vn_rcs)) == 0)
- RCS_rewrite (rcs, NULL, NULL);
- else
- {
- ierrno = errno;
- fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
- "WARNING: Couldn't add tag %s to %s", targv[i],
- rcs->path);
- error (0, retcode == -1 ? ierrno : 0,
- "WARNING: Couldn't add tag %s to %s", targv[i],
- rcs->path);
- }
- }
- freevers_ts (&vers);
- return (0);
-}
-
-/*
- * Stolen from rcs/src/rcsfnms.c, and adapted/extended.
- */
-struct compair
-{
- char *suffix, *comlead;
-};
-
-static const struct compair comtable[] =
-{
-
-/*
- * comtable pairs each filename suffix with a comment leader. The comment
- * leader is placed before each line generated by the $Log keyword. This
- * table is used to guess the proper comment leader from the working file's
- * suffix during initial ci (see InitAdmin()). Comment leaders are needed for
- * languages without multiline comments; for others they are optional.
- *
- * I believe that the comment leader is unused if you are using RCS 5.7, which
- * decides what leader to use based on the text surrounding the $Log keyword
- * rather than a specified comment leader.
- */
- {"a", "-- "}, /* Ada */
- {"ada", "-- "},
- {"adb", "-- "},
- {"asm", ";; "}, /* assembler (MS-DOS) */
- {"ads", "-- "}, /* Ada */
- {"bas", "' "}, /* Visual Basic code */
- {"bat", ":: "}, /* batch (MS-DOS) */
- {"body", "-- "}, /* Ada */
- {"c", " * "}, /* C */
- {"c++", "// "}, /* C++ in all its infinite guises */
- {"cc", "// "},
- {"cpp", "// "},
- {"cxx", "// "},
- {"m", "// "}, /* Objective-C */
- {"cl", ";;; "}, /* Common Lisp */
- {"cmd", ":: "}, /* command (OS/2) */
- {"cmf", "c "}, /* CM Fortran */
- {"cs", " * "}, /* C* */
- {"csh", "# "}, /* shell */
- {"dlg", " * "}, /* MS Windows dialog file */
- {"e", "# "}, /* efl */
- {"epsf", "% "}, /* encapsulated postscript */
- {"epsi", "% "}, /* encapsulated postscript */
- {"el", "; "}, /* Emacs Lisp */
- {"f", "c "}, /* Fortran */
- {"for", "c "},
- {"frm", "' "}, /* Visual Basic form */
- {"h", " * "}, /* C-header */
- {"hh", "// "}, /* C++ header */
- {"hpp", "// "},
- {"hxx", "// "},
- {"in", "# "}, /* for Makefile.in */
- {"l", " * "}, /* lex (conflict between lex and
- * franzlisp) */
- {"mac", ";; "}, /* macro (DEC-10, MS-DOS, PDP-11,
- * VMS, etc) */
- {"mak", "# "}, /* makefile, e.g. Visual C++ */
- {"me", ".\\\" "}, /* me-macros t/nroff */
- {"ml", "; "}, /* mocklisp */
- {"mm", ".\\\" "}, /* mm-macros t/nroff */
- {"ms", ".\\\" "}, /* ms-macros t/nroff */
- {"man", ".\\\" "}, /* man-macros t/nroff */
- {"1", ".\\\" "}, /* feeble attempt at man pages... */
- {"2", ".\\\" "},
- {"3", ".\\\" "},
- {"4", ".\\\" "},
- {"5", ".\\\" "},
- {"6", ".\\\" "},
- {"7", ".\\\" "},
- {"8", ".\\\" "},
- {"9", ".\\\" "},
- {"p", " * "}, /* pascal */
- {"pas", " * "},
- {"pl", "# "}, /* perl (conflict with Prolog) */
- {"ps", "% "}, /* postscript */
- {"psw", "% "}, /* postscript wrap */
- {"pswm", "% "}, /* postscript wrap */
- {"r", "# "}, /* ratfor */
- {"rc", " * "}, /* Microsoft Windows resource file */
- {"red", "% "}, /* psl/rlisp */
-#ifdef sparc
- {"s", "! "}, /* assembler */
-#endif
-#ifdef mc68000
- {"s", "| "}, /* assembler */
-#endif
-#ifdef pdp11
- {"s", "/ "}, /* assembler */
-#endif
-#ifdef vax
- {"s", "# "}, /* assembler */
-#endif
-#ifdef __ksr__
- {"s", "# "}, /* assembler */
- {"S", "# "}, /* Macro assembler */
-#endif
- {"sh", "# "}, /* shell */
- {"sl", "% "}, /* psl */
- {"spec", "-- "}, /* Ada */
- {"tex", "% "}, /* tex */
- {"y", " * "}, /* yacc */
- {"ye", " * "}, /* yacc-efl */
- {"yr", " * "}, /* yacc-ratfor */
- {"", "# "}, /* default for empty suffix */
- {NULL, "# "} /* default for unknown suffix; */
-/* must always be last */
-};
-
-static char *
-get_comment (user)
- const char *user;
-{
- char *cp, *suffix;
- char *suffix_path;
- int i;
- char *retval;
-
- suffix_path = xmalloc (strlen (user) + 5);
- cp = strrchr (user, '.');
- if (cp != NULL)
- {
- cp++;
-
- /*
- * Convert to lower-case, since we are not concerned about the
- * case-ness of the suffix.
- */
- (void) strcpy (suffix_path, cp);
- for (cp = suffix_path; *cp; cp++)
- if (isupper ((unsigned char) *cp))
- *cp = tolower (*cp);
- suffix = suffix_path;
- }
- else
- suffix = ""; /* will use the default */
- for (i = 0;; i++)
- {
- if (comtable[i].suffix == NULL)
- {
- /* Default. Note we'll always hit this case before we
- ever return NULL. */
- retval = comtable[i].comlead;
- break;
- }
- if (strcmp (suffix, comtable[i].suffix) == 0)
- {
- retval = comtable[i].comlead;
- break;
- }
- }
- free (suffix_path);
- return retval;
-}
-
-/* Create a new RCS file from scratch.
-
- This probably should be moved to rcs.c now that it is called from
- places outside import.c.
-
- Return value is 0 for success, or nonzero for failure (in which
- case an error message will have already been printed). */
-int
-add_rcs_file (message, rcs, user, add_vhead, key_opt,
- add_vbranch, vtag, targc, targv,
- desctext, desclen, add_logfp)
- /* Log message for the addition. Not used if add_vhead == NULL. */
- const char *message;
- /* Filename of the RCS file to create. */
- const char *rcs;
- /* Filename of the file to serve as the contents of the initial
- revision. Even if add_vhead is NULL, we use this to determine
- the modes to give the new RCS file. */
- const char *user;
-
- /* Revision number of head that we are adding. Normally 1.1 but
- could be another revision as long as ADD_VBRANCH is a branch
- from it. If NULL, then just add an empty file without any
- revisions (similar to the one created by "rcs -i"). */
- const char *add_vhead;
-
- /* Keyword expansion mode, e.g., "b" for binary. NULL means the
- default behavior. */
- const char *key_opt;
-
- /* Vendor branch to import to, or NULL if none. If non-NULL, then
- vtag should also be non-NULL. */
- const char *add_vbranch;
- const char *vtag;
- int targc;
- char *targv[];
-
- /* If non-NULL, description for the file. If NULL, the description
- will be empty. */
- const char *desctext;
- size_t desclen;
-
- /* Write errors to here as well as via error (), or NULL if we should
- use only error (). */
- FILE *add_logfp;
-{
- FILE *fprcs, *fpuser;
- struct stat sb;
- struct tm *ftm;
- time_t now;
- char altdate1[MAXDATELEN];
- char *author;
- int i, ierrno, err = 0;
- mode_t mode;
- char *tocvsPath;
- const char *userfile;
- char *free_opt = NULL;
- mode_t file_type;
-
- if (noexec)
- return (0);
-
- /* Note that as the code stands now, the -k option overrides any
- settings in wrappers (whether CVSROOT/cvswrappers, -W, or
- whatever). Some have suggested this should be the other way
- around. As far as I know the documentation doesn't say one way
- or the other. Before making a change of this sort, should think
- about what is best, document it (in cvs.texinfo and NEWS), &c. */
-
- if (key_opt == NULL)
- {
- if (wrap_name_has (user, WRAP_RCSOPTION))
- {
- key_opt = free_opt = wrap_rcsoption (user, 0);
- }
- }
-
- tocvsPath = wrap_tocvs_process_file (user);
- userfile = (tocvsPath == NULL ? user : tocvsPath);
-
- /* Opening in text mode is probably never the right thing for the
- server (because the protocol encodes text files in a fashion
- which does not depend on what the client or server OS is, as
- documented in cvsclient.texi), but as long as the server just
- runs on unix it is a moot point. */
-
- /* If PreservePermissions is set, then make sure that the file
- is a plain file before trying to open it. Longstanding (although
- often unpopular) CVS behavior has been to follow symlinks, so we
- maintain that behavior if PreservePermissions is not on.
-
- NOTE: this error message used to be `cannot fstat', but is now
- `cannot lstat'. I don't see a way around this, since we must
- stat the file before opening it. -twp */
-
- if (CVS_LSTAT (userfile, &sb) < 0)
- {
- /* not fatal, continue import */
- if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, errno,
- "ERROR: cannot lstat file %s", userfile);
- error (0, errno, "cannot lstat file %s", userfile);
- goto read_error;
- }
- file_type = sb.st_mode & S_IFMT;
-
- fpuser = NULL;
- if (!preserve_perms || file_type == S_IFREG)
- {
- fpuser = CVS_FOPEN (userfile,
- ((key_opt != NULL && strcmp (key_opt, "b") == 0)
- ? "rb"
- : "r")
- );
- if (fpuser == NULL)
- {
- /* not fatal, continue import */
- if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, errno,
- "ERROR: cannot read file %s", userfile);
- error (0, errno, "ERROR: cannot read file %s", userfile);
- goto read_error;
- }
- }
-
- fprcs = CVS_FOPEN (rcs, "w+b");
- if (fprcs == NULL)
- {
- ierrno = errno;
- goto write_error_noclose;
- }
-
- /*
- * putadmin()
- */
- if (add_vhead != NULL)
- {
- if (fprintf (fprcs, "head %s;\012", add_vhead) < 0)
- goto write_error;
- }
- else
- {
- if (fprintf (fprcs, "head ;\012") < 0)
- goto write_error;
- }
-
- if (add_vbranch != NULL)
- {
- if (fprintf (fprcs, "branch %s;\012", add_vbranch) < 0)
- goto write_error;
- }
- if (fprintf (fprcs, "access ;\012") < 0 ||
- fprintf (fprcs, "symbols ") < 0)
- {
- goto write_error;
- }
-
- for (i = targc - 1; i >= 0; i--)
- {
- /* RCS writes the symbols backwards */
- assert (add_vbranch != NULL);
- if (fprintf (fprcs, "%s:%s.1 ", targv[i], add_vbranch) < 0)
- goto write_error;
- }
-
- if (add_vbranch != NULL)
- {
- if (fprintf (fprcs, "%s:%s", vtag, add_vbranch) < 0)
- goto write_error;
- }
- if (fprintf (fprcs, ";\012") < 0)
- goto write_error;
-
- if (fprintf (fprcs, "locks ; strict;\012") < 0 ||
- /* XXX - make sure @@ processing works in the RCS file */
- fprintf (fprcs, "comment @%s@;\012", get_comment (user)) < 0)
- {
- goto write_error;
- }
-
- if (key_opt != NULL && strcmp (key_opt, "kv") != 0)
- {
- if (fprintf (fprcs, "expand @%s@;\012", key_opt) < 0)
- {
- goto write_error;
- }
- }
-
- if (fprintf (fprcs, "\012") < 0)
- goto write_error;
-
- /* Write the revision(s), with the date and author and so on
- (that is "delta" rather than "deltatext" from rcsfile(5)). */
- if (add_vhead != NULL)
- {
- if (use_file_modtime)
- now = sb.st_mtime;
- else
- (void) time (&now);
- ftm = gmtime (&now);
- (void) sprintf (altdate1, DATEFORM,
- ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
- ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
- ftm->tm_min, ftm->tm_sec);
- author = getcaller ();
-
- if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
- fprintf (fprcs, "date %s; author %s; state Exp;\012",
- altdate1, author) < 0)
- goto write_error;
-
- if (fprintf (fprcs, "branches") < 0)
- goto write_error;
- if (add_vbranch != NULL)
- {
- if (fprintf (fprcs, " %s.1", add_vbranch) < 0)
- goto write_error;
- }
- if (fprintf (fprcs, ";\012") < 0)
- goto write_error;
-
- if (fprintf (fprcs, "next ;\012") < 0)
- goto write_error;
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- /* Store initial permissions if necessary. */
- if (preserve_perms)
- {
- if (file_type == S_IFLNK)
- {
- char *link = xreadlink (userfile);
- if (fprintf (fprcs, "symlink\t@") < 0 ||
- expand_at_signs (link, strlen (link), fprcs) < 0 ||
- fprintf (fprcs, "@;\012") < 0)
- goto write_error;
- free (link);
- }
- else
- {
- if (fprintf (fprcs, "owner\t%u;\012", sb.st_uid) < 0)
- goto write_error;
- if (fprintf (fprcs, "group\t%u;\012", sb.st_gid) < 0)
- goto write_error;
- if (fprintf (fprcs, "permissions\t%o;\012",
- sb.st_mode & 07777) < 0)
- goto write_error;
- switch (file_type)
- {
- case S_IFREG: break;
- case S_IFCHR:
- case S_IFBLK:
-#ifdef HAVE_STRUCT_STAT_ST_RDEV
- if (fprintf (fprcs, "special\t%s %lu;\012",
- (file_type == S_IFCHR
- ? "character"
- : "block"),
- (unsigned long) sb.st_rdev) < 0)
- goto write_error;
-#else
- error (0, 0,
-"can't import %s: unable to import device files on this system",
-userfile);
-#endif
- break;
- default:
- error (0, 0,
- "can't import %s: unknown kind of special file",
- userfile);
- }
- }
- }
-#endif
-
- if (add_vbranch != NULL)
- {
- if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
- fprintf (fprcs, "date %s; author %s; state Exp;\012",
- altdate1, author) < 0 ||
- fprintf (fprcs, "branches ;\012") < 0 ||
- fprintf (fprcs, "next ;\012") < 0)
- goto write_error;
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- /* Store initial permissions if necessary. */
- if (preserve_perms)
- {
- if (file_type == S_IFLNK)
- {
- char *link = xreadlink (userfile);
- if (fprintf (fprcs, "symlink\t@") < 0 ||
- expand_at_signs (link, strlen (link), fprcs) < 0 ||
- fprintf (fprcs, "@;\012") < 0)
- goto write_error;
- free (link);
- }
- else
- {
- if (fprintf (fprcs, "owner\t%u;\012", sb.st_uid) < 0 ||
- fprintf (fprcs, "group\t%u;\012", sb.st_gid) < 0 ||
- fprintf (fprcs, "permissions\t%o;\012",
- sb.st_mode & 07777) < 0)
- goto write_error;
-
- switch (file_type)
- {
- case S_IFREG: break;
- case S_IFCHR:
- case S_IFBLK:
-#ifdef HAVE_STRUCT_STAT_ST_RDEV
- if (fprintf (fprcs, "special\t%s %lu;\012",
- (file_type == S_IFCHR
- ? "character"
- : "block"),
- (unsigned long) sb.st_rdev) < 0)
- goto write_error;
-#else
- error (0, 0,
-"can't import %s: unable to import device files on this system",
-userfile);
-#endif
- break;
- default:
- error (0, 0,
- "cannot import %s: special file of unknown type",
- userfile);
- }
- }
- }
-#endif
-
- if (fprintf (fprcs, "\012") < 0)
- goto write_error;
- }
- }
-
- /* Now write the description (possibly empty). */
- if (fprintf (fprcs, "\012desc\012") < 0 ||
- fprintf (fprcs, "@") < 0)
- goto write_error;
- if (desctext != NULL)
- {
- /* The use of off_t not size_t for the second argument is very
- strange, since we are dealing with something which definitely
- fits in memory. */
- if (expand_at_signs (desctext, (off_t) desclen, fprcs) < 0)
- goto write_error;
- }
- if (fprintf (fprcs, "@\012\012\012") < 0)
- goto write_error;
-
- /* Now write the log messages and contents for the revision(s) (that
- is, "deltatext" rather than "delta" from rcsfile(5)). */
- if (add_vhead != NULL)
- {
- if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
- fprintf (fprcs, "log\012@") < 0)
- goto write_error;
- if (add_vbranch != NULL)
- {
- /* We are going to put the log message in the revision on the
- branch. So putting it here too seems kind of redundant, I
- guess (and that is what CVS has always done, anyway). */
- if (fprintf (fprcs, "Initial revision\012") < 0)
- goto write_error;
- }
- else
- {
- if (expand_at_signs (message, (off_t) strlen (message), fprcs) < 0)
- goto write_error;
- }
- if (fprintf (fprcs, "@\012") < 0 ||
- fprintf (fprcs, "text\012@") < 0)
- {
- goto write_error;
- }
-
- /* Now copy over the contents of the file, expanding at signs.
- If preserve_perms is set, do this only for regular files. */
- if (!preserve_perms || file_type == S_IFREG)
- {
- char buf[8192];
- unsigned int len;
-
- while (1)
- {
- len = fread (buf, 1, sizeof buf, fpuser);
- if (len == 0)
- {
- if (ferror (fpuser))
- error (1, errno, "cannot read file %s for copying",
- user);
- break;
- }
- if (expand_at_signs (buf, len, fprcs) < 0)
- goto write_error;
- }
- }
- if (fprintf (fprcs, "@\012\012") < 0)
- goto write_error;
- if (add_vbranch != NULL)
- {
- if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
- fprintf (fprcs, "log\012@") < 0 ||
- expand_at_signs (message,
- (off_t) strlen (message), fprcs) < 0 ||
- fprintf (fprcs, "@\012text\012") < 0 ||
- fprintf (fprcs, "@@\012") < 0)
- goto write_error;
- }
- }
-
- if (fclose (fprcs) == EOF)
- {
- ierrno = errno;
- goto write_error_noclose;
- }
- /* Close fpuser only if we opened it to begin with. */
- if (fpuser != NULL)
- {
- if (fclose (fpuser) < 0)
- error (0, errno, "cannot close %s", user);
- }
-
- /*
- * Fix the modes on the RCS files. The user modes of the original
- * user file are propagated to the group and other modes as allowed
- * by the repository umask, except that all write permissions are
- * turned off.
- */
- mode = (sb.st_mode |
- (sb.st_mode & S_IRWXU) >> 3 |
- (sb.st_mode & S_IRWXU) >> 6) &
- ~cvsumask &
- ~(S_IWRITE | S_IWGRP | S_IWOTH);
- if (chmod (rcs, mode) < 0)
- {
- ierrno = errno;
- if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, ierrno,
- "WARNING: cannot change mode of file %s", rcs);
- error (0, ierrno, "WARNING: cannot change mode of file %s", rcs);
- err++;
- }
- if (tocvsPath)
- if (unlink_file_dir (tocvsPath) < 0)
- error (0, errno, "cannot remove %s", tocvsPath);
- if (free_opt != NULL)
- free (free_opt);
- return (err);
-
-write_error:
- ierrno = errno;
- if (fclose (fprcs) < 0)
- error (0, errno, "cannot close %s", rcs);
-write_error_noclose:
- if (fclose (fpuser) < 0)
- error (0, errno, "cannot close %s", user);
- if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
- error (0, ierrno, "ERROR: cannot write file %s", rcs);
- if (ierrno == ENOSPC)
- {
- if (CVS_UNLINK (rcs) < 0)
- error (0, errno, "cannot remove %s", rcs);
- if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, 0, "ERROR: out of space - aborting");
- error (1, 0, "ERROR: out of space - aborting");
- }
-read_error:
- if (tocvsPath)
- if (unlink_file_dir (tocvsPath) < 0)
- error (0, errno, "cannot remove %s", tocvsPath);
-
- if (free_opt != NULL)
- free (free_opt);
-
- return (err + 1);
-}
-
-/*
- * Write SIZE bytes at BUF to FP, expanding @ signs into double @
- * signs. If an error occurs, return a negative value and set errno
- * to indicate the error. If not, return a nonnegative value.
- */
-int
-expand_at_signs (buf, size, fp)
- const char *buf;
- off_t size;
- FILE *fp;
-{
- register const char *cp, *next;
-
- cp = buf;
- while ((next = memchr (cp, '@', size)) != NULL)
- {
- size_t len = ++next - cp;
- if (fwrite (cp, 1, len, fp) != len)
- return EOF;
- if (putc ('@', fp) == EOF)
- return EOF;
- cp = next;
- size -= len;
- }
-
- if (fwrite (cp, 1, size, fp) != size)
- return EOF;
-
- return 1;
-}
-
-/*
- * Write an update message to (potentially) the screen and the log file.
- */
-static void
-add_log (ch, fname)
- int ch;
- char *fname;
-{
- if (!really_quiet) /* write to terminal */
- {
- char buf[2];
- buf[0] = ch;
- buf[1] = ' ';
- cvs_output (buf, 2);
- if (repos_len)
- {
- cvs_output (repository + repos_len + 1, 0);
- cvs_output ("/", 1);
- }
- else if (repository[0] != '\0')
- {
- cvs_output (repository, 0);
- cvs_output ("/", 1);
- }
- cvs_output (fname, 0);
- cvs_output ("\n", 1);
- }
-
- if (repos_len) /* write to logfile */
- (void) fprintf (logfp, "%c %s/%s\n", ch,
- repository + repos_len + 1, fname);
- else if (repository[0])
- (void) fprintf (logfp, "%c %s/%s\n", ch, repository, fname);
- else
- (void) fprintf (logfp, "%c %s\n", ch, fname);
-}
-
-/*
- * This is the recursive function that walks the argument directory looking
- * for sub-directories that have CVS administration files in them and updates
- * them recursively.
- *
- * Note that we do not follow symbolic links here, which is a feature!
- */
-static int
-import_descend_dir (message, dir, vtag, targc, targv)
- char *message;
- char *dir;
- char *vtag;
- int targc;
- char *targv[];
-{
- struct saved_cwd cwd;
- char *cp;
- int ierrno, err;
- char *rcs = NULL;
-
- if (islink (dir))
- return (0);
- if (save_cwd (&cwd))
- {
- fperrmsg (logfp, 0, 0, "ERROR: cannot get working directory");
- return (1);
- }
-
- /* Concatenate DIR to the end of REPOSITORY. */
- if (repository[0] == '\0')
- {
- char *new = xstrdup (dir);
- free (repository);
- repository = new;
- }
- else
- {
- char *new = xmalloc (strlen (repository) + strlen (dir) + 10);
- strcpy (new, repository);
- (void) strcat (new, "/");
- (void) strcat (new, dir);
- free (repository);
- repository = new;
- }
-
- if (!quiet && !current_parsed_root->isremote)
- error (0, 0, "Importing %s", repository);
-
- if ( CVS_CHDIR (dir) < 0)
- {
- ierrno = errno;
- fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", dir);
- error (0, ierrno, "ERROR: cannot chdir to %s", dir);
- err = 1;
- goto out;
- }
- if (!current_parsed_root->isremote && !isdir (repository))
- {
- rcs = xmalloc (strlen (repository) + sizeof (RCSEXT) + 5);
- (void) sprintf (rcs, "%s%s", repository, RCSEXT);
- if (isfile (repository) || isfile(rcs))
- {
- fperrmsg (logfp, 0, 0,
- "ERROR: %s is a file, should be a directory!",
- repository);
- error (0, 0, "ERROR: %s is a file, should be a directory!",
- repository);
- err = 1;
- goto out;
- }
- if (noexec == 0 && CVS_MKDIR (repository, 0777) < 0)
- {
- ierrno = errno;
- fperrmsg (logfp, 0, ierrno,
- "ERROR: cannot mkdir %s -- not added", repository);
- error (0, ierrno,
- "ERROR: cannot mkdir %s -- not added", repository);
- err = 1;
- goto out;
- }
- }
- err = import_descend (message, vtag, targc, targv);
- out:
- if (rcs != NULL)
- free (rcs);
- if ((cp = strrchr (repository, '/')) != NULL)
- *cp = '\0';
- else
- repository[0] = '\0';
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- free_cwd (&cwd);
- return (err);
-}
diff --git a/contrib/cvs/src/lock.c b/contrib/cvs/src/lock.c
deleted file mode 100644
index d8e78fa38e2b..000000000000
--- a/contrib/cvs/src/lock.c
+++ /dev/null
@@ -1,1166 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Set Lock
- *
- * Lock file support for CVS.
- *
- * $FreeBSD$
- */
-
-/* The node Concurrency in doc/cvs.texinfo has a brief introduction to
- how CVS locks function, and some of the user-visible consequences of
- their existence. Here is a summary of why they exist (and therefore,
- the consequences of hacking CVS to read a repository without creating
- locks):
-
- There are two uses. One is the ability to prevent there from being
- two writers at the same time. This is necessary for any number of
- reasons (fileattr code, probably others). Commit needs to lock the
- whole tree so that nothing happens between the up-to-date check and
- the actual checkin.
-
- The second use is the ability to ensure that there is not a writer
- and a reader at the same time (several readers are allowed). Reasons
- for this are:
-
- * Readlocks ensure that once CVS has found a collection of rcs
- files using Find_Names, the files will still exist when it reads
- them (they may have moved in or out of the attic).
-
- * Readlocks provide some modicum of consistency, although this is
- kind of limited--see the node Concurrency in cvs.texinfo.
-
- * Readlocks ensure that the RCS file does not change between
- RCS_parse and RCS_reparsercsfile time. This one strikes me as
- important, although I haven't thought up what bad scenarios might
- be.
-
- * Readlocks ensure that we won't find the file in the state in
- which it is in between the calls to add_rcs_file and RCS_checkin in
- commit.c (when a file is being added). This state is a state in
- which the RCS file parsing routines in rcs.c cannot parse the file.
-
- * Readlocks ensure that a reader won't try to look at a
- half-written fileattr file (fileattr is not updated atomically).
-
- (see also the description of anonymous read-only access in
- "Password authentication security" node in doc/cvs.texinfo).
-
- While I'm here, I'll try to summarize a few random suggestions
- which periodically get made about how locks might be different:
-
- 1. Check for EROFS. Maybe useful, although in the presence of NFS
- EROFS does *not* mean that the file system is unchanging.
-
- 2. Provide an option to disable locks for operations which only
- read (see above for some of the consequences).
-
- 3. Have a server internally do the locking. Probably a good
- long-term solution, and many people have been working hard on code
- changes which would eventually make it possible to have a server
- which can handle various connections in one process, but there is
- much, much work still to be done before this is feasible. */
-
-#include "cvs.h"
-#include <assert.h>
-
-#ifdef HAVE_NANOSLEEP
-# include "xtime.h"
-#else /* HAVE_NANOSLEEP */
-# if !defined HAVE_USLEEP && defined HAVE_SELECT
- /* use select as a workaround */
-# include "xselect.h"
-# endif /* !defined HAVE_USLEEP && defined HAVE_SELECT */
-#endif /* !HAVE_NANOSLEEP */
-
-
-struct lock {
- /* This is the directory in which we may have a lock named by the
- readlock variable, a lock named by the writelock variable, and/or
- a lock named CVSLCK. The storage is not allocated along with the
- struct lock; it is allocated by the Reader_Lock caller or in the
- case of writelocks, it is just a pointer to the storage allocated
- for the ->key field. */
- char *repository;
-
- /* The name of the master lock dir. Usually CVSLCK. */
- const char *lockdirname;
-
- /* The full path to the lock dir, if we are currently holding it.
- *
- * This will be LOCKDIRNAME catted onto REPOSITORY. We waste a little
- * space by storing it, but save a later malloc/free.
- */
- char *lockdir;
-
- /* Note there is no way of knowing whether the readlock and writelock
- exist. The code which sets the locks doesn't use SIG_beginCrSect
- to set a flag like we do for CVSLCK. */
-};
-
-static void remove_locks PROTO((void));
-static int readers_exist PROTO((char *repository));
-static int set_lock PROTO ((struct lock *lock, int will_wait));
-static void clear_lock PROTO ((struct lock *lock));
-static void set_lockers_name PROTO((struct stat *statp));
-static int set_writelock_proc PROTO((Node * p, void *closure));
-static int unlock_proc PROTO((Node * p, void *closure));
-static int write_lock PROTO ((struct lock *lock));
-static void lock_simple_remove PROTO ((struct lock *lock));
-static void lock_wait PROTO((char *repository));
-static void lock_obtained PROTO((char *repository));
-
-/* Malloc'd array containing the username of the whoever has the lock.
- Will always be non-NULL in the cases where it is needed. */
-static char *lockers_name;
-/* Malloc'd array specifying name of a readlock within a directory.
- Or NULL if none. */
-static char *readlock;
-/* Malloc'd array specifying name of a writelock within a directory.
- Or NULL if none. */
-static char *writelock;
-/* Malloc'd array specifying the name of a CVSLCK file (absolute pathname).
- Will always be non-NULL in the cases where it is used. */
-static List *locklist;
-
-#define L_OK 0 /* success */
-#define L_ERROR 1 /* error condition */
-#define L_LOCKED 2 /* lock owned by someone else */
-
-/* This is the (single) readlock which is set by Reader_Lock. The
- repository field is NULL if there is no such lock. */
-static struct lock global_readlock = {NULL, CVSLCK, NULL};
-
-static struct lock global_history_lock = {NULL, CVSHISTORYLCK, NULL};
-static struct lock global_val_tags_lock = {NULL, CVSVALTAGSLCK, NULL};
-
-/* List of locks set by lock_tree_for_write. This is redundant
- with locklist, sort of. */
-static List *lock_tree_list;
-
-/* If we set locks with lock_dir_for_write, then locked_dir contains
- the malloc'd name of the repository directory which we have locked.
- locked_list is the same thing packaged into a list and is redundant
- with locklist the same way that lock_tree_list is. */
-static char *locked_dir;
-static List *locked_list;
-
-/* LockDir from CVSROOT/config. */
-char *lock_dir;
-
-static char *lock_name PROTO ((const char *repository, const char *name));
-
-/* Return a newly malloc'd string containing the name of the lock for the
- repository REPOSITORY and the lock file name within that directory
- NAME. Also create the directories in which to put the lock file
- if needed (if we need to, could save system call(s) by doing
- that only if the actual operation fails. But for now we'll keep
- things simple). */
-static char *
-lock_name (repository, name)
- const char *repository;
- const char *name;
-{
- char *retval;
- const char *p;
- char *q;
- const char *short_repos;
- mode_t save_umask = 0;
- int saved_umask = 0;
-
- if (lock_dir == NULL)
- {
- /* This is the easy case. Because the lock files go directly
- in the repository, no need to create directories or anything. */
- retval = xmalloc (strlen (repository) + strlen (name) + 10);
- (void) sprintf (retval, "%s/%s", repository, name);
- }
- else
- {
- struct stat sb;
- mode_t new_mode = 0;
-
- /* The interesting part of the repository is the part relative
- to CVSROOT. */
- assert (current_parsed_root != NULL);
- assert (current_parsed_root->directory != NULL);
- assert (strncmp (repository, current_parsed_root->directory,
- strlen (current_parsed_root->directory)) == 0);
- short_repos = repository + strlen (current_parsed_root->directory) + 1;
-
- if (strcmp (repository, current_parsed_root->directory) == 0)
- short_repos = ".";
- else
- assert (short_repos[-1] == '/');
-
- retval = xmalloc (strlen (lock_dir)
- + strlen (short_repos)
- + strlen (name)
- + 10);
- strcpy (retval, lock_dir);
- q = retval + strlen (retval);
- *q++ = '/';
-
- strcpy (q, short_repos);
-
- /* In the common case, where the directory already exists, let's
- keep it to one system call. */
- if (CVS_STAT (retval, &sb) < 0)
- {
- /* If we need to be creating more than one directory, we'll
- get the existence_error here. */
- if (!existence_error (errno))
- error (1, errno, "cannot stat directory %s", retval);
- }
- else
- {
- if (S_ISDIR (sb.st_mode))
- goto created;
- else
- error (1, 0, "%s is not a directory", retval);
- }
-
- /* Now add the directories one at a time, so we can create
- them if needed.
-
- The idea behind the new_mode stuff is that the directory we
- end up creating will inherit permissions from its parent
- directory (we re-set new_mode with each EEXIST). CVSUMASK
- isn't right, because typically the reason for LockDir is to
- use a different set of permissions. We probably want to
- inherit group ownership also (but we don't try to deal with
- that, some systems do it for us either always or when g+s is on).
-
- We don't try to do anything about the permissions on the lock
- files themselves. The permissions don't really matter so much
- because the locks will generally be removed by the process
- which created them. */
-
- if (CVS_STAT (lock_dir, &sb) < 0)
- error (1, errno, "cannot stat %s", lock_dir);
- new_mode = sb.st_mode;
- save_umask = umask (0000);
- saved_umask = 1;
-
- p = short_repos;
- while (1)
- {
- while (!ISDIRSEP (*p) && *p != '\0')
- ++p;
- if (ISDIRSEP (*p))
- {
- strncpy (q, short_repos, p - short_repos);
- q[p - short_repos] = '\0';
- if (!ISDIRSEP (q[p - short_repos - 1])
- && CVS_MKDIR (retval, new_mode) < 0)
- {
- int saved_errno = errno;
- if (saved_errno != EEXIST)
- error (1, errno, "cannot make directory %s", retval);
- else
- {
- if (CVS_STAT (retval, &sb) < 0)
- error (1, errno, "cannot stat %s", retval);
- new_mode = sb.st_mode;
- }
- }
- ++p;
- }
- else
- {
- strcpy (q, short_repos);
- if (CVS_MKDIR (retval, new_mode) < 0
- && errno != EEXIST)
- error (1, errno, "cannot make directory %s", retval);
- goto created;
- }
- }
- created:;
-
- strcat (retval, "/");
- strcat (retval, name);
-
- if (saved_umask)
- {
- assert (umask (save_umask) == 0000);
- saved_umask = 0;
- }
- }
- return retval;
-}
-
-/*
- * Clean up all outstanding locks
- */
-void
-Lock_Cleanup ()
-{
- /* FIXME: error handling here is kind of bogus; we sometimes will call
- error, which in turn can call us again. For the moment work around
- this by refusing to reenter this function (this is a kludge). */
- /* FIXME-reentrancy: the workaround isn't reentrant. */
- static int in_lock_cleanup = 0;
-
- if (trace)
- (void) fprintf (stderr, "%s-> Lock_Cleanup()\n", CLIENT_SERVER_STR);
-
- if (in_lock_cleanup)
- return;
- in_lock_cleanup = 1;
-
- remove_locks ();
-
- dellist (&lock_tree_list);
-
- if (locked_dir != NULL)
- {
- dellist (&locked_list);
- free (locked_dir);
- locked_dir = NULL;
- locked_list = NULL;
- }
-
- if (global_history_lock.repository) clear_history_lock ();
- if (global_val_tags_lock.repository) clear_val_tags_lock ();
-
- in_lock_cleanup = 0;
-}
-
-/*
- * Remove locks without discarding the lock information
- */
-static void
-remove_locks ()
-{
- /* clean up simple locks (if any) */
- if (global_readlock.repository != NULL)
- {
- lock_simple_remove (&global_readlock);
- global_readlock.repository = NULL;
- }
-
- /* clean up multiple locks (if any) */
- if (locklist != (List *) NULL)
- {
- (void) walklist (locklist, unlock_proc, NULL);
- locklist = (List *) NULL;
- }
-}
-
-/*
- * walklist proc for removing a list of locks
- */
-static int
-unlock_proc (p, closure)
- Node *p;
- void *closure;
-{
- lock_simple_remove (p->data);
- return (0);
-}
-
-
-
-/* Remove the lock files. */
-static void
-lock_simple_remove (lock)
- struct lock *lock;
-{
- char *tmp;
-
- /* If readlock is set, the lock directory *might* have been created, but
- since Reader_Lock doesn't use SIG_beginCrSect the way that set_lock
- does, we don't know that. That is why we need to check for
- existence_error here. */
- if (readlock != NULL)
- {
- tmp = lock_name (lock->repository, readlock);
- if (CVS_UNLINK (tmp) < 0 && ! existence_error (errno))
- error (0, errno, "failed to remove lock %s", tmp);
- free (tmp);
- }
-
- /* If writelock is set, the lock directory *might* have been created, but
- since write_lock doesn't use SIG_beginCrSect the way that set_lock
- does, we don't know that. That is why we need to check for
- existence_error here. */
- if (writelock != NULL)
- {
- tmp = lock_name (lock->repository, writelock);
- if (CVS_UNLINK (tmp) < 0 && ! existence_error (errno))
- error (0, errno, "failed to remove lock %s", tmp);
- free (tmp);
- }
-
- clear_lock (lock);
-}
-
-
-
-/*
- * Create a lock file for readers
- */
-int
-Reader_Lock (xrepository)
- char *xrepository;
-{
- int err = 0;
- FILE *fp;
- char *tmp;
-
- if (trace)
- (void) fprintf (stderr, "%s-> Reader_Lock(%s)\n", CLIENT_SERVER_STR,
- xrepository);
-
- if (noexec || readonlyfs)
- return 0;
-
- /* we only do one directory at a time for read locks! */
- if (global_readlock.repository != NULL)
- {
- error (0, 0, "Reader_Lock called while read locks set - Help!");
- return 1;
- }
-
- if (readlock == NULL)
- {
- readlock = xmalloc (strlen (hostname) + sizeof (CVSRFL) + 40);
- (void) sprintf (readlock,
-#ifdef HAVE_LONG_FILE_NAMES
- "%s.%s.%ld", CVSRFL, hostname,
-#else
- "%s.%ld", CVSRFL,
-#endif
- (long) getpid ());
- }
-
- /* remember what we're locking (for Lock_Cleanup) */
- global_readlock.repository = xrepository;
-
- /* get the lock dir for our own */
- if (set_lock (&global_readlock, 1) != L_OK)
- {
- error (0, 0, "failed to obtain dir lock in repository `%s'",
- xrepository);
- if (readlock != NULL)
- free (readlock);
- readlock = NULL;
- /* We don't set global_readlock.repository to NULL. I think this
- only works because recurse.c will give a fatal error if we return
- a nonzero value. */
- return 1;
- }
-
- /* write a read-lock */
- tmp = lock_name (xrepository, readlock);
- if ((fp = CVS_FOPEN (tmp, "w+")) == NULL || fclose (fp) == EOF)
- {
- error (0, errno, "cannot create read lock in repository `%s'",
- xrepository);
- if (readlock != NULL)
- free (readlock);
- readlock = NULL;
- err = 1;
- }
- free (tmp);
-
- /* free the lock dir */
- clear_lock (&global_readlock);
-
- return err;
-}
-
-
-
-/*
- * Lock a list of directories for writing
- */
-static char *lock_error_repos;
-static int lock_error;
-
-static int Writer_Lock PROTO ((List * list));
-
-static int
-Writer_Lock (list)
- List *list;
-{
- char *wait_repos;
-
- if (noexec)
- return 0;
-
- if (readonlyfs) {
- error (0, 0, "write lock failed - read-only repository");
- return (1);
- }
-
- /* We only know how to do one list at a time */
- if (locklist != (List *) NULL)
- {
- error (0, 0, "Writer_Lock called while write locks set - Help!");
- return 1;
- }
-
- wait_repos = NULL;
- for (;;)
- {
- /* try to lock everything on the list */
- lock_error = L_OK; /* init for set_writelock_proc */
- lock_error_repos = (char *) NULL; /* init for set_writelock_proc */
- locklist = list; /* init for Lock_Cleanup */
- if (lockers_name != NULL)
- free (lockers_name);
- lockers_name = xstrdup ("unknown");
-
- (void) walklist (list, set_writelock_proc, NULL);
-
- switch (lock_error)
- {
- case L_ERROR: /* Real Error */
- if (wait_repos != NULL)
- free (wait_repos);
- Lock_Cleanup (); /* clean up any locks we set */
- error (0, 0, "lock failed - giving up");
- return 1;
-
- case L_LOCKED: /* Someone already had a lock */
- remove_locks (); /* clean up any locks we set */
- lock_wait (lock_error_repos); /* sleep a while and try again */
- wait_repos = xstrdup (lock_error_repos);
- continue;
-
- case L_OK: /* we got the locks set */
- if (wait_repos != NULL)
- {
- lock_obtained (wait_repos);
- free (wait_repos);
- }
- return 0;
-
- default:
- if (wait_repos != NULL)
- free (wait_repos);
- error (0, 0, "unknown lock status %d in Writer_Lock",
- lock_error);
- return 1;
- }
- }
-}
-
-
-
-/*
- * walklist proc for setting write locks
- */
-static int
-set_writelock_proc (p, closure)
- Node *p;
- void *closure;
-{
- /* if some lock was not OK, just skip this one */
- if (lock_error != L_OK)
- return 0;
-
- /* apply the write lock */
- lock_error_repos = p->key;
- lock_error = write_lock (p->data);
- return 0;
-}
-
-
-
-/*
- * Create a lock file for writers returns L_OK if lock set ok, L_LOCKED if
- * lock held by someone else or L_ERROR if an error occurred
- */
-static int
-write_lock (lock)
- struct lock *lock;
-{
- int status;
- FILE *fp;
- char *tmp;
-
- if (trace)
- (void) fprintf (stderr, "%s-> write_lock(%s)\n",
- CLIENT_SERVER_STR, lock->repository);
-
- if (writelock == NULL)
- {
- writelock = xmalloc (strlen (hostname) + sizeof (CVSWFL) + 40);
- (void) sprintf (writelock,
-#ifdef HAVE_LONG_FILE_NAMES
- "%s.%s.%ld", CVSWFL, hostname,
-#else
- "%s.%ld", CVSWFL,
-#endif
- (long) getpid());
- }
-
- /* make sure the lock dir is ours (not necessarily unique to us!) */
- status = set_lock (lock, 0);
- if (status == L_OK)
- {
- /* we now own a writer - make sure there are no readers */
- if (readers_exist (lock->repository))
- {
- /* clean up the lock dir if we created it */
- if (status == L_OK)
- {
- clear_lock (lock);
- }
-
- /* indicate we failed due to read locks instead of error */
- return L_LOCKED;
- }
-
- /* write the write-lock file */
- tmp = lock_name (lock->repository, writelock);
- if ((fp = CVS_FOPEN (tmp, "w+")) == NULL || fclose (fp) == EOF)
- {
- int xerrno = errno;
-
- if ( CVS_UNLINK (tmp) < 0 && ! existence_error (errno))
- error (0, errno, "failed to remove lock %s", tmp);
-
- /* free the lock dir if we created it */
- if (status == L_OK)
- {
- clear_lock (lock);
- }
-
- /* return the error */
- error (0, xerrno, "cannot create write lock in repository `%s'",
- lock->repository);
- free (tmp);
- return L_ERROR;
- }
- free (tmp);
- return L_OK;
- }
- else
- return status;
-}
-
-
-
-/*
- * readers_exist() returns 0 if there are no reader lock files remaining in
- * the repository; else 1 is returned, to indicate that the caller should
- * sleep a while and try again.
- */
-static int
-readers_exist (repository)
- char *repository;
-{
- char *lockdir;
- char *line;
- DIR *dirp;
- struct dirent *dp;
- struct stat sb;
- int ret;
-#ifdef CVS_FUDGELOCKS
- time_t now;
- (void)time (&now);
-#endif
-
- lockdir = lock_name (repository, "");
-
- assert (lockdir != NULL);
-
- lockdir[strlen (lockdir) - 1] = '\0'; /* remove trailing slash */
-
- do {
- if ((dirp = CVS_OPENDIR (lockdir)) == NULL)
- error (1, 0, "cannot open directory %s", lockdir);
-
- ret = 0;
- errno = 0;
- while ((dp = CVS_READDIR (dirp)) != NULL)
- {
- if (CVS_FNMATCH (CVSRFLPAT, dp->d_name, 0) == 0)
- {
- line = xmalloc (strlen (lockdir) + 1 + strlen (dp->d_name) + 1);
- (void)sprintf (line, "%s/%s", lockdir, dp->d_name);
- if (CVS_STAT (line, &sb) != -1)
- {
-#ifdef CVS_FUDGELOCKS
- /*
- * If the create time of the file is more than CVSLCKAGE
- * seconds ago, try to clean-up the lock file, and if
- * successful, re-open the directory and try again.
- */
- if (now >= (sb.st_ctime + CVSLCKAGE) &&
- CVS_UNLINK (line) != -1)
- {
- free (line);
- ret = -1;
- break;
- }
-#endif
- set_lockers_name (&sb);
- }
- else
- {
- /* If the file doesn't exist, it just means that it
- * disappeared between the time we did the readdir and the
- * time we did the stat.
- */
- if (!existence_error (errno))
- error (0, errno, "cannot stat %s", line);
- }
- errno = 0;
- free (line);
- ret = 1;
- break;
- }
- errno = 0;
- }
- if (errno != 0)
- error (0, errno, "error reading directory %s", repository);
-
- CVS_CLOSEDIR (dirp);
- } while (ret < 0);
-
- if (lockdir != NULL)
- free (lockdir);
- return ret;
-}
-
-
-
-/*
- * Set the static variable lockers_name appropriately, based on the stat
- * structure passed in.
- */
-static void
-set_lockers_name (statp)
- struct stat *statp;
-{
- struct passwd *pw;
-
- if (lockers_name != NULL)
- free (lockers_name);
- if ((pw = (struct passwd *)getpwuid (statp->st_uid)) !=
- (struct passwd *)NULL)
- {
- lockers_name = xstrdup (pw->pw_name);
- }
- else
- {
- lockers_name = xmalloc (20);
- (void)sprintf (lockers_name, "uid%lu", (unsigned long) statp->st_uid);
- }
-}
-
-
-
-/*
- * Persistently tries to make the directory "lckdir", which serves as a
- * lock.
- *
- * #ifdef CVS_FUDGELOCKS
- * If the create time on the directory is greater than CVSLCKAGE
- * seconds old, just try to remove the directory.
- * #endif
- *
- */
-static int
-set_lock (lock, will_wait)
- struct lock *lock;
- int will_wait;
-{
- int waited;
- long us;
- struct stat sb;
- mode_t omask;
- char *masterlock;
- int status;
-#ifdef CVS_FUDGELOCKS
- time_t now;
-#endif
-
- masterlock = lock_name (lock->repository, lock->lockdirname);
-
- /*
- * Note that it is up to the callers of set_lock() to arrange for signal
- * handlers that do the appropriate things, like remove the lock
- * directory before they exit.
- */
- waited = 0;
- us = 1;
- for (;;)
- {
- status = -1;
- omask = umask (cvsumask);
- SIG_beginCrSect ();
- if (CVS_MKDIR (masterlock, 0777) == 0)
- {
- lock->lockdir = masterlock;
- SIG_endCrSect ();
- status = L_OK;
- if (waited)
- lock_obtained (lock->repository);
- goto after_sig_unblock;
- }
- SIG_endCrSect ();
- after_sig_unblock:
- (void) umask (omask);
- if (status != -1)
- goto done;
-
- if (errno != EEXIST)
- {
- error (0, errno,
- "failed to create lock directory for `%s' (%s)",
- lock->repository, masterlock);
- status = L_ERROR;
- goto done;
- }
-
- /* Find out who owns the lock. If the lock directory is
- non-existent, re-try the loop since someone probably just
- removed it (thus releasing the lock). */
- if (CVS_STAT (masterlock, &sb) < 0)
- {
- if (existence_error (errno))
- continue;
-
- error (0, errno, "couldn't stat lock directory `%s'", masterlock);
- status = L_ERROR;
- goto done;
- }
-
-#ifdef CVS_FUDGELOCKS
- /*
- * If the create time of the directory is more than CVSLCKAGE seconds
- * ago, try to clean-up the lock directory, and if successful, just
- * quietly retry to make it.
- */
- (void) time (&now);
- if (now >= (sb.st_ctime + CVSLCKAGE))
- {
- if (CVS_RMDIR (masterlock) >= 0)
- continue;
- }
-#endif
-
- /* set the lockers name */
- set_lockers_name (&sb);
-
- /* if he wasn't willing to wait, return an error */
- if (!will_wait)
- {
- status = L_LOCKED;
- goto done;
- }
-
- /* if possible, try a very short sleep without a message */
- if (!waited && us < 1000)
- {
- us += us;
-#if defined HAVE_NANOSLEEP
- {
- struct timespec ts;
- ts.tv_sec = 0;
- ts.tv_nsec = us * 1000;
- (void)nanosleep (&ts, NULL);
- continue;
- }
-#elif defined HAVE_USLEEP
- (void)usleep (us);
- continue;
-#elif defined HAVE_SELECT
- {
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = us;
- (void)select (0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL, &tv);
- continue;
- }
-#endif
- }
-
- lock_wait (lock->repository);
- waited = 1;
- }
-done:
- if (!lock->lockdir) free (masterlock);
- return status;
-}
-
-
-
-/*
- * Clear master lock.
- *
- * INPUTS
- * lock The lock information.
- *
- * OUTPUTS
- * Sets LOCK->lockdir to NULL after removing the directory it names and
- * freeing the storage.
- *
- * ASSUMPTIONS
- * If we own the master lock directory, its name is stored in LOCK->lockdir.
- * We may free LOCK->lockdir.
- *
- */
-static void
-clear_lock (lock)
- struct lock *lock;
-{
- SIG_beginCrSect ();
- if (lock->lockdir)
- {
- if (CVS_RMDIR (lock->lockdir) < 0)
- error (0, errno, "failed to remove lock dir `%s'", lock->lockdir);
- free (lock->lockdir);
- lock->lockdir = NULL;
- }
- SIG_endCrSect ();
-}
-
-
-
-/*
- * Print out a message that the lock is still held, then sleep a while.
- */
-static void
-lock_wait (repos)
- char *repos;
-{
- time_t now;
- char *msg;
- struct tm *tm_p;
-
- (void) time (&now);
- tm_p = gmtime (&now);
- msg = xmalloc (100 + strlen (lockers_name) + strlen (repos));
- sprintf (msg, "[%8.8s] waiting for %s's lock in %s",
- (tm_p ? asctime (tm_p) : ctime (&now)) + 11,
- lockers_name, repos);
- error (0, 0, "%s", msg);
- /* Call cvs_flusherr to ensure that the user sees this message as
- soon as possible. */
- cvs_flusherr ();
- free (msg);
- (void) sleep (CVSLCKSLEEP);
-}
-
-/*
- * Print out a message when we obtain a lock.
- */
-static void
-lock_obtained (repos)
- char *repos;
-{
- time_t now;
- char *msg;
- struct tm *tm_p;
-
- (void) time (&now);
- tm_p = gmtime (&now);
- msg = xmalloc (100 + strlen (repos));
- sprintf (msg, "[%8.8s] obtained lock in %s",
- (tm_p ? asctime (tm_p) : ctime (&now)) + 11, repos);
- error (0, 0, "%s", msg);
- /* Call cvs_flusherr to ensure that the user sees this message as
- soon as possible. */
- cvs_flusherr ();
- free (msg);
-}
-
-
-
-static int lock_filesdoneproc PROTO ((void *callerdat, int err,
- const char *repository,
- const char *update_dir,
- List *entries));
-
-/*
- * Create a list of repositories to lock
- */
-/* ARGSUSED */
-static int
-lock_filesdoneproc (callerdat, err, repository, update_dir, entries)
- void *callerdat;
- int err;
- const char *repository;
- const char *update_dir;
- List *entries;
-{
- Node *p;
-
- p = getnode ();
- p->type = LOCK;
- p->key = xstrdup (repository);
- p->data = xmalloc (sizeof (struct lock));
- ((struct lock *)p->data)->repository = p->key;
- ((struct lock *)p->data)->lockdirname = CVSLCK;
- ((struct lock *)p->data)->lockdir = NULL;
-
- /* FIXME-KRP: this error condition should not simply be passed by. */
- if (p->key == NULL || addnode (lock_tree_list, p) != 0)
- freenode (p);
- return (err);
-}
-
-void
-lock_tree_for_write (argc, argv, local, which, aflag)
- int argc;
- char **argv;
- int local;
- int which;
- int aflag;
-{
- /*
- * Run the recursion processor to find all the dirs to lock and lock all
- * the dirs
- */
- lock_tree_list = getlist ();
- start_recursion ((FILEPROC) NULL, lock_filesdoneproc,
- (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL, argc,
- argv, local, which, aflag, CVS_LOCK_NONE,
- (char *) NULL, 0, (char *) NULL);
- sortlist (lock_tree_list, fsortcmp);
- if (Writer_Lock (lock_tree_list) != 0)
- error (1, 0, "lock failed - giving up");
-}
-
-/* Lock a single directory in REPOSITORY. It is OK to call this if
- a lock has been set with lock_dir_for_write; the new lock will replace
- the old one. If REPOSITORY is NULL, don't do anything. */
-void
-lock_dir_for_write (repository)
- char *repository;
-{
- if (repository != NULL
- && (locked_dir == NULL
- || strcmp (locked_dir, repository) != 0))
- {
- Node *node;
-
- if (locked_dir != NULL)
- Lock_Cleanup ();
-
- locked_dir = xstrdup (repository);
- locked_list = getlist ();
- node = getnode ();
- node->type = LOCK;
- node->key = xstrdup (repository);
- node->data = xmalloc (sizeof (struct lock));
- ((struct lock *)node->data)->repository = node->key;
- ((struct lock *)node->data)->lockdirname = CVSLCK;
- ((struct lock *)node->data)->lockdir = NULL;
-
- (void) addnode (locked_list, node);
- Writer_Lock (locked_list);
- }
-}
-
-
-
-/* This is the internal implementation behind history_lock & val_tags_lock. It
- * gets a write lock for the history or val-tags file.
- *
- * RETURNS
- * true, on success
- * false, on error
- */
-static int internal_lock PROTO ((struct lock *lock, const char *xrepository));
-static int
-internal_lock (lock, xrepository)
- struct lock *lock;
- const char *xrepository;
-{
- /* remember what we're locking (for Lock_Cleanup) */
- assert (!lock->repository);
- lock->repository = xmalloc (strlen (xrepository) + sizeof (CVSROOTADM) + 2);
- sprintf (lock->repository, "%s/%s", xrepository, CVSROOTADM);
-
- /* get the lock dir for our own */
- if (set_lock (lock, 1) != L_OK)
- {
- if (!really_quiet)
- error (0, 0, "failed to obtain history lock in repository `%s'",
- xrepository);
-
- return 0;
- }
-
- return 1;
-}
-
-
-
-/* This is the internal implementation behind history_lock & val_tags_lock. It
- * removes the write lock for the history or val-tags file, when it exists.
- */
-static void internal_clear_lock PROTO((struct lock *lock));
-static void
-internal_clear_lock (lock)
- struct lock *lock;
-{
- SIG_beginCrSect ();
- if (lock->repository)
- {
- free (lock->repository);
- lock->repository = NULL;
- }
- SIG_endCrSect ();
-
- clear_lock (lock);
-}
-
-
-
-/* Lock the CVSROOT/history file for write.
- */
-int
-history_lock (xrepository)
- const char *xrepository;
-{
- return internal_lock (&global_history_lock, xrepository);
-}
-
-
-
-/* Remove the CVSROOT/history lock, if it exists.
- */
-void
-clear_history_lock ()
-{
- internal_clear_lock (&global_history_lock);
-}
-
-
-
-/* Lock the CVSROOT/val-tags file for write.
- */
-int
-val_tags_lock (xrepository)
- const char *xrepository;
-{
- return internal_lock (&global_val_tags_lock, xrepository);
-}
-
-
-
-/* Remove the CVSROOT/val-tags lock, if it exists.
- */
-void
-clear_val_tags_lock ()
-{
- internal_clear_lock (&global_val_tags_lock);
-}
diff --git a/contrib/cvs/src/log.c b/contrib/cvs/src/log.c
deleted file mode 100644
index 0bf44c756fd0..000000000000
--- a/contrib/cvs/src/log.c
+++ /dev/null
@@ -1,1818 +0,0 @@
-/*
- * Copyright (C) 1986-2008 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Print Log Information
- *
- * 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).
- *
- * $FreeBSD$
- */
-
-#include "cvs.h"
-#include <assert.h>
-
-/* This structure holds information parsed from the -r option. */
-
-struct option_revlist
-{
- /* The next -r option. */
- struct option_revlist *next;
- /* The first revision to print. This is NULL if the range is
- :rev, or if no revision is given. */
- char *first;
- /* The last revision to print. This is NULL if the range is rev:,
- or if no revision is given. If there is no colon, first and
- last are the same. */
- char *last;
- /* Nonzero if there was a trailing `.', which means to print only
- the head revision of a branch. */
- int branchhead;
- /* Nonzero if first and last are inclusive. */
- int inclusive;
-};
-
-/* This structure holds information derived from option_revlist given
- a particular RCS file. */
-
-struct revlist
-{
- /* The next pair. */
- struct revlist *next;
- /* The first numeric revision to print. */
- char *first;
- /* The last numeric revision to print. */
- char *last;
- /* The number of fields in these revisions (one more than
- numdots). */
- int fields;
- /* Whether first & last are to be included or excluded. */
- int inclusive;
-};
-
-/* This structure holds information parsed from the -d option. */
-
-struct datelist
-{
- /* The next date. */
- struct datelist *next;
- /* The starting date. */
- char *start;
- /* The ending date. */
- char *end;
- /* Nonzero if the range is inclusive rather than exclusive. */
- int inclusive;
-};
-
-/* This structure is used to pass information through start_recursion. */
-struct log_data
-{
- /* Nonzero if the -R option was given, meaning that only the name
- of the RCS file should be printed. */
- int nameonly;
- /* Nonzero if the -h option was given, meaning that only header
- information should be printed. */
- int header;
- /* Nonzero if the -t option was given, meaning that only the
- header and the descriptive text should be printed. */
- int long_header;
- /* Nonzero if the -N option was seen, meaning that tag information
- should not be printed. */
- int notags;
- /* Nonzero if the -b option was seen, meaning that revisions
- on the default branch should be printed. */
- int default_branch;
- /* Nonzero if the -S option was seen, meaning that the header/name
- should be suppressed if no revisions are selected. */
- int sup_header;
- /* If not NULL, the value given for the -r option, which lists
- sets of revisions to be printed. */
- struct option_revlist *revlist;
- /* If not NULL, the date pairs given for the -d option, which
- select date ranges to print. */
- struct datelist *datelist;
- /* If not NULL, the single dates given for the -d option, which
- select specific revisions to print based on a date. */
- struct datelist *singledatelist;
- /* If not NULL, the list of states given for the -s option, which
- only prints revisions of given states. */
- List *statelist;
- /* If not NULL, the list of login names given for the -w option,
- which only prints revisions checked in by given users. */
- List *authorlist;
-};
-
-/* This structure is used to pass information through walklist. */
-struct log_data_and_rcs
-{
- struct log_data *log_data;
- struct revlist *revlist;
- RCSNode *rcs;
-};
-
-static int rlog_proc PROTO((int argc, char **argv, char *xwhere,
- char *mwhere, char *mfile, int shorten,
- int local_specified, char *mname, char *msg));
-static Dtype log_dirproc PROTO ((void *callerdat, const char *dir,
- const char *repository,
- const char *update_dir,
- List *entries));
-static int log_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-static struct option_revlist *log_parse_revlist PROTO ((const char *));
-static void log_parse_date PROTO ((struct log_data *, const char *));
-static void log_parse_list PROTO ((List **, const char *));
-static struct revlist *log_expand_revlist PROTO ((RCSNode *, char *,
- struct option_revlist *,
- int));
-static void log_free_revlist PROTO ((struct revlist *));
-static int log_version_requested PROTO ((struct log_data *, struct revlist *,
- RCSNode *, RCSVers *));
-static int log_symbol PROTO ((Node *, void *));
-static int log_count PROTO ((Node *, void *));
-static int log_fix_singledate PROTO ((Node *, void *));
-static int log_count_print PROTO ((Node *, void *));
-static void log_tree PROTO ((struct log_data *, struct revlist *,
- RCSNode *, const char *));
-static void log_abranch PROTO ((struct log_data *, struct revlist *,
- RCSNode *, const char *));
-static void log_version PROTO ((struct log_data *, struct revlist *,
- RCSNode *, RCSVers *, int));
-static int log_branch PROTO ((Node *, void *));
-static int version_compare PROTO ((const char *, const char *, int));
-
-static struct log_data log_data;
-static int is_rlog;
-
-static const char *const log_usage[] =
-{
- "Usage: %s %s [-lRhtNb] [-r[revisions]] [-d dates] [-s states]\n",
- " [-w[logins]] [files...]\n",
- "\t-l\tLocal directory only, no recursion.\n",
- "\t-b\tList revisions on the default branch.\n",
- "\t-h\tOnly print header.\n",
- "\t-R\tOnly print name of RCS file.\n",
- "\t-t\tOnly print header and descriptive text.\n",
- "\t-N\tDo not list tags.\n",
- "\t-n\tList tags (default).\n",
- "\t-S\tDo not print name/header if no revisions selected. -d, -r,\n",
- "\t\t-s, & -w have little effect in conjunction with -b, -h, -R, and\n",
- "\t\t-t without this option.\n",
- "\t-r[revisions]\tA comma-separated list of revisions to print:\n",
- "\t rev1:rev2 Between rev1 and rev2, including rev1 and rev2.\n",
- "\t rev1::rev2 Between rev1 and rev2, excluding rev1.\n",
- "\t rev: rev and following revisions on the same branch.\n",
- "\t rev:: After rev on the same branch.\n",
- "\t :rev rev and previous revisions on the same branch.\n",
- "\t ::rev rev and previous revisions on the same branch.\n",
- "\t rev Just rev.\n",
- "\t branch All revisions on the branch.\n",
- "\t branch. The last revision on the branch.\n",
- "\t-d dates\tA semicolon-separated list of dates\n",
- "\t \t(D1<D2 for range, D for latest before).\n",
- "\t-s states\tOnly list revisions with specified states.\n",
- "\t-w[logins]\tOnly list revisions checked in by specified logins.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-#ifdef CLIENT_SUPPORT
-
-/* Helper function for send_arg_list. */
-static int send_one PROTO ((Node *, void *));
-
-static int
-send_one (node, closure)
- Node *node;
- void *closure;
-{
- char *option = (char *) closure;
-
- send_to_server ("Argument ", 0);
- send_to_server (option, 0);
- if (strcmp (node->key, "@@MYSELF") == 0)
- /* It is a bare -w option. Note that we must send it as
- -w rather than messing with getcaller() or something (which on
- the client will return garbage). */
- ;
- else
- send_to_server (node->key, 0);
- send_to_server ("\012", 0);
- return 0;
-}
-
-/* For each element in ARG, send an argument consisting of OPTION
- concatenated with that element. */
-static void send_arg_list PROTO ((char *, List *));
-
-static void
-send_arg_list (option, arg)
- char *option;
- List *arg;
-{
- if (arg == NULL)
- return;
- walklist (arg, send_one, (void *)option);
-}
-
-#endif
-
-int
-cvslog (argc, argv)
- int argc;
- char **argv;
-{
- int c;
- int err = 0;
- int local = 0;
- struct option_revlist **prl;
-
- is_rlog = (strcmp (cvs_cmd_name, "rlog") == 0);
-
- if (argc == -1)
- usage (log_usage);
-
- memset (&log_data, 0, sizeof log_data);
- prl = &log_data.revlist;
-
- optind = 0;
- while ((c = getopt (argc, argv, "+bd:hlNnSRr::s:tw::")) != -1)
- {
- switch (c)
- {
- case 'b':
- log_data.default_branch = 1;
- break;
- case 'd':
- log_parse_date (&log_data, optarg);
- break;
- case 'h':
- log_data.header = 1;
- break;
- case 'l':
- local = 1;
- break;
- case 'N':
- log_data.notags = 1;
- break;
- case 'n':
- log_data.notags = 0;
- break;
- case 'S':
- log_data.sup_header = 1;
- break;
- case 'R':
- log_data.nameonly = 1;
- break;
- case 'r':
- *prl = log_parse_revlist (optarg);
- prl = &(*prl)->next;
- break;
- case 's':
- log_parse_list (&log_data.statelist, optarg);
- break;
- case 't':
- log_data.long_header = 1;
- break;
- case 'w':
- if (optarg != NULL)
- log_parse_list (&log_data.authorlist, optarg);
- else
- log_parse_list (&log_data.authorlist, "@@MYSELF");
- break;
- case '?':
- default:
- usage (log_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- wrap_setup ();
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- struct datelist *p;
- struct option_revlist *rp;
- char datetmp[MAXDATELEN];
-
- /* We're the local client. Fire up the remote server. */
- start_server ();
-
- if (is_rlog && !supported_request ("rlog"))
- error (1, 0, "server does not support rlog");
-
- ign_setup ();
-
- if (log_data.default_branch)
- send_arg ("-b");
-
- while (log_data.datelist != NULL)
- {
- p = log_data.datelist;
- log_data.datelist = p->next;
- assert (p->start != NULL && p->end != NULL);
- send_to_server ("Argument -d\012", 0);
- send_to_server ("Argument ", 0);
- date_to_internet (datetmp, p->start);
- send_to_server (datetmp, 0);
- if (p->inclusive)
- send_to_server ("<=", 0);
- else
- send_to_server ("<", 0);
- date_to_internet (datetmp, p->end);
- send_to_server (datetmp, 0);
- send_to_server ("\012", 0);
- free (p->start);
- free (p->end);
- free (p);
- }
- while (log_data.singledatelist != NULL)
- {
- p = log_data.singledatelist;
- log_data.singledatelist = p->next;
- assert (p->end != NULL);
- send_to_server ("Argument -d\012", 0);
- send_to_server ("Argument ", 0);
- date_to_internet (datetmp, p->end);
- send_to_server (datetmp, 0);
- send_to_server ("\012", 0);
- free (p->end);
- free (p);
- }
-
- if (log_data.header)
- send_arg ("-h");
- if (local)
- send_arg("-l");
- if (log_data.notags)
- send_arg("-N");
- if (log_data.sup_header)
- send_arg("-S");
- if (log_data.nameonly)
- send_arg("-R");
- if (log_data.long_header)
- send_arg("-t");
-
- while (log_data.revlist != NULL)
- {
- rp = log_data.revlist;
- log_data.revlist = rp->next;
- send_to_server ("Argument -r", 0);
- if (rp->branchhead)
- {
- if (rp->first != NULL)
- send_to_server (rp->first, 0);
- send_to_server (".", 1);
- }
- else
- {
- if (rp->first != NULL)
- send_to_server (rp->first, 0);
- send_to_server (":", 1);
- if (!rp->inclusive)
- send_to_server (":", 1);
- if (rp->last != NULL)
- send_to_server (rp->last, 0);
- }
- send_to_server ("\012", 0);
- if (rp->first)
- free (rp->first);
- if (rp->last)
- free (rp->last);
- free (rp);
- }
- send_arg_list ("-s", log_data.statelist);
- dellist (&log_data.statelist);
- send_arg_list ("-w", log_data.authorlist);
- dellist (&log_data.authorlist);
- send_arg ("--");
-
- if (is_rlog)
- {
- int i;
- for (i = 0; i < argc; i++)
- send_arg (argv[i]);
- send_to_server ("rlog\012", 0);
- }
- else
- {
- send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
- send_file_names (argc, argv, SEND_EXPAND_WILD);
- send_to_server ("log\012", 0);
- }
- err = get_responses_and_close ();
- return err;
- }
-#endif
-
- /* OK, now that we know we are local/server, we can resolve @@MYSELF
- into our user name. */
- if (findnode (log_data.authorlist, "@@MYSELF") != NULL)
- log_parse_list (&log_data.authorlist, getcaller ());
-
- if (is_rlog)
- {
- DBM *db;
- int i;
- db = open_module ();
- for (i = 0; i < argc; i++)
- {
- err += do_module (db, argv[i], MISC, "Logging", rlog_proc,
- (char *) NULL, 0, local, 0, 0, (char *) NULL);
- }
- close_module (db);
- }
- else
- {
- err = rlog_proc (argc + 1, argv - 1, (char *) NULL,
- (char *) NULL, (char *) NULL, 0, local, (char *) NULL,
- (char *) NULL);
- }
-
- while (log_data.revlist)
- {
- struct option_revlist *rl = log_data.revlist->next;
- if (log_data.revlist->first)
- free (log_data.revlist->first);
- if (log_data.revlist->last)
- free (log_data.revlist->last);
- free (log_data.revlist);
- log_data.revlist = rl;
- }
- while (log_data.datelist)
- {
- struct datelist *nd = log_data.datelist->next;
- if (log_data.datelist->start)
- free (log_data.datelist->start);
- if (log_data.datelist->end)
- free (log_data.datelist->end);
- free (log_data.datelist);
- log_data.datelist = nd;
- }
- while (log_data.singledatelist)
- {
- struct datelist *nd = log_data.singledatelist->next;
- if (log_data.singledatelist->start)
- free (log_data.singledatelist->start);
- if (log_data.singledatelist->end)
- free (log_data.singledatelist->end);
- free (log_data.singledatelist);
- log_data.singledatelist = nd;
- }
- dellist (&log_data.statelist);
- dellist (&log_data.authorlist);
-
- return (err);
-}
-
-
-static int
-rlog_proc (argc, argv, xwhere, mwhere, mfile, shorten, local, mname, msg)
- int argc;
- char **argv;
- char *xwhere;
- char *mwhere;
- char *mfile;
- int shorten;
- int local;
- char *mname;
- char *msg;
-{
- /* Begin section which is identical to patch_proc--should this
- be abstracted out somehow? */
- char *myargv[2];
- int err = 0;
- int which;
- char *repository;
- char *where;
-
- if (is_rlog)
- {
- repository = xmalloc (strlen (current_parsed_root->directory)
- + strlen (argv[0])
- + (mfile == NULL ? 0 : strlen (mfile) + 1) + 2);
- (void)sprintf (repository, "%s/%s",
- current_parsed_root->directory, argv[0]);
- where = xmalloc (strlen (argv[0])
- + (mfile == NULL ? 0 : strlen (mfile) + 1)
- + 1);
- (void) strcpy (where, argv[0]);
-
- /* If mfile isn't null, we need to set up to do only part of theu
- * module.
- */
- if (mfile != NULL)
- {
- char *cp;
- char *path;
-
- /* If the portion of the module is a path, put the dir part on
- * repos.
- */
- if ((cp = strrchr (mfile, '/')) != NULL)
- {
- *cp = '\0';
- (void)strcat (repository, "/");
- (void)strcat (repository, mfile);
- (void)strcat (where, "/");
- (void)strcat (where, mfile);
- mfile = cp + 1;
- }
-
- /* take care of the rest */
- path = xmalloc (strlen (repository) + strlen (mfile) + 5);
- (void)sprintf (path, "%s/%s", repository, mfile);
- if (isdir (path))
- {
- /* directory means repository gets the dir tacked on */
- (void)strcpy (repository, path);
- (void)strcat (where, "/");
- (void)strcat (where, mfile);
- }
- else
- {
- myargv[0] = argv[0];
- myargv[1] = mfile;
- argc = 2;
- argv = myargv;
- }
- free (path);
- }
-
- /* cd to the starting repository */
- if (CVS_CHDIR (repository) < 0)
- {
- error (0, errno, "cannot chdir to %s", repository);
- free (repository);
- free (where);
- return 1;
- }
- /* End section which is identical to patch_proc. */
-
- which = W_REPOS | W_ATTIC;
- }
- else
- {
- repository = NULL;
- where = NULL;
- which = W_LOCAL | W_REPOS | W_ATTIC;
- }
-
- err = start_recursion (log_fileproc, (FILESDONEPROC) NULL, log_dirproc,
- (DIRLEAVEPROC) NULL, (void *) &log_data,
- argc - 1, argv + 1, local, which, 0, CVS_LOCK_READ,
- where, 1, repository);
-
- if (!(which & W_LOCAL)) free (repository);
- if (where) free (where);
-
- return err;
-}
-
-
-
-/*
- * Parse a revision list specification.
- */
-static struct option_revlist *
-log_parse_revlist (argstring)
- const char *argstring;
-{
- char *orig_copy, *copy;
- struct option_revlist *ret, **pr;
-
- /* Unfortunately, rlog accepts -r without an argument to mean that
- latest revision on the default branch, so we must support that
- for compatibility. */
- if (argstring == NULL)
- argstring = "";
-
- ret = NULL;
- pr = &ret;
-
- /* Copy the argument into memory so that we can change it. We
- don't want to change the argument because, at least as of this
- writing, we will use it if we send the arguments to the server. */
- orig_copy = copy = xstrdup (argstring);
- while (copy != NULL)
- {
- char *comma;
- struct option_revlist *r;
-
- comma = strchr (copy, ',');
- if (comma != NULL)
- *comma++ = '\0';
-
- r = (struct option_revlist *) xmalloc (sizeof *r);
- r->next = NULL;
- r->first = copy;
- r->branchhead = 0;
- r->last = strchr (copy, ':');
- if (r->last != NULL)
- {
- *r->last++ = '\0';
- r->inclusive = (*r->last != ':');
- if (!r->inclusive)
- r->last++;
- }
- else
- {
- r->last = r->first;
- r->inclusive = 1;
- if (r->first[0] != '\0' && r->first[strlen (r->first) - 1] == '.')
- {
- r->branchhead = 1;
- r->first[strlen (r->first) - 1] = '\0';
- }
- }
-
- if (*r->first == '\0')
- r->first = NULL;
- if (*r->last == '\0')
- r->last = NULL;
-
- if (r->first != NULL)
- r->first = xstrdup (r->first);
- if (r->last != NULL)
- r->last = xstrdup (r->last);
-
- *pr = r;
- pr = &r->next;
-
- copy = comma;
- }
-
- free (orig_copy);
- return ret;
-}
-
-/*
- * Parse a date specification.
- */
-static void
-log_parse_date (log_data, argstring)
- struct log_data *log_data;
- const char *argstring;
-{
- char *orig_copy, *copy;
-
- /* Copy the argument into memory so that we can change it. We
- don't want to change the argument because, at least as of this
- writing, we will use it if we send the arguments to the server. */
- orig_copy = copy = xstrdup (argstring);
- while (copy != NULL)
- {
- struct datelist *nd, **pd;
- char *cpend, *cp, *ds, *de;
-
- nd = (struct datelist *) xmalloc (sizeof *nd);
-
- cpend = strchr (copy, ';');
- if (cpend != NULL)
- *cpend++ = '\0';
-
- pd = &log_data->datelist;
- nd->inclusive = 0;
-
- if ((cp = strchr (copy, '>')) != NULL)
- {
- *cp++ = '\0';
- if (*cp == '=')
- {
- ++cp;
- nd->inclusive = 1;
- }
- ds = cp;
- de = copy;
- }
- else if ((cp = strchr (copy, '<')) != NULL)
- {
- *cp++ = '\0';
- if (*cp == '=')
- {
- ++cp;
- nd->inclusive = 1;
- }
- ds = copy;
- de = cp;
- }
- else
- {
- ds = NULL;
- de = copy;
- pd = &log_data->singledatelist;
- }
-
- if (ds == NULL)
- nd->start = NULL;
- else if (*ds != '\0')
- nd->start = Make_Date (ds);
- else
- {
- /* 1970 was the beginning of time, as far as get_date and
- Make_Date are concerned. FIXME: That is true only if time_t
- is a POSIX-style time and there is nothing in ANSI that
- mandates that. It would be cleaner to set a flag saying
- whether or not there is a start date. */
- nd->start = Make_Date ("1/1/1970 UTC");
- }
-
- if (*de != '\0')
- nd->end = Make_Date (de);
- else
- {
- /* We want to set the end date to some time sufficiently far
- in the future to pick up all revisions that have been
- created since the specified date and the time `cvs log'
- completes. FIXME: The date in question only makes sense
- if time_t is a POSIX-style time and it is 32 bits
- and signed. We should instead be setting a flag saying
- whether or not there is an end date. Note that using
- something like "next week" would break the testsuite (and,
- perhaps less importantly, loses if the clock is set grossly
- wrong). */
- nd->end = Make_Date ("2038-01-01");
- }
-
- nd->next = *pd;
- *pd = nd;
-
- copy = cpend;
- }
-
- free (orig_copy);
-}
-
-/*
- * Parse a comma separated list of items, and add each one to *PLIST.
- */
-static void
-log_parse_list (plist, argstring)
- List **plist;
- const char *argstring;
-{
- while (1)
- {
- Node *p;
- char *cp;
-
- p = getnode ();
-
- cp = strchr (argstring, ',');
- if (cp == NULL)
- p->key = xstrdup (argstring);
- else
- {
- size_t len;
-
- len = cp - argstring;
- p->key = xmalloc (len + 1);
- strncpy (p->key, argstring, len);
- p->key[len] = '\0';
- }
-
- if (*plist == NULL)
- *plist = getlist ();
- if (addnode (*plist, p) != 0)
- freenode (p);
-
- if (cp == NULL)
- break;
-
- argstring = cp + 1;
- }
-}
-
-static int printlock_proc PROTO ((Node *, void *));
-
-static int
-printlock_proc (lock, foo)
- Node *lock;
- void *foo;
-{
- cvs_output ("\n\t", 2);
- cvs_output (lock->data, 0);
- cvs_output (": ", 2);
- cvs_output (lock->key, 0);
- return 0;
-}
-
-
-
-/*
- * Do an rlog on a file
- */
-static int
-log_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- struct log_data *log_data = (struct log_data *) callerdat;
- Node *p;
- char *baserev;
- int selrev = -1;
- RCSNode *rcsfile;
- char buf[50];
- struct revlist *revlist = NULL;
- struct log_data_and_rcs log_data_and_rcs;
-
- rcsfile = finfo->rcs;
- p = findnode (finfo->entries, finfo->file);
- if (p != NULL)
- {
- Entnode *e = p->data;
- baserev = e->version;
- if (baserev[0] == '-') ++baserev;
- }
- else
- baserev = NULL;
-
- if (rcsfile == NULL)
- {
- /* no rcs file. What *do* we know about this file? */
- if (baserev != NULL)
- {
- if (baserev[0] == '0' && baserev[1] == '\0')
- {
- if (!really_quiet)
- error (0, 0, "%s has been added, but not committed",
- finfo->file);
- return 0;
- }
- }
-
- if (!really_quiet)
- error (0, 0, "nothing known about %s", finfo->file);
-
- return 1;
- }
-
- if (log_data->sup_header || !log_data->nameonly)
- {
-
- /* We will need all the information in the RCS file. */
- RCS_fully_parse (rcsfile);
-
- /* Turn any symbolic revisions in the revision list into numeric
- revisions. */
- revlist = log_expand_revlist (rcsfile, baserev, log_data->revlist,
- log_data->default_branch);
- if (log_data->sup_header
- || (!log_data->header && !log_data->long_header))
- {
- log_data_and_rcs.log_data = log_data;
- log_data_and_rcs.revlist = revlist;
- log_data_and_rcs.rcs = rcsfile;
-
- /* If any single dates were specified, we need to identify the
- revisions they select. Each one selects the single
- revision, which is otherwise selected, of that date or
- earlier. The log_fix_singledate routine will fill in the
- start date for each specific revision. */
- if (log_data->singledatelist != NULL)
- walklist (rcsfile->versions, log_fix_singledate,
- (void *)&log_data_and_rcs);
-
- selrev = walklist (rcsfile->versions, log_count_print,
- (void *)&log_data_and_rcs);
- if (log_data->sup_header && selrev == 0)
- {
- log_free_revlist (revlist);
- return 0;
- }
- }
-
- }
-
- if (log_data->nameonly)
- {
- cvs_output (rcsfile->path, 0);
- cvs_output ("\n", 1);
- log_free_revlist (revlist);
- return 0;
- }
-
- /* The output here is intended to be exactly compatible with the
- output of rlog. I'm not sure whether this code should be here
- or in rcs.c; I put it here because it is specific to the log
- function, even though it uses information gathered by the
- functions in rcs.c. */
-
- cvs_output ("\n", 1);
-
- cvs_output ("RCS file: ", 0);
- cvs_output (rcsfile->path, 0);
-
- if (!is_rlog)
- {
- cvs_output ("\nWorking file: ", 0);
- if (finfo->update_dir[0] != '\0')
- {
- cvs_output (finfo->update_dir, 0);
- cvs_output ("/", 0);
- }
- cvs_output (finfo->file, 0);
- }
-
- cvs_output ("\nhead:", 0);
- if (rcsfile->head != NULL)
- {
- cvs_output (" ", 1);
- cvs_output (rcsfile->head, 0);
- }
-
- cvs_output ("\nbranch:", 0);
- if (rcsfile->branch != NULL)
- {
- cvs_output (" ", 1);
- cvs_output (rcsfile->branch, 0);
- }
-
- cvs_output ("\nlocks:", 0);
- if (rcsfile->strict_locks)
- cvs_output (" strict", 0);
- walklist (RCS_getlocks (rcsfile), printlock_proc, NULL);
-
- cvs_output ("\naccess list:", 0);
- if (rcsfile->access != NULL)
- {
- const char *cp;
-
- cp = rcsfile->access;
- while (*cp != '\0')
- {
- const char *cp2;
-
- cvs_output ("\n\t", 2);
- cp2 = cp;
- while (!isspace ((unsigned char) *cp2) && *cp2 != '\0')
- ++cp2;
- cvs_output (cp, cp2 - cp);
- cp = cp2;
- while (isspace ((unsigned char) *cp) && *cp != '\0')
- ++cp;
- }
- }
-
- if (!log_data->notags)
- {
- List *syms;
-
- cvs_output ("\nsymbolic names:", 0);
- syms = RCS_symbols (rcsfile);
- walklist (syms, log_symbol, NULL);
- }
-
- cvs_output ("\nkeyword substitution: ", 0);
- if (rcsfile->expand == NULL)
- cvs_output ("kv", 2);
- else
- cvs_output (rcsfile->expand, 0);
-
- cvs_output ("\ntotal revisions: ", 0);
- sprintf (buf, "%d", walklist (rcsfile->versions, log_count, NULL));
- cvs_output (buf, 0);
-
- if (selrev >= 0)
- {
- cvs_output (";\tselected revisions: ", 0);
- sprintf (buf, "%d", selrev);
- cvs_output (buf, 0);
- }
-
- cvs_output ("\n", 1);
-
- if (!log_data->header || log_data->long_header)
- {
- cvs_output ("description:\n", 0);
- if (rcsfile->desc != NULL)
- cvs_output (rcsfile->desc, 0);
- }
-
- if (!log_data->header && ! log_data->long_header && rcsfile->head != NULL)
- {
- p = findnode (rcsfile->versions, rcsfile->head);
- if (p == NULL)
- error (1, 0, "can not find head revision in `%s'",
- finfo->fullname);
- while (p != NULL)
- {
- RCSVers *vers = p->data;
-
- log_version (log_data, revlist, rcsfile, vers, 1);
- if (vers->next == NULL)
- p = NULL;
- else
- {
- p = findnode (rcsfile->versions, vers->next);
- if (p == NULL)
- error (1, 0, "can not find next revision `%s' in `%s'",
- vers->next, finfo->fullname);
- }
- }
-
- log_tree (log_data, revlist, rcsfile, rcsfile->head);
- }
-
- cvs_output("\
-=============================================================================\n",
- 0);
-
- /* Free up the new revlist and restore the old one. */
- log_free_revlist (revlist);
-
- /* If singledatelist is not NULL, free up the start dates we added
- to it. */
- if (log_data->singledatelist != NULL)
- {
- struct datelist *d;
-
- for (d = log_data->singledatelist; d != NULL; d = d->next)
- {
- if (d->start != NULL)
- free (d->start);
- d->start = NULL;
- }
- }
-
- return 0;
-}
-
-
-
-/*
- * Fix up a revision list in order to compare it against versions.
- * Expand any symbolic revisions.
- */
-static struct revlist *
-log_expand_revlist (rcs, baserev, revlist, default_branch)
- RCSNode *rcs;
- char *baserev;
- struct option_revlist *revlist;
- int default_branch;
-{
- struct option_revlist *r;
- struct revlist *ret, **pr;
-
- ret = NULL;
- pr = &ret;
- for (r = revlist; r != NULL; r = r->next)
- {
- struct revlist *nr;
-
- nr = (struct revlist *) xmalloc (sizeof *nr);
- nr->inclusive = r->inclusive;
-
- if (r->first == NULL && r->last == NULL)
- {
- /* If both first and last are NULL, it means that we want
- just the head of the default branch, which is RCS_head. */
- nr->first = RCS_head (rcs);
- if (!nr->first)
- {
- if (!really_quiet)
- error (0, 0, "No head revision in archive `%s'.",
- rcs->path);
- nr->last = NULL;
- nr->fields = 0;
- }
- else
- {
- nr->last = xstrdup (nr->first);
- nr->fields = numdots (nr->first) + 1;
- }
- }
- else if (r->branchhead)
- {
- char *branch;
-
- assert (r->first != NULL);
-
- /* Print just the head of the branch. */
- if (isdigit ((unsigned char) r->first[0]))
- nr->first = RCS_getbranch (rcs, r->first, 1);
- else
- {
- branch = RCS_whatbranch (rcs, r->first);
- if (branch == NULL)
- nr->first = NULL;
- else
- {
- nr->first = RCS_getbranch (rcs, branch, 1);
- free (branch);
- }
- }
- if (!nr->first)
- {
- if (!really_quiet)
- error (0, 0, "warning: no branch `%s' in `%s'",
- r->first, rcs->path);
- nr->last = NULL;
- nr->fields = 0;
- }
- else
- {
- nr->last = xstrdup (nr->first);
- nr->fields = numdots (nr->first) + 1;
- }
- }
- else
- {
- if (r->first == NULL || isdigit ((unsigned char) r->first[0]))
- nr->first = xstrdup (r->first);
- else
- {
- if (baserev && strcmp (r->first, TAG_BASE) == 0)
- nr->first = xstrdup (baserev);
- else if (RCS_nodeisbranch (rcs, r->first))
- nr->first = RCS_whatbranch (rcs, r->first);
- else
- nr->first = RCS_gettag (rcs, r->first, 1, (int *) NULL);
- if (nr->first == NULL && !really_quiet)
- {
- error (0, 0, "warning: no revision `%s' in `%s'",
- r->first, rcs->path);
- }
- }
-
- if (r->last == r->first || (r->last != NULL && r->first != NULL &&
- strcmp (r->last, r->first) == 0))
- nr->last = xstrdup (nr->first);
- else if (r->last == NULL || isdigit ((unsigned char) r->last[0]))
- nr->last = xstrdup (r->last);
- else
- {
- if (baserev && strcmp (r->last, TAG_BASE) == 0)
- nr->last = xstrdup (baserev);
- else if (RCS_nodeisbranch (rcs, r->last))
- nr->last = RCS_whatbranch (rcs, r->last);
- else
- nr->last = RCS_gettag (rcs, r->last, 1, (int *) NULL);
- if (nr->last == NULL && !really_quiet)
- {
- error (0, 0, "warning: no revision `%s' in `%s'",
- r->last, rcs->path);
- }
- }
-
- /* Process the revision numbers the same way that rlog
- does. This code is a bit cryptic for my tastes, but
- keeping the same implementation as rlog ensures a
- certain degree of compatibility. */
- if (r->first == NULL && nr->last != NULL)
- {
- nr->fields = numdots (nr->last) + 1;
- if (nr->fields < 2)
- nr->first = xstrdup (".0");
- else
- {
- char *cp;
-
- nr->first = xstrdup (nr->last);
- cp = strrchr (nr->first, '.');
- assert (cp);
- strcpy (cp + 1, "0");
- }
- }
- else if (r->last == NULL && nr->first != NULL)
- {
- nr->fields = numdots (nr->first) + 1;
- nr->last = xstrdup (nr->first);
- if (nr->fields < 2)
- nr->last[0] = '\0';
- else
- {
- char *cp;
-
- cp = strrchr (nr->last, '.');
- assert (cp);
- *cp = '\0';
- }
- }
- else if (nr->first == NULL || nr->last == NULL)
- nr->fields = 0;
- else if (strcmp (nr->first, nr->last) == 0)
- nr->fields = numdots (nr->last) + 1;
- else
- {
- int ord;
- int dots1 = numdots (nr->first);
- int dots2 = numdots (nr->last);
- if (dots1 > dots2 || (dots1 == dots2 &&
- version_compare (nr->first, nr->last, dots1 + 1) > 0))
- {
- char *tmp = nr->first;
- nr->first = nr->last;
- nr->last = tmp;
- nr->fields = dots2 + 1;
- dots2 = dots1;
- dots1 = nr->fields - 1;
- }
- else
- nr->fields = dots1 + 1;
- dots1 += (nr->fields & 1);
- ord = version_compare (nr->first, nr->last, dots1);
- if (ord > 0 || (nr->fields > 2 && ord < 0))
- {
- error (0, 0,
- "invalid branch or revision pair %s:%s in `%s'",
- r->first, r->last, rcs->path);
- free (nr->first);
- nr->first = NULL;
- free (nr->last);
- nr->last = NULL;
- nr->fields = 0;
- }
- else
- {
- if (nr->fields <= dots2 && (nr->fields & 1))
- {
- char *p = xmalloc (strlen (nr->first) + 3);
- strcpy (p, nr->first);
- strcat (p, ".0");
- free (nr->first);
- nr->first = p;
- ++nr->fields;
- }
- while (nr->fields <= dots2)
- {
- char *p;
- int i;
-
- nr->next = NULL;
- *pr = nr;
- nr = (struct revlist *) xmalloc (sizeof *nr);
- nr->inclusive = 1;
- nr->first = xstrdup ((*pr)->last);
- nr->last = xstrdup ((*pr)->last);
- nr->fields = (*pr)->fields;
- p = (*pr)->last;
- for (i = 0; i < nr->fields; i++)
- p = strchr (p, '.') + 1;
- p[-1] = '\0';
- p = strchr (nr->first + (p - (*pr)->last), '.');
- if (p != NULL)
- {
- *++p = '0';
- *++p = '\0';
- nr->fields += 2;
- }
- else
- ++nr->fields;
- pr = &(*pr)->next;
- }
- }
- }
- }
-
- nr->next = NULL;
- *pr = nr;
- pr = &nr->next;
- }
-
- /* If the default branch was requested, add a revlist entry for
- it. This is how rlog handles this option. */
- if (default_branch
- && (rcs->head != NULL || rcs->branch != NULL))
- {
- struct revlist *nr;
-
- nr = (struct revlist *) xmalloc (sizeof *nr);
- if (rcs->branch != NULL)
- nr->first = xstrdup (rcs->branch);
- else
- {
- char *cp;
-
- nr->first = xstrdup (rcs->head);
- assert (nr->first);
- cp = strrchr (nr->first, '.');
- assert (cp);
- *cp = '\0';
- }
- nr->last = xstrdup (nr->first);
- nr->fields = numdots (nr->first) + 1;
- nr->inclusive = 1;
-
- nr->next = NULL;
- *pr = nr;
- }
-
- return ret;
-}
-
-/*
- * Free a revlist created by log_expand_revlist.
- */
-static void
-log_free_revlist (revlist)
- struct revlist *revlist;
-{
- struct revlist *r;
-
- r = revlist;
- while (r != NULL)
- {
- struct revlist *next;
-
- if (r->first != NULL)
- free (r->first);
- if (r->last != NULL)
- free (r->last);
- next = r->next;
- free (r);
- r = next;
- }
-}
-
-/*
- * Return nonzero if a revision should be printed, based on the
- * options provided.
- */
-static int
-log_version_requested (log_data, revlist, rcs, vnode)
- struct log_data *log_data;
- struct revlist *revlist;
- RCSNode *rcs;
- RCSVers *vnode;
-{
- /* Handle the list of states from the -s option. */
- if (log_data->statelist != NULL
- && findnode (log_data->statelist, vnode->state) == NULL)
- {
- return 0;
- }
-
- /* Handle the list of authors from the -w option. */
- if (log_data->authorlist != NULL)
- {
- if (vnode->author != NULL
- && findnode (log_data->authorlist, vnode->author) == NULL)
- {
- return 0;
- }
- }
-
- /* rlog considers all the -d options together when it decides
- whether to print a revision, so we must be compatible. */
- if (log_data->datelist != NULL || log_data->singledatelist != NULL)
- {
- struct datelist *d;
-
- for (d = log_data->datelist; d != NULL; d = d->next)
- {
- int cmp;
-
- cmp = RCS_datecmp (vnode->date, d->start);
- if (cmp > 0 || (cmp == 0 && d->inclusive))
- {
- cmp = RCS_datecmp (vnode->date, d->end);
- if (cmp < 0 || (cmp == 0 && d->inclusive))
- break;
- }
- }
-
- if (d == NULL)
- {
- /* Look through the list of specific dates. We want to
- select the revision with the exact date found in the
- start field. The commit code ensures that it is
- impossible to check in multiple revisions of a single
- file in a single second, so checking the date this way
- should never select more than one revision. */
- for (d = log_data->singledatelist; d != NULL; d = d->next)
- {
- if (d->start != NULL
- && RCS_datecmp (vnode->date, d->start) == 0)
- {
- break;
- }
- }
-
- if (d == NULL)
- return 0;
- }
- }
-
- /* If the -r or -b options were used, REVLIST will be non NULL,
- and we print the union of the specified revisions. */
- if (revlist != NULL)
- {
- char *v;
- int vfields;
- struct revlist *r;
-
- /* This code is taken from rlog. */
- v = vnode->version;
- vfields = numdots (v) + 1;
- for (r = revlist; r != NULL; r = r->next)
- {
- if (vfields == r->fields + (r->fields & 1) &&
- (r->inclusive ? version_compare (v, r->first, r->fields) >= 0 :
- version_compare (v, r->first, r->fields) > 0)
- && version_compare (v, r->last, r->fields) <= 0)
- {
- return 1;
- }
- }
-
- /* If we get here, then the -b and/or the -r option was used,
- but did not match this revision, so we reject it. */
-
- return 0;
- }
-
- /* By default, we print all revisions. */
- return 1;
-}
-
-
-
-/*
- * Output a single symbol. This is called via walklist.
- */
-/*ARGSUSED*/
-static int
-log_symbol (p, closure)
- Node *p;
- void *closure;
-{
- cvs_output ("\n\t", 2);
- cvs_output (p->key, 0);
- cvs_output (": ", 2);
- cvs_output (p->data, 0);
- return 0;
-}
-
-
-
-/*
- * Count the number of entries on a list. This is called via walklist.
- */
-/*ARGSUSED*/
-static int
-log_count (p, closure)
- Node *p;
- void *closure;
-{
- return 1;
-}
-
-
-
-/*
- * Sort out a single date specification by narrowing down the date
- * until we find the specific selected revision.
- */
-static int
-log_fix_singledate (p, closure)
- Node *p;
- void *closure;
-{
- struct log_data_and_rcs *data = (struct log_data_and_rcs *) closure;
- Node *pv;
- RCSVers *vnode;
- struct datelist *holdsingle, *holddate;
- int requested;
-
- pv = findnode (data->rcs->versions, p->key);
- if (pv == NULL)
- error (1, 0, "missing version `%s' in RCS file `%s'",
- p->key, data->rcs->path);
- vnode = pv->data;
-
- /* We are only interested if this revision passes any other tests.
- Temporarily clear log_data->singledatelist to avoid confusing
- log_version_requested. We also clear log_data->datelist,
- because rlog considers all the -d options together. We don't
- want to reject a revision because it does not match a date pair
- if we are going to select it on the basis of the singledate. */
- holdsingle = data->log_data->singledatelist;
- data->log_data->singledatelist = NULL;
- holddate = data->log_data->datelist;
- data->log_data->datelist = NULL;
- requested = log_version_requested (data->log_data, data->revlist,
- data->rcs, vnode);
- data->log_data->singledatelist = holdsingle;
- data->log_data->datelist = holddate;
-
- if (requested)
- {
- struct datelist *d;
-
- /* For each single date, if this revision is before the
- specified date, but is closer than the previously selected
- revision, select it instead. */
- for (d = data->log_data->singledatelist; d != NULL; d = d->next)
- {
- if (RCS_datecmp (vnode->date, d->end) <= 0
- && (d->start == NULL
- || RCS_datecmp (vnode->date, d->start) > 0))
- {
- if (d->start != NULL)
- free (d->start);
- d->start = xstrdup (vnode->date);
- }
- }
- }
-
- return 0;
-}
-
-
-
-/*
- * Count the number of revisions we are going to print.
- */
-static int
-log_count_print (p, closure)
- Node *p;
- void *closure;
-{
- struct log_data_and_rcs *data = (struct log_data_and_rcs *) closure;
- Node *pv;
-
- pv = findnode (data->rcs->versions, p->key);
- if (pv == NULL)
- error (1, 0, "missing version `%s' in RCS file `%s'",
- p->key, data->rcs->path);
- if (log_version_requested (data->log_data, data->revlist, data->rcs,
- pv->data))
- return 1;
- else
- return 0;
-}
-
-/*
- * Print the list of changes, not including the trunk, in reverse
- * order for each branch.
- */
-static void
-log_tree (log_data, revlist, rcs, ver)
- struct log_data *log_data;
- struct revlist *revlist;
- RCSNode *rcs;
- const char *ver;
-{
- Node *p;
- RCSVers *vnode;
-
- p = findnode (rcs->versions, ver);
- if (p == NULL)
- error (1, 0, "missing version `%s' in RCS file `%s'",
- ver, rcs->path);
- vnode = p->data;
- if (vnode->next != NULL)
- log_tree (log_data, revlist, rcs, vnode->next);
- if (vnode->branches != NULL)
- {
- Node *head, *branch;
-
- /* We need to do the branches in reverse order. This breaks
- the List abstraction, but so does most of the branch
- manipulation in rcs.c. */
- head = vnode->branches->list;
- for (branch = head->prev; branch != head; branch = branch->prev)
- {
- log_abranch (log_data, revlist, rcs, branch->key);
- log_tree (log_data, revlist, rcs, branch->key);
- }
- }
-}
-
-/*
- * Log the changes for a branch, in reverse order.
- */
-static void
-log_abranch (log_data, revlist, rcs, ver)
- struct log_data *log_data;
- struct revlist *revlist;
- RCSNode *rcs;
- const char *ver;
-{
- Node *p;
- RCSVers *vnode;
-
- p = findnode (rcs->versions, ver);
- if (p == NULL)
- error (1, 0, "missing version `%s' in RCS file `%s'",
- ver, rcs->path);
- vnode = p->data;
- if (vnode->next != NULL)
- log_abranch (log_data, revlist, rcs, vnode->next);
- log_version (log_data, revlist, rcs, vnode, 0);
-}
-
-/*
- * Print the log output for a single version.
- */
-static void
-log_version (log_data, revlist, rcs, ver, trunk)
- struct log_data *log_data;
- struct revlist *revlist;
- RCSNode *rcs;
- RCSVers *ver;
- int trunk;
-{
- Node *p;
- int year, mon, mday, hour, min, sec;
- char buf[100];
- Node *padd, *pdel;
-
- if (! log_version_requested (log_data, revlist, rcs, ver))
- return;
-
- cvs_output ("----------------------------\nrevision ", 0);
- cvs_output (ver->version, 0);
-
- p = findnode (RCS_getlocks (rcs), ver->version);
- if (p != NULL)
- {
- cvs_output ("\tlocked by: ", 0);
- cvs_output (p->data, 0);
- cvs_output (";", 1);
- }
-
- cvs_output ("\ndate: ", 0);
- (void) sscanf (ver->date, SDATEFORM, &year, &mon, &mday, &hour, &min,
- &sec);
- if (year < 1900)
- year += 1900;
- sprintf (buf, "%04d%c%02d%c%02d %02d:%02d:%02d",
- year, datesep, mon, datesep, mday, hour, min, sec);
- cvs_output (buf, 0);
-
- cvs_output ("; author: ", 0);
- cvs_output (ver->author, 0);
-
- cvs_output ("; state: ", 0);
- cvs_output (ver->state, 0);
- cvs_output (";", 1);
-
- if (! trunk)
- {
- padd = findnode (ver->other, ";add");
- pdel = findnode (ver->other, ";delete");
- }
- else if (ver->next == NULL)
- {
- padd = NULL;
- pdel = NULL;
- }
- else
- {
- Node *nextp;
- RCSVers *nextver;
-
- nextp = findnode (rcs->versions, ver->next);
- if (nextp == NULL)
- error (1, 0, "missing version `%s' in `%s'", ver->next,
- rcs->path);
- nextver = nextp->data;
- pdel = findnode (nextver->other, ";add");
- padd = findnode (nextver->other, ";delete");
- }
-
- if (padd != NULL)
- {
- assert (pdel);
- cvs_output (" lines: +", 0);
- cvs_output (padd->data, 0);
- cvs_output (" -", 2);
- cvs_output (pdel->data, 0);
- }
-
- if (ver->branches != NULL)
- {
- cvs_output ("\nbranches:", 0);
- walklist (ver->branches, log_branch, (void *) NULL);
- }
-
- cvs_output ("\n", 1);
-
- p = findnode (ver->other, "log");
- /* The p->date == NULL case is the normal one for an empty log
- message (rcs-14 in sanity.sh). I don't think the case where
- p->data is "" can happen (getrcskey in rcs.c checks for an
- empty string and set the value to NULL in that case). My guess
- would be the p == NULL case would mean an RCS file which was
- missing the "log" keyword (which is illegal according to
- rcsfile.5). */
- if (p == NULL || p->data == NULL || *(char *)p->data == '\0')
- cvs_output ("*** empty log message ***\n", 0);
- else
- {
- /* FIXME: Technically, the log message could contain a null
- byte. */
- cvs_output (p->data, 0);
- if (((char *)p->data)[strlen (p->data) - 1] != '\n')
- cvs_output ("\n", 1);
- }
-}
-
-/*
- * Output a branch version. This is called via walklist.
- */
-/*ARGSUSED*/
-static int
-log_branch (p, closure)
- Node *p;
- void *closure;
-{
- cvs_output (" ", 2);
- if ((numdots (p->key) & 1) == 0)
- cvs_output (p->key, 0);
- else
- {
- char *f, *cp;
-
- f = xstrdup (p->key);
- cp = strrchr (f, '.');
- *cp = '\0';
- cvs_output (f, 0);
- free (f);
- }
- cvs_output (";", 1);
- return 0;
-}
-
-/*
- * Print a warm fuzzy message
- */
-/* ARGSUSED */
-static Dtype
-log_dirproc (callerdat, dir, repository, update_dir, entries)
- void *callerdat;
- const char *dir;
- const char *repository;
- const char *update_dir;
- List *entries;
-{
- if (!isdir (dir))
- return (R_SKIP_ALL);
-
- if (!quiet)
- error (0, 0, "Logging %s", update_dir);
- return (R_PROCESS);
-}
-
-/*
- * Compare versions. This is taken from RCS compartial.
- */
-static int
-version_compare (v1, v2, len)
- const char *v1;
- const char *v2;
- int len;
-{
- while (1)
- {
- int d1, d2, r;
-
- if (*v1 == '\0')
- return 1;
- if (*v2 == '\0')
- return -1;
-
- while (*v1 == '0')
- ++v1;
- for (d1 = 0; isdigit ((unsigned char) v1[d1]); ++d1)
- ;
-
- while (*v2 == '0')
- ++v2;
- for (d2 = 0; isdigit ((unsigned char) v2[d2]); ++d2)
- ;
-
- if (d1 != d2)
- return d1 < d2 ? -1 : 1;
-
- r = memcmp (v1, v2, d1);
- if (r != 0)
- return r;
-
- --len;
- if (len == 0)
- return 0;
-
- v1 += d1;
- v2 += d1;
-
- if (*v1 == '.')
- ++v1;
- if (*v2 == '.')
- ++v2;
- }
-}
diff --git a/contrib/cvs/src/login.c b/contrib/cvs/src/login.c
deleted file mode 100644
index 1d20c97eb769..000000000000
--- a/contrib/cvs/src/login.c
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (c) 1995, Cyclic Software, Bloomington, IN, USA
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with CVS.
- *
- * Allow user to log in for an authenticating server.
- */
-
-#include "cvs.h"
-#include "getline.h"
-
-#ifdef AUTH_CLIENT_SUPPORT /* This covers the rest of the file. */
-
-/* There seems to be very little agreement on which system header
- getpass is declared in. With a lot of fancy autoconfiscation,
- we could perhaps detect this, but for now we'll just rely on
- _CRAY, since Cray is perhaps the only system on which our own
- declaration won't work (some Crays declare the 2#$@% thing as
- varadic, believe it or not). On Cray, getpass will be declared
- in either stdlib.h or unistd.h. */
-
-#ifndef CVS_PASSWORD_FILE
-#define CVS_PASSWORD_FILE ".cvspass"
-#endif
-
-/* If non-NULL, get_cvs_password() will just return this. */
-static char *cvs_password = NULL;
-
-static char *construct_cvspass_filename PROTO ((void));
-
-/* The return value will need to be freed. */
-static char *
-construct_cvspass_filename ()
-{
- char *homedir;
- char *passfile;
-
- /* Environment should override file. */
- if ((passfile = getenv ("CVS_PASSFILE")) != NULL)
- return xstrdup (passfile);
-
- /* Construct absolute pathname to user's password file. */
- /* todo: does this work under OS/2 ? */
- homedir = get_homedir ();
- if (! homedir)
- {
- /* FIXME? This message confuses a lot of users, at least
- on Win95 (which doesn't set HOMEDRIVE and HOMEPATH like
- NT does). I suppose the answer for Win95 is to store the
- passwords in the registry or something (??). And .cvsrc
- and such too? Wonder what WinCVS does (about .cvsrc, the
- right thing for a GUI is to just store the password in
- memory only)... */
- error (1, 0, "could not find out home directory");
- return (char *) NULL;
- }
-
- passfile = strcat_filename_onto_homedir (homedir, CVS_PASSWORD_FILE);
-
- /* Safety first and last, Scouts. */
- if (isfile (passfile))
- /* xchmod() is too polite. */
- chmod (passfile, 0600);
-
- return passfile;
-}
-
-
-
-/*
- * static char *
- * password_entry_parseline (
- * const char *cvsroot_canonical,
- * const unsigned char warn,
- * const int linenumber,
- * char *linebuf
- * );
- *
- * Internal function used by password_entry_operation. Parse a single line
- * from a ~/.cvsroot password file and return a pointer to the password if the
- * line refers to the same cvsroot as cvsroot_canonical
- *
- * INPUTS
- * cvsroot_canonical the root we are looking for
- * warn Boolean: print warnings for invalid lines?
- * linenumber the line number for error messages
- * linebuf the current line
- *
- * RETURNS
- * NULL if the line doesn't match
- * char *password as a pointer into linebuf
- *
- * NOTES
- * This function temporarily alters linebuf, so it isn't thread safe when
- * called on the same linebuf
- */
-static char *
-password_entry_parseline (cvsroot_canonical, warn, linenumber, linebuf)
- const char *cvsroot_canonical;
- const unsigned char warn;
- const int linenumber;
- char *linebuf;
-{
- char *password = NULL;
- char *p;
-
- /* look for '^/' */
- if (*linebuf == '/')
- {
- /* Yes: slurp '^/\d+\D' and parse the rest of the line according to version number */
- char *q;
- unsigned long int entry_version = 0;
-
- if (isspace(*(linebuf + 1)))
- {
- /* special case since strtoul ignores leading white space */
- q = linebuf + 1;
- }
- else
- {
- entry_version = strtoul (linebuf + 1, &q, 10);
- if (q != linebuf + 1)
- /* assume a delimiting seperator */
- q++;
- }
-
- switch (entry_version)
- {
- case 1:
- /* this means the same normalize_cvsroot we are using was
- * used to create this entry. strcmp is good enough for
- * us.
- */
- p = strchr (q, ' ');
- if (p == NULL)
- {
- if (warn && !really_quiet)
- error (0, 0, "warning: skipping invalid entry in password file at line %d",
- linenumber);
- }
- else
- {
- *p = '\0';
- if (strcmp (cvsroot_canonical, q) == 0)
- password = p + 1;
- *p = ' ';
- }
- break;
- case ULONG_MAX:
- if (warn && !really_quiet)
- {
- error (0, errno, "warning: unable to convert version number in password file at line %d",
- linenumber);
- error (0, 0, "skipping entry");
- }
- break;
- case 0:
- if (warn && !really_quiet)
- error (0, 0, "warning: skipping entry with invalid version string in password file at line %d",
- linenumber);
- break;
- default:
- if (warn && !really_quiet)
- error (0, 0, "warning: skipping entry with unknown version (%lu) in password file at line %d",
- entry_version, linenumber);
- break;
- }
- }
- else
- {
- /* No: assume:
- *
- * ^cvsroot Aencoded_password$
- *
- * as header comment specifies and parse accordingly
- */
- cvsroot_t *tmp_root;
- char *tmp_root_canonical;
-
- p = strchr (linebuf, ' ');
- if (p == NULL)
- {
- if (warn && !really_quiet)
- error (0, 0, "warning: skipping invalid entry in password file at line %d", linenumber);
- return NULL;;
- }
-
- *p = '\0';
- if ((tmp_root = parse_cvsroot (linebuf)) == NULL)
- {
- if (warn && !really_quiet)
- error (0, 0, "warning: skipping invalid entry in password file at line %d", linenumber);
- *p = ' ';
- return NULL;
- }
- *p = ' ';
- tmp_root_canonical = normalize_cvsroot (tmp_root);
- if (strcmp (cvsroot_canonical, tmp_root_canonical) == 0)
- password = p + 1;
-
- free (tmp_root_canonical);
- free_cvsroot_t (tmp_root);
- }
-
- return password;
-}
-
-
-
-/*
- * static char *
- * password_entry_operation (
- * password_entry_operation_t operation,
- * cvsroot_t *root,
- * char *newpassword
- * );
- *
- * Search the password file and depending on the value of operation:
- *
- * Mode Action
- * password_entry_lookup Return the password
- * password_entry_delete Delete the entry from the file, if it
- * exists.
- * password_entry_add Replace the line with the new one, else
- * append it.
- *
- * Because the user might be accessing multiple repositories, with
- * different passwords for each one, the format of ~/.cvspass is:
- *
- * [user@]host:[port]/path Aencoded_password
- * [user@]host:[port]/path Aencoded_password
- * ...
- *
- * New entries are always of the form:
- *
- * /1 user@host:port/path Aencoded_password
- *
- * but the old format is supported for backwards compatibility.
- * The entry version string wasn't strictly necessary, but it avoids the
- * overhead of parsing some entries since we know it is already in canonical
- * form and allows room for expansion later, say, if we want to allow spaces
- * and/or other characters to be escaped in the string. Also, the new entries
- * would have been ignored by old versions of CVS anyhow since those versions
- * didn't know how to parse a port number.
- *
- * The "A" before "encoded_password" is a literal capital A. It's a
- * version number indicating which form of scrambling we're doing on
- * the password -- someday we might provide something more secure than
- * the trivial encoding we do now, and when that day comes, it would
- * be nice to remain backward-compatible.
- *
- * Like .netrc, the file's permissions are the only thing preventing
- * it from being read by others. Unlike .netrc, we will not be
- * fascist about it, at most issuing a warning, and never refusing to
- * work.
- *
- * INPUTS
- * operation operation to perform
- * root cvsroot_t to look up
- * newpassword prescrambled new password, for password_entry_add_mode
- *
- * RETURNS
- * -1 if password_entry_lookup_mode not specified
- * NULL on failed lookup
- * pointer to a copy of the password string otherwise, which the caller is
- * responsible for disposing of
- */
-
-typedef enum password_entry_operation_e {
- password_entry_lookup,
- password_entry_delete,
- password_entry_add
-} password_entry_operation_t;
-
-static char *
-password_entry_operation (operation, root, newpassword)
- password_entry_operation_t operation;
- cvsroot_t *root;
- char *newpassword;
-{
- char *passfile;
- FILE *fp;
- char *cvsroot_canonical = NULL;
- char *password = NULL;
- int line_length;
- long line = -1;
- char *linebuf = NULL;
- size_t linebuf_len;
- char *p;
- int save_errno = 0;
-
- if (root->method != pserver_method)
- {
- error (0, 0, "\
-internal error: can only call password_entry_operation with pserver method");
- error (1, 0, "CVSROOT: %s", root->original);
- }
-
- cvsroot_canonical = normalize_cvsroot (root);
-
- /* Yes, the method below reads the user's password file twice when we have
- * to delete an entry. It's inefficient, but we're not talking about a gig of
- * data here.
- */
-
- passfile = construct_cvspass_filename ();
- fp = CVS_FOPEN (passfile, "r");
- if (fp == NULL)
- {
- error (0, errno, "warning: failed to open %s for reading", passfile);
- goto process;
- }
-
- /* Check each line to see if we have this entry already. */
- line = 0;
- while ((line_length = getline (&linebuf, &linebuf_len, fp)) >= 0)
- {
- line++;
- password = password_entry_parseline (cvsroot_canonical, 1, line,
- linebuf);
- if (password != NULL)
- /* this is it! break out and deal with linebuf */
- break;
- }
- if (line_length < 0 && !feof (fp))
- {
- error (0, errno, "cannot read %s", passfile);
- goto error_exit;
- }
- if (fclose (fp) < 0)
- /* not fatal, unless it cascades */
- error (0, errno, "cannot close %s", passfile);
- fp = NULL;
-
- /* Utter, total, raving paranoia, I know. */
- chmod (passfile, 0600);
-
- /* a copy to return or keep around so we can reuse linebuf */
- if (password != NULL)
- {
- /* chomp the EOL */
- p = strchr (password, '\n');
- if (p != NULL)
- *p = '\0';
- password = xstrdup (password);
- }
-
-process:
-
- /* might as well return now */
- if (operation == password_entry_lookup)
- goto out;
-
- /* same here */
- if (operation == password_entry_delete && password == NULL)
- {
- error (0, 0, "Entry not found.");
- goto out;
- }
-
- /* okay, file errors can simply be fatal from now on since we don't do
- * anything else if we're in lookup mode
- */
-
- /* copy the file with the entry deleted unless we're in add
- * mode and the line we found contains the same password we're supposed to
- * add
- */
- if (!noexec && password != NULL && (operation == password_entry_delete
- || (operation == password_entry_add
- && strcmp (password, newpassword))))
- {
- long found_at = line;
- char *tmp_name;
- FILE *tmp_fp;
-
- /* open the original file again */
- fp = CVS_FOPEN (passfile, "r");
- if (fp == NULL)
- error (1, errno, "failed to open %s for reading", passfile);
-
- /* create and open a temp file */
- if ((tmp_fp = cvs_temp_file (&tmp_name)) == NULL)
- error (1, errno, "unable to open temp file %s",
- tmp_name ? tmp_name : "(null)");
-
- line = 0;
- while ((line_length = getline (&linebuf, &linebuf_len, fp)) >= 0)
- {
- line++;
- if (line < found_at
- || (line != found_at
- && !password_entry_parseline (cvsroot_canonical, 0, line,
- linebuf)))
- {
- if (fprintf (tmp_fp, "%s", linebuf) == EOF)
- {
- /* try and clean up anyhow */
- error (0, errno, "fatal error: cannot write %s", tmp_name);
- if (fclose (tmp_fp) == EOF)
- error (0, errno, "cannot close %s", tmp_name);
- /* call CVS_UNLINK instead of unlink_file since the file
- * got created in noexec mode
- */
- if (CVS_UNLINK (tmp_name) < 0)
- error (0, errno, "cannot remove %s", tmp_name);
- /* but quit so we don't remove all the entries from a
- * user's password file accidentally
- */
- error (1, 0, "exiting");
- }
- }
- }
- if (line_length < 0 && !feof (fp))
- {
- error (0, errno, "cannot read %s", passfile);
- goto error_exit;
- }
- if (fclose (fp) < 0)
- /* not fatal, unless it cascades */
- error (0, errno, "cannot close %s", passfile);
- if (fclose (tmp_fp) < 0)
- /* not fatal, unless it cascades */
- /* FIXME - does copy_file return correct results if the file wasn't
- * closed? should this be fatal?
- */
- error (0, errno, "cannot close %s", tmp_name);
-
- /* FIXME: rename_file would make more sense (e.g. almost
- * always faster).
- *
- * I don't think so, unless we change the way rename_file works to
- * attempt a cp/rm sequence when rename fails since rename doesn't
- * work across file systems and it isn't uncommon to have /tmp
- * on its own partition.
- *
- * For that matter, it's probably not uncommon to have a home
- * directory on an NFS mount.
- */
- copy_file (tmp_name, passfile);
- if (CVS_UNLINK (tmp_name) < 0)
- error (0, errno, "cannot remove %s", tmp_name);
- free (tmp_name);
- }
-
- /* in add mode, if we didn't find an entry or found an entry with a
- * different password, append the new line
- */
- if (!noexec && operation == password_entry_add
- && (password == NULL || strcmp (password, newpassword)))
- {
- if ((fp = CVS_FOPEN (passfile, "a")) == NULL)
- error (1, errno, "could not open %s for writing", passfile);
-
- if (fprintf (fp, "/1 %s %s\n", cvsroot_canonical, newpassword) == EOF)
- error (1, errno, "cannot write %s", passfile);
- if (fclose (fp) < 0)
- error (1, errno, "cannot close %s", passfile);
- }
-
- /* Utter, total, raving paranoia, I know. */
- chmod (passfile, 0600);
-
- if (password)
- {
- free (password);
- password = NULL;
- }
- if (linebuf)
- free (linebuf);
-
-out:
- free (cvsroot_canonical);
- free (passfile);
- return password;
-
-error_exit:
- /* just exit when we're not in lookup mode */
- if (operation != password_entry_lookup)
- error (1, 0, "fatal error: exiting");
- /* clean up and exit in lookup mode so we can try a login with a NULL
- * password anyhow in case that's what we would have found
- */
- save_errno = errno;
- if (fp != NULL)
- {
- /* Utter, total, raving paranoia, I know. */
- chmod (passfile, 0600);
- if(fclose (fp) < 0)
- error (0, errno, "cannot close %s", passfile);
- }
- if (linebuf)
- free (linebuf);
- if (cvsroot_canonical)
- free (cvsroot_canonical);
- free (passfile);
- errno = save_errno;
- return NULL;
-}
-
-
-
-/* Prompt for a password, and store it in the file "CVS/.cvspass".
- */
-
-static const char *const login_usage[] =
-{
- "Usage: %s %s\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-int
-login (argc, argv)
- int argc;
- char **argv;
-{
- char *typed_password;
- char *cvsroot_canonical;
-
- if (argc < 0)
- usage (login_usage);
-
- if (current_parsed_root->method != pserver_method)
- {
- error (0, 0, "can only use `login' command with the 'pserver' method");
- error (1, 0, "CVSROOT: %s", current_parsed_root->original);
- }
-
- cvsroot_canonical = normalize_cvsroot(current_parsed_root);
- printf ("Logging in to %s\n", cvsroot_canonical);
- fflush (stdout);
-
- if (current_parsed_root->password)
- {
- typed_password = scramble (current_parsed_root->password);
- }
- else
- {
- char *tmp;
- tmp = getpass ("CVS password: ");
- /* Must deal with a NULL return value here. I haven't managed to
- * disconnect the CVS process from the tty and force a NULL return
- * in sanity.sh, but the Linux version of getpass is documented
- * to return NULL when it can't open /dev/tty...
- */
- if (!tmp) error (1, errno, "login: Failed to read password.");
- typed_password = scramble (tmp);
- memset (tmp, 0, strlen (tmp));
- }
-
- /* Force get_cvs_password() to use this one (when the client
- * confirms the new password with the server), instead of
- * consulting the file. We make a new copy because cvs_password
- * will get zeroed by connect_to_server(). */
- cvs_password = xstrdup (typed_password);
-
- connect_to_pserver (current_parsed_root, NULL, NULL, 1, 0);
-
- password_entry_operation (password_entry_add, current_parsed_root,
- typed_password);
-
- free_cvs_password (typed_password);
- free (cvsroot_canonical);
-
- return 0;
-}
-
-
-
-/* Free the password returned by get_cvs_password() and also free the
- * saved cvs_password if they are different pointers. Be paranoid
- * about the in-memory copy of the password and overwrite it with zero
- * bytes before doing the free().
- */
-void
-free_cvs_password (char *password)
-{
- if (password && password != cvs_password)
- {
- memset (password, 0, strlen (password));
- free (password);
- }
-
- if (cvs_password)
- {
- memset (cvs_password, 0, strlen (cvs_password));
- free (cvs_password);
- cvs_password = NULL;
- }
-}
-
-/* Returns the _scrambled_ password in freshly allocated memory. The server
- * must descramble before hashing and comparing. If password file not found,
- * or password not found in the file, just return NULL.
- */
-char *
-get_cvs_password ()
-{
- if (current_parsed_root->password)
- return scramble (current_parsed_root->password);
-
- /* If someone (i.e., login()) is calling connect_to_pserver() out of
- context, then assume they have supplied the correct, scrambled
- password. */
- if (cvs_password)
- return xstrdup (cvs_password);
-
- if (getenv ("CVS_PASSWORD") != NULL)
- {
- /* In previous versions of CVS one could specify a password in
- * CVS_PASSWORD. This is a bad idea, because in BSD variants
- * of unix anyone can see the environment variable with 'ps'.
- * But for users who were using that feature we want to at
- * least let them know what is going on. After printing this
- * warning, we should fall through to the regular error where
- * we tell them to run "cvs login" (unless they already ran
- * it, of course).
- */
- error (0, 0, "CVS_PASSWORD is no longer supported; ignored");
- }
-
- if (current_parsed_root->method != pserver_method)
- {
- error (0, 0, "can only call get_cvs_password with pserver method");
- error (1, 0, "CVSROOT: %s", current_parsed_root->original);
- }
-
- return password_entry_operation (password_entry_lookup,
- current_parsed_root, NULL);
-}
-
-
-
-static const char *const logout_usage[] =
-{
- "Usage: %s %s\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-/* Remove any entry for the CVSRoot repository found in .cvspass. */
-int
-logout (argc, argv)
- int argc;
- char **argv;
-{
- char *cvsroot_canonical;
-
- if (argc < 0)
- usage (logout_usage);
-
- if (current_parsed_root->method != pserver_method)
- {
- error (0, 0, "can only use pserver method with `logout' command");
- error (1, 0, "CVSROOT: %s", current_parsed_root->original);
- }
-
- /* Hmm. Do we want a variant of this command which deletes _all_
- the entries from the current .cvspass? Might be easier to
- remember than "rm ~/.cvspass" but then again if people are
- mucking with HOME (common in Win95 as the system doesn't set
- it), then this variant of "cvs logout" might give a false sense
- of security, in that it wouldn't delete entries from any
- .cvspass files but the current one. */
-
- if (!quiet)
- {
- cvsroot_canonical = normalize_cvsroot(current_parsed_root);
- printf ("Logging out of %s\n", cvsroot_canonical);
- fflush (stdout);
- free (cvsroot_canonical);
- }
-
- password_entry_operation (password_entry_delete, current_parsed_root, NULL);
-
- return 0;
-}
-
-#endif /* AUTH_CLIENT_SUPPORT from beginning of file. */
diff --git a/contrib/cvs/src/logmsg.c b/contrib/cvs/src/logmsg.c
deleted file mode 100644
index 6878aaf8c256..000000000000
--- a/contrib/cvs/src/logmsg.c
+++ /dev/null
@@ -1,988 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * $FreeBSD$
- */
-
-#include <assert.h>
-
-#include "cvs.h"
-#include "getline.h"
-
-static int find_type PROTO((Node * p, void *closure));
-static int fmt_proc PROTO((Node * p, void *closure));
-static int logfile_write PROTO((const char *repository, const char *filter,
- const char *message, FILE * logfp,
- List * changes));
-static int rcsinfo_proc PROTO((const char *repository, const char *template));
-static int title_proc PROTO((Node * p, void *closure));
-static int update_logfile_proc PROTO((const char *repository,
- const char *filter));
-static void setup_tmpfile PROTO((FILE * xfp, char *xprefix, List * changes));
-static int editinfo_proc PROTO((const char *repository, const char *template));
-static int verifymsg_proc PROTO((const char *repository, const char *script));
-
-static FILE *fp;
-static char *str_list;
-static char *str_list_format; /* The format for str_list's contents. */
-static char *editinfo_editor;
-static char *verifymsg_script;
-static Ctype type;
-
-/*
- * Should the logmsg be re-read during the do_verify phase?
- * RereadLogAfterVerify=no|stat|yes
- * LOGMSG_REREAD_NEVER - never re-read the logmsg
- * LOGMSG_REREAD_STAT - re-read the logmsg only if it has changed
- * LOGMSG_REREAD_ALWAYS - always re-read the logmsg
- */
-int RereadLogAfterVerify = LOGMSG_REREAD_ALWAYS;
-
-/*
- * Puts a standard header on the output which is either being prepared for an
- * editor session, or being sent to a logfile program. The modified, added,
- * and removed files are included (if any) and formatted to look pretty. */
-static char *prefix;
-static int col;
-static char *tag;
-static void
-setup_tmpfile (xfp, xprefix, changes)
- FILE *xfp;
- char *xprefix;
- List *changes;
-{
- /* set up statics */
- fp = xfp;
- prefix = xprefix;
-
- type = T_MODIFIED;
- if (walklist (changes, find_type, NULL) != 0)
- {
- (void) fprintf (fp, "%sModified Files:\n", prefix);
- col = 0;
- (void) walklist (changes, fmt_proc, NULL);
- (void) fprintf (fp, "\n");
- if (tag != NULL)
- {
- free (tag);
- tag = NULL;
- }
- }
- type = T_ADDED;
- if (walklist (changes, find_type, NULL) != 0)
- {
- (void) fprintf (fp, "%sAdded Files:\n", prefix);
- col = 0;
- (void) walklist (changes, fmt_proc, NULL);
- (void) fprintf (fp, "\n");
- if (tag != NULL)
- {
- free (tag);
- tag = NULL;
- }
- }
- type = T_REMOVED;
- if (walklist (changes, find_type, NULL) != 0)
- {
- (void) fprintf (fp, "%sRemoved Files:\n", prefix);
- col = 0;
- (void) walklist (changes, fmt_proc, NULL);
- (void) fprintf (fp, "\n");
- if (tag != NULL)
- {
- free (tag);
- tag = NULL;
- }
- }
-}
-
-/*
- * Looks for nodes of a specified type and returns 1 if found
- */
-static int
-find_type (p, closure)
- Node *p;
- void *closure;
-{
- struct logfile_info *li = p->data;
-
- if (li->type == type)
- return (1);
- else
- return (0);
-}
-
-/*
- * Breaks the files list into reasonable sized lines to avoid line wrap...
- * all in the name of pretty output. It only works on nodes whose types
- * match the one we're looking for
- */
-static int
-fmt_proc (p, closure)
- Node *p;
- void *closure;
-{
- struct logfile_info *li;
-
- li = p->data;
- if (li->type == type)
- {
- if (li->tag == NULL
- ? tag != NULL
- : tag == NULL || strcmp (tag, li->tag) != 0)
- {
- if (col > 0)
- (void) fprintf (fp, "\n");
- (void) fputs (prefix, fp);
- col = strlen (prefix);
- while (col < 6)
- {
- (void) fprintf (fp, " ");
- ++col;
- }
-
- if (li->tag == NULL)
- (void) fprintf (fp, "No tag");
- else
- (void) fprintf (fp, "Tag: %s", li->tag);
-
- if (tag != NULL)
- free (tag);
- tag = xstrdup (li->tag);
-
- /* Force a new line. */
- col = 70;
- }
-
- if (col == 0)
- {
- (void) fprintf (fp, "%s\t", prefix);
- col = 8;
- }
- else if (col > 8 && (col + (int) strlen (p->key)) > 70)
- {
- (void) fprintf (fp, "\n%s\t", prefix);
- col = 8;
- }
- (void) fprintf (fp, "%s ", p->key);
- col += strlen (p->key) + 1;
- }
- return (0);
-}
-
-/*
- * Builds a temporary file using setup_tmpfile() and invokes the user's
- * editor on the file. The header garbage in the resultant file is then
- * stripped and the log message is stored in the "message" argument.
- *
- * If REPOSITORY is non-NULL, process rcsinfo for that repository; if it
- * is NULL, use the CVSADM_TEMPLATE file instead. REPOSITORY should be
- * NULL when running in client mode.
- */
-void
-do_editor (dir, messagep, repository, changes)
- const char *dir;
- char **messagep;
- const char *repository;
- List *changes;
-{
- static int reuse_log_message = 0;
- char *line;
- int line_length;
- size_t line_chars_allocated;
- char *fname;
- struct stat pre_stbuf, post_stbuf;
- int retcode = 0;
-
- assert (!current_parsed_root->isremote != !repository);
-
- if (noexec || reuse_log_message)
- return;
-
- /* Abort creation of temp file if no editor is defined */
- if (strcmp (Editor, "") == 0 && !editinfo_editor)
- error(1, 0, "no editor defined, must use -e or -m");
-
- /* Create a temporary file */
- /* FIXME - It's possible we should be relying on cvs_temp_file to open
- * the file here - we get race conditions otherwise.
- */
- fname = cvs_temp_name ();
- again:
- if ((fp = CVS_FOPEN (fname, "w+")) == NULL)
- error (1, 0, "cannot create temporary file %s", fname);
-
- if (*messagep)
- {
- (void) fputs (*messagep, fp);
-
- if ((*messagep)[0] == '\0' ||
- (*messagep)[strlen (*messagep) - 1] != '\n')
- (void) fprintf (fp, "\n");
- }
- else
- (void) fprintf (fp, "\n");
-
- if (repository != NULL)
- /* tack templates on if necessary */
- (void) Parse_Info (CVSROOTADM_RCSINFO, repository, rcsinfo_proc, 1);
- else
- {
- FILE *tfp;
- char buf[1024];
- size_t n;
- size_t nwrite;
-
- /* Why "b"? */
- tfp = CVS_FOPEN (CVSADM_TEMPLATE, "rb");
- if (tfp == NULL)
- {
- if (!existence_error (errno))
- error (1, errno, "cannot read %s", CVSADM_TEMPLATE);
- }
- else
- {
- while (!feof (tfp))
- {
- char *p = buf;
- n = fread (buf, 1, sizeof buf, tfp);
- nwrite = n;
- while (nwrite > 0)
- {
- n = fwrite (p, 1, nwrite, fp);
- nwrite -= n;
- p += n;
- }
- if (ferror (tfp))
- error (1, errno, "cannot read %s", CVSADM_TEMPLATE);
- }
- if (fclose (tfp) < 0)
- error (0, errno, "cannot close %s", CVSADM_TEMPLATE);
- }
- }
-
- (void) fprintf (fp,
- "%s----------------------------------------------------------------------\n",
- CVSEDITPREFIX);
- (void) fprintf (fp,
- "%sEnter Log. Lines beginning with `%.*s' are removed automatically\n%s\n",
- CVSEDITPREFIX, CVSEDITPREFIXLEN, CVSEDITPREFIX,
- CVSEDITPREFIX);
- if (dir != NULL && *dir)
- (void) fprintf (fp, "%sCommitting in %s\n%s\n", CVSEDITPREFIX,
- dir, CVSEDITPREFIX);
- if (changes != NULL)
- setup_tmpfile (fp, CVSEDITPREFIX, changes);
- (void) fprintf (fp,
- "%s----------------------------------------------------------------------\n",
- CVSEDITPREFIX);
-
- /* finish off the temp file */
- if (fclose (fp) == EOF)
- error (1, errno, "%s", fname);
- if ( CVS_STAT (fname, &pre_stbuf) == -1)
- pre_stbuf.st_mtime = 0;
-
- if (editinfo_editor)
- free (editinfo_editor);
- editinfo_editor = (char *) NULL;
- if (!current_parsed_root->isremote && repository != NULL)
- (void) Parse_Info (CVSROOTADM_EDITINFO, repository, editinfo_proc, 0);
-
- /* run the editor */
- run_setup (editinfo_editor ? editinfo_editor : Editor);
- run_arg (fname);
- if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY,
- RUN_NORMAL | RUN_SIGIGNORE)) != 0)
- error (editinfo_editor ? 1 : 0, retcode == -1 ? errno : 0,
- editinfo_editor ? "Logfile verification failed" :
- "warning: editor session failed");
-
- /* put the entire message back into the *messagep variable */
-
- fp = open_file (fname, "r");
-
- if (*messagep)
- free (*messagep);
-
- if ( CVS_STAT (fname, &post_stbuf) != 0)
- error (1, errno, "cannot find size of temp file %s", fname);
-
- if (post_stbuf.st_size == 0)
- *messagep = NULL;
- else
- {
- /* On NT, we might read less than st_size bytes, but we won't
- read more. So this works. */
- *messagep = (char *) xmalloc (post_stbuf.st_size + 1);
- (*messagep)[0] = '\0';
- }
-
- line = NULL;
- line_chars_allocated = 0;
-
- if (*messagep)
- {
- size_t message_len = post_stbuf.st_size + 1;
- size_t offset = 0;
- while (1)
- {
- line_length = getline (&line, &line_chars_allocated, fp);
- if (line_length == -1)
- {
- if (ferror (fp))
- error (0, errno, "warning: cannot read %s", fname);
- break;
- }
- if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0)
- continue;
- if (offset + line_length >= message_len)
- expand_string (messagep, &message_len,
- offset + line_length + 1);
- (void) strcpy (*messagep + offset, line);
- offset += line_length;
- }
- }
- if (fclose (fp) < 0)
- error (0, errno, "warning: cannot close %s", fname);
-
- /* canonicalize emply messages */
- if (*messagep != NULL &&
- (**messagep == '\0' || strcmp (*messagep, "\n") == 0))
- {
- free (*messagep);
- *messagep = NULL;
- }
-
- if (pre_stbuf.st_mtime == post_stbuf.st_mtime || *messagep == NULL)
- {
- for (;;)
- {
- (void) printf ("\nLog message unchanged or not specified\n");
- (void) printf ("a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs\n");
- (void) printf ("Action: (continue) ");
- (void) fflush (stdout);
- line_length = getline (&line, &line_chars_allocated, stdin);
- if (line_length < 0)
- {
- error (0, errno, "cannot read from stdin");
- if (unlink_file (fname) < 0)
- error (0, errno,
- "warning: cannot remove temp file %s", fname);
- error (1, 0, "aborting");
- }
- else if (line_length == 0
- || *line == '\n' || *line == 'c' || *line == 'C')
- break;
- if (*line == 'a' || *line == 'A')
- {
- if (unlink_file (fname) < 0)
- error (0, errno, "warning: cannot remove temp file %s", fname);
- error (1, 0, "aborted by user");
- }
- if (*line == 'e' || *line == 'E')
- goto again;
- if (*line == '!')
- {
- reuse_log_message = 1;
- break;
- }
- (void) printf ("Unknown input\n");
- }
- }
- if (line)
- free (line);
- if (unlink_file (fname) < 0)
- error (0, errno, "warning: cannot remove temp file %s", fname);
- free (fname);
-}
-
-/* Runs the user-defined verification script as part of the commit or import
- process. This verification is meant to be run whether or not the user
- included the -m atribute. unlike the do_editor function, this is
- independant of the running of an editor for getting a message.
- */
-void
-do_verify (messagep, repository)
- char **messagep;
- const char *repository;
-{
- FILE *fp;
- char *fname;
- int retcode = 0;
-
- struct stat pre_stbuf, post_stbuf;
-
- if (current_parsed_root->isremote)
- /* The verification will happen on the server. */
- return;
-
- /* FIXME? Do we really want to skip this on noexec? What do we do
- for the other administrative files? */
- if (noexec || repository == NULL)
- return;
-
- /* Get the name of the verification script to run */
-
- if (Parse_Info (CVSROOTADM_VERIFYMSG, repository, verifymsg_proc, 0) > 0)
- error (1, 0, "Message verification failed");
-
- if (!verifymsg_script)
- return;
-
- /* open a temporary file, write the message to the
- temp file, and close the file. */
-
- if ((fp = cvs_temp_file (&fname)) == NULL)
- error (1, errno, "cannot create temporary file %s",
- fname ? fname : "(null)");
-
- if (*messagep != NULL)
- fputs (*messagep, fp);
- if (*messagep == NULL ||
- (*messagep)[0] == '\0' ||
- (*messagep)[strlen (*messagep) - 1] != '\n')
- putc ('\n', fp);
- if (fclose (fp) == EOF)
- error (1, errno, "%s", fname);
-
- if (RereadLogAfterVerify == LOGMSG_REREAD_STAT)
- {
- /* Remember the status of the temp file for later */
- if ( CVS_STAT (fname, &pre_stbuf) != 0 )
- error (1, errno, "cannot stat temp file %s", fname);
-
- /*
- * See if we need to sleep before running the verification
- * script to avoid time-stamp races.
- */
- sleep_past (pre_stbuf.st_mtime);
- }
-
- run_setup (verifymsg_script);
- run_arg (fname);
- if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY,
- RUN_NORMAL | RUN_SIGIGNORE)) != 0)
- {
- /* Since following error() exits, delete the temp file now. */
- if (unlink_file (fname) < 0)
- error (0, errno, "cannot remove %s", fname);
-
- error (1, retcode == -1 ? errno : 0,
- "Message verification failed");
- }
-
- /* Get the mod time and size of the possibly new log message
- * in always and stat modes.
- */
- if (RereadLogAfterVerify == LOGMSG_REREAD_ALWAYS ||
- RereadLogAfterVerify == LOGMSG_REREAD_STAT)
- {
- if ( CVS_STAT (fname, &post_stbuf) != 0 )
- error (1, errno, "cannot find size of temp file %s", fname);
- }
-
- /* And reread the log message in `always' mode or in `stat' mode when it's
- * changed
- */
- if (RereadLogAfterVerify == LOGMSG_REREAD_ALWAYS ||
- (RereadLogAfterVerify == LOGMSG_REREAD_STAT &&
- (pre_stbuf.st_mtime != post_stbuf.st_mtime ||
- pre_stbuf.st_size != post_stbuf.st_size)))
- {
- /* put the entire message back into the *messagep variable */
-
- if (*messagep) free (*messagep);
-
- if (post_stbuf.st_size == 0)
- *messagep = NULL;
- else
- {
- char *line = NULL;
- int line_length;
- size_t line_chars_allocated = 0;
- char *p;
-
- if ( (fp = open_file (fname, "r")) == NULL )
- error (1, errno, "cannot open temporary file %s", fname);
-
- /* On NT, we might read less than st_size bytes,
- but we won't read more. So this works. */
- p = *messagep = (char *) xmalloc (post_stbuf.st_size + 1);
- *messagep[0] = '\0';
-
- while (1)
- {
- line_length = getline (&line,
- &line_chars_allocated,
- fp);
- if (line_length == -1)
- {
- if (ferror (fp))
- /* Fail in this case because otherwise we will have no
- * log message
- */
- error (1, errno, "cannot read %s", fname);
- break;
- }
- if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0)
- continue;
- (void) strcpy (p, line);
- p += line_length;
- }
- if (line) free (line);
- if (fclose (fp) < 0)
- error (0, errno, "warning: cannot close %s", fname);
- }
- }
-
- /* Delete the temp file */
-
- if (unlink_file (fname) < 0)
- error (0, errno, "cannot remove %s", fname);
- free (fname);
- free (verifymsg_script);
- verifymsg_script = NULL;
-}
-
-/*
- * callback proc for Parse_Info for rcsinfo templates this routine basically
- * copies the matching template onto the end of the tempfile we are setting
- * up
- */
-/* ARGSUSED */
-static int
-rcsinfo_proc (repository, template)
- const char *repository;
- const char *template;
-{
- static char *last_template;
- FILE *tfp;
-
- /* nothing to do if the last one included is the same as this one */
- if (last_template && strcmp (last_template, template) == 0)
- return (0);
- if (last_template)
- free (last_template);
- last_template = xstrdup (template);
-
- if ((tfp = CVS_FOPEN (template, "r")) != NULL)
- {
- char *line = NULL;
- size_t line_chars_allocated = 0;
-
- while (getline (&line, &line_chars_allocated, tfp) >= 0)
- (void) fputs (line, fp);
- if (ferror (tfp))
- error (0, errno, "warning: cannot read %s", template);
- if (fclose (tfp) < 0)
- error (0, errno, "warning: cannot close %s", template);
- if (line)
- free (line);
- return (0);
- }
- else
- {
- error (0, errno, "Couldn't open rcsinfo template file %s", template);
- return (1);
- }
-}
-
-/*
- * Uses setup_tmpfile() to pass the updated message on directly to any
- * logfile programs that have a regular expression match for the checked in
- * directory in the source repository. The log information is fed into the
- * specified program as standard input.
- */
-static FILE *logfp;
-static const char *message;
-static List *changes;
-
-void
-Update_Logfile (repository, xmessage, xlogfp, xchanges)
- const char *repository;
- const char *xmessage;
- FILE *xlogfp;
- List *xchanges;
-{
- /* nothing to do if the list is empty */
- if (xchanges == NULL || xchanges->list->next == xchanges->list)
- return;
-
- /* set up static vars for update_logfile_proc */
- message = xmessage;
- logfp = xlogfp;
- changes = xchanges;
-
- /* call Parse_Info to do the actual logfile updates */
- (void) Parse_Info (CVSROOTADM_LOGINFO, repository, update_logfile_proc, 1);
-}
-
-
-
-/*
- * callback proc to actually do the logfile write from Update_Logfile
- */
-static int
-update_logfile_proc (repository, filter)
- const char *repository;
- const char *filter;
-{
- return logfile_write (repository, filter, message, logfp, changes);
-}
-
-
-
-/*
- * concatenate each filename/version onto str_list
- */
-static int
-title_proc (p, closure)
- Node *p;
- void *closure;
-{
- char *c;
- struct logfile_info *li = p->data;
-
- if (li->type == type)
- {
- /* Until we decide on the correct logging solution when we add
- directories or perform imports, T_TITLE nodes will only
- tack on the name provided, regardless of the format string.
- You can verify that this assumption is safe by checking the
- code in add.c (add_directory) and import.c (import). */
-
- str_list = xrealloc (str_list, strlen (str_list) + 5);
- (void) strcat (str_list, " ");
-
- if (li->type == T_TITLE)
- {
- str_list = xrealloc (str_list,
- strlen (str_list) + strlen (p->key) + 5);
- (void) strcat (str_list, p->key);
- }
- else
- {
- /* All other nodes use the format string. */
-
- for (c = str_list_format; *c != '\0'; c++)
- {
- switch (*c)
- {
- case 's':
- str_list =
- xrealloc (str_list,
- strlen (str_list) + strlen (p->key) + 5);
- (void) strcat (str_list, p->key);
- break;
- case 'V':
- str_list =
- xrealloc (str_list,
- (strlen (str_list)
- + (li->rev_old ? strlen (li->rev_old) : 0)
- + 10)
- );
- (void) strcat (str_list, (li->rev_old
- ? li->rev_old : "NONE"));
- break;
- case 'v':
- str_list =
- xrealloc (str_list,
- (strlen (str_list)
- + (li->rev_new ? strlen (li->rev_new) : 0)
- + 10)
- );
- (void) strcat (str_list, (li->rev_new
- ? li->rev_new : "NONE"));
- break;
- /* All other characters, we insert an empty field (but
- we do put in the comma separating it from other
- fields). This way if future CVS versions add formatting
- characters, one can write a loginfo file which at least
- won't blow up on an old CVS. */
- /* Note that people who have to deal with spaces in file
- and directory names are using space to get a known
- delimiter for the directory name, so it's probably
- not a good idea to ever define that as a formatting
- character. */
- }
- if (*(c + 1) != '\0')
- {
- str_list = xrealloc (str_list, strlen (str_list) + 5);
- (void) strcat (str_list, ",");
- }
- }
- }
- }
- return (0);
-}
-
-/*
- * Writes some stuff to the logfile "filter" and returns the status of the
- * filter program.
- */
-static int
-logfile_write (repository, filter, message, logfp, changes)
- const char *repository;
- const char *filter;
- const char *message;
- FILE *logfp;
- List *changes;
-{
- FILE *pipefp;
- char *prog;
- char *cp;
- int c;
- int pipestatus;
- char *fmt_percent; /* the location of the percent sign
- that starts the format string. */
-
- assert (repository);
-
- /* The user may specify a format string as part of the filter.
- Originally, `%s' was the only valid string. The string that
- was substituted for it was:
-
- <repository-name> <file1> <file2> <file3> ...
-
- Each file was either a new directory/import (T_TITLE), or a
- added (T_ADDED), modified (T_MODIFIED), or removed (T_REMOVED)
- file.
-
- It is desirable to preserve that behavior so lots of commitlog
- scripts won't die when they get this new code. At the same
- time, we'd like to pass other information about the files (like
- version numbers, statuses, or checkin times).
-
- The solution is to allow a format string that allows us to
- specify those other pieces of information. The format string
- will be composed of `%' followed by a single format character,
- or followed by a set of format characters surrounded by `{' and
- `}' as separators. The format characters are:
-
- s = file name
- V = old version number (pre-checkin)
- v = new version number (post-checkin)
-
- For example, valid format strings are:
-
- %{}
- %s
- %{s}
- %{sVv}
-
- There's no reason that more items couldn't be added (like
- modification date or file status [added, modified, updated,
- etc.]) -- the code modifications would be minimal (logmsg.c
- (title_proc) and commit.c (check_fileproc)).
-
- The output will be a string of tokens separated by spaces. For
- backwards compatibility, the the first token will be the
- repository name. The rest of the tokens will be
- comma-delimited lists of the information requested in the
- format string. For example, if `/u/src/master' is the
- repository, `%{sVv}' is the format string, and three files
- (ChangeLog, Makefile, foo.c) were modified, the output might
- be:
-
- /u/src/master ChangeLog,1.1,1.2 Makefile,1.3,1.4 foo.c,1.12,1.13
-
- Why this duplicates the old behavior when the format string is
- `%s' is left as an exercise for the reader. */
-
- fmt_percent = strchr (filter, '%');
- if (fmt_percent)
- {
- int len;
- const char *srepos;
- char *fmt_begin, *fmt_end; /* beginning and end of the
- format string specified in
- filter. */
- char *fmt_continue; /* where the string continues
- after the format string (we
- might skip a '}') somewhere
- in there... */
-
- /* Grab the format string. */
-
- if ((*(fmt_percent + 1) == ' ') || (*(fmt_percent + 1) == '\0'))
- {
- /* The percent stands alone. This is an error. We could
- be treating ' ' like any other formatting character, but
- using it as a formatting character seems like it would be
- a mistake. */
-
- /* Would be nice to also be giving the line number. */
- error (0, 0, "loginfo: '%%' not followed by formatting character");
- fmt_begin = fmt_percent + 1;
- fmt_end = fmt_begin;
- fmt_continue = fmt_begin;
- }
- else if (*(fmt_percent + 1) == '{')
- {
- /* The percent has a set of characters following it. */
-
- fmt_begin = fmt_percent + 2;
- fmt_end = strchr (fmt_begin, '}');
- if (fmt_end)
- {
- /* Skip over the '}' character. */
-
- fmt_continue = fmt_end + 1;
- }
- else
- {
- /* There was no close brace -- assume that format
- string continues to the end of the line. */
-
- /* Would be nice to also be giving the line number. */
- error (0, 0, "loginfo: '}' missing");
- fmt_end = fmt_begin + strlen (fmt_begin);
- fmt_continue = fmt_end;
- }
- }
- else
- {
- /* The percent has a single character following it. FIXME:
- %% should expand to a regular percent sign. */
-
- fmt_begin = fmt_percent + 1;
- fmt_end = fmt_begin + 1;
- fmt_continue = fmt_end;
- }
-
- len = fmt_end - fmt_begin;
- str_list_format = xmalloc (len + 1);
- strncpy (str_list_format, fmt_begin, len);
- str_list_format[len] = '\0';
-
- /* Allocate an initial chunk of memory. As we build up the string
- we will realloc it. */
- if (!str_list)
- str_list = xmalloc (1);
- str_list[0] = '\0';
-
- /* Add entries to the string. Don't bother looking for
- entries if the format string is empty. */
-
- if (str_list_format[0] != '\0')
- {
- type = T_TITLE;
- (void) walklist (changes, title_proc, NULL);
- type = T_ADDED;
- (void) walklist (changes, title_proc, NULL);
- type = T_MODIFIED;
- (void) walklist (changes, title_proc, NULL);
- type = T_REMOVED;
- (void) walklist (changes, title_proc, NULL);
- }
-
- free (str_list_format);
-
- /* Construct the final string. */
-
- srepos = Short_Repository (repository);
-
- prog = cp = xmalloc ((fmt_percent - filter) + 2 * strlen (srepos)
- + 2 * strlen (str_list) + strlen (fmt_continue)
- + 10);
- (void) memcpy (cp, filter, fmt_percent - filter);
- cp += fmt_percent - filter;
- *cp++ = '"';
- cp = shell_escape (cp, srepos);
- cp = shell_escape (cp, str_list);
- *cp++ = '"';
- (void) strcpy (cp, fmt_continue);
-
- /* To be nice, free up some memory. */
-
- free (str_list);
- str_list = (char *) NULL;
- }
- else
- {
- /* There's no format string. */
- prog = xstrdup (filter);
- }
-
- if ((pipefp = run_popen (prog, "w")) == NULL)
- {
- if (!noexec)
- error (0, 0, "cannot write entry to log filter: %s", prog);
- free (prog);
- return (1);
- }
- (void) fprintf (pipefp, "Update of %s\n", repository);
- (void) fprintf (pipefp, "In directory %s:", hostname);
- cp = xgetwd ();
- if (cp == NULL)
- fprintf (pipefp, "<cannot get working directory: %s>\n\n",
- strerror (errno));
- else
- {
- fprintf (pipefp, "%s\n\n", cp);
- free (cp);
- }
-
- setup_tmpfile (pipefp, "", changes);
- (void) fprintf (pipefp, "Log Message:\n%s\n", (message) ? message : "");
- if (logfp != (FILE *) 0)
- {
- (void) fprintf (pipefp, "Status:\n");
- rewind (logfp);
- while ((c = getc (logfp)) != EOF)
- (void) putc ((char) c, pipefp);
- }
- free (prog);
- pipestatus = pclose (pipefp);
- return ((pipestatus == -1) || (pipestatus == 127)) ? 1 : 0;
-}
-
-/*
- * We choose to use the *last* match within the editinfo file for this
- * repository. This allows us to have a global editinfo program for the
- * root of some hierarchy, for example, and different ones within different
- * sub-directories of the root (like a special checker for changes made to
- * the "src" directory versus changes made to the "doc" or "test"
- * directories.
- */
-/* ARGSUSED */
-static int
-editinfo_proc(repository, editor)
- const char *repository;
- const char *editor;
-{
- /* nothing to do if the last match is the same as this one */
- if (editinfo_editor && strcmp (editinfo_editor, editor) == 0)
- return (0);
- if (editinfo_editor)
- free (editinfo_editor);
-
- editinfo_editor = xstrdup (editor);
- return (0);
-}
-
-/* This routine is calld by Parse_Info. it asigns the name of the
- * message verification script to the global variable verify_script
- */
-static int
-verifymsg_proc (repository, script)
- const char *repository;
- const char *script;
-{
- if (verifymsg_script && strcmp (verifymsg_script, script) == 0)
- return (0);
- if (verifymsg_script)
- free (verifymsg_script);
- verifymsg_script = xstrdup (script);
- return (0);
-}
diff --git a/contrib/cvs/src/main.c b/contrib/cvs/src/main.c
deleted file mode 100644
index 332946a3ecd3..000000000000
--- a/contrib/cvs/src/main.c
+++ /dev/null
@@ -1,1240 +0,0 @@
-/*
- * Copyright (C) 1986-2008 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2006 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License
- * as specified in the README file that comes with the CVS source distribution.
- *
- * This is the main C driver for the CVS system.
- *
- * Credit to Dick Grune, Vrije Universiteit, Amsterdam, for writing
- * the shell-script CVS system that this is based on.
- *
- * $FreeBSD$
- */
-
-#include <assert.h>
-#include "cvs.h"
-#include "prepend_args.h"
-
-#ifdef HAVE_WINSOCK_H
-#include <winsock.h>
-#else
-extern int gethostname ();
-#endif
-
-const char *program_name;
-const char *program_path;
-const char *cvs_cmd_name;
-
-/* I'd dynamically allocate this, but it seems like gethostname
- requires a fixed size array. If I'm remembering the RFCs right,
- 256 should be enough. */
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN 256
-#endif
-
-char hostname[MAXHOSTNAMELEN];
-
-int use_editor = 1;
-int use_cvsrc = 1;
-int cvswrite = !CVSREAD_DFLT;
-int really_quiet = 0;
-int quiet = 0;
-int trace = 0;
-int noexec = 0;
-int readonlyfs = 0;
-int require_real_user = 0;
-int logoff = 0;
-
-/*
- * Zero if compression isn't supported or requested; non-zero to indicate
- * a compression level to request from gzip.
- */
-int gzip_level;
-
-/* Set if we should be writing CVSADM directories at top level. At
- least for now we'll make the default be off (the CVS 1.9, not CVS
- 1.9.2, behavior). */
-int top_level_admin = 0;
-
-mode_t cvsumask = UMASK_DFLT;
-
-char *CurDir;
-
-/*
- * Defaults, for the environment variables that are not set
- */
-char *Tmpdir = TMPDIR_DFLT;
-char *Editor = EDITOR_DFLT;
-
-
-/* When our working directory contains subdirectories with different
- values in CVS/Root files, we maintain a list of them. */
-List *root_directories = NULL;
-
-static const struct cmd
-{
- char *fullname; /* Full name of the function (e.g. "commit") */
-
- /* Synonyms for the command, nick1 and nick2. We supply them
- mostly for two reasons: (1) CVS has always supported them, and
- we need to maintain compatibility, (2) if there is a need for a
- version which is shorter than the fullname, for ease in typing.
- Synonyms have the disadvantage that people will see "new" and
- then have to think about it, or look it up, to realize that is
- the operation they know as "add". Also, this means that one
- cannot create a command "cvs new" with a different meaning. So
- new synonyms are probably best used sparingly, and where used
- should be abbreviations of the fullname (preferably consisting
- of the first 2 or 3 or so letters).
-
- One thing that some systems do is to recognize any unique
- abbreviation, for example "annotat" "annota", etc., for
- "annotate". The problem with this is that scripts and user
- habits will expect a certain abbreviation to be unique, and in
- a future release of CVS it may not be. So it is better to
- accept only an explicit list of abbreviations and plan on
- supporting them in the future as well as now. */
-
- char *nick1;
- char *nick2;
-
- int (*func) (); /* Function takes (argc, argv) arguments. */
- unsigned long attr; /* Attributes. */
-} cmds[] =
-
-{
- { "add", "ad", "new", add, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "admin", "adm", "rcs", admin, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "annotate", "ann", "blame", annotate, CVS_CMD_USES_WORK_DIR },
- { "checkout", "co", "get", checkout, 0 },
- { "commit", "ci", "com", commit, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "diff", "di", "dif", diff, CVS_CMD_USES_WORK_DIR },
- { "edit", NULL, NULL, edit, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "editors", NULL, NULL, editors, CVS_CMD_USES_WORK_DIR },
- { "export", "exp", "ex", checkout, CVS_CMD_USES_WORK_DIR },
- { "history", "hi", "his", history, CVS_CMD_USES_WORK_DIR },
- { "import", "im", "imp", import, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR | CVS_CMD_IGNORE_ADMROOT},
- { "init", NULL, NULL, init, CVS_CMD_MODIFIES_REPOSITORY },
-#if defined (HAVE_KERBEROS) && defined (SERVER_SUPPORT)
- { "kserver", NULL, NULL, server, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, /* placeholder */
-#endif
- { "log", "lo", NULL, cvslog, CVS_CMD_USES_WORK_DIR },
-#ifdef AUTH_CLIENT_SUPPORT
- { "login", "logon", "lgn", login, 0 },
- { "logout", NULL, NULL, logout, 0 },
-#endif /* AUTH_CLIENT_SUPPORT */
-#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
- { "pserver", NULL, NULL, server, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, /* placeholder */
-#endif
- { "rannotate","rann", "ra", annotate, 0 },
- { "rdiff", "patch", "pa", patch, 0 },
- { "release", "re", "rel", release, 0 },
- { "remove", "rm", "delete", cvsremove, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "rlog", "rl", NULL, cvslog, 0 },
- { "rtag", "rt", "rfreeze", cvstag, CVS_CMD_MODIFIES_REPOSITORY },
-#ifdef SERVER_SUPPORT
- { "server", NULL, NULL, server, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
-#endif
- { "status", "st", "stat", cvsstatus, CVS_CMD_USES_WORK_DIR },
- { "tag", "ta", "freeze", cvstag, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "unedit", NULL, NULL, unedit, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "update", "up", "upd", update, CVS_CMD_USES_WORK_DIR },
- { "version", "ve", "ver", version, 0 },
- { "watch", NULL, NULL, watch, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
- { "watchers", NULL, NULL, watchers, CVS_CMD_USES_WORK_DIR },
- { NULL, NULL, NULL, NULL, 0 },
-};
-
-static const char *const usg[] =
-{
- /* CVS usage messages never have followed the GNU convention of
- putting metavariables in uppercase. I don't know whether that
- is a good convention or not, but if it changes it would have to
- change in all the usage messages. For now, they consistently
- use lowercase, as far as I know. Punctuation is pretty funky,
- though. Sometimes they use none, as here. Sometimes they use
- single quotes (not the TeX-ish `' stuff), as in --help-options.
- Sometimes they use double quotes, as in cvs -H add.
-
- Most (not all) of the usage messages seem to have periods at
- the end of each line. I haven't tried to duplicate this style
- in --help as it is a rather different format from the rest. */
-
- "Usage: %s [cvs-options] command [command-options-and-arguments]\n",
- " where cvs-options are -q, -n, etc.\n",
- " (specify --help-options for a list of options)\n",
- " where command is add, admin, etc.\n",
- " (specify --help-commands for a list of commands\n",
- " or --help-synonyms for a list of command synonyms)\n",
- " where command-options-and-arguments depend on the specific command\n",
- " (specify -H followed by a command name for command-specific help)\n",
- " Specify --help to receive this message\n",
- "\n",
-
- /* Some people think that a bug-reporting address should go here. IMHO,
- the web sites are better because anything else is very likely to go
- obsolete in the years between a release and when someone might be
- reading this help. Besides, we could never adequately discuss
- bug reporting in a concise enough way to put in a help message. */
-
- /* I was going to put this at the top, but usage() wants the %s to
- be in the first line. */
- "The Concurrent Versions System (CVS) is a tool for version control.\n",
- /* I really don't think I want to try to define "version control"
- in one line. I'm not sure one can get more concise than the
- paragraph in ../cvs.spec without assuming the reader knows what
- version control means. */
-
- "For CVS updates and additional information, see\n",
- " the CVS home page at http://cvs.nongnu.org/\n",
- NULL,
-};
-
-static const char *const cmd_usage[] =
-{
- "CVS commands are:\n",
- " add Add a new file/directory to the repository\n",
- " admin Administration front end for rcs\n",
- " annotate Show last revision where each line was modified\n",
- " checkout Checkout sources for editing\n",
- " commit Check files into the repository\n",
- " diff Show differences between revisions\n",
- " edit Get ready to edit a watched file\n",
- " editors See who is editing a watched file\n",
- " export Export sources from CVS, similar to checkout\n",
- " history Show repository access history\n",
- " import Import sources into CVS, using vendor branches\n",
- " init Create a CVS repository if it doesn't exist\n",
-#if defined (HAVE_KERBEROS) && defined (SERVER_SUPPORT)
- " kserver Kerberos server mode\n",
-#endif
- " log Print out history information for files\n",
-#ifdef AUTH_CLIENT_SUPPORT
- " login Prompt for password for authenticating server\n",
- " logout Removes entry in .cvspass for remote repository\n",
-#endif /* AUTH_CLIENT_SUPPORT */
-#if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
- " pserver Password server mode\n",
-#endif
- " rannotate Show last revision where each line of module was modified\n",
- " rdiff Create 'patch' format diffs between releases\n",
- " release Indicate that a Module is no longer in use\n",
- " remove Remove an entry from the repository\n",
- " rlog Print out history information for a module\n",
- " rtag Add a symbolic tag to a module\n",
-#ifdef SERVER_SUPPORT
- " server Server mode\n",
-#endif
- " status Display status information on checked out files\n",
- " tag Add a symbolic tag to checked out version of files\n",
- " unedit Undo an edit command\n",
- " update Bring work tree in sync with repository\n",
- " version Show current CVS version(s)\n",
- " watch Set watches\n",
- " watchers See who is watching a file\n",
- "(Specify the --help option for a list of other help options)\n",
- NULL,
-};
-
-static const char *const opt_usage[] =
-{
- /* Omit -b because it is just for compatibility. */
- "CVS global options (specified before the command name) are:\n",
- " -H Displays usage information for command.\n",
- " -Q Cause CVS to be really quiet.\n",
- " -q Cause CVS to be somewhat quiet.\n",
- " -r Make checked-out files read-only.\n",
- " -w Make checked-out files read-write (default).\n",
- " -g Force group-write perms on checked-out files.\n",
- " -n Do not execute anything that will change the disk.\n",
- " -t Show trace of program execution -- try with -n.\n",
- " -R Assume repository is read-only, such as CDROM\n",
- " -v CVS version and copyright.\n",
- " -T tmpdir Use 'tmpdir' for temporary files.\n",
- " -e editor Use 'editor' for editing log information.\n",
- " -d CVS_root Overrides $CVSROOT as the root of the CVS tree.\n",
- " -f Do not use the ~/.cvsrc file.\n",
-#ifdef CLIENT_SUPPORT
- " -z # Use compression level '#' for net traffic.\n",
-#ifdef ENCRYPTION
- " -x Encrypt all net traffic.\n",
-#endif
- " -a Authenticate all net traffic.\n",
-#endif
- " -s VAR=VAL Set CVS user variable.\n",
- "(Specify the --help option for a list of other help options)\n",
- NULL
-};
-
-
-static int
-set_root_directory (p, ignored)
- Node *p;
- void *ignored;
-{
- if (current_parsed_root == NULL && p->data != NULL)
- {
- current_parsed_root = p->data;
- return 1;
- }
- return 0;
-}
-
-
-static const char * const*
-cmd_synonyms ()
-{
- char ** synonyms;
- char ** line;
- const struct cmd *c = &cmds[0];
- /* Three more for title, "specify --help" line, and NULL. */
- int numcmds = 3;
-
- while (c->fullname != NULL)
- {
- numcmds++;
- c++;
- }
-
- synonyms = (char **) xmalloc(numcmds * sizeof(char *));
- line = synonyms;
- *line++ = "CVS command synonyms are:\n";
- for (c = &cmds[0]; c->fullname != NULL; c++)
- {
- if (c->nick1 || c->nick2)
- {
- *line = xmalloc (strlen (c->fullname)
- + (c->nick1 != NULL ? strlen (c->nick1) : 0)
- + (c->nick2 != NULL ? strlen (c->nick2) : 0)
- + 40);
- sprintf(*line, " %-12s %s %s\n", c->fullname,
- c->nick1 ? c->nick1 : "",
- c->nick2 ? c->nick2 : "");
- line++;
- }
- }
- *line++ = "(Specify the --help option for a list of other help options)\n";
- *line = NULL;
-
- return (const char * const*) synonyms; /* will never be freed */
-}
-
-
-unsigned long int
-lookup_command_attribute (cmd_name)
- char *cmd_name;
-{
- const struct cmd *cm;
-
- for (cm = cmds; cm->fullname; cm++)
- {
- if (strcmp (cmd_name, cm->fullname) == 0)
- break;
- }
- if (!cm->fullname)
- error (1, 0, "unknown command: %s", cmd_name);
- return cm->attr;
-}
-
-
-static RETSIGTYPE
-main_cleanup (sig)
- int sig;
-{
-#ifndef DONT_USE_SIGNALS
- const char *name;
- char temp[10];
-
- switch (sig)
- {
-#ifdef SIGABRT
- case SIGABRT:
- name = "abort";
- break;
-#endif
-#ifdef SIGHUP
- case SIGHUP:
- name = "hangup";
- break;
-#endif
-#ifdef SIGINT
- case SIGINT:
- name = "interrupt";
- break;
-#endif
-#ifdef SIGQUIT
- case SIGQUIT:
- name = "quit";
- break;
-#endif
-#ifdef SIGPIPE
- case SIGPIPE:
- name = "broken pipe";
- break;
-#endif
-#ifdef SIGTERM
- case SIGTERM:
- name = "termination";
- break;
-#endif
- default:
- /* This case should never be reached, because we list above all
- the signals for which we actually establish a signal handler. */
- sprintf (temp, "%d", sig);
- name = temp;
- break;
- }
-
- error (1, 0, "received %s signal", name);
-#endif /* !DONT_USE_SIGNALS */
-}
-
-int
-main (argc, argv)
- int argc;
- char **argv;
-{
- cvsroot_t *CVSroot_parsed = NULL;
- int cvsroot_update_env = 1;
- char *cp, *end;
- const struct cmd *cm;
- int c, err = 0;
- int tmpdir_update_env;
- int free_Editor = 0;
- int free_Tmpdir = 0;
-
- int help = 0; /* Has the user asked for help? This
- lets us support the `cvs -H cmd'
- convention to give help for cmd. */
- static const char short_options[] = "+QqgrwtnRvb:T:e:d:Hfz:s:xaU";
- static struct option long_options[] =
- {
- {"help", 0, NULL, 'H'},
- {"version", 0, NULL, 'v'},
- {"help-commands", 0, NULL, 1},
- {"help-synonyms", 0, NULL, 2},
- {"help-options", 0, NULL, 4},
- {"allow-root", required_argument, NULL, 3},
- {0, 0, 0, 0}
- };
- /* `getopt_long' stores the option index here, but right now we
- don't use it. */
- int option_index = 0;
-
-#ifdef SYSTEM_INITIALIZE
- /* Hook for OS-specific behavior, for example socket subsystems on
- NT and OS2 or dealing with windows and arguments on Mac. */
- SYSTEM_INITIALIZE (&argc, &argv);
-#endif
-
-#ifdef HAVE_TZSET
- /* On systems that have tzset (which is almost all the ones I know
- of), it's a good idea to call it. */
- tzset ();
-#endif
-
- /*
- * Just save the last component of the path for error messages
- */
- program_path = xstrdup (argv[0]);
-#ifdef ARGV0_NOT_PROGRAM_NAME
- /* On some systems, e.g. VMS, argv[0] is not the name of the command
- which the user types to invoke the program. */
- program_name = "cvs";
-#else
- program_name = last_component (argv[0]);
-#endif
-
- /*
- * Query the environment variables up-front, so that
- * they can be overridden by command line arguments
- */
- tmpdir_update_env = *Tmpdir; /* TMPDIR_DFLT must be set */
- if ((cp = getenv (TMPDIR_ENV)) != NULL)
- {
- Tmpdir = cp;
- tmpdir_update_env = 0; /* it's already there */
- }
- if ((cp = getenv (EDITOR1_ENV)) != NULL)
- Editor = cp;
- else if ((cp = getenv (EDITOR2_ENV)) != NULL)
- Editor = cp;
- else if ((cp = getenv (EDITOR3_ENV)) != NULL)
- Editor = cp;
- if (getenv (CVSREAD_ENV) != NULL)
- cvswrite = 0;
- if (getenv (CVSREADONLYFS_ENV) != NULL) {
- readonlyfs = 1;
- logoff = 1;
- }
-
- prepend_default_options (getenv ("CVS_OPTIONS"), &argc, &argv);
-
- /* Set this to 0 to force getopt initialization. getopt() sets
- this to 1 internally. */
- optind = 0;
-
- /* We have to parse the options twice because else there is no
- chance to avoid reading the global options from ".cvsrc". Set
- opterr to 0 for avoiding error messages about invalid options.
- */
- opterr = 0;
-
- while ((c = getopt_long
- (argc, argv, short_options, long_options, &option_index))
- != EOF)
- {
- if (c == 'f')
- use_cvsrc = 0;
- }
-
- /*
- * Scan cvsrc file for global options.
- */
- if (use_cvsrc)
- read_cvsrc (&argc, &argv, "cvs");
-
- optind = 0;
- opterr = 1;
-
- while ((c = getopt_long
- (argc, argv, short_options, long_options, &option_index))
- != EOF)
- {
- switch (c)
- {
- case 1:
- /* --help-commands */
- usage (cmd_usage);
- break;
- case 2:
- /* --help-synonyms */
- usage (cmd_synonyms());
- break;
- case 4:
- /* --help-options */
- usage (opt_usage);
- break;
- case 3:
- /* --allow-root */
- root_allow_add (optarg);
- break;
- case 'Q':
- really_quiet = 1;
- /* FALL THROUGH */
- case 'q':
- quiet = 1;
- break;
- case 'r':
- cvswrite = 0;
- break;
- case 'w':
- cvswrite = 1;
- break;
- case 'g':
- /*
- * force full group write perms (used for shared checked-out
- * source trees, see manual page)
- */
- umask(umask(077) & 007);
- break;
- case 't':
- trace = 1;
- break;
- case 'R':
- readonlyfs = 1;
- logoff = 1;
- break;
- case 'n':
- noexec = 1;
- logoff = 1;
- break;
- case 'v':
- (void) fputs ("\n", stdout);
- version (0, (char **) NULL);
- (void) fputs ("\n", stdout);
- (void) fputs ("\
-Copyright (C) 2006 Free Software Foundation, Inc.\n\
-\n\
-Senior active maintainers include Larry Jones, Derek R. Price,\n\
-and Mark D. Baushke. Please see the AUTHORS and README files from the CVS\n\
-distribution kit for a complete list of contributors and copyrights.\n",
- stdout);
- (void) fputs ("\n", stdout);
- (void) fputs ("CVS may be copied only under the terms of the GNU General Public License,\n", stdout);
- (void) fputs ("a copy of which can be found with the CVS distribution kit.\n", stdout);
- (void) fputs ("\n", stdout);
-
- (void) fputs ("Specify the --help option for further information about CVS\n", stdout);
-
-#ifdef SYSTEM_CLEANUP
- /* Hook for OS-specific behavior, for example socket subsystems
- * on NT and OS2 or dealing with windows and arguments on Mac.
- */
- SYSTEM_CLEANUP ();
-#endif
- exit (0);
- break;
- case 'b':
- /* This option used to specify the directory for RCS
- executables. But since we don't run them any more,
- this is a noop. Silently ignore it so that .cvsrc
- and scripts and inetd.conf and such can work with
- either new or old CVS. */
- break;
- case 'T':
- if (free_Tmpdir) free (Tmpdir);
- Tmpdir = xstrdup (optarg);
- free_Tmpdir = 1;
- tmpdir_update_env = 1; /* need to update environment */
- break;
- case 'e':
- if (free_Editor) free (Editor);
- Editor = xstrdup (optarg);
- free_Editor = 1;
- break;
- case 'd':
- if (CVSroot_cmdline != NULL)
- free (CVSroot_cmdline);
- CVSroot_cmdline = xstrdup (optarg);
- break;
- case 'H':
- help = 1;
- break;
- case 'f':
- use_cvsrc = 0; /* unnecessary, since we've done it above */
- break;
- case 'z':
- gzip_level = strtol (optarg, &end, 10);
- if (*end != '\0' || gzip_level < 0 || gzip_level > 9)
- error (1, 0,
- "gzip compression level must be between 0 and 9");
- /* If no CLIENT_SUPPORT, we just silently ignore the gzip
- * level, so that users can have it in their .cvsrc and not
- * cause any trouble.
- *
- * We still parse the argument to -z for correctness since
- * one user complained of being bitten by a run of
- * `cvs -z -n up' which read -n as the argument to -z without
- * complaining. */
- break;
- case 's':
- variable_set (optarg);
- break;
- case 'x':
-#ifdef CLIENT_SUPPORT
- cvsencrypt = 1;
-#endif /* CLIENT_SUPPORT */
- /* If no CLIENT_SUPPORT, ignore -x, so that users can
- have it in their .cvsrc and not cause any trouble.
- If no ENCRYPTION, we still accept -x, but issue an
- error if we are being run as a client. */
- break;
- case 'a':
-#ifdef CLIENT_SUPPORT
- cvsauthenticate = 1;
-#endif
- /* If no CLIENT_SUPPORT, ignore -a, so that users can
- have it in their .cvsrc and not cause any trouble.
- We will issue an error later if stream
- authentication is not supported. */
- break;
- case 'U':
-#ifdef SERVER_SUPPORT
- require_real_user = 1;
-#endif
- break;
- case '?':
- default:
- usage (usg);
- }
- }
-
- argc -= optind;
- argv += optind;
- if (argc < 1)
- usage (usg);
-
-
- /* Look up the command name. */
-
- cvs_cmd_name = argv[0];
- for (cm = cmds; cm->fullname; cm++)
- {
- if (cm->nick1 && !strcmp (cvs_cmd_name, cm->nick1))
- break;
- if (cm->nick2 && !strcmp (cvs_cmd_name, cm->nick2))
- break;
- if (!strcmp (cvs_cmd_name, cm->fullname))
- break;
- }
-
- if (!cm->fullname)
- {
- fprintf (stderr, "Unknown command: `%s'\n\n", cvs_cmd_name);
- usage (cmd_usage);
- }
- else
- cvs_cmd_name = cm->fullname; /* Global pointer for later use */
-
- if (help)
- {
- argc = -1; /* some functions only check for this */
- err = (*(cm->func)) (argc, argv);
- }
- else
- {
- /* The user didn't ask for help, so go ahead and authenticate,
- set up CVSROOT, and the rest of it. */
-
- /* The UMASK environment variable isn't handled with the
- others above, since we don't want to signal errors if the
- user has asked for help. This won't work if somebody adds
- a command-line flag to set the umask, since we'll have to
- parse it before we get here. */
-
- if ((cp = getenv (CVSUMASK_ENV)) != NULL)
- {
- /* FIXME: Should be accepting symbolic as well as numeric mask. */
- cvsumask = strtol (cp, &end, 8) & 0777;
- if (*end != '\0')
- error (1, errno, "invalid umask value in %s (%s)",
- CVSUMASK_ENV, cp);
- }
-
-#ifdef SERVER_SUPPORT
-
-# ifdef HAVE_KERBEROS
- /* If we are invoked with a single argument "kserver", then we are
- running as Kerberos server as root. Do the authentication as
- the very first thing, to minimize the amount of time we are
- running as root. */
- if (strcmp (cvs_cmd_name, "kserver") == 0)
- {
- kserver_authenticate_connection ();
-
- /* Pretend we were invoked as a plain server. */
- cvs_cmd_name = "server";
- }
-# endif /* HAVE_KERBEROS */
-
-
-# if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)
- if (strcmp (cvs_cmd_name, "pserver") == 0)
- {
- /* The reason that --allow-root is not a command option
- is mainly the comment in server() about how argc,argv
- might be from .cvsrc. I'm not sure about that, and
- I'm not sure it is only true of command options, but
- it seems easier to make it a global option. */
-
- /* Gets username and password from client, authenticates, then
- switches to run as that user and sends an ACK back to the
- client. */
- pserver_authenticate_connection ();
-
- /* Pretend we were invoked as a plain server. */
- cvs_cmd_name = "server";
- }
-# endif /* AUTH_SERVER_SUPPORT || HAVE_GSSAPI */
-#endif /* SERVER_SUPPORT */
-
- server_active = strcmp (cvs_cmd_name, "server") == 0;
-
- /* This is only used for writing into the history file. For
- remote connections, it might be nice to have hostname
- and/or remote path, on the other hand I'm not sure whether
- it is worth the trouble. */
-
- if (server_active)
- CurDir = xstrdup ("<remote>");
- else
- {
- CurDir = xgetwd ();
- if (CurDir == NULL)
- error (1, errno, "cannot get working directory");
- }
-
- if (Tmpdir == NULL || Tmpdir[0] == '\0')
- {
- if (free_Tmpdir) free (Tmpdir);
- Tmpdir = "/tmp";
- }
-
-#ifdef HAVE_PUTENV
- if (tmpdir_update_env)
- {
- char *env;
- env = xmalloc (strlen (TMPDIR_ENV) + strlen (Tmpdir) + 1 + 1);
- (void) sprintf (env, "%s=%s", TMPDIR_ENV, Tmpdir);
- (void) putenv (env);
- /* do not free env, as putenv has control of it */
- }
- {
- char *env;
- env = xmalloc (sizeof "CVS_PID=" + 32); /* XXX pid < 10^32 */
- (void) sprintf (env, "CVS_PID=%ld", (long) getpid ());
- (void) putenv (env);
- }
-#endif
-
-#ifndef DONT_USE_SIGNALS
- /* make sure we clean up on error */
-#ifdef SIGABRT
- (void) SIG_register (SIGABRT, main_cleanup);
-#endif
-#ifdef SIGHUP
- (void) SIG_register (SIGHUP, main_cleanup);
-#endif
-#ifdef SIGINT
- (void) SIG_register (SIGINT, main_cleanup);
-#endif
-#ifdef SIGQUIT
- (void) SIG_register (SIGQUIT, main_cleanup);
-#endif
-#ifdef SIGPIPE
- (void) SIG_register (SIGPIPE, main_cleanup);
-#endif
-#ifdef SIGTERM
- (void) SIG_register (SIGTERM, main_cleanup);
-#endif
-#endif /* !DONT_USE_SIGNALS */
-
- gethostname(hostname, sizeof (hostname));
-
-#ifdef KLUDGE_FOR_WNT_TESTSUITE
- /* Probably the need for this will go away at some point once
- we call fflush enough places (e.g. fflush (stdout) in
- cvs_outerr). */
- (void) setvbuf (stdout, (char *) NULL, _IONBF, 0);
- (void) setvbuf (stderr, (char *) NULL, _IONBF, 0);
-#endif /* KLUDGE_FOR_WNT_TESTSUITE */
-
- if (use_cvsrc)
- read_cvsrc (&argc, &argv, cvs_cmd_name);
-
- /* Fiddling with CVSROOT doesn't make sense if we're running
- * in server mode, since the client will send the repository
- * directory after the connection is made.
- */
- if (!server_active)
- {
- /* First check if a root was set via the command line. */
- if (CVSroot_cmdline)
- {
- if (!(CVSroot_parsed = parse_cvsroot (CVSroot_cmdline)))
- error (1, 0, "Bad CVSROOT: `%s'.", CVSroot_cmdline);
- }
-
- /* See if we are able to find a 'better' value for CVSroot
- * in the CVSADM_ROOT directory.
- *
- * "cvs import" shouldn't check CVS/Root; in general it
- * ignores CVS directories and CVS/Root is likely to
- * specify a different repository than the one we are
- * importing to, but if this is not import and no root was
- * specified on the command line, set the root from the
- * CVS/Root file.
- */
- if (!CVSroot_parsed
- && !(cm->attr & CVS_CMD_IGNORE_ADMROOT)
- )
- CVSroot_parsed = Name_Root (NULL, NULL);
-
- /* Now, if there is no root on the command line and we didn't find
- * one in a file, set it via the $CVSROOT env var.
- */
- if (!CVSroot_parsed)
- {
- char *tmp = getenv (CVSROOT_ENV);
- if (tmp)
- {
- if (!(CVSroot_parsed = parse_cvsroot (tmp)))
- error (1, 0, "Bad CVSROOT: `%s'.", tmp);
- cvsroot_update_env = 0;
- }
- }
-
-#ifdef CVSROOT_DFLT
- if (!CVSroot_parsed)
- {
- if (!(CVSroot_parsed = parse_cvsroot (CVSROOT_DFLT)))
- error (1, 0, "Bad CVSROOT: `%s'.", CVSROOT_DFLT);
- }
-#endif /* CVSROOT_DFLT */
-
- /* Now we've reconciled CVSROOT from the command line, the
- CVS/Root file, and the environment variable. Do the
- last sanity checks on the variable. */
- if (!CVSroot_parsed)
- {
- error (0, 0,
- "No CVSROOT specified! Please use the `-d' option");
- error (1, 0,
- "or set the %s environment variable.", CVSROOT_ENV);
- }
- }
-
- /* Here begins the big loop over unique cvsroot values. We
- need to call do_recursion once for each unique value found
- in CVS/Root. Prime the list with the current value. */
-
- /* Create the list. */
- assert (root_directories == NULL);
- root_directories = getlist ();
-
- /* Prime it. */
- if (CVSroot_parsed)
- {
- Node *n;
- n = getnode ();
- n->type = NT_UNKNOWN;
- n->key = xstrdup (CVSroot_parsed->original);
- n->data = CVSroot_parsed;
-
- if (addnode (root_directories, n))
- error (1, 0, "cannot add initial CVSROOT %s", n->key);
- }
-
- assert (current_parsed_root == NULL);
-
- /* If we're running the server, we want to execute this main
- loop once and only once (we won't be serving multiple roots
- from this connection, so there's no need to do it more than
- once). To get out of the loop, we perform a "break" at the
- end of things. */
-
- while (server_active ||
- walklist (root_directories, set_root_directory, NULL))
- {
- /* Fiddling with CVSROOT doesn't make sense if we're running
- in server mode, since the client will send the repository
- directory after the connection is made. */
-
- if (!server_active)
- {
- /* Now we're 100% sure that we have a valid CVSROOT
- variable. Parse it to see if we're supposed to do
- remote accesses or use a special access method. */
-
- if (trace)
- fprintf (stderr, "%s-> main loop with CVSROOT=%s\n",
- CLIENT_SERVER_STR, current_parsed_root->original);
-
- /*
- * Check to see if the repository exists.
- */
- if (!current_parsed_root->isremote)
- {
- char *path;
- int save_errno;
-
- path = xmalloc (strlen (current_parsed_root->directory)
- + strlen (CVSROOTADM) + 2);
- sprintf (path, "%s/%s", current_parsed_root->directory,
- CVSROOTADM);
- if (!isaccessible (path, R_OK | X_OK))
- {
- save_errno = errno;
- /* If this is "cvs init", the root need not exist yet.
- */
- if (strcmp (cvs_cmd_name, "init"))
- error (1, save_errno, "%s", path);
- }
- free (path);
- }
-
-#ifdef HAVE_PUTENV
- /* Update the CVSROOT environment variable. */
- if (cvsroot_update_env)
- {
- static char *prev;
- char *env;
-
- env = xmalloc (strlen (CVSROOT_ENV)
- + strlen (current_parsed_root->original)
- + 2);
- sprintf (env, "%s=%s", CVSROOT_ENV,
- current_parsed_root->original);
- (void) putenv (env);
- /* do not free env yet, as putenv has control of it */
- /* but do free the previous value, if any */
- if (prev != NULL)
- free (prev);
- prev = env;
- }
-#endif
- }
-
- /* Parse the CVSROOT/config file, but only for local. For the
- server, we parse it after we know $CVSROOT. For the
- client, it doesn't get parsed at all, obviously. The
- presence of the parse_config call here is not mean to
- predetermine whether CVSROOT/config overrides things from
- read_cvsrc and other such places or vice versa. That sort
- of thing probably needs more thought. */
- if (!server_active && !current_parsed_root->isremote)
- {
- /* If there was an error parsing the config file, parse_config
- already printed an error. We keep going. Why? Because
- if we didn't, then there would be no way to check in a new
- CVSROOT/config file to fix the broken one! */
- parse_config (current_parsed_root->directory);
-
- /* Now is a convenient time to read CVSROOT/options */
- parseopts(current_parsed_root->directory);
- }
-
-#ifdef CLIENT_SUPPORT
- /* Need to check for current_parsed_root != NULL here since
- * we could still be in server mode before the server function
- * gets called below and sets the root
- */
- if (current_parsed_root != NULL && current_parsed_root->isremote)
- {
- /* Create a new list for directory names that we've
- sent to the server. */
- if (dirs_sent_to_server != NULL)
- dellist (&dirs_sent_to_server);
- dirs_sent_to_server = getlist ();
- }
-#endif
-
- err = (*(cm->func)) (argc, argv);
-
- /* Mark this root directory as done. When the server is
- active, our list will be empty -- don't try and
- remove it from the list. */
-
- if (!server_active)
- {
- Node *n = findnode (root_directories,
- current_parsed_root->original);
- assert (n != NULL);
- assert (n->data != NULL);
- free_cvsroot_t (n->data);
- n->data = NULL;
- current_parsed_root = NULL;
- }
-
- if (server_active)
- {
- server_active = 0;
- break;
- }
- } /* end of loop for cvsroot values */
-
- dellist (&root_directories);
- } /* end of stuff that gets done if the user DOESN'T ask for help */
-
- Lock_Cleanup ();
-
- /* It's okay to cast out the const below since we know we allocated this in
- * this function. The const was to keep other functions from messing with
- * this.
- */
- free ((char *)program_path);
- if (CVSroot_cmdline != NULL)
- free (CVSroot_cmdline);
- if (free_Editor)
- free (Editor);
- if (free_Tmpdir)
- free (Tmpdir);
- root_allow_free ();
-
-#ifdef SYSTEM_CLEANUP
- /* Hook for OS-specific behavior, for example socket subsystems on
- NT and OS2 or dealing with windows and arguments on Mac. */
- SYSTEM_CLEANUP ();
-#endif
-
- /* This is exit rather than return because apparently that keeps
- some tools which check for memory leaks happier. */
- exit (err ? EXIT_FAILURE : 0);
- /* Keep picky/stupid compilers (e.g. Visual C++ 5.0) happy. */
- return 0;
-}
-
-char *
-Make_Date (rawdate)
- char *rawdate;
-{
- time_t unixtime;
-
- unixtime = get_date (rawdate, (struct timeb *) NULL);
- if (unixtime == (time_t) - 1)
- error (1, 0, "Can't parse date/time: %s", rawdate);
- return date_from_time_t (unixtime);
-}
-
-/* Convert a time_t to an RCS format date. This is mainly for the
- use of "cvs history", because the CVSROOT/history file contains
- time_t format dates; most parts of CVS will want to avoid using
- time_t's directly, and instead use RCS_datecmp, Make_Date, &c.
- Assuming that the time_t is in GMT (as it generally should be),
- then the result will be in GMT too.
-
- Returns a newly malloc'd string. */
-
-char *
-date_from_time_t (unixtime)
- time_t unixtime;
-{
- struct tm *ftm;
- char date[MAXDATELEN];
- char *ret;
-
- ftm = gmtime (&unixtime);
- if (ftm == NULL)
- /* This is a system, like VMS, where the system clock is in local
- time. Hopefully using localtime here matches the "zero timezone"
- hack I added to get_date (get_date of course being the relevant
- issue for Make_Date, and for history.c too I think). */
- ftm = localtime (&unixtime);
-
- (void) sprintf (date, DATEFORM,
- ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
- ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
- ftm->tm_min, ftm->tm_sec);
- ret = xstrdup (date);
- return (ret);
-}
-
-/* Convert a date to RFC822/1123 format. This is used in contexts like
- dates to send in the protocol; it should not vary based on locale or
- other such conventions for users. We should have another routine which
- does that kind of thing.
-
- The SOURCE date is in our internal RCS format. DEST should point to
- storage managed by the caller, at least MAXDATELEN characters. */
-void
-date_to_internet (dest, source)
- char *dest;
- const char *source;
-{
- struct tm date;
-
- date_to_tm (&date, source);
- tm_to_internet (dest, &date);
-}
-
-void
-date_to_tm (dest, source)
- struct tm *dest;
- const char *source;
-{
- if (sscanf (source, SDATEFORM,
- &dest->tm_year, &dest->tm_mon, &dest->tm_mday,
- &dest->tm_hour, &dest->tm_min, &dest->tm_sec)
- != 6)
- /* Is there a better way to handle errors here? I made this
- non-fatal in case we are called from the code which can't
- deal with fatal errors. */
- error (0, 0, "internal error: bad date %s", source);
-
- if (dest->tm_year > 100)
- dest->tm_year -= 1900;
-
- dest->tm_mon -= 1;
-}
-
-/* Convert a date to RFC822/1123 format. This is used in contexts like
- dates to send in the protocol; it should not vary based on locale or
- other such conventions for users. We should have another routine which
- does that kind of thing.
-
- The SOURCE date is a pointer to a struct tm. DEST should point to
- storage managed by the caller, at least MAXDATELEN characters. */
-void
-tm_to_internet (dest, source)
- char *dest;
- const struct tm *source;
-{
- /* Just to reiterate, these strings are from RFC822 and do not vary
- according to locale. */
- static const char *const month_names[] =
- {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-
- sprintf (dest, "%d %s %d %02d:%02d:%02d -0000", source->tm_mday,
- source->tm_mon < 0 || source->tm_mon > 11 ? "???" : month_names[source->tm_mon],
- source->tm_year + 1900, source->tm_hour, source->tm_min, source->tm_sec);
-}
-
-void
-usage (cpp)
- register const char *const *cpp;
-{
- (void) fprintf (stderr, *cpp++, program_name, cvs_cmd_name);
- for (; *cpp; cpp++)
- (void) fprintf (stderr, *cpp);
- error_exit ();
-}
-
-void
-parseopts(root)
- const char *root;
-{
- char path[PATH_MAX];
- int save_errno;
- char buf[1024];
- const char *p;
- char *q;
- FILE *fp;
-
- if (root == NULL) {
- printf("no CVSROOT in parseopts\n");
- return;
- }
- p = strchr (root, ':');
- if (p)
- p++;
- else
- p = root;
- if (p == NULL) {
- printf("mangled CVSROOT in parseopts\n");
- return;
- }
- (void) sprintf (path, "%s/%s/%s", p, CVSROOTADM, CVSROOTADM_OPTIONS);
- if ((fp = fopen(path, "r")) != NULL) {
- while (fgets(buf, sizeof buf, fp) != NULL) {
- if (buf[0] == '#')
- continue;
- q = strrchr(buf, '\n');
- if (q)
- *q = '\0';
-
- if (!strcmp(buf, "iso8601")) {
- datesep = '-';
- }
- if (!strncmp(buf, "tag=", 4)) {
- char *what;
- char *rcs_localid;
-
- rcs_localid = buf + 4;
- RCS_setlocalid(rcs_localid);
- }
- if (!strncmp(buf, "tagexpand=", 10)) {
- char *what;
- char *rcs_incexc;
-
- rcs_incexc = buf + 10;
- RCS_setincexc(rcs_incexc);
- }
- /*
- * OpenBSD has a "umask=" and "dlimit=" command, we silently
- * ignore them here since they are not much use to us. cvsumask
- * defaults to 002 already, and the dlimit (data size limit)
- * should really be handled elsewhere (eg: login.conf).
- */
- }
- fclose(fp);
- }
-}
diff --git a/contrib/cvs/src/mkmodules.c b/contrib/cvs/src/mkmodules.c
deleted file mode 100644
index 751d4c73e4d7..000000000000
--- a/contrib/cvs/src/mkmodules.c
+++ /dev/null
@@ -1,1054 +0,0 @@
-/*
- * Copyright (C) 1986-2008 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS kit. */
-
-#include <assert.h>
-#include "cvs.h"
-#include "getline.h"
-#include "history.h"
-#include "savecwd.h"
-
-#ifndef DBLKSIZ
-#define DBLKSIZ 4096 /* since GNU ndbm doesn't define it */
-#endif
-
-static int checkout_file PROTO((char *file, char *temp));
-static char *make_tempfile PROTO((void));
-static void rename_rcsfile PROTO((char *temp, char *real));
-
-#ifndef MY_NDBM
-static void rename_dbmfile PROTO((char *temp));
-static void write_dbmfile PROTO((char *temp));
-#endif /* !MY_NDBM */
-
-/* Structure which describes an administrative file. */
-struct admin_file {
- /* Name of the file, within the CVSROOT directory. */
- char *filename;
-
- /* This is a one line description of what the file is for. It is not
- currently used, although one wonders whether it should be, somehow.
- If NULL, then don't process this file in mkmodules (FIXME?: a bit of
- a kludge; probably should replace this with a flags field). */
- char *errormsg;
-
- /* Contents which the file should have in a new repository. To avoid
- problems with brain-dead compilers which choke on long string constants,
- this is a pointer to an array of char * terminated by NULL--each of
- the strings is concatenated.
-
- If this field is NULL, the file is not created in a new
- repository, but it can be added with "cvs add" (just as if one
- had created the repository with a version of CVS which didn't
- know about the file) and the checked-out copy will be updated
- without having to add it to checkoutlist. */
- const char * const *contents;
-};
-
-static const char *const loginfo_contents[] = {
- "# The \"loginfo\" file controls where \"cvs commit\" log information\n",
- "# is sent. The first entry on a line is a regular expression which must match\n",
- "# the directory that the change is being made to, relative to the\n",
- "# $CVSROOT. If a match is found, then the remainder of the line is a filter\n",
- "# program that should expect log information on its standard input.\n",
- "#\n",
- "# If the repository name does not match any of the regular expressions in this\n",
- "# file, the \"DEFAULT\" line is used, if it is specified.\n",
- "#\n",
- "# If the name ALL appears as a regular expression it is always used\n",
- "# in addition to the first matching regex or DEFAULT.\n",
- "#\n",
- "# You may specify a format string as part of the\n",
- "# filter. The string is composed of a `%' followed\n",
- "# by a single format character, or followed by a set of format\n",
- "# characters surrounded by `{' and `}' as separators. The format\n",
- "# characters are:\n",
- "#\n",
- "# s = file name\n",
- "# V = old version number (pre-checkin)\n",
- "# v = new version number (post-checkin)\n",
- "#\n",
- "# For example:\n",
- "#DEFAULT (echo \"\"; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog\n",
- "# or\n",
- "#DEFAULT (echo \"\"; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog\n",
- NULL
-};
-
-static const char *const rcsinfo_contents[] = {
- "# The \"rcsinfo\" file is used to control templates with which the editor\n",
- "# is invoked on commit and import.\n",
- "#\n",
- "# The first entry on a line is a regular expression which is tested\n",
- "# against the directory that the change is being made to, relative to the\n",
- "# $CVSROOT. For the first match that is found, then the remainder of the\n",
- "# line is the name of the file that contains the template.\n",
- "#\n",
- "# If the repository name does not match any of the regular expressions in this\n",
- "# file, the \"DEFAULT\" line is used, if it is specified.\n",
- "#\n",
- "# If the name \"ALL\" appears as a regular expression it is always used\n",
- "# in addition to the first matching regex or \"DEFAULT\".\n",
- NULL
-};
-
-static const char *const editinfo_contents[] = {
- "# The \"editinfo\" file is used to allow verification of logging\n",
- "# information. It works best when a template (as specified in the\n",
- "# rcsinfo file) is provided for the logging procedure. Given a\n",
- "# template with locations for, a bug-id number, a list of people who\n",
- "# reviewed the code before it can be checked in, and an external\n",
- "# process to catalog the differences that were code reviewed, the\n",
- "# following test can be applied to the code:\n",
- "#\n",
- "# Making sure that the entered bug-id number is correct.\n",
- "# Validating that the code that was reviewed is indeed the code being\n",
- "# checked in (using the bug-id number or a seperate review\n",
- "# number to identify this particular code set.).\n",
- "#\n",
- "# If any of the above test failed, then the commit would be aborted.\n",
- "#\n",
- "# Actions such as mailing a copy of the report to each reviewer are\n",
- "# better handled by an entry in the loginfo file.\n",
- "#\n",
- "# One thing that should be noted is the the ALL keyword is not\n",
- "# supported. There can be only one entry that matches a given\n",
- "# repository.\n",
- NULL
-};
-
-static const char *const verifymsg_contents[] = {
- "# The \"verifymsg\" file is used to allow verification of logging\n",
- "# information. It works best when a template (as specified in the\n",
- "# rcsinfo file) is provided for the logging procedure. Given a\n",
- "# template with locations for, a bug-id number, a list of people who\n",
- "# reviewed the code before it can be checked in, and an external\n",
- "# process to catalog the differences that were code reviewed, the\n",
- "# following test can be applied to the code:\n",
- "#\n",
- "# Making sure that the entered bug-id number is correct.\n",
- "# Validating that the code that was reviewed is indeed the code being\n",
- "# checked in (using the bug-id number or a seperate review\n",
- "# number to identify this particular code set.).\n",
- "#\n",
- "# If any of the above test failed, then the commit would be aborted.\n",
- "#\n",
- "# Actions such as mailing a copy of the report to each reviewer are\n",
- "# better handled by an entry in the loginfo file.\n",
- "#\n",
- "# One thing that should be noted is the the ALL keyword is not\n",
- "# supported. There can be only one entry that matches a given\n",
- "# repository.\n",
- NULL
-};
-
-static const char *const commitinfo_contents[] = {
- "# The \"commitinfo\" file is used to control pre-commit checks.\n",
- "# The filter on the right is invoked with the repository and a list \n",
- "# of files to check. A non-zero exit of the filter program will \n",
- "# cause the commit to be aborted.\n",
- "#\n",
- "# The first entry on a line is a regular expression which is tested\n",
- "# against the directory that the change is being committed to, relative\n",
- "# to the $CVSROOT. For the first match that is found, then the remainder\n",
- "# of the line is the name of the filter to run.\n",
- "#\n",
- "# If the repository name does not match any of the regular expressions in this\n",
- "# file, the \"DEFAULT\" line is used, if it is specified.\n",
- "#\n",
- "# If the name \"ALL\" appears as a regular expression it is always used\n",
- "# in addition to the first matching regex or \"DEFAULT\".\n",
- NULL
-};
-
-static const char *const taginfo_contents[] = {
- "# The \"taginfo\" file is used to control pre-tag checks.\n",
- "# The filter on the right is invoked with the following arguments:\n",
- "#\n",
- "# $1 -- tagname\n",
- "# $2 -- operation \"add\" for tag, \"mov\" for tag -F, and \"del\" for tag -d\n",
- "# $3 -- repository\n",
- "# $4-> file revision [file revision ...]\n",
- "#\n",
- "# A non-zero exit of the filter program will cause the tag to be aborted.\n",
- "#\n",
- "# The first entry on a line is a regular expression which is tested\n",
- "# against the directory that the change is being committed to, relative\n",
- "# to the $CVSROOT. For the first match that is found, then the remainder\n",
- "# of the line is the name of the filter to run.\n",
- "#\n",
- "# If the repository name does not match any of the regular expressions in this\n",
- "# file, the \"DEFAULT\" line is used, if it is specified.\n",
- "#\n",
- "# If the name \"ALL\" appears as a regular expression it is always used\n",
- "# in addition to the first matching regex or \"DEFAULT\".\n",
- NULL
-};
-
-static const char *const checkoutlist_contents[] = {
- "# The \"checkoutlist\" file is used to support additional version controlled\n",
- "# administrative files in $CVSROOT/CVSROOT, such as template files.\n",
- "#\n",
- "# The first entry on a line is a filename which will be checked out from\n",
- "# the corresponding RCS file in the $CVSROOT/CVSROOT directory.\n",
- "# The remainder of the line is an error message to use if the file cannot\n",
- "# be checked out.\n",
- "#\n",
- "# File format:\n",
- "#\n",
- "# [<whitespace>]<filename>[<whitespace><error message>]<end-of-line>\n",
- "#\n",
- "# comment lines begin with '#'\n",
- NULL
-};
-
-static const char *const cvswrappers_contents[] = {
- "# This file affects handling of files based on their names.\n",
- "#\n",
-#if 0 /* see comments in wrap_add in wrapper.c */
- "# The -t/-f options allow one to treat directories of files\n",
- "# as a single file, or to transform a file in other ways on\n",
- "# its way in and out of CVS.\n",
- "#\n",
-#endif
- "# The -m option specifies whether CVS attempts to merge files.\n",
- "#\n",
- "# The -k option specifies keyword expansion (e.g. -kb for binary).\n",
- "#\n",
- "# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)\n",
- "#\n",
- "# wildcard [option value][option value]...\n",
- "#\n",
- "# where option is one of\n",
- "# -f from cvs filter value: path to filter\n",
- "# -t to cvs filter value: path to filter\n",
- "# -m update methodology value: MERGE or COPY\n",
- "# -k expansion mode value: b, o, kkv, &c\n",
- "#\n",
- "# and value is a single-quote delimited value.\n",
- "# For example:\n",
- "#*.gif -k 'b'\n",
- NULL
-};
-
-static const char *const notify_contents[] = {
- "# The \"notify\" file controls where notifications from watches set by\n",
- "# \"cvs watch add\" or \"cvs edit\" are sent. The first entry on a line is\n",
- "# a regular expression which is tested against the directory that the\n",
- "# change is being made to, relative to the $CVSROOT. If it matches,\n",
- "# then the remainder of the line is a filter program that should contain\n",
- "# one occurrence of %s for the user to notify, and information on its\n",
- "# standard input.\n",
- "#\n",
- "# \"ALL\" or \"DEFAULT\" can be used in place of the regular expression.\n",
- "#\n",
- "# For example:\n",
- "#ALL mail -s \"CVS notification\" %s\n",
- NULL
-};
-
-static const char *const modules_contents[] = {
- "# Three different line formats are valid:\n",
- "# key -a aliases...\n",
- "# key [options] directory\n",
- "# key [options] directory files...\n",
- "#\n",
- "# Where \"options\" are composed of:\n",
- "# -o prog Run \"prog\" on \"cvs checkout\" of module.\n",
- "# -e prog Run \"prog\" on \"cvs export\" of module.\n",
- "# -t prog Run \"prog\" on \"cvs rtag\" of module.\n",
- "# -u prog Run \"prog\" on \"cvs update\" of module.\n",
- "# -d dir Place module in directory \"dir\" instead of module name.\n",
- "# -l Top-level directory only -- do not recurse.\n",
- "#\n",
- "# NOTE: If you change any of the \"Run\" options above, you'll have to\n",
- "# release and re-checkout any working directories of these modules.\n",
- "#\n",
- "# And \"directory\" is a path to a directory relative to $CVSROOT.\n",
- "#\n",
- "# The \"-a\" option specifies an alias. An alias is interpreted as if\n",
- "# everything on the right of the \"-a\" had been typed on the command line.\n",
- "#\n",
- "# You can encode a module within a module by using the special '&'\n",
- "# character to interpose another module into the current module. This\n",
- "# can be useful for creating a module that consists of many directories\n",
- "# spread out over the entire source repository.\n",
- NULL
-};
-
-static const char *const config_contents[] = {
- "# Set this to \"no\" if pserver shouldn't check system users/passwords\n",
- "#SystemAuth=yes\n",
- "\n",
- "# Set `IgnoreUnknownConfigKeys' to `yes' to ignore unknown config\n",
- "# keys which are supported in a future version of CVS.\n",
- "# This option is intended to be useful as a transition for read-only\n",
- "# mirror sites when sites may need to be updated later than the\n",
- "# primary CVS repository.\n",
- "#IgnoreUnknownConfigKeys=no\n",
- "\n",
- "# Put CVS lock files in this directory rather than directly in the repository.\n",
- "#LockDir=/var/lock/cvs\n",
- "\n",
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- "# Set `PreservePermissions' to `yes' to save file status information\n",
- "# in the repository.\n",
- "#PreservePermissions=no\n",
- "\n",
-#endif
- "# Set `TopLevelAdmin' to `yes' to create a CVS directory at the top\n",
- "# level of the new working directory when using the `cvs checkout'\n",
- "# command.\n",
- "#TopLevelAdmin=no\n",
- "\n",
- "# Set `LogHistory' to `all' or `" ALL_HISTORY_REC_TYPES "' to log all transactions to the\n",
- "# history file, or a subset as needed (ie `TMAR' logs all write operations)\n",
- "#LogHistory=" ALL_HISTORY_REC_TYPES "\n",
- "\n",
- "# Set `RereadLogAfterVerify' to `always' (the default) to allow the verifymsg\n",
- "# script to change the log message. Set it to `stat' to force CVS to verify\n",
- "# that the file has changed before reading it (this can take up to an extra\n",
- "# second per directory being committed, so it is not recommended for large\n",
- "# repositories. Set it to `never' (the previous CVS behavior) to prevent\n",
- "# verifymsg scripts from changing the log message.\n",
- "#RereadLogAfterVerify=always\n",
- NULL
-};
-
-static const struct admin_file filelist[] = {
- {CVSROOTADM_LOGINFO,
- "no logging of 'cvs commit' messages is done without a %s file",
- &loginfo_contents[0]},
- {CVSROOTADM_RCSINFO,
- "a %s file can be used to configure 'cvs commit' templates",
- rcsinfo_contents},
- {CVSROOTADM_EDITINFO,
- "a %s file can be used to validate log messages",
- editinfo_contents},
- {CVSROOTADM_VERIFYMSG,
- "a %s file can be used to validate log messages",
- verifymsg_contents},
- {CVSROOTADM_COMMITINFO,
- "a %s file can be used to configure 'cvs commit' checking",
- commitinfo_contents},
- {CVSROOTADM_TAGINFO,
- "a %s file can be used to configure 'cvs tag' checking",
- taginfo_contents},
- {CVSROOTADM_IGNORE,
- "a %s file can be used to specify files to ignore",
- NULL},
- {CVSROOTADM_CHECKOUTLIST,
- "a %s file can specify extra CVSROOT files to auto-checkout",
- checkoutlist_contents},
- {CVSROOTADM_WRAPPER,
- "a %s file can be used to specify files to treat as wrappers",
- cvswrappers_contents},
- {CVSROOTADM_NOTIFY,
- "a %s file can be used to specify where notifications go",
- notify_contents},
- {CVSROOTADM_MODULES,
- /* modules is special-cased in mkmodules. */
- NULL,
- modules_contents},
- {CVSROOTADM_READERS,
- "a %s file specifies read-only users",
- NULL},
- {CVSROOTADM_WRITERS,
- "a %s file specifies read/write users",
- NULL},
-
- /* Some have suggested listing CVSROOTADM_PASSWD here too. This
- would mean that CVS commands which operate on the
- CVSROOTADM_PASSWD file would transmit hashed passwords over the
- net. This might seem to be no big deal, as pserver normally
- transmits cleartext passwords, but the difference is that
- CVSROOTADM_PASSWD contains *all* passwords, not just the ones
- currently being used. For example, it could be too easy to
- accidentally give someone readonly access to CVSROOTADM_PASSWD
- (e.g. via anonymous CVS or cvsweb), and then if there are any
- guessable passwords for read/write access (usually there will be)
- they get read/write access.
-
- Another worry is the implications of storing old passwords--if
- someone used a password in the past they might be using it
- elsewhere, using a similar password, etc, and so saving old
- passwords, even hashed, is probably not a good idea. */
-
- {CVSROOTADM_CONFIG,
- "a %s file configures various behaviors",
- config_contents},
- {NULL, NULL, NULL}
-};
-
-/* Rebuild the checked out administrative files in directory DIR. */
-int
-mkmodules (dir)
- char *dir;
-{
- struct saved_cwd cwd;
- char *temp;
- char *cp, *last, *fname;
-#ifdef MY_NDBM
- DBM *db;
-#endif
- FILE *fp;
- char *line = NULL;
- size_t line_allocated = 0;
- const struct admin_file *fileptr;
-
- if (noexec)
- return 0;
-
- if (save_cwd (&cwd))
- error_exit ();
-
- if ( CVS_CHDIR (dir) < 0)
- error (1, errno, "cannot chdir to %s", dir);
-
- /*
- * First, do the work necessary to update the "modules" database.
- */
- temp = make_tempfile ();
- switch (checkout_file (CVSROOTADM_MODULES, temp))
- {
-
- case 0: /* everything ok */
-#ifdef MY_NDBM
- /* open it, to generate any duplicate errors */
- if ((db = dbm_open (temp, O_RDONLY, 0666)) != NULL)
- dbm_close (db);
-#else
- write_dbmfile (temp);
- rename_dbmfile (temp);
-#endif
- rename_rcsfile (temp, CVSROOTADM_MODULES);
- break;
-
- default:
- error (0, 0,
- "'cvs checkout' is less functional without a %s file",
- CVSROOTADM_MODULES);
- break;
- } /* switch on checkout_file() */
-
- if (unlink_file (temp) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", temp);
- free (temp);
-
- /* Checkout the files that need it in CVSROOT dir */
- for (fileptr = filelist; fileptr && fileptr->filename; fileptr++) {
- if (fileptr->errormsg == NULL)
- continue;
- temp = make_tempfile ();
- if (checkout_file (fileptr->filename, temp) == 0)
- rename_rcsfile (temp, fileptr->filename);
-#if 0
- /*
- * If there was some problem other than the file not existing,
- * checkout_file already printed a real error message. If the
- * file does not exist, it is harmless--it probably just means
- * that the repository was created with an old version of CVS
- * which didn't have so many files in CVSROOT.
- */
- else if (fileptr->errormsg)
- error (0, 0, fileptr->errormsg, fileptr->filename);
-#endif
- if (unlink_file (temp) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", temp);
- free (temp);
- }
-
- fp = CVS_FOPEN (CVSROOTADM_CHECKOUTLIST, "r");
- if (fp)
- {
- /*
- * File format:
- * [<whitespace>]<filename>[<whitespace><error message>]<end-of-line>
- *
- * comment lines begin with '#'
- */
- while (getline (&line, &line_allocated, fp) >= 0)
- {
- /* skip lines starting with # */
- if (line[0] == '#')
- continue;
-
- if ((last = strrchr (line, '\n')) != NULL)
- *last = '\0'; /* strip the newline */
-
- /* Skip leading white space. */
- for (fname = line;
- *fname && isspace ((unsigned char) *fname);
- fname++)
- ;
-
- /* Find end of filename. */
- for (cp = fname; *cp && !isspace ((unsigned char) *cp); cp++)
- ;
- *cp = '\0';
-
- temp = make_tempfile ();
- if (checkout_file (fname, temp) == 0)
- {
- rename_rcsfile (temp, fname);
- }
- else
- {
- /* Skip leading white space before the error message. */
- for (cp++;
- cp < last && *cp && isspace ((unsigned char) *cp);
- cp++)
- ;
- if (cp < last && *cp)
- error (0, 0, "%s", cp);
- }
- if (unlink_file (temp) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", temp);
- free (temp);
- }
- if (line)
- free (line);
- if (ferror (fp))
- error (0, errno, "cannot read %s", CVSROOTADM_CHECKOUTLIST);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", CVSROOTADM_CHECKOUTLIST);
- }
- else
- {
- /* Error from CVS_FOPEN. */
- if (!existence_error (errno))
- error (0, errno, "cannot open %s", CVSROOTADM_CHECKOUTLIST);
- }
-
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- free_cwd (&cwd);
-
- return (0);
-}
-
-/*
- * Yeah, I know, there are NFS race conditions here.
- */
-static char *
-make_tempfile ()
-{
- static int seed = 0;
- int fd;
- char *temp;
-
- if (seed == 0)
- seed = getpid ();
- temp = xmalloc (sizeof (BAKPREFIX) + 40);
- while (1)
- {
- (void) sprintf (temp, "%s%d", BAKPREFIX, seed++);
- if ((fd = CVS_OPEN (temp, O_CREAT|O_EXCL|O_RDWR, 0666)) != -1)
- break;
- if (errno != EEXIST)
- error (1, errno, "cannot create temporary file %s", temp);
- }
- if (close(fd) < 0)
- error(1, errno, "cannot close temporary file %s", temp);
- return temp;
-}
-
-/* Get a file. If the file does not exist, return 1 silently. If
- there is an error, print a message and return 1 (FIXME: probably
- not a very clean convention). On success, return 0. */
-
-static int
-checkout_file (file, temp)
- char *file;
- char *temp;
-{
- char *rcs;
- RCSNode *rcsnode;
- int retcode = 0;
-
- if (noexec)
- return 0;
-
- rcs = xmalloc (strlen (file) + 5);
- strcpy (rcs, file);
- strcat (rcs, RCSEXT);
- if (!isfile (rcs))
- {
- free (rcs);
- return (1);
- }
-
- rcsnode = RCS_parsercsfile (rcs);
- if (!rcsnode)
- {
- /* Probably not necessary (?); RCS_parsercsfile already printed a
- message. */
- error (0, 0, "Failed to parse `%s'.", rcs);
- free (rcs);
- return 1;
- }
-
- retcode = RCS_checkout (rcsnode, NULL, NULL, NULL, NULL, temp,
- (RCSCHECKOUTPROC) NULL, (void *) NULL);
- if (retcode != 0)
- {
- /* Probably not necessary (?); RCS_checkout already printed a
- message. */
- error (0, 0, "failed to check out %s file",
- file);
- }
- freercsnode (&rcsnode);
- free (rcs);
- return (retcode);
-}
-
-#ifndef MY_NDBM
-
-static void
-write_dbmfile (temp)
- char *temp;
-{
- char line[DBLKSIZ], value[DBLKSIZ];
- FILE *fp;
- DBM *db;
- char *cp, *vp;
- datum key, val;
- int len, cont, err = 0;
-
- fp = open_file (temp, "r");
- if ((db = dbm_open (temp, O_RDWR | O_CREAT | O_TRUNC, 0666)) == NULL)
- error (1, errno, "cannot open dbm file %s for creation", temp);
- for (cont = 0; fgets (line, sizeof (line), fp) != NULL;)
- {
- if ((cp = strrchr (line, '\n')) != NULL)
- *cp = '\0'; /* strip the newline */
-
- /*
- * Add the line to the value, at the end if this is a continuation
- * line; otherwise at the beginning, but only after any trailing
- * backslash is removed.
- */
- vp = value;
- if (cont)
- vp += strlen (value);
-
- /*
- * See if the line we read is a continuation line, and strip the
- * backslash if so.
- */
- len = strlen (line);
- if (len > 0)
- cp = &line[len - 1];
- else
- cp = line;
- if (*cp == '\\')
- {
- cont = 1;
- *cp = '\0';
- }
- else
- {
- cont = 0;
- }
- (void) strcpy (vp, line);
- if (value[0] == '#')
- continue; /* comment line */
- vp = value;
- while (*vp && isspace ((unsigned char) *vp))
- vp++;
- if (*vp == '\0')
- continue; /* empty line */
-
- /*
- * If this was not a continuation line, add the entry to the database
- */
- if (!cont)
- {
- key.dptr = vp;
- while (*vp && !isspace ((unsigned char) *vp))
- vp++;
- key.dsize = vp - key.dptr;
- *vp++ = '\0'; /* NULL terminate the key */
- while (*vp && isspace ((unsigned char) *vp))
- vp++; /* skip whitespace to value */
- if (*vp == '\0')
- {
- error (0, 0, "warning: NULL value for key `%s'", key.dptr);
- continue;
- }
- val.dptr = vp;
- val.dsize = strlen (vp);
- if (dbm_store (db, key, val, DBM_INSERT) == 1)
- {
- error (0, 0, "duplicate key found for `%s'", key.dptr);
- err++;
- }
- }
- }
- dbm_close (db);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", temp);
- if (err)
- {
- /* I think that the size of the buffer needed here is
- just determined by sizeof (CVSROOTADM_MODULES), the
- filenames created by make_tempfile, and other things that won't
- overflow. */
- char dotdir[50], dotpag[50], dotdb[50];
-
- (void) sprintf (dotdir, "%s.dir", temp);
- (void) sprintf (dotpag, "%s.pag", temp);
- (void) sprintf (dotdb, "%s.db", temp);
- if (unlink_file (dotdir) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", dotdir);
- if (unlink_file (dotpag) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", dotpag);
- if (unlink_file (dotdb) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", dotdb);
- error (1, 0, "DBM creation failed; correct above errors");
- }
-}
-
-static void
-rename_dbmfile (temp)
- char *temp;
-{
- /* I think that the size of the buffer needed here is
- just determined by sizeof (CVSROOTADM_MODULES), the
- filenames created by make_tempfile, and other things that won't
- overflow. */
- char newdir[50], newpag[50], newdb[50];
- char dotdir[50], dotpag[50], dotdb[50];
- char bakdir[50], bakpag[50], bakdb[50];
-
- int dir1_errno = 0, pag1_errno = 0, db1_errno = 0;
- int dir2_errno = 0, pag2_errno = 0, db2_errno = 0;
- int dir3_errno = 0, pag3_errno = 0, db3_errno = 0;
-
- (void) sprintf (dotdir, "%s.dir", CVSROOTADM_MODULES);
- (void) sprintf (dotpag, "%s.pag", CVSROOTADM_MODULES);
- (void) sprintf (dotdb, "%s.db", CVSROOTADM_MODULES);
- (void) sprintf (bakdir, "%s%s.dir", BAKPREFIX, CVSROOTADM_MODULES);
- (void) sprintf (bakpag, "%s%s.pag", BAKPREFIX, CVSROOTADM_MODULES);
- (void) sprintf (bakdb, "%s%s.db", BAKPREFIX, CVSROOTADM_MODULES);
- (void) sprintf (newdir, "%s.dir", temp);
- (void) sprintf (newpag, "%s.pag", temp);
- (void) sprintf (newdb, "%s.db", temp);
-
- (void) chmod (newdir, 0666);
- (void) chmod (newpag, 0666);
- (void) chmod (newdb, 0666);
-
- /* don't mess with me */
- SIG_beginCrSect ();
-
- /* rm .#modules.dir .#modules.pag */
- if (unlink_file (bakdir) < 0)
- dir1_errno = errno;
- if (unlink_file (bakpag) < 0)
- pag1_errno = errno;
- if (unlink_file (bakdb) < 0)
- db1_errno = errno;
-
- /* mv modules.dir .#modules.dir */
- if (CVS_RENAME (dotdir, bakdir) < 0)
- dir2_errno = errno;
- /* mv modules.pag .#modules.pag */
- if (CVS_RENAME (dotpag, bakpag) < 0)
- pag2_errno = errno;
- /* mv modules.db .#modules.db */
- if (CVS_RENAME (dotdb, bakdb) < 0)
- db2_errno = errno;
-
- /* mv "temp".dir modules.dir */
- if (CVS_RENAME (newdir, dotdir) < 0)
- dir3_errno = errno;
- /* mv "temp".pag modules.pag */
- if (CVS_RENAME (newpag, dotpag) < 0)
- pag3_errno = errno;
- /* mv "temp".db modules.db */
- if (CVS_RENAME (newdb, dotdb) < 0)
- db3_errno = errno;
-
- /* OK -- make my day */
- SIG_endCrSect ();
-
- /* I didn't want to call error() when we had signals blocked
- (unnecessary?), but do it now. */
- if (dir1_errno && !existence_error (dir1_errno))
- error (0, dir1_errno, "cannot remove %s", bakdir);
- if (pag1_errno && !existence_error (pag1_errno))
- error (0, pag1_errno, "cannot remove %s", bakpag);
- if (db1_errno && !existence_error (db1_errno))
- error (0, db1_errno, "cannot remove %s", bakdb);
-
- if (dir2_errno && !existence_error (dir2_errno))
- error (0, dir2_errno, "cannot remove %s", bakdir);
- if (pag2_errno && !existence_error (pag2_errno))
- error (0, pag2_errno, "cannot remove %s", bakpag);
- if (db2_errno && !existence_error (db2_errno))
- error (0, db2_errno, "cannot remove %s", bakdb);
-
- if (dir3_errno && !existence_error (dir3_errno))
- error (0, dir3_errno, "cannot remove %s", bakdir);
- if (pag3_errno && !existence_error (pag3_errno))
- error (0, pag3_errno, "cannot remove %s", bakpag);
- if (db3_errno && !existence_error (db3_errno))
- error (0, db3_errno, "cannot remove %s", bakdb);
-}
-
-#endif /* !MY_NDBM */
-
-static void
-rename_rcsfile (temp, real)
- char *temp;
- char *real;
-{
- char *bak;
- struct stat statbuf;
- char *rcs;
-
- /* Set "x" bits if set in original. */
- rcs = xmalloc (strlen (real) + sizeof (RCSEXT) + 10);
- (void) sprintf (rcs, "%s%s", real, RCSEXT);
- statbuf.st_mode = 0; /* in case rcs file doesn't exist, but it should... */
- if (CVS_STAT (rcs, &statbuf) < 0
- && !existence_error (errno))
- error (0, errno, "cannot stat %s", rcs);
- free (rcs);
-
- if (chmod (temp, 0444 | (statbuf.st_mode & 0111)) < 0)
- error (0, errno, "warning: cannot chmod %s", temp);
- bak = xmalloc (strlen (real) + sizeof (BAKPREFIX) + 10);
- (void) sprintf (bak, "%s%s", BAKPREFIX, real);
-
- /* rm .#loginfo */
- if (unlink_file (bak) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", bak);
-
- /* mv loginfo .#loginfo */
- if (CVS_RENAME (real, bak) < 0
- && !existence_error (errno))
- error (0, errno, "cannot rename %s to %s", real, bak);
-
- /* mv "temp" loginfo */
- if (CVS_RENAME (temp, real) < 0
- && !existence_error (errno))
- error (0, errno, "cannot rename %s to %s", temp, real);
-
- free (bak);
-}
-
-/*
- * Walk PATH backwards to the root directory looking for the root of a
- * repository.
- */
-static char *
-in_repository (const char *path)
-{
- char *cp = xstrdup (path);
-
- for (;;)
- {
- if (isdir (cp))
- {
- int foundit;
- char *adm = xmalloc (strlen(cp) + strlen(CVSROOTADM) + 2);
- sprintf (adm, "%s/%s", cp, CVSROOTADM);
- foundit = isdir (adm);
- free (adm);
- if (foundit) return cp;
- }
-
- /* If last_component() returns the empty string, then cp either
- * points at the system root or is the empty string itself.
- */
- if (!*last_component (cp) || !strcmp (cp, ".")
- || last_component(cp) == cp)
- break;
-
- cp[strlen(cp) - strlen(last_component(cp)) - 1] = '\0';
- }
-
- return NULL;
-}
-
-
-const char *const init_usage[] = {
- "Usage: %s %s\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-int
-init (argc, argv)
- int argc;
- char **argv;
-{
- /* Name of CVSROOT directory. */
- char *adm;
- /* Name of this administrative file. */
- char *info;
- /* Name of ,v file for this administrative file. */
- char *info_v;
- /* Exit status. */
- int err = 0;
-
- char *root_dir;
- const struct admin_file *fileptr;
-
- assert (!server_active);
-
- umask (cvsumask);
-
- if (argc == -1 || argc > 1)
- usage (init_usage);
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- start_server ();
-
- ign_setup ();
- send_init_command ();
- return get_responses_and_close ();
- }
-#endif /* CLIENT_SUPPORT */
-
- root_dir = in_repository (current_parsed_root->directory);
-
- if (root_dir && strcmp (root_dir, current_parsed_root->directory))
- error (1, 0,
- "Cannot initialize repository under existing CVSROOT: `%s'",
- root_dir);
- free (root_dir);
-
- /* Note: we do *not* create parent directories as needed like the
- old cvsinit.sh script did. Few utilities do that, and a
- non-existent parent directory is as likely to be a typo as something
- which needs to be created. */
- mkdir_if_needed (current_parsed_root->directory);
-
- adm = xmalloc (strlen (current_parsed_root->directory) + sizeof (CVSROOTADM) + 2);
- sprintf (adm, "%s/%s", current_parsed_root->directory, CVSROOTADM);
- mkdir_if_needed (adm);
-
- /* This is needed because we pass "fileptr->filename" not "info"
- to add_rcs_file below. I think this would be easy to change,
- thus nuking the need for CVS_CHDIR here, but I haven't looked
- closely (e.g. see wrappers calls within add_rcs_file). */
- if ( CVS_CHDIR (adm) < 0)
- error (1, errno, "cannot change to directory %s", adm);
-
- /* Make Emptydir so it's there if we need it */
- mkdir_if_needed (CVSNULLREPOS);
-
- /* 80 is long enough for all the administrative file names, plus
- "/" and so on. */
- info = xmalloc (strlen (adm) + 80);
- info_v = xmalloc (strlen (adm) + 80);
- for (fileptr = filelist; fileptr && fileptr->filename; ++fileptr)
- {
- if (fileptr->contents == NULL)
- continue;
- strcpy (info, adm);
- strcat (info, "/");
- strcat (info, fileptr->filename);
- strcpy (info_v, info);
- strcat (info_v, RCSEXT);
- if (isfile (info_v))
- /* We will check out this file in the mkmodules step.
- Nothing else is required. */
- ;
- else
- {
- int retcode;
-
- if (!isfile (info))
- {
- FILE *fp;
- const char * const *p;
-
- fp = open_file (info, "w");
- for (p = fileptr->contents; *p != NULL; ++p)
- if (fputs (*p, fp) < 0)
- error (1, errno, "cannot write %s", info);
- if (fclose (fp) < 0)
- error (1, errno, "cannot close %s", info);
- }
- /* The message used to say " of " and fileptr->filename after
- "initial checkin" but I fail to see the point as we know what
- file it is from the name. */
- retcode = add_rcs_file ("initial checkin", info_v,
- fileptr->filename, "1.1", NULL,
-
- /* No vendor branch. */
- NULL, NULL, 0, NULL,
-
- NULL, 0, NULL);
- if (retcode != 0)
- /* add_rcs_file already printed an error message. */
- err = 1;
- }
- }
-
- /* Turn on history logging by default. The user can remove the file
- to disable it. */
- strcpy (info, adm);
- strcat (info, "/");
- strcat (info, CVSROOTADM_HISTORY);
- if (!isfile (info))
- {
- FILE *fp;
-
- fp = open_file (info, "w");
- if (fclose (fp) < 0)
- error (1, errno, "cannot close %s", info);
-
- /* Make the new history file world-writeable, since every CVS
- user will need to be able to write to it. We use chmod()
- because xchmod() is too shy. */
- chmod (info, 0666);
- }
-
- /* Make an empty val-tags file to prevent problems creating it later. */
- strcpy (info, adm);
- strcat (info, "/");
- strcat (info, CVSROOTADM_VALTAGS);
- if (!isfile (info))
- {
- FILE *fp;
-
- fp = open_file (info, "w");
- if (fclose (fp) < 0)
- error (1, errno, "cannot close %s", info);
-
- /* Make the new val-tags file world-writeable, since every CVS
- user will need to be able to write to it. We use chmod()
- because xchmod() is too shy. */
- chmod (info, 0666);
- }
-
- free (info);
- free (info_v);
-
- mkmodules (adm);
-
- free (adm);
- return err;
-}
diff --git a/contrib/cvs/src/modules.c b/contrib/cvs/src/modules.c
deleted file mode 100644
index 5cbc2ecca5e1..000000000000
--- a/contrib/cvs/src/modules.c
+++ /dev/null
@@ -1,1101 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License
- * as specified in the README file that comes with the CVS source
- * distribution.
- *
- * Modules
- *
- * Functions for accessing the modules file.
- *
- * The modules file supports basically three formats of lines:
- * key [options] directory files... [ -x directory [files] ] ...
- * key [options] directory [ -x directory [files] ] ...
- * key -a aliases...
- *
- * The -a option allows an aliasing step in the parsing of the modules
- * file. The "aliases" listed on a line following the -a are
- * processed one-by-one, as if they were specified as arguments on the
- * command line.
- */
-
-#include <assert.h>
-#include "cvs.h"
-#include "savecwd.h"
-
-
-/* Defines related to the syntax of the modules file. */
-
-/* Options in modules file. Note that it is OK to use GNU getopt features;
- we already are arranging to make sure we are using the getopt distributed
- with CVS. */
-#define CVSMODULE_OPTS "+ad:lo:e:s:t:"
-
-/* Special delimiter. */
-#define CVSMODULE_SPEC '&'
-
-struct sortrec
-{
- /* Name of the module, malloc'd. */
- char *modname;
- /* If Status variable is set, this is either def_status or the malloc'd
- name of the status. If Status is not set, the field is left
- uninitialized. */
- char *status;
- /* Pointer to a malloc'd array which contains (1) the raw contents
- of the options and arguments, excluding comments, (2) a '\0',
- and (3) the storage for the "comment" field. */
- char *rest;
- char *comment;
-};
-
-static int sort_order PROTO((const PTR l, const PTR r));
-static void save_d PROTO((char *k, int ks, char *d, int ds));
-
-
-/*
- * Open the modules file, and die if the CVSROOT environment variable
- * was not set. If the modules file does not exist, that's fine, and
- * a warning message is displayed and a NULL is returned.
- */
-DBM *
-open_module ()
-{
- char *mfile;
- DBM *retval;
-
- if (current_parsed_root == NULL)
- {
- error (0, 0, "must set the CVSROOT environment variable");
- error (1, 0, "or specify the '-d' global option");
- }
- mfile = xmalloc (strlen (current_parsed_root->directory)
- + sizeof (CVSROOTADM)
- + sizeof (CVSROOTADM_MODULES) + 3);
- (void) sprintf (mfile, "%s/%s/%s", current_parsed_root->directory,
- CVSROOTADM, CVSROOTADM_MODULES);
- retval = dbm_open (mfile, O_RDONLY, 0666);
- free (mfile);
- return retval;
-}
-
-/*
- * Close the modules file, if the open succeeded, that is
- */
-void
-close_module (db)
- DBM *db;
-{
- if (db != NULL)
- dbm_close (db);
-}
-
-
-
-/*
- * This is the recursive function that processes a module name.
- * It calls back the passed routine for each directory of a module
- * It runs the post checkout or post tag proc from the modules file
- */
-static int
-my_module (db, mname, m_type, msg, callback_proc, where, shorten,
- local_specified, run_module_prog, build_dirs, extra_arg,
- stack)
- DBM *db;
- char *mname;
- enum mtype m_type;
- char *msg;
- CALLBACKPROC callback_proc;
- char *where;
- int shorten;
- int local_specified;
- int run_module_prog;
- int build_dirs;
- char *extra_arg;
- List *stack;
-{
- char *checkout_prog = NULL;
- char *export_prog = NULL;
- char *tag_prog = NULL;
- struct saved_cwd cwd;
- int cwd_saved = 0;
- char *line;
- int modargc;
- int xmodargc;
- char **modargv = NULL;
- char **xmodargv = NULL;
- /* Found entry from modules file, including options and such. */
- char *value = NULL;
- char *mwhere = NULL;
- char *mfile = NULL;
- char *spec_opt = NULL;
- int alias = 0;
- datum key, val;
- char *cp;
- int c, err = 0;
- int nonalias_opt = 0;
-
-#ifdef SERVER_SUPPORT
- int restore_server_dir = 0;
- char *server_dir_to_restore = NULL;
- if (trace)
- {
- char *buf;
-
- /* We use cvs_outerr, rather than fprintf to stderr, because
- this may be called by server code with error_use_protocol
- set. */
- buf = xmalloc (100
- + strlen (mname)
- + strlen (msg)
- + (where ? strlen (where) : 0)
- + (extra_arg ? strlen (extra_arg) : 0));
- sprintf (buf, "%s-> my_module (%s, %s, %s, %s)\n",
- CLIENT_SERVER_STR,
- mname, msg, where ? where : "",
- extra_arg ? extra_arg : "");
- cvs_outerr (buf, 0);
- free (buf);
- }
-#endif
-
- /* Don't process absolute directories. Anything else could be a security
- * problem. Before this check was put in place:
- *
- * $ cvs -d:fork:/cvsroot co /foo
- * cvs server: warning: cannot make directory CVS in /: Permission denied
- * cvs [server aborted]: cannot make directory /foo: Permission denied
- * $
- */
- if (isabsolute (mname))
- error (1, 0, "Absolute module reference invalid: `%s'", mname);
-
- /* Similarly for directories that attempt to step above the root of the
- * repository.
- */
- if (pathname_levels (mname) > 0)
- error (1, 0, "up-level in module reference (`..') invalid: `%s'.",
- mname);
-
- /* if this is a directory to ignore, add it to that list */
- if (mname[0] == '!' && mname[1] != '\0')
- {
- ign_dir_add (mname+1);
- goto do_module_return;
- }
-
- /* strip extra stuff from the module name */
- strip_trailing_slashes (mname);
-
- /*
- * Look up the module using the following scheme:
- * 1) look for mname as a module name
- * 2) look for mname as a directory
- * 3) look for mname as a file
- * 4) take mname up to the first slash and look it up as a module name
- * (this is for checking out only part of a module)
- */
-
- /* look it up as a module name */
- key.dptr = mname;
- key.dsize = strlen (key.dptr);
- if (db != NULL)
- val = dbm_fetch (db, key);
- else
- val.dptr = NULL;
- if (val.dptr != NULL)
- {
- /* copy and null terminate the value */
- value = xmalloc (val.dsize + 1);
- memcpy (value, val.dptr, val.dsize);
- value[val.dsize] = '\0';
-
- /* If the line ends in a comment, strip it off */
- if ((cp = strchr (value, '#')) != NULL)
- *cp = '\0';
- else
- cp = value + val.dsize;
-
- /* Always strip trailing spaces */
- while (cp > value && isspace ((unsigned char) *--cp))
- *cp = '\0';
-
- mwhere = xstrdup (mname);
- goto found;
- }
- else
- {
- char *file;
- char *attic_file;
- char *acp;
- int is_found = 0;
-
- /* check to see if mname is a directory or file */
- file = xmalloc (strlen (current_parsed_root->directory)
- + strlen (mname) + sizeof(RCSEXT) + 2);
- (void) sprintf (file, "%s/%s", current_parsed_root->directory, mname);
- attic_file = xmalloc (strlen (current_parsed_root->directory)
- + strlen (mname)
- + sizeof (CVSATTIC) + sizeof (RCSEXT) + 3);
- if ((acp = strrchr (mname, '/')) != NULL)
- {
- *acp = '\0';
- (void) sprintf (attic_file, "%s/%s/%s/%s%s", current_parsed_root->directory,
- mname, CVSATTIC, acp + 1, RCSEXT);
- *acp = '/';
- }
- else
- (void) sprintf (attic_file, "%s/%s/%s%s",
- current_parsed_root->directory,
- CVSATTIC, mname, RCSEXT);
-
- if (isdir (file))
- {
- modargv = xmalloc (sizeof (*modargv));
- modargv[0] = xstrdup (mname);
- modargc = 1;
- is_found = 1;
- }
- else
- {
- (void) strcat (file, RCSEXT);
- if (isfile (file) || isfile (attic_file))
- {
- /* if mname was a file, we have to split it into "dir file" */
- if ((cp = strrchr (mname, '/')) != NULL && cp != mname)
- {
- 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
- {
- /*
- * the only '/' at the beginning or no '/' at all
- * means the file we are interested in is in CVSROOT
- * itself so the directory should be '.'
- */
- if (cp == mname)
- {
- /* drop the leading / if specified */
- modargv = xmalloc (2 * sizeof (*modargv));
- modargv[0] = xstrdup (".");
- modargv[1] = xstrdup (mname + 1);
- modargc = 2;
- }
- else
- {
- /* otherwise just copy it */
- modargv = xmalloc (2 * sizeof (*modargv));
- modargv[0] = xstrdup (".");
- modargv[1] = xstrdup (mname);
- modargc = 2;
- }
- }
- is_found = 1;
- }
- }
- free (attic_file);
- free (file);
-
- if (is_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 */
- if (mname[0] != '/' && (cp = strchr (mname, '/')) != NULL)
- {
- /* Make the slash the new end of the string temporarily */
- *cp = '\0';
- key.dptr = mname;
- key.dsize = strlen (key.dptr);
-
- /* do the lookup */
- if (db != NULL)
- val = dbm_fetch (db, key);
- else
- val.dptr = NULL;
-
- /* if we found it, clean up the value and life is good */
- if (val.dptr != NULL)
- {
- char *cp2;
-
- /* copy and null terminate the value */
- value = xmalloc (val.dsize + 1);
- memcpy (value, val.dptr, val.dsize);
- value[val.dsize] = '\0';
-
- /* If the line ends in a comment, strip it off */
- if ((cp2 = strchr (value, '#')) != NULL)
- *cp2 = '\0';
- else
- cp2 = value + val.dsize;
-
- /* Always strip trailing spaces */
- while (cp2 > value && isspace ((unsigned char) *--cp2))
- *cp2 = '\0';
-
- /* mwhere gets just the module name */
- mwhere = xstrdup (mname);
- mfile = cp + 1;
- assert (strlen (mfile));
-
- /* put the / back in mname */
- *cp = '/';
-
- goto found;
- }
-
- /* put the / back in mname */
- *cp = '/';
- }
-
- /* if we got here, we couldn't find it using our search, so give up */
- error (0, 0, "cannot find module `%s' - ignored", mname);
- err++;
- goto do_module_return;
-
-
- /*
- * At this point, we found what we were looking for in one
- * of the many different forms.
- */
- found:
-
- /* remember where we start */
- if (save_cwd (&cwd))
- error_exit ();
- cwd_saved = 1;
-
- assert (value != NULL);
-
- /* search the value for the special delimiter and save for later */
- if ((cp = strchr (value, CVSMODULE_SPEC)) != NULL)
- {
- *cp = '\0'; /* null out the special char */
- spec_opt = cp + 1; /* save the options for later */
-
- /* strip whitespace if necessary */
- while (cp > value && isspace ((unsigned char) *--cp))
- *cp = '\0';
- }
-
- /* don't do special options only part of a module was specified */
- if (mfile != NULL)
- spec_opt = NULL;
-
- /*
- * value now contains one of the following:
- * 1) dir
- * 2) dir file
- * 3) the value from modules without any special args
- * [ args ] dir [file] [file] ...
- * or -a module [ module ] ...
- */
-
- /* Put the value on a line with XXX prepended for getopt to eat */
- line = xmalloc (strlen (value) + 5);
- strcpy(line, "XXX ");
- strcpy(line + 4, value);
-
- /* turn the line into an argv[] array */
- line2argv (&xmodargc, &xmodargv, line, " \t");
- free (line);
- modargc = xmodargc;
- modargv = xmodargv;
-
- /* parse the args */
- optind = 0;
- while ((c = getopt (modargc, modargv, CVSMODULE_OPTS)) != -1)
- {
- switch (c)
- {
- case 'a':
- alias = 1;
- break;
- case 'd':
- if (mwhere)
- free (mwhere);
- mwhere = xstrdup (optarg);
- nonalias_opt = 1;
- break;
- case 'l':
- local_specified = 1;
- nonalias_opt = 1;
- break;
- case 'o':
- if (checkout_prog)
- free (checkout_prog);
- checkout_prog = xstrdup (optarg);
- nonalias_opt = 1;
- break;
- case 'e':
- if (export_prog)
- free (export_prog);
- export_prog = xstrdup (optarg);
- nonalias_opt = 1;
- break;
- case 't':
- if (tag_prog)
- free (tag_prog);
- tag_prog = xstrdup (optarg);
- nonalias_opt = 1;
- break;
- case '?':
- error (0, 0,
- "modules file has invalid option for key %s value %s",
- key.dptr, value);
- err++;
- goto do_module_return;
- }
- }
- modargc -= optind;
- modargv += optind;
- if (modargc == 0 && spec_opt == NULL)
- {
- error (0, 0, "modules file missing directory for module %s", mname);
- ++err;
- goto do_module_return;
- }
-
- if (alias && nonalias_opt)
- {
- /* The documentation has never said it is legal to specify
- -a along with another option. And I believe that in the past
- CVS has ignored the options other than -a, more or less, in this
- situation. */
- error (0, 0, "\
--a cannot be specified in the modules file along with other options");
- ++err;
- goto do_module_return;
- }
-
- /* if this was an alias, call ourselves recursively for each module */
- if (alias)
- {
- int i;
-
- for (i = 0; i < modargc; i++)
- {
- /*
- * Recursion check: if an alias module calls itself or a module
- * which causes the first to be called again, print an error
- * message and stop recursing.
- *
- * Algorithm:
- *
- * 1. Check that MNAME isn't in the stack.
- * 2. Push MNAME onto the stack.
- * 3. Call do_module().
- * 4. Pop MNAME from the stack.
- */
- if (stack && findnode (stack, mname))
- error (0, 0,
- "module `%s' in modules file contains infinite loop",
- mname);
- else
- {
- if (!stack) stack = getlist();
- push_string (stack, mname);
- err += my_module (db, modargv[i], m_type, msg, callback_proc,
- where, shorten, local_specified,
- run_module_prog, build_dirs, extra_arg,
- stack);
- pop_string (stack);
- if (isempty (stack)) dellist (&stack);
- }
- }
- goto do_module_return;
- }
-
- if (mfile != NULL && modargc > 1)
- {
- error (0, 0, "\
-module `%s' is a request for a file in a module which is not a directory",
- mname);
- ++err;
- goto do_module_return;
- }
-
- /* otherwise, process this module */
- if (modargc > 0)
- {
- err += callback_proc (modargc, modargv, where, mwhere, mfile, shorten,
- local_specified, mname, msg);
- }
- else
- {
- /*
- * we had nothing but special options, so we must
- * make the appropriate directory and cd to it
- */
- char *dir;
-
- if (!build_dirs)
- goto do_special;
-
- dir = where ? where : (mwhere ? mwhere : mname);
- /* XXX - think about making null repositories at each dir here
- instead of just at the bottom */
- make_directories (dir);
- if (CVS_CHDIR (dir) < 0)
- {
- error (0, errno, "cannot chdir to %s", dir);
- spec_opt = NULL;
- err++;
- goto do_special;
- }
- if (!isfile (CVSADM))
- {
- char *nullrepos;
-
- nullrepos = emptydir_name ();
-
- Create_Admin (".", dir,
- nullrepos, (char *) NULL, (char *) NULL, 0, 0, 1);
- if (!noexec)
- {
- FILE *fp;
-
- fp = open_file (CVSADM_ENTSTAT, "w+");
- if (fclose (fp) == EOF)
- error (1, errno, "cannot close %s", CVSADM_ENTSTAT);
-#ifdef SERVER_SUPPORT
- if (server_active)
- server_set_entstat (dir, nullrepos);
-#endif
- }
- free (nullrepos);
- }
- }
-
- /* if there were special include args, process them now */
-
- do_special:
-
- free_names (&xmodargc, xmodargv);
- xmodargv = NULL;
-
- /* blow off special options if -l was specified */
- if (local_specified)
- spec_opt = NULL;
-
-#ifdef SERVER_SUPPORT
- /* We want to check out into the directory named by the module.
- So we set a global variable which tells the server to glom that
- directory name onto the front. A cleaner approach would be some
- way of passing it down to the recursive call, through the
- callback_proc, to start_recursion, and then into the update_dir in
- the struct file_info. That way the "Updating foo" message could
- print the actual directory we are checking out into.
-
- For local CVS, this is handled by the chdir call above
- (directly or via the callback_proc). */
- if (server_active && spec_opt != NULL)
- {
- char *change_to;
-
- change_to = where ? where : (mwhere ? mwhere : mname);
- server_dir_to_restore = server_dir;
- restore_server_dir = 1;
- server_dir =
- xmalloc ((server_dir_to_restore != NULL
- ? strlen (server_dir_to_restore)
- : 0)
- + strlen (change_to)
- + 5);
- server_dir[0] = '\0';
- if (server_dir_to_restore != NULL)
- {
- strcat (server_dir, server_dir_to_restore);
- strcat (server_dir, "/");
- }
- strcat (server_dir, change_to);
- }
-#endif
-
- while (spec_opt != NULL)
- {
- char *next_opt;
-
- cp = strchr (spec_opt, CVSMODULE_SPEC);
- if (cp != NULL)
- {
- /* save the beginning of the next arg */
- next_opt = cp + 1;
-
- /* strip whitespace off the end */
- do
- *cp = '\0';
- while (cp > spec_opt && isspace ((unsigned char) *--cp));
- }
- else
- next_opt = NULL;
-
- /* strip whitespace from front */
- while (isspace ((unsigned char) *spec_opt))
- spec_opt++;
-
- if (*spec_opt == '\0')
- error (0, 0, "Mal-formed %c option for module %s - ignored",
- CVSMODULE_SPEC, mname);
- else
- err += my_module (db, spec_opt, m_type, msg, callback_proc,
- (char *) NULL, 0, local_specified,
- run_module_prog, build_dirs, extra_arg,
- stack);
- spec_opt = next_opt;
- }
-
-#ifdef SERVER_SUPPORT
- if (server_active && restore_server_dir)
- {
- free (server_dir);
- server_dir = server_dir_to_restore;
- }
-#endif
-
- /* cd back to where we started */
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- free_cwd (&cwd);
- cwd_saved = 0;
-
- /* run checkout or tag prog if appropriate */
- if (err == 0 && run_module_prog)
- {
- if ((m_type == TAG && tag_prog != NULL) ||
- (m_type == CHECKOUT && checkout_prog != NULL) ||
- (m_type == EXPORT && export_prog != NULL))
- {
- /*
- * If a relative pathname is specified as the checkout, tag
- * or export proc, try to tack on the current "where" value.
- * if we can't find a matching program, just punt and use
- * whatever is specified in the modules file.
- */
- char *real_prog = NULL;
- char *prog = (m_type == TAG ? tag_prog :
- (m_type == CHECKOUT ? checkout_prog : export_prog));
- char *real_where = (where != NULL ? where : mwhere);
- char *expanded_path;
-
- if ((*prog != '/') && (*prog != '.'))
- {
- real_prog = xmalloc (strlen (real_where) + strlen (prog)
- + 10);
- (void) sprintf (real_prog, "%s/%s", real_where, prog);
- if (isfile (real_prog))
- prog = real_prog;
- }
-
- /* XXX can we determine the line number for this entry??? */
- expanded_path = expand_path (prog, "modules", 0);
- if (expanded_path != NULL)
- {
- run_setup (expanded_path);
- run_arg (real_where);
-
- if (extra_arg)
- run_arg (extra_arg);
-
- if (!quiet)
- {
- cvs_output (program_name, 0);
- cvs_output (" ", 1);
- cvs_output (cvs_cmd_name, 0);
- cvs_output (": Executing '", 0);
- run_print (stdout);
- cvs_output ("'\n", 0);
- cvs_flushout ();
- }
- err += run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
- free (expanded_path);
- }
- if (real_prog) free (real_prog);
- }
- }
-
- do_module_return:
- /* clean up */
- if (xmodargv != NULL)
- free_names (&xmodargc, xmodargv);
- if (mwhere)
- free (mwhere);
- if (checkout_prog)
- free (checkout_prog);
- if (export_prog)
- free (export_prog);
- if (tag_prog)
- free (tag_prog);
- if (cwd_saved)
- free_cwd (&cwd);
- if (value != NULL)
- free (value);
-
- return (err);
-}
-
-
-
-/* External face of do_module so that we can have an internal version which
- * accepts a stack argument to track alias recursion.
- */
-int
-do_module (db, mname, m_type, msg, callback_proc, where, shorten,
- local_specified, run_module_prog, build_dirs, extra_arg)
- DBM *db;
- char *mname;
- enum mtype m_type;
- char *msg;
- CALLBACKPROC callback_proc;
- char *where;
- int shorten;
- int local_specified;
- int run_module_prog;
- int build_dirs;
- char *extra_arg;
-{
- return my_module (db, mname, m_type, msg, callback_proc, where, shorten,
- local_specified, run_module_prog, build_dirs, extra_arg,
- NULL);
-}
-
-
-
-/* - Read all the records from the modules database into an array.
- - Sort the array depending on what format is desired.
- - Print the array in the format desired.
-
- Currently, there are only two "desires":
-
- 1. Sort by module name and format the whole entry including switches,
- files and the comment field: (Including aliases)
-
- modulename -s switches, one per line, even if
- it has many switches.
- Directories and files involved, formatted
- to cover multiple lines if necessary.
- # Comment, also formatted to cover multiple
- # lines if necessary.
-
- 2. Sort by status field string and print: (*not* including aliases)
-
- modulename STATUS Directories and files involved, formatted
- to cover multiple lines if necessary.
- # Comment, also formatted to cover multiple
- # lines if necessary.
-*/
-
-static struct sortrec *s_head;
-
-static int s_max = 0; /* Number of elements allocated */
-static int s_count = 0; /* Number of elements used */
-
-static int Status; /* Nonzero if the user is
- interested in status
- information as well as
- module name */
-static char def_status[] = "NONE";
-
-/* Sort routine for qsort:
- - If we want the "Status" field to be sorted, check it first.
- - Then compare the "module name" fields. Since they are unique, we don't
- have to look further.
-*/
-static int
-sort_order (l, r)
- const PTR l;
- const PTR r;
-{
- int i;
- const struct sortrec *left = (const struct sortrec *) l;
- const struct sortrec *right = (const struct sortrec *) r;
-
- if (Status)
- {
- /* If Sort by status field, compare them. */
- if ((i = strcmp (left->status, right->status)) != 0)
- return (i);
- }
- return (strcmp (left->modname, right->modname));
-}
-
-static void
-save_d (k, ks, d, ds)
- char *k;
- int ks;
- char *d;
- int ds;
-{
- char *cp, *cp2;
- struct sortrec *s_rec;
-
- if (Status && *d == '-' && *(d + 1) == 'a')
- return; /* We want "cvs co -s" and it is an alias! */
-
- if (s_count == s_max)
- {
- s_max += 64;
- s_head = (struct sortrec *) xrealloc ((char *) s_head, s_max * sizeof (*s_head));
- }
- s_rec = &s_head[s_count];
- s_rec->modname = cp = xmalloc (ks + 1);
- (void) strncpy (cp, k, ks);
- *(cp + ks) = '\0';
-
- s_rec->rest = cp2 = xmalloc (ds + 1);
- cp = d;
- *(cp + ds) = '\0'; /* Assumes an extra byte at end of static dbm buffer */
-
- while (isspace ((unsigned char) *cp))
- cp++;
- /* Turn <spaces> into one ' ' -- makes the rest of this routine simpler */
- while (*cp)
- {
- if (isspace ((unsigned char) *cp))
- {
- *cp2++ = ' ';
- while (isspace ((unsigned char) *cp))
- cp++;
- }
- else
- *cp2++ = *cp++;
- }
- *cp2 = '\0';
-
- /* Look for the "-s statusvalue" text */
- if (Status)
- {
- s_rec->status = def_status;
-
- for (cp = s_rec->rest; (cp2 = strchr (cp, '-')) != NULL; cp = ++cp2)
- {
- if (*(cp2 + 1) == 's' && *(cp2 + 2) == ' ')
- {
- char *status_start;
-
- cp2 += 3;
- status_start = cp2;
- while (*cp2 != ' ' && *cp2 != '\0')
- cp2++;
- s_rec->status = xmalloc (cp2 - status_start + 1);
- strncpy (s_rec->status, status_start, cp2 - status_start);
- s_rec->status[cp2 - status_start] = '\0';
- cp = cp2;
- break;
- }
- }
- }
- else
- cp = s_rec->rest;
-
- /* Find comment field, clean up on all three sides & compress blanks */
- if ((cp2 = cp = strchr (cp, '#')) != NULL)
- {
- if (*--cp2 == ' ')
- *cp2 = '\0';
- if (*++cp == ' ')
- cp++;
- s_rec->comment = cp;
- }
- else
- s_rec->comment = "";
-
- s_count++;
-}
-
-/* Print out the module database as we know it. If STATUS is
- non-zero, print out status information for each module. */
-
-void
-cat_module (status)
- int status;
-{
- DBM *db;
- datum key, val;
- int i, c, wid, argc, cols = 80, indent, fill;
- int moduleargc;
- struct sortrec *s_h;
- char *cp, *cp2, **argv;
- char **moduleargv;
-
- Status = status;
-
- /* Read the whole modules file into allocated records */
- if (!(db = open_module ()))
- error (1, 0, "failed to open the modules file");
-
- for (key = dbm_firstkey (db); key.dptr != NULL; key = dbm_nextkey (db))
- {
- val = dbm_fetch (db, key);
- if (val.dptr != NULL)
- save_d (key.dptr, key.dsize, val.dptr, val.dsize);
- }
-
- close_module (db);
-
- /* Sort the list as requested */
- qsort ((PTR) s_head, s_count, sizeof (struct sortrec), sort_order);
-
- /*
- * Run through the sorted array and format the entries
- * indent = space for modulename + space for status field
- */
- indent = 12 + (status * 12);
- fill = cols - (indent + 2);
- for (s_h = s_head, i = 0; i < s_count; i++, s_h++)
- {
- char *line;
-
- /* Print module name (and status, if wanted) */
- line = xmalloc (strlen (s_h->modname) + 15);
- sprintf (line, "%-12s", s_h->modname);
- cvs_output (line, 0);
- free (line);
- if (status)
- {
- line = xmalloc (strlen (s_h->status) + 15);
- sprintf (line, " %-11s", s_h->status);
- cvs_output (line, 0);
- free (line);
- }
-
- line = xmalloc (strlen (s_h->modname) + strlen (s_h->rest) + 15);
- /* Parse module file entry as command line and print options */
- (void) sprintf (line, "%s %s", s_h->modname, s_h->rest);
- line2argv (&moduleargc, &moduleargv, line, " \t");
- free (line);
- argc = moduleargc;
- argv = moduleargv;
-
- optind = 0;
- wid = 0;
- while ((c = getopt (argc, argv, CVSMODULE_OPTS)) != -1)
- {
- if (!status)
- {
- if (c == 'a' || c == 'l')
- {
- char buf[5];
-
- sprintf (buf, " -%c", c);
- cvs_output (buf, 0);
- wid += 3; /* Could just set it to 3 */
- }
- else
- {
- char buf[10];
-
- if (strlen (optarg) + 4 + wid > (unsigned) fill)
- {
- int j;
-
- cvs_output ("\n", 1);
- for (j = 0; j < indent; ++j)
- cvs_output (" ", 1);
- wid = 0;
- }
- sprintf (buf, " -%c ", c);
- cvs_output (buf, 0);
- cvs_output (optarg, 0);
- wid += strlen (optarg) + 4;
- }
- }
- }
- argc -= optind;
- argv += optind;
-
- /* Format and Print all the files and directories */
- for (; argc--; argv++)
- {
- if (strlen (*argv) + wid > (unsigned) fill)
- {
- int j;
-
- cvs_output ("\n", 1);
- for (j = 0; j < indent; ++j)
- cvs_output (" ", 1);
- wid = 0;
- }
- cvs_output (" ", 1);
- cvs_output (*argv, 0);
- wid += strlen (*argv) + 1;
- }
- cvs_output ("\n", 1);
-
- /* Format the comment field -- save_d (), compressed spaces */
- for (cp2 = cp = s_h->comment; *cp; cp2 = cp)
- {
- int j;
-
- for (j = 0; j < indent; ++j)
- cvs_output (" ", 1);
- cvs_output (" # ", 0);
- if (strlen (cp2) < (unsigned) (fill - 2))
- {
- cvs_output (cp2, 0);
- cvs_output ("\n", 1);
- break;
- }
- cp += fill - 2;
- while (*cp != ' ' && cp > cp2)
- cp--;
- if (cp == cp2)
- {
- cvs_output (cp2, 0);
- cvs_output ("\n", 1);
- break;
- }
-
- *cp++ = '\0';
- cvs_output (cp2, 0);
- cvs_output ("\n", 1);
- }
-
- free_names(&moduleargc, moduleargv);
- /* FIXME-leak: here is where we would free s_h->modname, s_h->rest,
- and if applicable, s_h->status. Not exactly a memory leak,
- in the sense that we are about to exit(), but may be worth
- noting if we ever do a multithreaded server or something of
- the sort. */
- }
- /* FIXME-leak: as above, here is where we would free s_head. */
-}
diff --git a/contrib/cvs/src/myndbm.c b/contrib/cvs/src/myndbm.c
deleted file mode 100644
index cb99cc27eb9e..000000000000
--- a/contrib/cvs/src/myndbm.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * A simple ndbm-emulator for CVS. It parses a text file of the format:
- *
- * key value
- *
- * at dbm_open time, and loads the entire file into memory. As such, it is
- * probably only good for fairly small modules files. Ours is about 30K in
- * size, and this code works fine.
- */
-
-#include <assert.h>
-#include "cvs.h"
-#include "getline.h"
-
-#ifdef MY_NDBM
-# ifndef O_ACCMODE
-# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
-# endif /* defined O_ACCMODE */
-
-static void mydbm_load_file PROTO ((FILE *, List *, char *));
-
-/* Returns NULL on error in which case errno has been set to indicate
- the error. Can also call error() itself. */
-/* ARGSUSED */
-DBM *
-mydbm_open (file, flags, mode)
- char *file;
- int flags;
- int mode;
-{
- FILE *fp;
- DBM *db;
-
- fp = CVS_FOPEN (file, (flags & O_ACCMODE) != O_RDONLY ?
- FOPEN_BINARY_READWRITE : FOPEN_BINARY_READ);
- if (fp == NULL && !(existence_error (errno) && (flags & O_CREAT)))
- return ((DBM *) 0);
-
- db = (DBM *) xmalloc (sizeof (*db));
- db->dbm_list = getlist ();
- db->modified = 0;
- db->name = xstrdup (file);
-
- if (fp != NULL)
- {
- mydbm_load_file (fp, db->dbm_list, file);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", file);
- }
- return (db);
-}
-
-static int write_item PROTO ((Node *, void *));
-
-static int
-write_item (node, data)
- Node *node;
- void *data;
-{
- FILE *fp = (FILE *)data;
- fputs (node->key, fp);
- fputs (" ", fp);
- fputs (node->data, fp);
- fputs ("\012", fp);
- return 0;
-}
-
-void
-mydbm_close (db)
- DBM *db;
-{
- if (db->modified)
- {
- FILE *fp;
- fp = CVS_FOPEN (db->name, FOPEN_BINARY_WRITE);
- if (fp == NULL)
- error (1, errno, "cannot write %s", db->name);
- walklist (db->dbm_list, write_item, (void *)fp);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", db->name);
- }
- free (db->name);
- dellist (&db->dbm_list);
- free ((char *) db);
-}
-
-datum
-mydbm_fetch (db, key)
- DBM *db;
- datum key;
-{
- Node *p;
- char *s;
- datum val;
-
- /* make sure it's null-terminated */
- s = xmalloc (key.dsize + 1);
- (void) strncpy (s, key.dptr, key.dsize);
- s[key.dsize] = '\0';
-
- p = findnode (db->dbm_list, s);
- if (p)
- {
- val.dptr = p->data;
- val.dsize = strlen (p->data);
- }
- else
- {
- val.dptr = (char *) NULL;
- val.dsize = 0;
- }
- free (s);
- return (val);
-}
-
-datum
-mydbm_firstkey (db)
- DBM *db;
-{
- Node *head, *p;
- datum key;
-
- head = db->dbm_list->list;
- p = head->next;
- if (p != head)
- {
- key.dptr = p->key;
- key.dsize = strlen (p->key);
- }
- else
- {
- key.dptr = (char *) NULL;
- key.dsize = 0;
- }
- db->dbm_next = p->next;
- return (key);
-}
-
-datum
-mydbm_nextkey (db)
- DBM *db;
-{
- Node *head, *p;
- datum key;
-
- head = db->dbm_list->list;
- p = db->dbm_next;
- if (p != head)
- {
- key.dptr = p->key;
- key.dsize = strlen (p->key);
- }
- else
- {
- key.dptr = (char *) NULL;
- key.dsize = 0;
- }
- db->dbm_next = p->next;
- return (key);
-}
-
-/* Note: only updates the in-memory copy, which is written out at
- mydbm_close time. Note: Also differs from DBM in that on duplication,
- it gives a warning, rather than either DBM_INSERT or DBM_REPLACE
- behavior. */
-int
-mydbm_store (db, key, value, flags)
- DBM *db;
- datum key;
- datum value;
- int flags;
-{
- Node *node;
-
- node = getnode ();
- node->type = NDBMNODE;
-
- node->key = xmalloc (key.dsize + 1);
- *node->key = '\0';
- strncat (node->key, key.dptr, key.dsize);
-
- node->data = xmalloc (value.dsize + 1);
- *(char *)node->data = '\0';
- strncat (node->data, value.dptr, value.dsize);
-
- db->modified = 1;
- if (addnode (db->dbm_list, node) == -1)
- {
- error (0, 0, "attempt to insert duplicate key `%s'", node->key);
- freenode (node);
- return 0;
- }
- return 0;
-}
-
-static void
-mydbm_load_file (fp, list, filename)
- FILE *fp;
- List *list;
- char *filename; /* Used in error messages. */
-{
- char *line = NULL;
- size_t line_size;
- char *value;
- size_t value_allocated;
- char *cp, *vp;
- int cont;
- int line_length;
- int line_num;
-
- value_allocated = 1;
- value = xmalloc (value_allocated);
-
- cont = 0;
- line_num=0;
- while ((line_length =
- getstr (&line, &line_size, fp, '\012', 0, GETLINE_NO_LIMIT)) >= 0)
- {
- line_num++;
- if (line_length > 0 && line[line_length - 1] == '\012')
- {
- /* Strip the newline. */
- --line_length;
- line[line_length] = '\0';
- }
- if (line_length > 0 && line[line_length - 1] == '\015')
- {
- /* If the file (e.g. modules) was written on an NT box, it will
- contain CRLF at the ends of lines. Strip them (we can't do
- this by opening the file in text mode because we might be
- running on unix). */
- --line_length;
- line[line_length] = '\0';
- }
-
- /*
- * Add the line to the value, at the end if this is a continuation
- * line; otherwise at the beginning, but only after any trailing
- * backslash is removed.
- */
- if (!cont)
- value[0] = '\0';
-
- /*
- * See if the line we read is a continuation line, and strip the
- * backslash if so.
- */
- if (line_length > 0)
- cp = &line[line_length - 1];
- else
- cp = line;
- if (*cp == '\\')
- {
- cont = 1;
- *cp = '\0';
- --line_length;
- }
- else
- {
- cont = 0;
- }
- expand_string (&value,
- &value_allocated,
- strlen (value) + line_length + 5);
- strcat (value, line);
-
- if (value[0] == '#')
- continue; /* comment line */
- vp = value;
- while (*vp && isspace ((unsigned char) *vp))
- vp++;
- if (*vp == '\0')
- continue; /* empty line */
-
- /*
- * If this was not a continuation line, add the entry to the database
- */
- if (!cont)
- {
- Node *p = getnode ();
- char *kp;
-
- kp = vp;
- while (*vp && !isspace ((unsigned char) *vp))
- vp++;
- if (*vp)
- *vp++ = '\0'; /* NULL terminate the key */
- p->type = NDBMNODE;
- p->key = xstrdup (kp);
- while (*vp && isspace ((unsigned char) *vp))
- vp++; /* skip whitespace to value */
- if (*vp == '\0')
- {
- if (!really_quiet)
- error (0, 0,
- "warning: NULL value for key `%s' at line %d of `%s'",
- p->key, line_num, filename);
- freenode (p);
- continue;
- }
- p->data = xstrdup (vp);
- if (addnode (list, p) == -1)
- {
- if (!really_quiet)
- error (0, 0,
- "duplicate key found for `%s' at line %d of `%s'",
- p->key, line_num, filename);
- freenode (p);
- }
- }
- }
- if (line_length < 0 && !feof (fp))
- /* FIXME: should give the name of the file. */
- error (0, errno, "cannot read file in mydbm_load_file");
-
- free (line);
- free (value);
-}
-
-#endif /* MY_NDBM */
diff --git a/contrib/cvs/src/myndbm.h b/contrib/cvs/src/myndbm.h
deleted file mode 100644
index de23519944d7..000000000000
--- a/contrib/cvs/src/myndbm.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 1994-2005 The Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifdef MY_NDBM
-
-#define DBLKSIZ 4096
-
-typedef struct
-{
- List *dbm_list; /* cached database */
- Node *dbm_next; /* next key to return for nextkey() */
-
- /* Name of the file to write to if modified is set. malloc'd. */
- char *name;
-
- /* Nonzero if the database has been modified and dbm_close needs to
- write it out to disk. */
- int modified;
-} DBM;
-
-typedef struct
-{
- char *dptr;
- int dsize;
-} datum;
-
-/*
- * So as not to conflict with other dbm_open, etc., routines that may
- * be included by someone's libc, all of my emulation routines are prefixed
- * by "my" and we define the "standard" ones to be "my" ones here.
- */
-#define dbm_open mydbm_open
-#define dbm_close mydbm_close
-#define dbm_fetch mydbm_fetch
-#define dbm_firstkey mydbm_firstkey
-#define dbm_nextkey mydbm_nextkey
-#define dbm_store mydbm_store
-#define DBM_INSERT 0
-#define DBM_REPLACE 1
-
-DBM *mydbm_open PROTO((char *file, int flags, int mode));
-void mydbm_close PROTO((DBM * db));
-datum mydbm_fetch PROTO((DBM * db, datum key));
-datum mydbm_firstkey PROTO((DBM * db));
-datum mydbm_nextkey PROTO((DBM * db));
-extern int mydbm_store PROTO ((DBM *, datum, datum, int));
-
-#endif /* MY_NDBM */
diff --git a/contrib/cvs/src/no_diff.c b/contrib/cvs/src/no_diff.c
deleted file mode 100644
index 45847a1abe27..000000000000
--- a/contrib/cvs/src/no_diff.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * No Difference
- *
- * The user file looks modified judging from its time stamp; however it needn't
- * be. No_Difference() finds out whether it is or not. If it is not, it
- * updates the administration.
- *
- * returns 0 if no differences are found and non-zero otherwise
- */
-
-#include "cvs.h"
-#include <assert.h>
-
-int
-No_Difference (finfo, vers)
- struct file_info *finfo;
- Vers_TS *vers;
-{
- Node *p;
- int ret;
- char *ts, *options;
- int retcode = 0;
- char *tocvsPath;
-
- /* If ts_user is "Is-modified", we can only conclude the files are
- different (since we don't have the file's contents). */
- if (vers->ts_user != NULL
- && strcmp (vers->ts_user, "Is-modified") == 0)
- return -1;
-
- if (!vers->srcfile || !vers->srcfile->path)
- return (-1); /* different since we couldn't tell */
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- /* If special files are in use, then any mismatch of file metadata
- information also means that the files should be considered different. */
- if (preserve_perms && special_file_mismatch (finfo, vers->vn_user, NULL))
- return 1;
-#endif
-
- if (vers->entdata && vers->entdata->options)
- options = xstrdup (vers->entdata->options);
- else
- options = xstrdup ("");
-
- tocvsPath = wrap_tocvs_process_file (finfo->file);
- retcode = RCS_cmp_file( vers->srcfile, vers->vn_user, (char **)NULL,
- (char *)NULL, options,
- tocvsPath == NULL ? finfo->file : tocvsPath );
- if (retcode == 0)
- {
- /* no difference was found, so fix the entries file */
- ts = time_stamp (finfo->file);
- Register (finfo->entries, finfo->file,
- vers->vn_user ? vers->vn_user : vers->vn_rcs, ts,
- options, vers->tag, vers->date, (char *) 0);
-#ifdef SERVER_SUPPORT
- if (server_active)
- {
- /* We need to update the entries line on the client side. */
- server_update_entries
- (finfo->file, finfo->update_dir, finfo->repository, SERVER_UPDATED);
- }
-#endif
- free (ts);
-
- /* update the entdata pointer in the vers_ts structure */
- p = findnode (finfo->entries, finfo->file);
- assert (p);
- vers->entdata = p->data;
-
- ret = 0;
- }
- else
- ret = 1; /* files were really different */
-
- if (tocvsPath)
- {
- /* Need to call unlink myself because the noexec variable
- * has been set to 1. */
- if (trace)
- (void) fprintf (stderr, "%s-> unlink (%s)\n",
- CLIENT_SERVER_STR, tocvsPath);
- if ( CVS_UNLINK (tocvsPath) < 0)
- error (0, errno, "could not remove %s", tocvsPath);
- }
-
- free (options);
- return (ret);
-}
diff --git a/contrib/cvs/src/parseinfo.c b/contrib/cvs/src/parseinfo.c
deleted file mode 100644
index bf1e095fdd10..000000000000
--- a/contrib/cvs/src/parseinfo.c
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- * Copyright (C) 1986-2008 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * $FreeBSD$
- */
-
-#include "cvs.h"
-#include "getline.h"
-#include <assert.h>
-#include "history.h"
-
-extern char *logHistory;
-
-/*
- * Parse the INFOFILE file for the specified REPOSITORY. Invoke CALLPROC for
- * the first line in the file that matches the REPOSITORY, or if ALL != 0, any
- * lines matching "ALL", or if no lines match, the last line matching
- * "DEFAULT".
- *
- * Return 0 for success, -1 if there was not an INFOFILE, and >0 for failure.
- */
-int
-Parse_Info (infofile, repository, callproc, all)
- const char *infofile;
- const char *repository;
- CALLPROC callproc;
- int all;
-{
- int err = 0;
- FILE *fp_info;
- char *infopath;
- char *line = NULL;
- size_t line_allocated = 0;
- char *default_value = NULL;
- int default_line = 0;
- char *expanded_value;
- int callback_done, line_number;
- char *cp, *exp, *value;
- const char *srepos;
- const char *regex_err;
-
- assert (repository);
-
- if (current_parsed_root == NULL)
- {
- /* XXX - should be error maybe? */
- error (0, 0, "CVSROOT variable not set");
- return (1);
- }
-
- /* find the info file and open it */
- infopath = xmalloc (strlen (current_parsed_root->directory)
- + strlen (infofile)
- + sizeof (CVSROOTADM)
- + 3);
- (void) sprintf (infopath, "%s/%s/%s", current_parsed_root->directory,
- CVSROOTADM, infofile);
- fp_info = CVS_FOPEN (infopath, "r");
- if (fp_info == NULL)
- {
- /* If no file, don't do anything special. */
- if (!existence_error (errno))
- error (0, errno, "cannot open %s", infopath);
- free (infopath);
- return 0;
- }
-
- /* strip off the CVSROOT if repository was absolute */
- srepos = Short_Repository (repository);
-
- if (trace)
- (void) fprintf (stderr, "%s-> Parse_Info (%s, %s, %s)\n",
-#ifdef SERVER_SUPPORT
- server_active ? "S" : " ",
-#else
- "",
-#endif
- infopath, srepos, all ? "ALL" : "not ALL");
-
- /* search the info file for lines that match */
- callback_done = line_number = 0;
- while (getline (&line, &line_allocated, fp_info) >= 0)
- {
- line_number++;
-
- /* skip lines starting with # */
- if (line[0] == '#')
- continue;
-
- /* skip whitespace at beginning of line */
- for (cp = line; *cp && isspace ((unsigned char) *cp); cp++)
- ;
-
- /* if *cp is null, the whole line was blank */
- if (*cp == '\0')
- continue;
-
- /* the regular expression is everything up to the first space */
- 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 ((unsigned char) *cp))
- cp++;
-
- /* no value to match with the regular expression is an error */
- if (*cp == '\0')
- {
- error (0, 0, "syntax error at line %d file %s; ignored",
- line_number, infofile);
- continue;
- }
- value = cp;
-
- /* strip the newline off the end of the value */
- if ((cp = strrchr (value, '\n')) != NULL)
- *cp = '\0';
-
- /*
- * At this point, exp points to the regular expression, and value
- * points to the value to call the callback routine with. Evaluate
- * the regular expression against srepos and callback with the value
- * if it matches.
- */
-
- /* save the default value so we have it later if we need it */
- if (strcmp (exp, "DEFAULT") == 0)
- {
- if (default_value != NULL)
- {
- error (0, 0, "Multiple `DEFAULT' lines (%d and %d) in %s file",
- default_line, line_number, infofile);
- free (default_value);
- }
- default_value = xstrdup(value);
- default_line = line_number;
- continue;
- }
-
- /*
- * For a regular expression of "ALL", do the callback always We may
- * execute lots of ALL callbacks in addition to *one* regular matching
- * callback or default
- */
- if (strcmp (exp, "ALL") == 0)
- {
- if (!all)
- error(0, 0, "Keyword `ALL' is ignored at line %d in %s file",
- line_number, infofile);
- else if ((expanded_value = expand_path (value, infofile,
- line_number)) != NULL)
- {
- err += callproc (repository, expanded_value);
- free (expanded_value);
- }
- else
- err++;
- continue;
- }
-
- if (callback_done)
- /* only first matching, plus "ALL"'s */
- continue;
-
- /* see if the repository matched this regular expression */
- if ((regex_err = re_comp (exp)) != NULL)
- {
- error (0, 0, "bad regular expression at line %d file %s: %s",
- line_number, infofile, regex_err);
- continue;
- }
- if (re_exec (srepos) == 0)
- continue; /* no match */
-
- /* it did, so do the callback and note that we did one */
- if ((expanded_value = expand_path (value, infofile, line_number)) != NULL)
- {
- err += callproc (repository, expanded_value);
- free (expanded_value);
- }
- else
- err++;
- callback_done = 1;
- }
- if (ferror (fp_info))
- error (0, errno, "cannot read %s", infopath);
- if (fclose (fp_info) < 0)
- error (0, errno, "cannot close %s", infopath);
-
- /* if we fell through and didn't callback at all, do the default */
- if (callback_done == 0 && default_value != NULL)
- {
- if ((expanded_value = expand_path (default_value, infofile, default_line)) != NULL)
- {
- err += callproc (repository, expanded_value);
- free (expanded_value);
- }
- else
- err++;
- }
-
- /* free up space if necessary */
- if (default_value != NULL)
- free (default_value);
- free (infopath);
- if (line != NULL)
- free (line);
-
- return (err);
-}
-
-
-/* Parse the CVS config file. The syntax right now is a bit ad hoc
- but tries to draw on the best or more common features of the other
- *info files and various unix (or non-unix) config file syntaxes.
- Lines starting with # are comments. Settings are lines of the form
- KEYWORD=VALUE. There is currently no way to have a multi-line
- VALUE (would be nice if there was, probably).
-
- CVSROOT is the $CVSROOT directory
- (current_parsed_root->directory might not be set yet, so this
- function takes the cvsroot as a function argument).
-
- Returns 0 for success, negative value for failure. Call
- error(0, ...) on errors in addition to the return value. */
-int
-parse_config (cvsroot)
- char *cvsroot;
-{
- char *infopath;
- FILE *fp_info;
- char *line = NULL;
- size_t line_allocated = 0;
- size_t len;
- char *p;
- /* FIXME-reentrancy: If we do a multi-threaded server, this would need
- to go to the per-connection data structures. */
- static int parsed = 0;
- int ignore_unknown_config_keys = 0;
-
- /* Authentication code and serve_root might both want to call us.
- Let this happen smoothly. */
- if (parsed)
- return 0;
- parsed = 1;
-
- infopath = xmalloc (strlen (cvsroot)
- + sizeof (CVSROOTADM_CONFIG)
- + sizeof (CVSROOTADM)
- + 10);
- if (infopath == NULL)
- {
- error (0, 0, "out of memory; cannot allocate infopath");
- goto error_return;
- }
-
- strcpy (infopath, cvsroot);
- strcat (infopath, "/");
- strcat (infopath, CVSROOTADM);
- strcat (infopath, "/");
- strcat (infopath, CVSROOTADM_CONFIG);
-
- fp_info = CVS_FOPEN (infopath, "r");
- if (fp_info == NULL)
- {
- /* If no file, don't do anything special. */
- if (!existence_error (errno))
- {
- /* Just a warning message; doesn't affect return
- value, currently at least. */
- error (0, errno, "cannot open %s", infopath);
- }
- goto set_defaults_and_return;
- }
-
- while (getline (&line, &line_allocated, fp_info) >= 0)
- {
- /* Skip comments. */
- if (line[0] == '#')
- continue;
-
- /* At least for the moment we don't skip whitespace at the start
- of the line. Too picky? Maybe. But being insufficiently
- picky leads to all sorts of confusion, and it is a lot easier
- to start out picky and relax it than the other way around.
-
- Is there any kind of written standard for the syntax of this
- sort of config file? Anywhere in POSIX for example (I guess
- makefiles are sort of close)? Red Hat Linux has a bunch of
- these too (with some GUI tools which edit them)...
-
- Along the same lines, we might want a table of keywords,
- with various types (boolean, string, &c), as a mechanism
- for making sure the syntax is consistent. Any good examples
- to follow there (Apache?)? */
-
- /* Strip the trailing newline. There will be one unless we
- read a partial line without a newline, and then got end of
- file (or error?). */
-
- len = strlen (line) - 1;
- if (line[len] == '\n')
- line[len] = '\0';
-
- /* Skip blank lines. */
- if (line[0] == '\0')
- continue;
-
- /* The first '=' separates keyword from value. */
- p = strchr (line, '=');
- if (p == NULL)
- {
- /* Probably should be printing line number. */
- error (0, 0, "syntax error in %s: line '%s' is missing '='",
- infopath, line);
- goto error_return;
- }
-
- *p++ = '\0';
-
- if (strcmp (line, "RCSBIN") == 0)
- {
- /* This option used to specify the directory for RCS
- executables. But since we don't run them any more,
- this is a noop. Silently ignore it so that a
- repository can work with either new or old CVS. */
- ;
- }
- else if (strcmp (line, "SystemAuth") == 0)
- {
- if (strcmp (p, "no") == 0)
-#ifdef AUTH_SERVER_SUPPORT
- system_auth = 0;
-#else
- /* Still parse the syntax but ignore the
- option. That way the same config file can
- be used for local and server. */
- ;
-#endif
- else if (strcmp (p, "yes") == 0)
-#ifdef AUTH_SERVER_SUPPORT
- system_auth = 1;
-#else
- ;
-#endif
- else
- {
- error (0, 0, "unrecognized value '%s' for SystemAuth", p);
- goto error_return;
- }
- }
- else if (strcmp (line, "tag") == 0) {
- RCS_setlocalid(p);
- }
- else if (strcmp (line, "umask") == 0) {
- cvsumask = (mode_t)(strtol(p, NULL, 8) & 0777);
- }
- else if (strcmp (line, "dlimit") == 0) {
-#ifdef BSD
-#include <sys/resource.h>
- struct rlimit rl;
-
- if (getrlimit(RLIMIT_DATA, &rl) != -1) {
- rl.rlim_cur = atoi(p);
- rl.rlim_cur *= 1024;
-
- (void) setrlimit(RLIMIT_DATA, &rl);
- }
-#endif /* BSD */
- }
- else if (strcmp (line, "PreservePermissions") == 0)
- {
- if (strcmp (p, "no") == 0)
- preserve_perms = 0;
- else if (strcmp (p, "yes") == 0)
- {
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- preserve_perms = 1;
-#else
- error (0, 0, "\
-warning: this CVS does not support PreservePermissions");
-#endif
- }
- else
- {
- error (0, 0, "unrecognized value '%s' for PreservePermissions",
- p);
- goto error_return;
- }
- }
- else if (strcmp (line, "TopLevelAdmin") == 0)
- {
- if (strcmp (p, "no") == 0)
- top_level_admin = 0;
- else if (strcmp (p, "yes") == 0)
- top_level_admin = 1;
- else
- {
- error (0, 0, "unrecognized value '%s' for TopLevelAdmin", p);
- 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 if (strcmp (line, "LogHistory") == 0)
- {
- if (strcmp (p, "all") != 0)
- {
- if (logHistory) free (logHistory);
- logHistory = xstrdup (p);
- }
- }
- else if (strcmp (line, "RereadLogAfterVerify") == 0)
- {
- if (strcmp (p, "no") == 0 || strcmp (p, "never") == 0)
- RereadLogAfterVerify = LOGMSG_REREAD_NEVER;
- else if (strcmp (p, "yes") == 0 || strcmp (p, "always") == 0)
- RereadLogAfterVerify = LOGMSG_REREAD_ALWAYS;
- else if (strcmp (p, "stat") == 0)
- RereadLogAfterVerify = LOGMSG_REREAD_STAT;
- }
- else if (strcmp(line, "LocalKeyword") == 0)
- {
- /* Recognize cvs-1.12-style keyword control rather than erroring out. */
- RCS_setlocalid(p);
- }
- else if (strcmp(line, "KeywordExpand") == 0)
- {
- /* Recognize cvs-1.12-style keyword control rather than erroring out. */
- RCS_setincexc(p);
- }
- else if (strcmp (line, "IgnoreUnknownConfigKeys") == 0)
- {
- if (strcmp (p, "no") == 0 || strcmp (p, "false") == 0
- || strcmp (p, "off") == 0 || strcmp (p, "0") == 0)
- ignore_unknown_config_keys = 0;
- else if (strcmp (p, "yes") == 0 || strcmp (p, "true") == 0
- || strcmp (p, "on") == 0 || strcmp (p, "1") == 0)
- ignore_unknown_config_keys = 1;
- else
- {
- error (0, 0, "%s: unrecognized value '%s' for '%s'",
- infopath, p, line);
- goto error_return;
- }
- }
- else if (ignore_unknown_config_keys)
- ;
- else
- {
- /* We may be dealing with a keyword which was added in a
- subsequent version of CVS. In that case it is a good idea
- to complain, as (1) the keyword might enable a behavior like
- alternate locking behavior, in which it is dangerous and hard
- to detect if some CVS's have it one way and others have it
- the other way, (2) in general, having us not do what the user
- had in mind when they put in the keyword violates the
- principle of least surprise. Note that one corollary is
- adding new keywords to your CVSROOT/config file is not
- particularly recommended unless you are planning on using
- the new features. */
- error (0, 0, "%s: unrecognized keyword '%s'",
- infopath, line);
- goto error_return;
- }
- }
- if (ferror (fp_info))
- {
- error (0, errno, "cannot read %s", infopath);
- goto error_return;
- }
- if (fclose (fp_info) < 0)
- {
- error (0, errno, "cannot close %s", infopath);
- goto error_return;
- }
-set_defaults_and_return:
- if (!logHistory)
- logHistory = xstrdup (ALL_HISTORY_REC_TYPES);
- free (infopath);
- if (line != NULL)
- free (line);
- return 0;
-
- error_return:
- if (!logHistory)
- logHistory = xstrdup (ALL_HISTORY_REC_TYPES);
- if (infopath != NULL)
- free (infopath);
- if (line != NULL)
- free (line);
- return -1;
-}
diff --git a/contrib/cvs/src/patch.c b/contrib/cvs/src/patch.c
deleted file mode 100644
index 65f5051ea7c6..000000000000
--- a/contrib/cvs/src/patch.c
+++ /dev/null
@@ -1,849 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Patch
- *
- * Create a Larry Wall format "patch" file between a previous release and the
- * current head of a module, or between two releases. Can specify the
- * release as either a date or a revision number.
- *
- * $FreeBSD$
- */
-
-#include <assert.h>
-#include "cvs.h"
-#include "getline.h"
-
-static RETSIGTYPE patch_cleanup PROTO((void));
-static Dtype patch_dirproc PROTO ((void *callerdat, const char *dir,
- const char *repos, const char *update_dir,
- List *entries));
-static int patch_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-static int patch_proc PROTO((int argc, char **argv, char *xwhere,
- char *mwhere, char *mfile, int shorten,
- int local_specified, char *mname, char *msg));
-
-static int force_tag_match = 1;
-static int patch_short = 0;
-static int toptwo_diffs = 0;
-static char *options = NULL;
-static char *rev1 = NULL;
-static int rev1_validated = 0;
-static char *rev2 = NULL;
-static int rev2_validated = 0;
-static char *date1 = NULL;
-static char *date2 = NULL;
-static char *tmpfile1 = NULL;
-static char *tmpfile2 = NULL;
-static char *tmpfile3 = NULL;
-static int unidiff = 0;
-
-static const char *const patch_usage[] =
-{
- "Usage: %s %s [-flR] [-c|-u] [-s|-t] [-V %%d] [-k kopt]\n",
- " -r rev|-D date [-r rev2 | -D date2] modules...\n",
- "\t-f\tForce a head revision match if tag/date not found.\n",
- "\t-l\tLocal directory only, not recursive\n",
- "\t-R\tProcess directories recursively.\n",
- "\t-c\tContext diffs (default)\n",
- "\t-u\tUnidiff format.\n",
- "\t-s\tShort patch - one liner per file.\n",
- "\t-t\tTop two diffs - last change made to the file.\n",
- "\t-V vers\tUse RCS Version \"vers\" for keyword expansion.\n",
- "\t-k kopt\tSpecify keyword expansion mode.\n",
- "\t-D date\tDate.\n",
- "\t-r rev\tRevision - symbolic or numeric.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-
-
-int
-patch (argc, argv)
- int argc;
- char **argv;
-{
- register int i;
- int local = 0;
- int c;
- int err = 0;
- DBM *db;
-
- if (argc == -1)
- usage (patch_usage);
-
- optind = 0;
- while ((c = getopt (argc, argv, "+V:k:cuftsQqlRD:r:")) != -1)
- {
- switch (c)
- {
- case 'Q':
- case 'q':
- /* The CVS 1.5 client sends these options (in addition to
- Global_option requests), so we must ignore them. */
- if (!server_active)
- error (1, 0,
- "-q or -Q must be specified before \"%s\"",
- cvs_cmd_name);
- break;
- case 'f':
- force_tag_match = 0;
- break;
- case 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case 't':
- toptwo_diffs = 1;
- break;
- case 's':
- patch_short = 1;
- break;
- case 'D':
- if (rev2 != NULL || date2 != NULL)
- error (1, 0,
- "no more than two revisions/dates can be specified");
- if (rev1 != NULL || date1 != NULL)
- date2 = Make_Date (optarg);
- else
- date1 = Make_Date (optarg);
- break;
- case 'r':
- if (rev2 != NULL || date2 != NULL)
- error (1, 0,
- "no more than two revisions/dates can be specified");
- if (rev1 != NULL || date1 != NULL)
- rev2 = optarg;
- else
- rev1 = optarg;
- break;
- case 'k':
- if (options)
- free (options);
- options = RCS_check_kflag (optarg);
- break;
- case 'V':
- /* This option is pretty seriously broken:
- 1. It is not clear what it does (does it change keyword
- expansion behavior? If so, how? Or does it have
- something to do with what version of RCS we are using?
- Or the format we write RCS files in?).
- 2. Because both it and -k use the options variable,
- specifying both -V and -k doesn't work.
- 3. At least as of CVS 1.9, it doesn't work (failed
- assertion in RCS_checkout where it asserts that options
- starts with -k). Few people seem to be complaining.
- In the future (perhaps the near future), I have in mind
- removing it entirely, and updating NEWS and cvs.texinfo,
- but in case it is a good idea to give people more time
- to complain if they would miss it, I'll just add this
- quick and dirty error message for now. */
- error (1, 0,
- "the -V option is obsolete and should not be used");
-#if 0
- if (atoi (optarg) <= 0)
- error (1, 0, "must specify a version number to -V");
- if (options)
- free (options);
- options = xmalloc (strlen (optarg) + 1 + 2); /* for the -V */
- (void) sprintf (options, "-V%s", optarg);
-#endif
- break;
- case 'u':
- unidiff = 1; /* Unidiff */
- break;
- case 'c': /* Context diff */
- unidiff = 0;
- break;
- case '?':
- default:
- usage (patch_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- /* Sanity checks */
- if (argc < 1)
- usage (patch_usage);
-
- if (toptwo_diffs && patch_short)
- error (1, 0, "-t and -s options are mutually exclusive");
- if (toptwo_diffs && (date1 != NULL || date2 != NULL ||
- rev1 != NULL || rev2 != NULL))
- error (1, 0, "must not specify revisions/dates with -t option!");
-
- if (!toptwo_diffs && (date1 == NULL && date2 == NULL &&
- rev1 == NULL && rev2 == NULL))
- error (1, 0, "must specify at least one revision/date!");
- if (date1 != NULL && date2 != NULL)
- if (RCS_datecmp (date1, date2) >= 0)
- error (1, 0, "second date must come after first date!");
-
- /* if options is NULL, make it a NULL string */
- if (options == NULL)
- options = xstrdup ("");
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- /* We're the client side. Fire up the remote server. */
- start_server ();
-
- ign_setup ();
-
- if (local)
- send_arg("-l");
- if (!force_tag_match)
- send_arg("-f");
- if (toptwo_diffs)
- send_arg("-t");
- if (patch_short)
- send_arg("-s");
- if (unidiff)
- send_arg("-u");
-
- if (rev1)
- option_with_arg ("-r", rev1);
- if (date1)
- client_senddate (date1);
- if (rev2)
- option_with_arg ("-r", rev2);
- if (date2)
- client_senddate (date2);
- if (options[0] != '\0')
- send_arg (options);
-
- {
- int i;
- for (i = 0; i < argc; ++i)
- send_arg (argv[i]);
- }
-
- send_to_server ("rdiff\012", 0);
- return get_responses_and_close ();
- }
-#endif
-
- /* clean up if we get a signal */
-#ifdef SIGABRT
- (void)SIG_register (SIGABRT, patch_cleanup);
-#endif
-#ifdef SIGHUP
- (void)SIG_register (SIGHUP, patch_cleanup);
-#endif
-#ifdef SIGINT
- (void)SIG_register (SIGINT, patch_cleanup);
-#endif
-#ifdef SIGQUIT
- (void)SIG_register (SIGQUIT, patch_cleanup);
-#endif
-#ifdef SIGPIPE
- (void)SIG_register (SIGPIPE, patch_cleanup);
-#endif
-#ifdef SIGTERM
- (void)SIG_register (SIGTERM, patch_cleanup);
-#endif
-
- db = open_module ();
- for (i = 0; i < argc; i++)
- err += do_module (db, argv[i], PATCH, "Patching", patch_proc,
- (char *)NULL, 0, local, 0, 0, (char *)NULL);
- close_module (db);
- free (options);
- patch_cleanup ();
- return err;
-}
-
-
-
-/*
- * callback proc for doing the real work of patching
- */
-/* ARGSUSED */
-static int
-patch_proc (argc, argv, xwhere, mwhere, mfile, shorten, local_specified,
- mname, msg)
- int argc;
- char **argv;
- char *xwhere;
- char *mwhere;
- char *mfile;
- int shorten;
- int local_specified;
- char *mname;
- char *msg;
-{
- char *myargv[2];
- int err = 0;
- int which;
- char *repository;
- char *where;
-
- repository = xmalloc (strlen (current_parsed_root->directory)
- + strlen (argv[0])
- + (mfile == NULL ? 0 : strlen (mfile) + 1) + 2);
- (void)sprintf (repository, "%s/%s",
- current_parsed_root->directory, argv[0]);
- where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile) + 1)
- + 1);
- (void)strcpy (where, argv[0]);
-
- /* if mfile isn't null, we need to set up to do only part of the module */
- if (mfile != NULL)
- {
- char *cp;
- char *path;
-
- /* if the portion of the module is a path, put the dir part on repos */
- if ((cp = strrchr (mfile, '/')) != NULL)
- {
- *cp = '\0';
- (void)strcat (repository, "/");
- (void)strcat (repository, mfile);
- (void)strcat (where, "/");
- (void)strcat (where, mfile);
- mfile = cp + 1;
- }
-
- /* take care of the rest */
- path = xmalloc (strlen (repository) + strlen (mfile) + 2);
- (void)sprintf (path, "%s/%s", repository, mfile);
- if (isdir (path))
- {
- /* directory means repository gets the dir tacked on */
- (void)strcpy (repository, path);
- (void)strcat (where, "/");
- (void)strcat (where, mfile);
- }
- else
- {
- myargv[0] = argv[0];
- myargv[1] = mfile;
- argc = 2;
- argv = myargv;
- }
- free (path);
- }
-
- /* cd to the starting repository */
- if ( CVS_CHDIR (repository) < 0)
- {
- error (0, errno, "cannot chdir to %s", repository);
- free (repository);
- free (where);
- return 1;
- }
-
- if (force_tag_match)
- which = W_REPOS | W_ATTIC;
- else
- which = W_REPOS;
-
- if (rev1 != NULL && !rev1_validated)
- {
- tag_check_valid (rev1, argc - 1, argv + 1, local_specified, 0,
- repository);
- rev1_validated = 1;
- }
- if (rev2 != NULL && !rev2_validated)
- {
- tag_check_valid (rev2, argc - 1, argv + 1, local_specified, 0,
- repository);
- rev2_validated = 1;
- }
-
- /* start the recursion processor */
- err = start_recursion (patch_fileproc, (FILESDONEPROC)NULL, patch_dirproc,
- (DIRLEAVEPROC)NULL, NULL,
- argc - 1, argv + 1, local_specified,
- which, 0, CVS_LOCK_READ, where, 1, repository);
- free (repository);
- free (where);
-
- return err;
-}
-
-
-
-/*
- * Called to examine a particular RCS file, as appropriate with the options
- * that were set above.
- */
-/* ARGSUSED */
-static int
-patch_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- struct utimbuf t;
- char *vers_tag, *vers_head;
- char *rcs = NULL;
- char *rcs_orig = NULL;
- RCSNode *rcsfile;
- FILE *fp1, *fp2, *fp3;
- int ret = 0;
- int isattic = 0;
- int retcode = 0;
- char *file1;
- char *file2;
- char *strippath;
- char *line1, *line2;
- size_t line1_chars_allocated;
- size_t line2_chars_allocated;
- char *cp1, *cp2;
- FILE *fp;
- int line_length;
- int dargc = 0;
- size_t darg_allocated = 0;
- char **dargv = NULL;
-
- line1 = NULL;
- line1_chars_allocated = 0;
- line2 = NULL;
- line2_chars_allocated = 0;
- vers_tag = vers_head = NULL;
-
- /* find the parsed rcs file */
- if ((rcsfile = finfo->rcs) == NULL)
- {
- ret = 1;
- goto out2;
- }
- if ((rcsfile->flags & VALID) && (rcsfile->flags & INATTIC))
- isattic = 1;
-
- rcs_orig = rcs = xmalloc (strlen (finfo->file) + sizeof (RCSEXT) + 5);
- (void) sprintf (rcs, "%s%s", finfo->file, RCSEXT);
-
- /* if vers_head is NULL, may have been removed from the release */
- if (isattic && rev2 == NULL && date2 == NULL)
- vers_head = NULL;
- else
- {
- vers_head = RCS_getversion (rcsfile, rev2, date2, force_tag_match,
- (int *) NULL);
- if (vers_head != NULL && RCS_isdead (rcsfile, vers_head))
- {
- free (vers_head);
- vers_head = NULL;
- }
- }
-
- if (toptwo_diffs)
- {
- if (vers_head == NULL)
- {
- ret = 1;
- goto out2;
- }
-
- if (!date1)
- date1 = xmalloc (MAXDATELEN);
- *date1 = '\0';
- if (RCS_getrevtime (rcsfile, vers_head, date1, 1) == (time_t)-1)
- {
- if (!really_quiet)
- error (0, 0, "cannot find date in rcs file %s revision %s",
- rcs, vers_head);
- ret = 1;
- goto out2;
- }
- }
- vers_tag = RCS_getversion (rcsfile, rev1, date1, force_tag_match,
- (int *) NULL);
- if (vers_tag != NULL && RCS_isdead (rcsfile, vers_tag))
- {
- free (vers_tag);
- vers_tag = NULL;
- }
-
- if ((vers_tag == NULL && vers_head == NULL) ||
- (vers_tag != NULL && vers_head != NULL &&
- strcmp (vers_head, vers_tag) == 0))
- {
- /* Nothing known about specified revs or
- * not changed between releases.
- */
- ret = 0;
- goto out2;
- }
-
- if( patch_short && ( vers_tag == NULL || vers_head == NULL ) )
- {
- /* For adds & removes with a short patch requested, we can print our
- * error message now and get out.
- */
- cvs_output ("File ", 0);
- cvs_output (finfo->fullname, 0);
- if (vers_tag == NULL)
- {
- cvs_output( " is new; ", 0 );
- cvs_output( rev2 ? rev2 : date2 ? date2 : "current", 0 );
- cvs_output( " revision ", 0 );
- cvs_output (vers_head, 0);
- cvs_output ("\n", 1);
- }
- else
- {
- cvs_output( " is removed; ", 0 );
- cvs_output( rev1 ? rev1 : date1, 0 );
- cvs_output( " revision ", 0 );
- cvs_output( vers_tag, 0 );
- cvs_output ("\n", 1);
- }
- ret = 0;
- goto out2;
- }
-
- /* Create 3 empty files. I'm not really sure there is any advantage
- * to doing so now rather than just waiting until later.
- *
- * There is - cvs_temp_file opens the file so that it can guarantee that
- * we have exclusive write access to the file. Unfortunately we spoil that
- * by closing it and reopening it again. Of course any better solution
- * requires that the RCS functions accept open file pointers rather than
- * simple file names.
- */
- if ((fp1 = cvs_temp_file (&tmpfile1)) == NULL)
- {
- error (0, errno, "cannot create temporary file %s",
- tmpfile1 ? tmpfile1 : "(null)");
- ret = 1;
- goto out;
- }
- else
- if (fclose (fp1) < 0)
- error (0, errno, "warning: cannot close %s", tmpfile1);
- if ((fp2 = cvs_temp_file (&tmpfile2)) == NULL)
- {
- error (0, errno, "cannot create temporary file %s",
- tmpfile2 ? tmpfile2 : "(null)");
- ret = 1;
- goto out;
- }
- else
- if (fclose (fp2) < 0)
- error (0, errno, "warning: cannot close %s", tmpfile2);
- if ((fp3 = cvs_temp_file (&tmpfile3)) == NULL)
- {
- error (0, errno, "cannot create temporary file %s",
- tmpfile3 ? tmpfile3 : "(null)");
- ret = 1;
- goto out;
- }
- else
- if (fclose (fp3) < 0)
- error (0, errno, "warning: cannot close %s", tmpfile3);
-
- if (vers_tag != NULL)
- {
- retcode = RCS_checkout (rcsfile, (char *)NULL, vers_tag,
- rev1, options, tmpfile1,
- (RCSCHECKOUTPROC)NULL, (void *)NULL);
- if (retcode != 0)
- {
- error (0, 0,
- "cannot check out revision %s of %s", vers_tag, rcs);
- ret = 1;
- goto out;
- }
- memset ((char *) &t, 0, sizeof (t));
- if ((t.actime = t.modtime = RCS_getrevtime (rcsfile, vers_tag,
- (char *) 0, 0)) != -1)
- /* I believe this timestamp only affects the dates in our diffs,
- and therefore should be on the server, not the client. */
- (void) utime (tmpfile1, &t);
- }
- else if (toptwo_diffs)
- {
- ret = 1;
- goto out;
- }
- if (vers_head != NULL)
- {
- retcode = RCS_checkout (rcsfile, (char *)NULL, vers_head,
- rev2, options, tmpfile2,
- (RCSCHECKOUTPROC)NULL, (void *)NULL);
- if (retcode != 0)
- {
- error (0, 0,
- "cannot check out revision %s of %s", vers_head, rcs);
- ret = 1;
- goto out;
- }
- if ((t.actime = t.modtime = RCS_getrevtime (rcsfile, vers_head,
- (char *)0, 0)) != -1)
- /* I believe this timestamp only affects the dates in our diffs,
- and therefore should be on the server, not the client. */
- (void)utime (tmpfile2, &t);
- }
-
- if (unidiff) run_add_arg_p (&dargc, &darg_allocated, &dargv, "-u");
- else run_add_arg_p (&dargc, &darg_allocated, &dargv, "-c");
- switch (diff_exec (tmpfile1, tmpfile2, NULL, NULL, dargc, dargv,
- tmpfile3))
- {
- case -1: /* fork/wait failure */
- error (1, errno, "fork for diff failed on %s", rcs);
- break;
- case 0: /* nothing to do */
- break;
- case 1:
- /*
- * The two revisions are really different, so read the first two
- * lines of the diff output file, and munge them to include more
- * reasonable file names that "patch" will understand, unless the
- * user wanted a short patch. In that case, just output the short
- * message.
- */
- if( patch_short )
- {
- cvs_output ("File ", 0);
- cvs_output (finfo->fullname, 0);
- cvs_output (" changed from revision ", 0);
- cvs_output (vers_tag, 0);
- cvs_output (" to ", 0);
- cvs_output (vers_head, 0);
- cvs_output ("\n", 1);
- ret = 0;
- goto out;
- }
-
- /* Output an "Index:" line for patch to use */
- cvs_output ("Index: ", 0);
- cvs_output (finfo->fullname, 0);
- cvs_output ("\n", 1);
-
- /* Now the munging. */
- fp = open_file (tmpfile3, "r");
- if (getline (&line1, &line1_chars_allocated, fp) < 0 ||
- getline (&line2, &line2_chars_allocated, fp) < 0)
- {
- if (feof (fp))
- error (0, 0, "\
-failed to read diff file header %s for %s: end of file", tmpfile3, rcs);
- else
- error (0, errno,
- "failed to read diff file header %s for %s",
- tmpfile3, rcs);
- ret = 1;
- if (fclose (fp) < 0)
- error (0, errno, "error closing %s", tmpfile3);
- goto out;
- }
- if (!unidiff)
- {
- if (strncmp (line1, "*** ", 4) != 0 ||
- strncmp (line2, "--- ", 4) != 0 ||
- (cp1 = strchr (line1, '\t')) == NULL ||
- (cp2 = strchr (line2, '\t')) == NULL)
- {
- error (0, 0, "invalid diff header for %s", rcs);
- ret = 1;
- if (fclose (fp) < 0)
- error (0, errno, "error closing %s", tmpfile3);
- goto out;
- }
- }
- else
- {
- if (strncmp (line1, "--- ", 4) != 0 ||
- strncmp (line2, "+++ ", 4) != 0 ||
- (cp1 = strchr (line1, '\t')) == NULL ||
- (cp2 = strchr (line2, '\t')) == NULL)
- {
- error (0, 0, "invalid unidiff header for %s", rcs);
- ret = 1;
- if (fclose (fp) < 0)
- error (0, errno, "error closing %s", tmpfile3);
- goto out;
- }
- }
- assert (current_parsed_root != NULL);
- assert (current_parsed_root->directory != NULL);
- {
- strippath = xmalloc (strlen (current_parsed_root->directory)
- + 2);
- (void)sprintf (strippath, "%s/",
- current_parsed_root->directory);
- }
- /*else
- strippath = xstrdup (REPOS_STRIP); */
- if (strncmp (rcs, strippath, strlen (strippath)) == 0)
- rcs += strlen (strippath);
- free (strippath);
- if (vers_tag != NULL)
- {
- file1 = xmalloc (strlen (finfo->fullname)
- + strlen (vers_tag)
- + 10);
- (void)sprintf (file1, "%s:%s", finfo->fullname, vers_tag);
- }
- else
- {
- file1 = xstrdup (DEVNULL);
- }
- file2 = xmalloc (strlen (finfo->fullname)
- + (vers_head != NULL ? strlen (vers_head) : 10)
- + 10);
- (void)sprintf (file2, "%s:%s", finfo->fullname,
- vers_head ? vers_head : "removed");
-
- /* Note that the string "diff" is specified by POSIX (for -c)
- and is part of the diff output format, not the name of a
- program. */
- if (unidiff)
- {
- cvs_output ("diff -u ", 0);
- cvs_output (file1, 0);
- cvs_output (" ", 1);
- cvs_output (file2, 0);
- cvs_output ("\n", 1);
-
- cvs_output ("--- ", 0);
- cvs_output (file1, 0);
- cvs_output (cp1, 0);
- cvs_output ("+++ ", 0);
- }
- else
- {
- cvs_output ("diff -c ", 0);
- cvs_output (file1, 0);
- cvs_output (" ", 1);
- cvs_output (file2, 0);
- cvs_output ("\n", 1);
-
- cvs_output ("*** ", 0);
- cvs_output (file1, 0);
- cvs_output (cp1, 0);
- cvs_output ("--- ", 0);
- }
-
- cvs_output (finfo->fullname, 0);
- cvs_output (cp2, 0);
-
- /* spew the rest of the diff out */
- while ((line_length
- = getline (&line1, &line1_chars_allocated, fp))
- >= 0)
- cvs_output (line1, 0);
- if (line_length < 0 && !feof (fp))
- error (0, errno, "cannot read %s", tmpfile3);
-
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", tmpfile3);
- free (file1);
- free (file2);
- break;
- default:
- error (0, 0, "diff failed for %s", finfo->fullname);
- }
- out:
- if (line1)
- free (line1);
- if (line2)
- free (line2);
- if (tmpfile1 != NULL)
- {
- if (CVS_UNLINK (tmpfile1) < 0)
- error (0, errno, "cannot unlink %s", tmpfile1);
- free (tmpfile1);
- tmpfile1 = NULL;
- }
- if (tmpfile2 != NULL)
- {
- if (CVS_UNLINK (tmpfile2) < 0)
- error (0, errno, "cannot unlink %s", tmpfile2);
- free (tmpfile2);
- tmpfile2 = NULL;
- }
- if (tmpfile3 != NULL)
- {
- if (CVS_UNLINK (tmpfile3) < 0)
- error (0, errno, "cannot unlink %s", tmpfile3);
- free (tmpfile3);
- tmpfile3 = NULL;
- }
-
- if (dargc)
- {
- run_arg_free_p (dargc, dargv);
- free (dargv);
- }
-
- out2:
- if (vers_tag != NULL)
- free (vers_tag);
- if (vers_head != NULL)
- free (vers_head);
- if (rcs_orig)
- free (rcs_orig);
- return ret;
-}
-
-
-
-/*
- * Print a warm fuzzy message
- */
-/* ARGSUSED */
-static Dtype
-patch_dirproc (callerdat, dir, repos, update_dir, entries)
- void *callerdat;
- const char *dir;
- const char *repos;
- const char *update_dir;
- List *entries;
-{
- if (!quiet)
- error (0, 0, "Diffing %s", update_dir);
- return (R_PROCESS);
-}
-
-/*
- * Clean up temporary files
- */
-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)
- {
- if (unlink_file (tmpfile1) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", tmpfile1);
- free (tmpfile1);
- }
- if (tmpfile2 != NULL)
- {
- if (unlink_file (tmpfile2) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", tmpfile2);
- free (tmpfile2);
- }
- if (tmpfile3 != NULL)
- {
- 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/rcs.c b/contrib/cvs/src/rcs.c
deleted file mode 100644
index 3358e9142b1e..000000000000
--- a/contrib/cvs/src/rcs.c
+++ /dev/null
@@ -1,9074 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * The routines contained in this file do all the rcs file parsing and
- * manipulation
- *
- * $FreeBSD$
- */
-
-#include <assert.h>
-#include "cvs.h"
-#include "edit.h"
-#include "hardlink.h"
-
-/* These need to be source after cvs.h or HAVE_MMAP won't be set... */
-#ifdef HAVE_MMAP
-# include <sys/mman.h>
-# ifndef HAVE_GETPAGESIZE
-# include "getpagesize.h"
-# endif
-# ifndef MAP_FAILED
-# define MAP_FAILED NULL
-# endif
-#endif
-
-#ifdef MMAP_FALLBACK_TEST
-void *my_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
-{
- if (rand() & 1) return mmap(addr, len, prot, flags, fd, offset);
- return NULL;
-}
-#define mmap my_mmap
-#endif
-
-int datesep = '/';
-int preserve_perms = 0;
-
-/* The RCS -k options, and a set of enums that must match the array.
- These come first so that we can use enum kflag in function
- prototypes. */
-static const char *const kflags[] =
- {"kv", "kvl", "k", "v", "o", "b", (char *) NULL};
-enum kflag { KFLAG_KV = 0, KFLAG_KVL, KFLAG_K, KFLAG_V, KFLAG_O, KFLAG_B };
-
-/* A structure we use to buffer the contents of an RCS file. The
- various fields are only referenced directly by the rcsbuf_*
- functions. We declare the struct here so that we can allocate it
- on the stack, rather than in memory. */
-
-struct rcsbuffer
-{
- /* Points to the current position in the buffer. */
- char *ptr;
- /* Points just after the last valid character in the buffer. */
- char *ptrend;
- /* The file. */
- FILE *fp;
- /* The name of the file, used for error messages. */
- const char *filename;
- /* The starting file position of the data in the buffer. */
- unsigned long pos;
- /* The length of the value. */
- size_t vlen;
- /* Whether the value contains an '@' string. If so, we can not
- compress whitespace characters. */
- int at_string;
- /* The number of embedded '@' characters in an '@' string. If
- this is non-zero, we must search the string for pairs of '@'
- and convert them to a single '@'. */
- int embedded_at;
- /* Whether the buffer has been mmap'ed or not. */
- int mmapped;
-};
-
-static RCSNode *RCS_parsercsfile_i PROTO((FILE * fp, const char *rcsfile));
-static char *RCS_getdatebranch PROTO((RCSNode * rcs, const char *date,
- const char *branch));
-static void rcsbuf_open PROTO ((struct rcsbuffer *, FILE *fp,
- const char *filename, unsigned long pos));
-static void rcsbuf_close PROTO ((struct rcsbuffer *));
-static int rcsbuf_getkey PROTO ((struct rcsbuffer *, char **keyp,
- char **valp));
-static int rcsbuf_getrevnum PROTO ((struct rcsbuffer *, char **revp));
-static char *rcsbuf_fill PROTO ((struct rcsbuffer *, char *ptr, char **keyp,
- char **valp));
-static int rcsbuf_valcmp PROTO ((struct rcsbuffer *));
-static char *rcsbuf_valcopy PROTO ((struct rcsbuffer *, char *val, int polish,
- size_t *lenp));
-static void rcsbuf_valpolish PROTO ((struct rcsbuffer *, char *val, int polish,
- size_t *lenp));
-static void rcsbuf_valpolish_internal PROTO ((struct rcsbuffer *, char *to,
- const char *from, size_t *lenp));
-static unsigned long rcsbuf_ftell PROTO ((struct rcsbuffer *));
-static void rcsbuf_get_buffered PROTO ((struct rcsbuffer *, char **datap,
- size_t *lenp));
-static void rcsbuf_cache PROTO ((RCSNode *, struct rcsbuffer *));
-static void rcsbuf_cache_close PROTO ((void));
-static void rcsbuf_cache_open PROTO ((RCSNode *, long, FILE **,
- struct rcsbuffer *));
-static int checkmagic_proc PROTO((Node *p, void *closure));
-static void do_branches PROTO((List * list, char *val));
-static void do_symbols PROTO((List * list, char *val));
-static void do_locks PROTO((List * list, char *val));
-static void free_rcsnode_contents PROTO((RCSNode *));
-static void free_rcsvers_contents PROTO((RCSVers *));
-static void rcsvers_delproc PROTO((Node * p));
-static char *translate_symtag PROTO((RCSNode *, const char *));
-static char *RCS_addbranch PROTO ((RCSNode *, const char *));
-static char *truncate_revnum_in_place PROTO ((char *));
-static char *truncate_revnum PROTO ((const char *));
-static char *printable_date PROTO((const char *));
-static char *escape_keyword_value PROTO ((const char *, int *));
-static void expand_keywords PROTO((RCSNode *, RCSVers *, const char *,
- const char *, size_t, enum kflag, char *,
- size_t, char **, size_t *));
-static void cmp_file_buffer PROTO((void *, const char *, size_t));
-
-/* Routines for reading, parsing and writing RCS files. */
-static RCSVers *getdelta PROTO ((struct rcsbuffer *, char *, char **,
- char **));
-static Deltatext *RCS_getdeltatext PROTO ((RCSNode *, FILE *,
- struct rcsbuffer *));
-static void freedeltatext PROTO ((Deltatext *));
-
-static void RCS_putadmin PROTO ((RCSNode *, FILE *));
-static void RCS_putdtree PROTO ((RCSNode *, char *, FILE *));
-static void RCS_putdesc PROTO ((RCSNode *, FILE *));
-static void putdelta PROTO ((RCSVers *, FILE *));
-static int putrcsfield_proc PROTO ((Node *, void *));
-static int putsymbol_proc PROTO ((Node *, void *));
-static void RCS_copydeltas PROTO ((RCSNode *, FILE *, struct rcsbuffer *,
- FILE *, Deltatext *, char *));
-static int count_delta_actions PROTO ((Node *, void *));
-static void putdeltatext PROTO ((FILE *, Deltatext *));
-
-static FILE *rcs_internal_lockfile PROTO ((char *));
-static void rcs_internal_unlockfile PROTO ((FILE *, char *));
-static char *rcs_lockfilename PROTO ((const char *));
-
-/* The RCS file reading functions are called a lot, and they do some
- string comparisons. This macro speeds things up a bit by skipping
- the function call when the first characters are different. It
- evaluates its arguments multiple times. */
-#define STREQ(a, b) (*(char *)(a) == *(char *)(b) && strcmp ((a), (b)) == 0)
-
-static char * getfullCVSname PROTO ((char *, char **));
-
-/*
- * We don't want to use isspace() from the C library because:
- *
- * 1. The definition of "whitespace" in RCS files includes ASCII
- * backspace, but the C locale doesn't.
- * 2. isspace is an very expensive function call in some implementations
- * due to the addition of wide character support.
- */
-static const char spacetab[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x00 - 0x0f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x8f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 - 0xff */
-};
-
-#define whitespace(c) (spacetab[(unsigned char)c] != 0)
-
-static char *rcs_lockfile;
-static int rcs_lockfd = -1;
-
-
-
-/*
- * char *
- * locate_rcs ( const char* file, const char *repository , int *inattic )
- *
- * Find an RCS file in the repository, case insensitively when the cased name
- * doesn't exist, we are running as the server, and a client has asked us to
- * ignore case.
- *
- * Most parts of CVS will want to rely instead on RCS_parse which calls this
- * function and is called by recurse.c which then puts the result in useful
- * places like the rcs field of struct file_info.
- *
- * INPUTS
- *
- * repository the repository (including the directory)
- * file the filename within that directory (without RCSEXT).
- * inattic NULL or a pointer to the output boolean
- *
- * OUTPUTS
- *
- * inattic If this input was non-null, the destination will be
- * set to true if the file was found in the attic or
- * false if not. If no RCS file is found, this value
- * is undefined.
- *
- * RETURNS
- *
- * a newly-malloc'd array containing the absolute pathname of the RCS
- * file that was found or NULL when none was found.
- *
- * ERRORS
- *
- * errno can be set by the return value of the final call to
- * locate_file_in_dir(). This should resolve to the system's existence error
- * value (sometime ENOENT) if the Attic directory did not exist and ENOENT if
- * the Attic was found but no matching files were found in the Attic or its
- * parent.
- */
-static char *
-locate_rcs (repository, file, inattic)
- const char *repository;
- const char *file;
- int *inattic;
-{
- char *retval;
-
- /* First, try to find the file as cased. */
- retval = xmalloc (strlen (repository)
- + sizeof (CVSATTIC)
- + strlen (file)
- + sizeof (RCSEXT)
- + 3);
- sprintf (retval, "%s/%s%s", repository, file, RCSEXT);
- if (isreadable (retval))
- {
- if (inattic)
- *inattic = 0;
- return retval;
- }
- sprintf (retval, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT);
- if (isreadable (retval))
- {
- if (inattic)
- *inattic = 1;
- return retval;
- }
- free (retval);
-
- return NULL;
-}
-
-
-
-/* A few generic thoughts on error handling, in particular the
- printing of unexpected characters that we find in the RCS file
- (that is, why we use '\x%x' rather than %c or some such).
-
- * Avoiding %c means we don't have to worry about what is printable
- and other such stuff. In error handling, often better to keep it
- simple.
-
- * Hex rather than decimal or octal because character set standards
- tend to use hex.
-
- * Saying "character 0x%x" might make it sound like we are printing
- a file offset. So we use '\x%x'.
-
- * Would be nice to print the offset within the file, but I can
- imagine various portability hassles (in particular, whether
- unsigned long is always big enough to hold file offsets). */
-
-/* Parse an rcsfile given a user file name and a repository. If there is
- an error, we print an error message and return NULL. If the file
- does not exist, we return NULL without printing anything (I'm not
- sure this allows the caller to do anything reasonable, but it is
- the current behavior). */
-RCSNode *
-RCS_parse (file, repos)
- const char *file;
- const char *repos;
-{
- RCSNode *rcs;
- FILE *fp;
- RCSNode *retval = NULL;
- char *rcsfile;
- int inattic;
-
- /* We're creating a new RCSNode, so there is no hope of finding it
- in the cache. */
- rcsbuf_cache_close ();
-
- if ((rcsfile = locate_rcs (repos, file, &inattic)) == NULL)
- {
- /* Handle the error cases */
- }
- else if ((fp = CVS_FOPEN (rcsfile, FOPEN_BINARY_READ)) != NULL)
- {
- rcs = RCS_parsercsfile_i(fp, rcsfile);
- if (rcs != NULL)
- {
- rcs->flags |= VALID;
- if ( inattic )
- rcs->flags |= INATTIC;
- }
-
- free ( rcsfile );
- retval = rcs;
- }
- else if (! existence_error (errno))
- {
- error (0, errno, "cannot open %s", rcsfile);
- free (rcsfile);
- }
-
- return retval;
-}
-
-/*
- * Parse a specific rcsfile.
- */
-RCSNode *
-RCS_parsercsfile (rcsfile)
- const char *rcsfile;
-{
- FILE *fp;
- RCSNode *rcs;
-
- /* We're creating a new RCSNode, so there is no hope of finding it
- in the cache. */
- rcsbuf_cache_close ();
-
- /* open the rcsfile */
- if ((fp = CVS_FOPEN (rcsfile, FOPEN_BINARY_READ)) == NULL)
- {
- error (0, errno, "Couldn't open rcs file `%s'", rcsfile);
- return (NULL);
- }
-
- rcs = RCS_parsercsfile_i (fp, rcsfile);
-
- return (rcs);
-}
-
-
-
-/*
- */
-static RCSNode *
-RCS_parsercsfile_i (fp, rcsfile)
- FILE *fp;
- const char *rcsfile;
-{
- RCSNode *rdata;
- struct rcsbuffer rcsbuf;
- char *key, *value;
-
- /* make a node */
- rdata = (RCSNode *) xmalloc (sizeof (RCSNode));
- memset ((char *)rdata, 0, sizeof (RCSNode));
- rdata->refcount = 1;
- rdata->path = xstrdup (rcsfile);
-
- /* Process HEAD, BRANCH, and EXPAND keywords from the RCS header.
-
- Most cvs operations on the main branch don't need any more
- information. Those that do call RCS_reparsercsfile to parse
- the rest of the header and the deltas. */
-
- rcsbuf_open (&rcsbuf, fp, rcsfile, 0);
-
- if (! rcsbuf_getkey (&rcsbuf, &key, &value))
- goto l_error;
- if (STREQ (key, RCSDESC))
- goto l_error;
-
- if (STREQ (RCSHEAD, key) && value != NULL)
- rdata->head = rcsbuf_valcopy (&rcsbuf, value, 0, (size_t *)NULL);
-
- if (! rcsbuf_getkey (&rcsbuf, &key, &value))
- goto l_error;
- if (STREQ (key, RCSDESC))
- goto l_error;
-
- if (STREQ (RCSBRANCH, key) && value != NULL)
- {
- char *cp;
-
- rdata->branch = rcsbuf_valcopy (&rcsbuf, value, 0, (size_t *)NULL);
- if ((numdots (rdata->branch) & 1) != 0)
- {
- /* turn it into a branch if it's a revision */
- cp = strrchr (rdata->branch, '.');
- *cp = '\0';
- }
- }
-
- /* Look ahead for expand, stopping when we see desc or a revision
- number. */
- while (1)
- {
- char *cp;
-
- if (STREQ (RCSEXPAND, key))
- {
- rdata->expand = rcsbuf_valcopy (&rcsbuf, value, 0,
- (size_t *)NULL);
- break;
- }
-
- for (cp = key;
- (isdigit ((unsigned char)*cp) || *cp == '.') && *cp != '\0';
- cp++)
- /* do nothing */ ;
- if (*cp == '\0')
- break;
-
- if (STREQ (RCSDESC, key))
- break;
-
- if (! rcsbuf_getkey (&rcsbuf, &key, &value))
- break;
- }
-
- rdata->flags |= PARTIAL;
-
- rcsbuf_cache (rdata, &rcsbuf);
-
- return rdata;
-
-l_error:
- error (0, 0, "`%s' does not appear to be a valid rcs file",
- rcsfile);
- rcsbuf_close (&rcsbuf);
- freercsnode (&rdata);
- fclose (fp);
- return NULL;
-}
-
-
-
-/* Do the real work of parsing an RCS file.
-
- On error, die with a fatal error; if it returns at all it was successful.
-
- If PFP is NULL, close the file when done. Otherwise, leave it open
- and store the FILE * in *PFP. */
-void
-RCS_reparsercsfile (rdata, pfp, rcsbufp)
- RCSNode *rdata;
- FILE **pfp;
- struct rcsbuffer *rcsbufp;
-{
- FILE *fp;
- char *rcsfile;
- struct rcsbuffer rcsbuf;
- Node *q, *kv;
- RCSVers *vnode;
- int gotkey;
- char *cp;
- char *key, *value;
-
- assert (rdata != NULL);
- rcsfile = rdata->path;
-
- rcsbuf_cache_open (rdata, 0, &fp, &rcsbuf);
-
- /* make a node */
- /* This probably shouldn't be done until later: if a file has an
- empty revision tree (which is permissible), rdata->versions
- should be NULL. -twp */
- rdata->versions = getlist ();
-
- /*
- * process all the special header information, break out when we get to
- * the first revision delta
- */
- gotkey = 0;
- for (;;)
- {
- /* get the next key/value pair */
- if (!gotkey)
- {
- if (! rcsbuf_getkey (&rcsbuf, &key, &value))
- {
- error (1, 0, "`%s' does not appear to be a valid rcs file",
- rcsfile);
- }
- }
-
- gotkey = 0;
-
- /* Skip head, branch and expand tags; we already have them. */
- if (STREQ (key, RCSHEAD)
- || STREQ (key, RCSBRANCH)
- || STREQ (key, RCSEXPAND))
- {
- continue;
- }
-
- if (STREQ (key, "access"))
- {
- if (value != NULL)
- {
- /* We pass the POLISH parameter as 1 because
- RCS_addaccess expects nothing but spaces. FIXME:
- It would be easy and more efficient to change
- RCS_addaccess. */
- if (rdata->access)
- {
- error (0, 0,
- "Duplicate `access' keyword found in RCS file.");
- free (rdata->access);
- }
- rdata->access = rcsbuf_valcopy (&rcsbuf, value, 1, NULL);
- }
- continue;
- }
-
- /* We always save lock information, so that we can handle
- -kkvl correctly when checking out a file. */
- if (STREQ (key, "locks"))
- {
- if (value != NULL)
- {
- if (rdata->locks_data)
- {
- error (0, 0,
- "Duplicate `locks' keyword found in RCS file.");
- free (rdata->locks_data);
- }
- rdata->locks_data = rcsbuf_valcopy (&rcsbuf, value, 0, NULL);
- }
- if (! rcsbuf_getkey (&rcsbuf, &key, &value))
- {
- error (1, 0, "premature end of file reading %s", rcsfile);
- }
- if (STREQ (key, "strict") && value == NULL)
- {
- rdata->strict_locks = 1;
- }
- else
- gotkey = 1;
- continue;
- }
-
- if (STREQ (RCSSYMBOLS, key))
- {
- if (value != NULL)
- {
- if (rdata->symbols_data)
- {
- error (0, 0,
- "Duplicate `%s' keyword found in RCS file.",
- RCSSYMBOLS);
- free (rdata->symbols_data);
- }
- rdata->symbols_data = rcsbuf_valcopy (&rcsbuf, value, 0, NULL);
- }
- continue;
- }
-
- /*
- * check key for '.''s and digits (probably a rev) if it is a
- * revision or `desc', we are done with the headers and are down to the
- * revision deltas, so we break out of the loop
- */
- for (cp = key;
- (isdigit ((unsigned char) *cp) || *cp == '.') && *cp != '\0';
- cp++)
- /* do nothing */ ;
- /* Note that when comparing with RCSDATE, we are not massaging
- VALUE from the string found in the RCS file. This is OK
- since we know exactly what to expect. */
- if (*cp == '\0' && strncmp (RCSDATE, value, (sizeof RCSDATE) - 1) == 0)
- break;
-
- if (STREQ (key, RCSDESC))
- break;
-
- if (STREQ (key, "comment"))
- {
- if (rdata->comment)
- {
- error (0, 0,
- "warning: duplicate key `%s' in RCS file `%s'",
- key, rcsfile);
- free (rdata->comment);
- }
- rdata->comment = rcsbuf_valcopy (&rcsbuf, value, 0, NULL);
- continue;
- }
- if (rdata->other == NULL)
- rdata->other = getlist ();
- kv = getnode ();
- kv->type = rcsbuf_valcmp (&rcsbuf) ? RCSCMPFLD : RCSFIELD;
- kv->key = xstrdup (key);
- kv->data = rcsbuf_valcopy (&rcsbuf, value, kv->type == RCSFIELD,
- (size_t *) NULL);
- if (addnode (rdata->other, kv) != 0)
- {
- error (0, 0, "warning: duplicate key `%s' in RCS file `%s'",
- key, rcsfile);
- freenode (kv);
- }
-
- /* if we haven't grabbed it yet, we didn't want it */
- }
-
- /* We got out of the loop, so we have the first part of the first
- revision delta in KEY (the revision) and VALUE (the date key
- and its value). This is what getdelta expects to receive. */
-
- while ((vnode = getdelta (&rcsbuf, rcsfile, &key, &value)) != NULL)
- {
- /* get the node */
- q = getnode ();
- q->type = RCSVERS;
- q->delproc = rcsvers_delproc;
- q->data = vnode;
- q->key = vnode->version;
-
- /* add the nodes to the list */
- if (addnode (rdata->versions, q))
- error (1, 0, "Multiple %s revision deltas found in `%s'",
- q->key, rcsfile);
- }
-
- /* Here KEY and VALUE are whatever caused getdelta to return NULL. */
-
- if (STREQ (key, RCSDESC))
- {
- if (rdata->desc != NULL)
- {
- error (0, 0,
- "warning: duplicate key `%s' in RCS file `%s'",
- key, rcsfile);
- free (rdata->desc);
- }
- rdata->desc = rcsbuf_valcopy (&rcsbuf, value, 1, (size_t *) NULL);
- }
-
- rdata->delta_pos = rcsbuf_ftell (&rcsbuf);
-
- if (pfp == NULL)
- rcsbuf_cache (rdata, &rcsbuf);
- else
- {
- *pfp = fp;
- *rcsbufp = rcsbuf;
- }
- rdata->flags &= ~PARTIAL;
-}
-
-/* Move RCS into or out of the Attic, depending on TOATTIC. If the
- file is already in the desired place, return without doing
- anything. At some point may want to think about how this relates
- to RCS_rewrite but that is a bit hairy (if one wants renames to be
- atomic, or that kind of thing). If there is an error, print a message
- and return 1. On success, return 0. */
-int
-RCS_setattic (rcs, toattic)
- RCSNode *rcs;
- int toattic;
-{
- char *newpath;
- const char *p;
- char *q;
-
- /* Some systems aren't going to let us rename an open file. */
- rcsbuf_cache_close ();
-
- /* Could make the pathname computations in this file, and probably
- in other parts of rcs.c too, easier if the REPOS and FILE
- arguments to RCS_parse got stashed in the RCSNode. */
-
- if (toattic)
- {
- mode_t omask;
-
- if (rcs->flags & INATTIC)
- return 0;
-
- /* Example: rcs->path is "/foo/bar/baz,v". */
- newpath = xmalloc (strlen (rcs->path) + sizeof CVSATTIC + 5);
- p = last_component (rcs->path);
- strncpy (newpath, rcs->path, p - rcs->path);
- strcpy (newpath + (p - rcs->path), CVSATTIC);
-
- /* Create the Attic directory if it doesn't exist. */
- omask = umask (cvsumask);
- if (CVS_MKDIR (newpath, 0777) < 0 && errno != EEXIST)
- error (0, errno, "cannot make directory %s", newpath);
- (void) umask (omask);
-
- strcat (newpath, "/");
- strcat (newpath, p);
-
- if (CVS_RENAME (rcs->path, newpath) < 0)
- {
- int save_errno = errno;
-
- /* The checks for isreadable look awfully fishy, but
- I'm going to leave them here for now until I
- can think harder about whether they take care of
- some cases which should be handled somehow. */
-
- if (isreadable (rcs->path) || !isreadable (newpath))
- {
- error (0, save_errno, "cannot rename %s to %s",
- rcs->path, newpath);
- free (newpath);
- return 1;
- }
- }
- }
- else
- {
- if (!(rcs->flags & INATTIC))
- return 0;
-
- newpath = xmalloc (strlen (rcs->path));
-
- /* Example: rcs->path is "/foo/bar/Attic/baz,v". */
- p = last_component (rcs->path);
- strncpy (newpath, rcs->path, p - rcs->path - 1);
- newpath[p - rcs->path - 1] = '\0';
- q = newpath + (p - rcs->path - 1) - (sizeof CVSATTIC - 1);
- assert (strncmp (q, CVSATTIC, sizeof CVSATTIC - 1) == 0);
- strcpy (q, p);
-
- if (CVS_RENAME (rcs->path, newpath) < 0)
- {
- error (0, errno, "failed to move `%s' out of the attic",
- rcs->path);
- free (newpath);
- return 1;
- }
- }
-
- free (rcs->path);
- rcs->path = newpath;
-
- return 0;
-}
-
-/*
- * Fully parse the RCS file. Store all keyword/value pairs, fetch the
- * log messages for each revision, and fetch add and delete counts for
- * each revision (we could fetch the entire text for each revision,
- * but the only caller, log_fileproc, doesn't need that information,
- * so we don't waste the memory required to store it). The add and
- * delete counts are stored on the OTHER field of the RCSVERSNODE
- * structure, under the names ";add" and ";delete", so that we don't
- * waste the memory space of extra fields in RCSVERSNODE for code
- * which doesn't need this information.
- */
-
-void
-RCS_fully_parse (rcs)
- RCSNode *rcs;
-{
- FILE *fp;
- struct rcsbuffer rcsbuf;
-
- RCS_reparsercsfile (rcs, &fp, &rcsbuf);
-
- while (1)
- {
- char *key, *value;
- Node *vers;
- RCSVers *vnode;
-
- /* Rather than try to keep track of how much information we
- have read, just read to the end of the file. */
- if (!rcsbuf_getrevnum (&rcsbuf, &key))
- break;
-
- vers = findnode (rcs->versions, key);
- if (!vers)
- error (1, 0,
- "Delta text %s without revision information in `%s'.",
- key, rcs->path);
-
- vnode = vers->data;
-
- while (rcsbuf_getkey (&rcsbuf, &key, &value))
- {
- if (!STREQ (key, "text"))
- {
- Node *kv;
-
- if (vnode->other == NULL)
- vnode->other = getlist ();
- kv = getnode ();
- kv->type = rcsbuf_valcmp (&rcsbuf) ? RCSCMPFLD : RCSFIELD;
- kv->key = xstrdup (key);
- kv->data = rcsbuf_valcopy (&rcsbuf, value, kv->type == RCSFIELD,
- (size_t *)NULL);
- if (addnode (vnode->other, kv) != 0)
- {
- error (0, 0,
- "\
-warning: duplicate key `%s' in version `%s' of RCS file `%s'",
- key, vnode->version, rcs->path);
- freenode (kv);
- }
-
- continue;
- }
-
- if (!STREQ (vnode->version, rcs->head))
- {
- unsigned long add, del;
- char buf[50];
- Node *kv;
-
- /* This is a change text. Store the add and delete
- counts. */
- add = 0;
- del = 0;
- if (value != NULL)
- {
- size_t vallen;
- const char *cp;
-
- rcsbuf_valpolish (&rcsbuf, value, 0, &vallen);
- cp = value;
- while (cp < value + vallen)
- {
- char op;
- unsigned long count;
-
- op = *cp++;
- if (op != 'a' && op != 'd')
- error (1, 0, "\
-unrecognized operation '\\x%x' in %s revision %s",
- op, rcs->path, vnode->version);
- (void) strtoul (cp, (char **) &cp, 10);
- if (*cp++ != ' ')
- error (1, 0, "space expected in %s revision %s",
- rcs->path, vnode->version);
- count = strtoul (cp, (char **) &cp, 10);
- if (*cp++ != '\012')
- error (1, 0, "linefeed expected in %s revision %s",
- rcs->path, vnode->version);
-
- if (op == 'd')
- del += count;
- else
- {
- add += count;
- while (count != 0)
- {
- if (*cp == '\012')
- --count;
- else if (cp == value + vallen)
- {
- if (count != 1)
- error (1, 0, "\
-premature end of value in %s revision %s",
- rcs->path, vnode->version);
- else
- break;
- }
- ++cp;
- }
- }
- }
- }
-
- sprintf (buf, "%lu", add);
- kv = getnode ();
- kv->type = RCSFIELD;
- kv->key = xstrdup (";add");
- kv->data = xstrdup (buf);
- if (addnode (vnode->other, kv) != 0)
- {
- error (0, 0,
- "\
-warning: duplicate key `%s' in version `%s' of RCS file `%s'",
- key, vnode->version, rcs->path);
- freenode (kv);
- }
-
- sprintf (buf, "%lu", del);
- kv = getnode ();
- kv->type = RCSFIELD;
- kv->key = xstrdup (";delete");
- kv->data = xstrdup (buf);
- if (addnode (vnode->other, kv) != 0)
- {
- error (0, 0,
- "\
-warning: duplicate key `%s' in version `%s' of RCS file `%s'",
- key, vnode->version, rcs->path);
- freenode (kv);
- }
- }
-
- /* We have found the "text" key which ends the data for
- this revision. Break out of the loop and go on to the
- next revision. */
- break;
- }
- }
-
- rcsbuf_cache (rcs, &rcsbuf);
-}
-
-
-
-/*
- * freercsnode - free up the info for an RCSNode
- */
-void
-freercsnode (rnodep)
- RCSNode **rnodep;
-{
- if (rnodep == NULL || *rnodep == NULL)
- return;
-
- ((*rnodep)->refcount)--;
- if ((*rnodep)->refcount != 0)
- {
- *rnodep = (RCSNode *) NULL;
- return;
- }
- free ((*rnodep)->path);
- if ((*rnodep)->head != (char *) NULL)
- free ((*rnodep)->head);
- if ((*rnodep)->branch != (char *) NULL)
- free ((*rnodep)->branch);
- free_rcsnode_contents (*rnodep);
- free ((char *) *rnodep);
- *rnodep = (RCSNode *) NULL;
-}
-
-/*
- * free_rcsnode_contents - free up the contents of an RCSNode without
- * freeing the node itself, or the file name, or the head, or the
- * path. This returns the RCSNode to the state it is in immediately
- * after a call to RCS_parse.
- */
-static void
-free_rcsnode_contents (rnode)
- RCSNode *rnode;
-{
- dellist (&rnode->versions);
- if (rnode->symbols != (List *) NULL)
- dellist (&rnode->symbols);
- if (rnode->symbols_data != (char *) NULL)
- free (rnode->symbols_data);
- if (rnode->expand != NULL)
- free (rnode->expand);
- if (rnode->other != (List *) NULL)
- dellist (&rnode->other);
- if (rnode->access != NULL)
- free (rnode->access);
- if (rnode->locks_data != NULL)
- free (rnode->locks_data);
- if (rnode->locks != (List *) NULL)
- dellist (&rnode->locks);
- if (rnode->comment != NULL)
- free (rnode->comment);
- if (rnode->desc != NULL)
- free (rnode->desc);
-}
-
-/* free_rcsvers_contents -- free up the contents of an RCSVers node,
- but also free the pointer to the node itself. */
-/* Note: The `hardlinks' list is *not* freed, since it is merely a
- pointer into the `hardlist' structure (defined in hardlink.c), and
- that structure is freed elsewhere in the program. */
-
-static void
-free_rcsvers_contents (rnode)
- RCSVers *rnode;
-{
- if (rnode->branches != (List *) NULL)
- dellist (&rnode->branches);
- if (rnode->date != (char *) NULL)
- free (rnode->date);
- if (rnode->next != (char *) NULL)
- free (rnode->next);
- if (rnode->author != (char *) NULL)
- free (rnode->author);
- if (rnode->state != (char *) NULL)
- free (rnode->state);
- if (rnode->other != (List *) NULL)
- dellist (&rnode->other);
- if (rnode->other_delta != NULL)
- dellist (&rnode->other_delta);
- if (rnode->text != NULL)
- freedeltatext (rnode->text);
- free ((char *) rnode);
-}
-
-/*
- * rcsvers_delproc - free up an RCSVers type node
- */
-static void
-rcsvers_delproc (p)
- Node *p;
-{
- free_rcsvers_contents (p->data);
-}
-
-/* These functions retrieve keys and values from an RCS file using a
- buffer. We use this somewhat complex approach because it turns out
- that for many common operations, CVS spends most of its time
- reading keys, so it's worth doing some fairly hairy optimization. */
-
-/* The number of bytes we try to read each time we need more data. */
-
-#define RCSBUF_BUFSIZE (8192)
-
-/* The buffer we use to store data. This grows as needed. */
-
-static char *rcsbuf_buffer = NULL;
-static size_t rcsbuf_buffer_size = 0;
-
-/* Whether rcsbuf_buffer is in use. This is used as a sanity check. */
-
-static int rcsbuf_inuse;
-
-/* Set up to start gathering keys and values from an RCS file. This
- initializes RCSBUF. */
-
-static void
-rcsbuf_open (rcsbuf, fp, filename, pos)
- struct rcsbuffer *rcsbuf;
- FILE *fp;
- const char *filename;
- unsigned long pos;
-{
-#ifdef HAVE_MMAP
- void *p;
- struct stat fs;
- size_t mmap_off = 0;
-#endif
-
- if (rcsbuf_inuse)
- error (1, 0, "rcsbuf_open: internal error");
- rcsbuf_inuse = 1;
-
-#ifdef HAVE_MMAP
- /* When we have mmap, it is much more efficient to let the system do the
- * buffering and caching for us
- */
-
- if ( fstat (fileno(fp), &fs) < 0 )
- error ( 1, errno, "Could not stat RCS archive %s for mapping", filename );
-
- if (pos)
- {
- size_t ps = getpagesize ();
- mmap_off = ( pos / ps ) * ps;
- }
-
- /* Map private here since this particular buffer is read only */
- p = mmap ( NULL, fs.st_size - mmap_off, PROT_READ | PROT_WRITE,
- MAP_PRIVATE, fileno(fp), mmap_off );
- if (p != NULL && p != MAP_FAILED)
- {
- if (rcsbuf_buffer) free (rcsbuf_buffer);
- rcsbuf_buffer = p;
- rcsbuf_buffer_size = fs.st_size - mmap_off;
- rcsbuf->mmapped = 1;
- rcsbuf->ptr = rcsbuf_buffer + pos - mmap_off;
- rcsbuf->ptrend = rcsbuf_buffer + fs.st_size - mmap_off;
- rcsbuf->pos = mmap_off;
- }
- else
- {
-#ifndef MMAP_FALLBACK_TEST
- error (0, errno, "Could not map memory to RCS archive %s", filename);
-#endif
-#endif /* HAVE_MMAP */
- if (rcsbuf_buffer_size < RCSBUF_BUFSIZE)
- expand_string (&rcsbuf_buffer, &rcsbuf_buffer_size, RCSBUF_BUFSIZE);
-
- rcsbuf->mmapped = 0;
- rcsbuf->ptr = rcsbuf_buffer;
- rcsbuf->ptrend = rcsbuf_buffer;
- rcsbuf->pos = pos;
-#ifdef HAVE_MMAP
- }
-#endif /* HAVE_MMAP */
- rcsbuf->fp = fp;
- rcsbuf->filename = filename;
- rcsbuf->vlen = 0;
- rcsbuf->at_string = 0;
- rcsbuf->embedded_at = 0;
-}
-
-/* Stop gathering keys from an RCS file. */
-
-static void
-rcsbuf_close (rcsbuf)
- struct rcsbuffer *rcsbuf;
-{
- if (! rcsbuf_inuse)
- error (1, 0, "rcsbuf_close: internal error");
-#ifdef HAVE_MMAP
- if (rcsbuf->mmapped)
- {
- munmap ( rcsbuf_buffer, rcsbuf_buffer_size );
- rcsbuf_buffer = NULL;
- rcsbuf_buffer_size = 0;
- }
-#endif
- rcsbuf_inuse = 0;
-}
-
-/* Read a key/value pair from an RCS file. This sets *KEYP to point
- to the key, and *VALUEP to point to the value. A missing or empty
- value is indicated by setting *VALUEP to NULL.
-
- This function returns 1 on success, or 0 on EOF. If there is an
- error reading the file, or an EOF in an unexpected location, it
- gives a fatal error.
-
- This sets *KEYP and *VALUEP to point to storage managed by
- rcsbuf_getkey. Moreover, *VALUEP has not been massaged from the
- RCS format: it may contain embedded whitespace and embedded '@'
- characters. Call rcsbuf_valcopy or rcsbuf_valpolish to do
- appropriate massaging. */
-
-/* Note that the extreme hair in rcsbuf_getkey is because profiling
- statistics show that it was worth it. */
-
-static int
-rcsbuf_getkey (rcsbuf, keyp, valp)
- struct rcsbuffer *rcsbuf;
- char **keyp;
- char **valp;
-{
- register const char * const my_spacetab = spacetab;
- register char *ptr, *ptrend;
- char c;
-
-#define my_whitespace(c) (my_spacetab[(unsigned char)c] != 0)
-
- rcsbuf->vlen = 0;
- rcsbuf->at_string = 0;
- rcsbuf->embedded_at = 0;
-
- ptr = rcsbuf->ptr;
- ptrend = rcsbuf->ptrend;
-
- /* Sanity check. */
- assert (ptr >= rcsbuf_buffer && ptr <= rcsbuf_buffer + rcsbuf_buffer_size);
- assert (ptrend >= rcsbuf_buffer && ptrend <= rcsbuf_buffer + rcsbuf_buffer_size);
-
- /* If the pointer is more than RCSBUF_BUFSIZE bytes into the
- buffer, move back to the start of the buffer. This keeps the
- buffer from growing indefinitely. */
- if (!rcsbuf->mmapped && ptr - rcsbuf_buffer >= RCSBUF_BUFSIZE)
- {
- int len;
-
- len = ptrend - ptr;
-
- /* Sanity check: we don't read more than RCSBUF_BUFSIZE bytes
- at a time, so we can't have more bytes than that past PTR. */
- assert (len <= RCSBUF_BUFSIZE);
-
- /* Update the POS field, which holds the file offset of the
- first byte in the RCSBUF_BUFFER buffer. */
- rcsbuf->pos += ptr - rcsbuf_buffer;
-
- memcpy (rcsbuf_buffer, ptr, len);
- ptr = rcsbuf_buffer;
- ptrend = ptr + len;
- rcsbuf->ptrend = ptrend;
- }
-
- /* Skip leading whitespace. */
-
- while (1)
- {
- if (ptr >= ptrend)
- {
- ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
- if (ptr == NULL)
- return 0;
- ptrend = rcsbuf->ptrend;
- }
-
- c = *ptr;
- if (! my_whitespace (c))
- break;
-
- ++ptr;
- }
-
- /* We've found the start of the key. */
-
- *keyp = ptr;
-
- if (c != ';')
- {
- while (1)
- {
- ++ptr;
- if (ptr >= ptrend)
- {
- ptr = rcsbuf_fill (rcsbuf, ptr, keyp, (char **) NULL);
- if (ptr == NULL)
- error (1, 0, "EOF in key in RCS file %s",
- rcsbuf->filename);
- ptrend = rcsbuf->ptrend;
- }
- c = *ptr;
- if (c == ';' || my_whitespace (c))
- break;
- }
- }
-
- /* Here *KEYP points to the key in the buffer, C is the character
- we found at the of the key, and PTR points to the location in
- the buffer where we found C. We must set *PTR to \0 in order
- to terminate the key. If the key ended with ';', then there is
- no value. */
-
- *ptr = '\0';
- ++ptr;
-
- if (c == ';')
- {
- *valp = NULL;
- rcsbuf->ptr = ptr;
- return 1;
- }
-
- /* C must be whitespace. Skip whitespace between the key and the
- value. If we find ';' now, there is no value. */
-
- while (1)
- {
- if (ptr >= ptrend)
- {
- ptr = rcsbuf_fill (rcsbuf, ptr, keyp, (char **) NULL);
- if (ptr == NULL)
- error (1, 0, "EOF while looking for value in RCS file %s",
- rcsbuf->filename);
- ptrend = rcsbuf->ptrend;
- }
- c = *ptr;
- if (c == ';')
- {
- *valp = NULL;
- rcsbuf->ptr = ptr + 1;
- return 1;
- }
- if (! my_whitespace (c))
- break;
- ++ptr;
- }
-
- /* Now PTR points to the start of the value, and C is the first
- character of the value. */
-
- if (c != '@')
- *valp = ptr;
- else
- {
- char *pat;
- size_t vlen;
-
- /* Optimize the common case of a value composed of a single
- '@' string. */
-
- rcsbuf->at_string = 1;
-
- ++ptr;
-
- *valp = ptr;
-
- while (1)
- {
- while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL)
- {
- /* Note that we pass PTREND as the PTR value to
- rcsbuf_fill, so that we will wind up setting PTR to
- the location corresponding to the old PTREND, so
- that we don't search the same bytes again. */
- ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
- if (ptr == NULL)
- error (1, 0,
- "EOF while looking for end of string in RCS file %s",
- rcsbuf->filename);
- ptrend = rcsbuf->ptrend;
- }
-
- /* Handle the special case of an '@' right at the end of
- the known bytes. */
- if (pat + 1 >= ptrend)
- {
- /* Note that we pass PAT, not PTR, here. */
- pat = rcsbuf_fill (rcsbuf, pat, keyp, valp);
- if (pat == NULL)
- {
- /* EOF here is OK; it just means that the last
- character of the file was an '@' terminating a
- value for a key type which does not require a
- trailing ';'. */
- pat = rcsbuf->ptrend - 1;
-
- }
- ptrend = rcsbuf->ptrend;
-
- /* Note that the value of PTR is bogus here. This is
- OK, because we don't use it. */
- }
-
- if (pat + 1 >= ptrend || pat[1] != '@')
- break;
-
- /* We found an '@' pair in the string. Keep looking. */
- ++rcsbuf->embedded_at;
- ptr = pat + 2;
- }
-
- /* Here PAT points to the final '@' in the string. */
-
- *pat = '\0';
-
- vlen = pat - *valp;
- if (vlen == 0)
- *valp = NULL;
- rcsbuf->vlen = vlen;
-
- ptr = pat + 1;
- }
-
- /* Certain keywords only have a '@' string. If there is no '@'
- string, then the old getrcskey function assumed that they had
- no value, and we do the same. */
-
- {
- char *k;
-
- k = *keyp;
- if (STREQ (k, RCSDESC)
- || STREQ (k, "text")
- || STREQ (k, "log"))
- {
- if (c != '@')
- *valp = NULL;
- rcsbuf->ptr = ptr;
- return 1;
- }
- }
-
- /* If we've already gathered a '@' string, try to skip whitespace
- and find a ';'. */
- if (c == '@')
- {
- while (1)
- {
- char n;
-
- if (ptr >= ptrend)
- {
- ptr = rcsbuf_fill (rcsbuf, ptr, keyp, valp);
- if (ptr == NULL)
- error (1, 0, "EOF in value in RCS file %s",
- rcsbuf->filename);
- ptrend = rcsbuf->ptrend;
- }
- n = *ptr;
- if (n == ';')
- {
- /* We're done. We already set everything up for this
- case above. */
- rcsbuf->ptr = ptr + 1;
- return 1;
- }
- if (! my_whitespace (n))
- break;
- ++ptr;
- }
-
- /* The value extends past the '@' string. We need to undo the
- '@' stripping done in the default case above. This
- case never happens in a plain RCS file, but it can happen
- if user defined phrases are used. */
- ((*valp)--)[rcsbuf->vlen++] = '@';
- }
-
- /* Here we have a value which is not a simple '@' string. We need
- to gather up everything until the next ';', including any '@'
- strings. *VALP points to the start of the value. If
- RCSBUF->VLEN is not zero, then we have already read an '@'
- string, and PTR points to the data following the '@' string.
- Otherwise, PTR points to the start of the value. */
-
- while (1)
- {
- char *start, *psemi, *pat;
-
- /* Find the ';' which must end the value. */
- start = ptr;
- while ((psemi = memchr (ptr, ';', ptrend - ptr)) == NULL)
- {
- int slen;
-
- /* Note that we pass PTREND as the PTR value to
- rcsbuf_fill, so that we will wind up setting PTR to the
- location corresponding to the old PTREND, so that we
- don't search the same bytes again. */
- slen = start - *valp;
- ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
- if (ptr == NULL)
- error (1, 0, "EOF in value in RCS file %s", rcsbuf->filename);
- start = *valp + slen;
- ptrend = rcsbuf->ptrend;
- }
-
- /* See if there are any '@' strings in the value. */
- pat = memchr (start, '@', psemi - start);
-
- if (pat == NULL)
- {
- size_t vlen;
-
- /* We're done with the value. Trim any trailing
- whitespace. */
-
- rcsbuf->ptr = psemi + 1;
-
- start = *valp;
- while (psemi > start && my_whitespace (psemi[-1]))
- --psemi;
- *psemi = '\0';
-
- vlen = psemi - start;
- if (vlen == 0)
- *valp = NULL;
- rcsbuf->vlen = vlen;
-
- return 1;
- }
-
- /* We found an '@' string in the value. We set RCSBUF->AT_STRING
- and RCSBUF->EMBEDDED_AT to indicate that we won't be able to
- compress whitespace correctly for this type of value.
- Since this type of value never arises in a normal RCS file,
- this should not be a big deal. It means that if anybody
- adds a phrase which can have both an '@' string and regular
- text, they will have to handle whitespace compression
- themselves. */
-
- rcsbuf->at_string = 1;
- rcsbuf->embedded_at = -1;
-
- ptr = pat + 1;
-
- while (1)
- {
- while ((pat = memchr (ptr, '@', ptrend - ptr)) == NULL)
- {
- /* Note that we pass PTREND as the PTR value to
- rcsbuff_fill, so that we will wind up setting PTR
- to the location corresponding to the old PTREND, so
- that we don't search the same bytes again. */
- ptr = rcsbuf_fill (rcsbuf, ptrend, keyp, valp);
- if (ptr == NULL)
- error (1, 0,
- "EOF while looking for end of string in RCS file %s",
- rcsbuf->filename);
- ptrend = rcsbuf->ptrend;
- }
-
- /* Handle the special case of an '@' right at the end of
- the known bytes. */
- if (pat + 1 >= ptrend)
- {
- ptr = rcsbuf_fill (rcsbuf, ptr, keyp, valp);
- if (ptr == NULL)
- error (1, 0, "EOF in value in RCS file %s",
- rcsbuf->filename);
- ptrend = rcsbuf->ptrend;
- }
-
- if (pat[1] != '@')
- break;
-
- /* We found an '@' pair in the string. Keep looking. */
- ptr = pat + 2;
- }
-
- /* Here PAT points to the final '@' in the string. */
- ptr = pat + 1;
- }
-
-#undef my_whitespace
-}
-
-/* Read an RCS revision number from an RCS file. This sets *REVP to
- point to the revision number; it will point to space that is
- managed by the rcsbuf functions, and is only good until the next
- call to rcsbuf_getkey or rcsbuf_getrevnum.
-
- This function returns 1 on success, or 0 on EOF. If there is an
- error reading the file, or an EOF in an unexpected location, it
- gives a fatal error. */
-
-static int
-rcsbuf_getrevnum (rcsbuf, revp)
- struct rcsbuffer *rcsbuf;
- char **revp;
-{
- char *ptr, *ptrend;
- char c;
-
- ptr = rcsbuf->ptr;
- ptrend = rcsbuf->ptrend;
-
- *revp = NULL;
-
- /* Skip leading whitespace. */
-
- while (1)
- {
- if (ptr >= ptrend)
- {
- ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, (char **) NULL);
- if (ptr == NULL)
- return 0;
- ptrend = rcsbuf->ptrend;
- }
-
- c = *ptr;
- if (! whitespace (c))
- break;
-
- ++ptr;
- }
-
- if (! isdigit ((unsigned char) c) && c != '.')
- error (1, 0,
- "\
-unexpected '\\x%x' reading revision number in RCS file %s",
- c, rcsbuf->filename);
-
- *revp = ptr;
-
- do
- {
- ++ptr;
- if (ptr >= ptrend)
- {
- ptr = rcsbuf_fill (rcsbuf, ptr, revp, (char **) NULL);
- if (ptr == NULL)
- error (1, 0,
- "unexpected EOF reading revision number in RCS file %s",
- rcsbuf->filename);
- ptrend = rcsbuf->ptrend;
- }
-
- c = *ptr;
- }
- while (isdigit ((unsigned char) c) || c == '.');
-
- if (! whitespace (c))
- error (1, 0, "\
-unexpected '\\x%x' reading revision number in RCS file %s",
- c, rcsbuf->filename);
-
- *ptr = '\0';
-
- rcsbuf->ptr = ptr + 1;
-
- return 1;
-}
-
-/* Fill RCSBUF_BUFFER with bytes from the file associated with RCSBUF,
- updating PTR and the PTREND field. If KEYP and *KEYP are not NULL,
- then *KEYP points into the buffer, and must be adjusted if the
- buffer is changed. Likewise for VALP. Returns the new value of
- PTR, or NULL on error. */
-
-static char *
-rcsbuf_fill (rcsbuf, ptr, keyp, valp)
- struct rcsbuffer *rcsbuf;
- char *ptr;
- char **keyp;
- char **valp;
-{
- int got;
-
- if (rcsbuf->mmapped)
- return NULL;
-
- if (rcsbuf->ptrend - rcsbuf_buffer + RCSBUF_BUFSIZE > rcsbuf_buffer_size)
- {
- int poff, peoff, koff, voff;
-
- poff = ptr - rcsbuf_buffer;
- peoff = rcsbuf->ptrend - rcsbuf_buffer;
- koff = keyp == NULL ? 0 : *keyp - rcsbuf_buffer;
- voff = valp == NULL ? 0 : *valp - rcsbuf_buffer;
-
- expand_string (&rcsbuf_buffer, &rcsbuf_buffer_size,
- rcsbuf_buffer_size + RCSBUF_BUFSIZE);
-
- ptr = rcsbuf_buffer + poff;
- rcsbuf->ptrend = rcsbuf_buffer + peoff;
- if (keyp != NULL)
- *keyp = rcsbuf_buffer + koff;
- if (valp != NULL)
- *valp = rcsbuf_buffer + voff;
- }
-
- got = fread (rcsbuf->ptrend, 1, RCSBUF_BUFSIZE, rcsbuf->fp);
- if (got == 0)
- {
- if (ferror (rcsbuf->fp))
- error (1, errno, "cannot read %s", rcsbuf->filename);
- return NULL;
- }
-
- rcsbuf->ptrend += got;
-
- return ptr;
-}
-
-/* Test whether the last value returned by rcsbuf_getkey is a composite
- value or not. */
-
-static int
-rcsbuf_valcmp (rcsbuf)
- struct rcsbuffer *rcsbuf;
-{
- return rcsbuf->at_string && rcsbuf->embedded_at < 0;
-}
-
-/* Copy the value VAL returned by rcsbuf_getkey into a memory buffer,
- returning the memory buffer. Polish the value like
- rcsbuf_valpolish, q.v. */
-
-static char *
-rcsbuf_valcopy (rcsbuf, val, polish, lenp)
- struct rcsbuffer *rcsbuf;
- char *val;
- int polish;
- size_t *lenp;
-{
- size_t vlen;
- int embedded_at;
- char *ret;
-
- if (val == NULL)
- {
- if (lenp != NULL)
- *lenp = 0;
- return NULL;
- }
-
- vlen = rcsbuf->vlen;
- embedded_at = rcsbuf->embedded_at < 0 ? 0 : rcsbuf->embedded_at;
-
- ret = xmalloc (vlen - embedded_at + 1);
-
- if (rcsbuf->at_string ? embedded_at == 0 : ! polish)
- {
- /* No special action to take. */
- memcpy (ret, val, vlen + 1);
- if (lenp != NULL)
- *lenp = vlen;
- return ret;
- }
-
- rcsbuf_valpolish_internal (rcsbuf, ret, val, lenp);
- return ret;
-}
-
-/* Polish the value VAL returned by rcsbuf_getkey. The POLISH
- parameter is non-zero if multiple embedded whitespace characters
- should be compressed into a single whitespace character. Note that
- leading and trailing whitespace was already removed by
- rcsbuf_getkey. Within an '@' string, pairs of '@' characters are
- compressed into a single '@' character regardless of the value of
- POLISH. If LENP is not NULL, set *LENP to the length of the value. */
-
-static void
-rcsbuf_valpolish (rcsbuf, val, polish, lenp)
- struct rcsbuffer *rcsbuf;
- char *val;
- int polish;
- size_t *lenp;
-{
- if (val == NULL)
- {
- if (lenp != NULL)
- *lenp= 0;
- return;
- }
-
- if (rcsbuf->at_string ? rcsbuf->embedded_at == 0 : ! polish)
- {
- /* No special action to take. */
- if (lenp != NULL)
- *lenp = rcsbuf->vlen;
- return;
- }
-
- rcsbuf_valpolish_internal (rcsbuf, val, val, lenp);
-}
-
-/* Internal polishing routine, called from rcsbuf_valcopy and
- rcsbuf_valpolish. */
-
-static void
-rcsbuf_valpolish_internal (rcsbuf, to, from, lenp)
- struct rcsbuffer *rcsbuf;
- char *to;
- const char *from;
- size_t *lenp;
-{
- size_t len;
-
- len = rcsbuf->vlen;
-
- if (! rcsbuf->at_string)
- {
- char *orig_to;
- size_t clen;
-
- orig_to = to;
-
- for (clen = len; clen > 0; ++from, --clen)
- {
- char c;
-
- c = *from;
- if (whitespace (c))
- {
- /* Note that we know that clen can not drop to zero
- while we have whitespace, because we know there is
- no trailing whitespace. */
- while (whitespace (from[1]))
- {
- ++from;
- --clen;
- }
- c = ' ';
- }
- *to++ = c;
- }
-
- *to = '\0';
-
- if (lenp != NULL)
- *lenp = to - orig_to;
- }
- else
- {
- const char *orig_from;
- char *orig_to;
- int embedded_at;
- size_t clen;
-
- orig_from = from;
- orig_to = to;
-
- embedded_at = rcsbuf->embedded_at;
- assert (embedded_at > 0);
-
- if (lenp != NULL)
- *lenp = len - embedded_at;
-
- for (clen = len; clen > 0; ++from, --clen)
- {
- char c;
-
- c = *from;
- *to++ = c;
- if (c == '@')
- {
- ++from;
-
- /* Sanity check.
- *
- * FIXME: I restored this to an abort from an assert based on
- * advice from Larry Jones that asserts should not be used to
- * confirm the validity of an RCS file... This leaves two
- * issues here: 1) I am uncertain that the fact that we will
- * only find double '@'s hasn't already been confirmed; and:
- * 2) If this is the proper place to spot the error in the RCS
- * file, then we should print a much clearer error here for the
- * user!!!!!!!
- *
- * - DRP
- */
- if (*from != '@' || clen == 0)
- abort ();
-
- --clen;
-
- --embedded_at;
- if (embedded_at == 0)
- {
- /* We've found all the embedded '@' characters.
- We can just memcpy the rest of the buffer after
- this '@' character. */
- if (orig_to != orig_from)
- memcpy (to, from + 1, clen - 1);
- else
- memmove (to, from + 1, clen - 1);
- from += clen;
- to += clen - 1;
- break;
- }
- }
- }
-
- /* Sanity check. */
- assert (from == orig_from + len
- && to == orig_to + (len - rcsbuf->embedded_at));
-
- *to = '\0';
- }
-}
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
-
-/* Copy the next word from the value VALP returned by rcsbuf_getkey into a
- memory buffer, updating VALP and returning the memory buffer. Return
- NULL when there are no more words. */
-
-static char *
-rcsbuf_valword (rcsbuf, valp)
- struct rcsbuffer *rcsbuf;
- char **valp;
-{
- register const char * const my_spacetab = spacetab;
- register char *ptr, *pat;
- char c;
-
-# define my_whitespace(c) (my_spacetab[(unsigned char)c] != 0)
-
- if (*valp == NULL)
- return NULL;
-
- for (ptr = *valp; my_whitespace (*ptr); ++ptr) ;
- if (*ptr == '\0')
- {
- assert (ptr - *valp == rcsbuf->vlen);
- *valp = NULL;
- rcsbuf->vlen = 0;
- return NULL;
- }
-
- /* PTR now points to the start of a value. Find out whether it is
- a num, an id, a string or a colon. */
- c = *ptr;
- if (c == ':')
- {
- rcsbuf->vlen -= ++ptr - *valp;
- *valp = ptr;
- return xstrdup (":");
- }
-
- if (c == '@')
- {
- int embedded_at = 0;
- size_t vlen;
-
- pat = ++ptr;
- while ((pat = strchr (pat, '@')) != NULL)
- {
- if (pat[1] != '@')
- break;
- ++embedded_at;
- pat += 2;
- }
-
- /* Here PAT points to the final '@' in the string. */
- *pat++ = '\0';
- assert (rcsbuf->at_string);
- vlen = rcsbuf->vlen - (pat - *valp);
- rcsbuf->vlen = pat - ptr - 1;
- rcsbuf->embedded_at = embedded_at;
- ptr = rcsbuf_valcopy (rcsbuf, ptr, 0, (size_t *) NULL);
- *valp = pat;
- rcsbuf->vlen = vlen;
- if (strchr (pat, '@') == NULL)
- rcsbuf->at_string = 0;
- else
- rcsbuf->embedded_at = -1;
- return ptr;
- }
-
- /* *PTR is neither `:', `;' nor `@', so it should be the start of a num
- or an id. Make sure it is not another special character. */
- if (c == '$' || c == '.' || c == ',')
- {
- error (1, 0, "invalid special character in RCS field in %s",
- rcsbuf->filename);
- }
-
- pat = ptr;
- while (1)
- {
- /* Legitimate ID characters are digits, dots and any `graphic
- printing character that is not a special.' This test ought
- to do the trick. */
- c = *++pat;
- if (!isprint ((unsigned char) c) ||
- c == ';' || c == '$' || c == ',' || c == '@' || c == ':')
- break;
- }
-
- /* PAT points to the last non-id character in this word, and C is
- the character in its memory cell. Check to make sure that it
- is a legitimate word delimiter -- whitespace or end. */
- if (c != '\0' && !my_whitespace (c))
- error (1, 0, "invalid special character in RCS field in %s",
- rcsbuf->filename);
-
- *pat = '\0';
- rcsbuf->vlen -= pat - *valp;
- *valp = pat;
- return xstrdup (ptr);
-
-# undef my_whitespace
-}
-
-#endif
-
-/* Return the current position of an rcsbuf. */
-
-static unsigned long
-rcsbuf_ftell (rcsbuf)
- struct rcsbuffer *rcsbuf;
-{
- return rcsbuf->pos + (rcsbuf->ptr - rcsbuf_buffer);
-}
-
-/* Return a pointer to any data buffered for RCSBUF, along with the
- length. */
-
-static void
-rcsbuf_get_buffered (rcsbuf, datap, lenp)
- struct rcsbuffer *rcsbuf;
- char **datap;
- size_t *lenp;
-{
- *datap = rcsbuf->ptr;
- *lenp = rcsbuf->ptrend - rcsbuf->ptr;
-}
-
-/* CVS optimizes by quickly reading some header information from a
- file. If it decides it needs to do more with the file, it reopens
- it. We speed that up here by maintaining a cache of a single open
- file, to save the time it takes to reopen the file in the common
- case. */
-
-static RCSNode *cached_rcs;
-static struct rcsbuffer cached_rcsbuf;
-
-/* Cache RCS and RCSBUF. This takes responsibility for closing
- RCSBUF->FP. */
-
-static void
-rcsbuf_cache (rcs, rcsbuf)
- RCSNode *rcs;
- struct rcsbuffer *rcsbuf;
-{
- if (cached_rcs != NULL)
- rcsbuf_cache_close ();
- cached_rcs = rcs;
- ++rcs->refcount;
- cached_rcsbuf = *rcsbuf;
-}
-
-/* If there is anything in the cache, close it. */
-
-static void
-rcsbuf_cache_close ()
-{
- if (cached_rcs != NULL)
- {
- rcsbuf_close (&cached_rcsbuf);
- if (fclose (cached_rcsbuf.fp) != 0)
- error (0, errno, "cannot close %s", cached_rcsbuf.filename);
- freercsnode (&cached_rcs);
- cached_rcs = NULL;
- }
-}
-
-/* Open an rcsbuffer for RCS, getting it from the cache if possible.
- Set *FPP to the file, and *RCSBUFP to the rcsbuf. The file should
- be put at position POS. */
-
-static void
-rcsbuf_cache_open (rcs, pos, pfp, prcsbuf)
- RCSNode *rcs;
- long pos;
- FILE **pfp;
- struct rcsbuffer *prcsbuf;
-{
- if (cached_rcs == rcs && !cached_rcsbuf.mmapped)
- {
- if (rcsbuf_ftell (&cached_rcsbuf) != pos)
- {
- if (fseek (cached_rcsbuf.fp, pos, SEEK_SET) != 0)
- error (1, 0, "cannot fseek RCS file %s",
- cached_rcsbuf.filename);
- cached_rcsbuf.ptr = rcsbuf_buffer;
- cached_rcsbuf.ptrend = rcsbuf_buffer;
- cached_rcsbuf.pos = pos;
- }
- *pfp = cached_rcsbuf.fp;
-
- /* When RCS_parse opens a file using fopen_case, it frees the
- filename which we cached in CACHED_RCSBUF and stores a new
- file name in RCS->PATH. We avoid problems here by always
- copying the filename over. FIXME: This is hackish. */
- cached_rcsbuf.filename = rcs->path;
-
- *prcsbuf = cached_rcsbuf;
-
- cached_rcs = NULL;
-
- /* Removing RCS from the cache removes a reference to it. */
- --rcs->refcount;
- if (rcs->refcount <= 0)
- error (1, 0, "rcsbuf_cache_open: internal error");
- }
- else
- {
- /* FIXME: If these routines can be rewritten to not write to the
- * rcs file buffer, there would be a considerably larger memory savings
- * from using mmap since the shared file would never need be copied to
- * process memory.
- *
- * If this happens, cached mmapped buffers would be usable, but don't
- * forget to make sure rcs->pos < pos here...
- */
- if (cached_rcs != NULL)
- rcsbuf_cache_close ();
-
- *pfp = CVS_FOPEN (rcs->path, FOPEN_BINARY_READ);
- if (*pfp == NULL)
- error (1, 0, "unable to reopen `%s'", rcs->path);
- if (pos != 0)
- {
- if (fseek (*pfp, pos, SEEK_SET) != 0)
- error (1, 0, "cannot fseek RCS file %s", rcs->path);
- }
- rcsbuf_open (prcsbuf, *pfp, rcs->path, pos);
- }
-}
-
-
-/*
- * process the symbols list of the rcs file
- */
-static void
-do_symbols (list, val)
- List *list;
- char *val;
-{
- Node *p;
- char *cp = val;
- char *tag, *rev;
-
- assert (cp);
-
- for (;;)
- {
- /* skip leading whitespace */
- while (whitespace (*cp))
- cp++;
-
- /* if we got to the end, we are done */
- if (*cp == '\0')
- break;
-
- /* split it up into tag and rev */
- tag = cp;
- cp = strchr (cp, ':');
- *cp++ = '\0';
- rev = cp;
- while (!whitespace (*cp) && *cp != '\0')
- cp++;
- if (*cp != '\0')
- *cp++ = '\0';
-
- /* make a new node and add it to the list */
- p = getnode ();
- p->key = xstrdup (tag);
- p->data = xstrdup (rev);
- (void) addnode (list, p);
- }
-}
-
-/*
- * process the locks list of the rcs file
- * Like do_symbols, but hash entries are keyed backwards: i.e.
- * an entry like `user:rev' is keyed on REV rather than on USER.
- */
-static void
-do_locks (list, val)
- List *list;
- char *val;
-{
- Node *p;
- char *cp = val;
- char *user, *rev;
-
- assert (cp);
-
- for (;;)
- {
- /* skip leading whitespace */
- while (whitespace (*cp))
- cp++;
-
- /* if we got to the end, we are done */
- if (*cp == '\0')
- break;
-
- /* split it up into user and rev */
- user = cp;
- cp = strchr (cp, ':');
- *cp++ = '\0';
- rev = cp;
- while (!whitespace (*cp) && *cp != '\0')
- cp++;
- if (*cp != '\0')
- *cp++ = '\0';
-
- /* make a new node and add it to the list */
- p = getnode ();
- p->key = xstrdup (rev);
- p->data = xstrdup (user);
- (void) addnode (list, p);
- }
-}
-
-/*
- * process the branches list of a revision delta
- */
-static void
-do_branches (list, val)
- List *list;
- char *val;
-{
- Node *p;
- char *cp = val;
- char *branch;
-
- for (;;)
- {
- /* skip leading whitespace */
- while (whitespace (*cp))
- cp++;
-
- /* if we got to the end, we are done */
- if (*cp == '\0')
- break;
-
- /* find the end of this branch */
- branch = cp;
- while (!whitespace (*cp) && *cp != '\0')
- cp++;
- if (*cp != '\0')
- *cp++ = '\0';
-
- /* make a new node and add it to the list */
- p = getnode ();
- p->key = xstrdup (branch);
- (void) addnode (list, p);
- }
-}
-
-/*
- * Version Number
- *
- * Returns the requested version number of the RCS file, satisfying tags and/or
- * dates, and walking branches, if necessary.
- *
- * The result is returned; null-string if error.
- */
-char *
-RCS_getversion (rcs, tag, date, force_tag_match, simple_tag)
- RCSNode *rcs;
- const char *tag;
- const char *date;
- int force_tag_match;
- int *simple_tag;
-{
- if (simple_tag != NULL)
- *simple_tag = 0;
-
- /* make sure we have something to look at... */
- assert (rcs != NULL);
-
- if (tag && date)
- {
- char *branch, *rev;
-
- if (! RCS_nodeisbranch (rcs, tag))
- {
- /* We can't get a particular date if the tag is not a
- branch. */
- return NULL;
- }
-
- /* Work out the branch. */
- if (! isdigit ((unsigned char) tag[0]))
- branch = RCS_whatbranch (rcs, tag);
- else
- branch = xstrdup (tag);
-
- /* Fetch the revision of branch as of date. */
- rev = RCS_getdatebranch (rcs, date, branch);
- free (branch);
- return (rev);
- }
- else if (tag)
- return RCS_gettag (rcs, tag, force_tag_match, simple_tag);
- else if (date)
- return RCS_getdate (rcs, date, force_tag_match);
- else
- return RCS_head (rcs);
-
-}
-
-
-
-/*
- * Get existing revision number corresponding to tag or revision.
- * Similar to RCS_gettag but less interpretation imposed.
- * For example:
- * -- If tag designates a magic branch, RCS_tag2rev
- * returns the magic branch number.
- * -- If tag is a branch tag, returns the branch number, not
- * the revision of the head of the branch.
- * If tag or revision is not valid or does not exist in file,
- * return NULL.
- */
-char *
-RCS_tag2rev (rcs, tag)
- RCSNode *rcs;
- char *tag;
-{
- char *rev, *pa, *pb;
- int i;
-
- assert (rcs != NULL);
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- /* If a valid revision, try to look it up */
- if ( RCS_valid_rev (tag) )
- {
- /* Make a copy so we can scribble on it */
- rev = xstrdup (tag);
-
- /* If revision exists, return the copy */
- if (RCS_exist_rev (rcs, tag))
- return rev;
-
- /* Nope, none such. If tag is not a branch we're done. */
- i = numdots (rev);
- if ((i & 1) == 1 )
- {
- pa = strrchr (rev, '.');
- if (i == 1 || *(pa-1) != RCS_MAGIC_BRANCH || *(pa-2) != '.')
- {
- free (rev);
- error (1, 0, "revision `%s' does not exist", tag);
- }
- }
-
- /* Try for a real (that is, exists in the RCS deltas) branch
- (RCS_exist_rev just checks for real revisions and revisions
- which have tags pointing to them). */
- pa = RCS_getbranch (rcs, rev, 1);
- if (pa != NULL)
- {
- free (pa);
- return rev;
- }
-
- /* Tag is branch, but does not exist, try corresponding
- * magic branch tag.
- *
- * FIXME: assumes all magic branches are of
- * form "n.n.n ... .0.n". I'll fix if somebody can
- * send me a method to get a magic branch tag with
- * the 0 in some other position -- <dan@gasboy.com>
- */
- pa = strrchr (rev, '.');
- if (!pa)
- /* This might happen, for instance, if an RCS file only contained
- * revisions 2.x and higher, and REV == "1".
- */
- error (1, 0, "revision `%s' does not exist", tag);
-
- pb = xmalloc (strlen (rev) + 3);
- *pa++ = 0;
- (void) sprintf (pb, "%s.%d.%s", rev, RCS_MAGIC_BRANCH, pa);
- free (rev);
- rev = pb;
- if (RCS_exist_rev (rcs, rev))
- return rev;
- error (1, 0, "revision `%s' does not exist", tag);
- }
-
-
- RCS_check_tag (tag); /* exit if not a valid tag */
-
- /* If tag is "HEAD", special case to get head RCS revision */
- if (tag && STREQ (tag, TAG_HEAD))
- return (RCS_head (rcs));
-
- /* If valid tag let translate_symtag say yea or nay. */
- rev = translate_symtag (rcs, tag);
-
- if (rev)
- return rev;
-
- /* Trust the caller to print warnings. */
- return NULL;
-}
-
-/*
- * Find the revision for a specific tag.
- * If force_tag_match is set, return NULL if an exact match is not
- * possible otherwise return RCS_head (). We are careful to look for
- * and handle "magic" revisions specially.
- *
- * If the matched tag is a branch tag, find the head of the branch.
- *
- * Returns pointer to newly malloc'd string, or NULL.
- */
-char *
-RCS_gettag (rcs, symtag, force_tag_match, simple_tag)
- RCSNode *rcs;
- const char *symtag;
- int force_tag_match;
- int *simple_tag;
-{
- char *tag;
-
- if (simple_tag != NULL)
- *simple_tag = 0;
-
- /* make sure we have something to look at... */
- assert (rcs != NULL);
-
- /* XXX this is probably not necessary, --jtc */
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- /* If symtag is "HEAD", special case to get head RCS revision */
- if (symtag && STREQ (symtag, TAG_HEAD))
-#if 0 /* This #if 0 is only in the Cygnus code. Why? Death support? */
- if (force_tag_match && (rcs->flags & VALID) && (rcs->flags & INATTIC))
- return ((char *) NULL); /* head request for removed file */
- else
-#endif
- return RCS_head (rcs);
-
- if (!isdigit ((unsigned char) symtag[0]))
- {
- char *version;
-
- /* If we got a symbolic tag, resolve it to a numeric */
- version = translate_symtag (rcs, symtag);
- if (version != NULL)
- {
- int dots;
- char *magic, *branch, *cp;
-
- tag = version;
-
- /*
- * If this is a magic revision, we turn it into either its
- * physical branch equivalent (if one exists) or into
- * its base revision, which we assume exists.
- */
- dots = numdots (tag);
- if (dots > 2 && (dots & 1) != 0)
- {
- branch = strrchr (tag, '.');
- cp = branch++ - 1;
- while (*cp != '.')
- cp--;
-
- /* see if we have .magic-branch. (".0.") */
- magic = xmalloc (strlen (tag) + 1);
- (void) sprintf (magic, ".%d.", RCS_MAGIC_BRANCH);
- if (strncmp (magic, cp, strlen (magic)) == 0)
- {
- /* it's magic. See if the branch exists */
- *cp = '\0'; /* turn it into a revision */
- (void) sprintf (magic, "%s.%s", tag, branch);
- branch = RCS_getbranch (rcs, magic, 1);
- free (magic);
- if (branch != NULL)
- {
- free (tag);
- return branch;
- }
- return tag;
- }
- free (magic);
- }
- }
- else
- {
- /* The tag wasn't there, so return the head or NULL */
- if (force_tag_match)
- return NULL;
- else
- return RCS_head (rcs);
- }
- }
- else
- tag = xstrdup (symtag);
-
- /* tag is always allocated and numeric now. */
-
- /*
- * numeric tag processing:
- * 1) revision number - just return it
- * 2) branch number - find head of branch
- */
-
- /* strip trailing dots */
- while (tag[strlen (tag) - 1] == '.')
- tag[strlen (tag) - 1] = '\0';
-
- if ((numdots (tag) & 1) == 0)
- {
- char *branch;
-
- /* we have a branch tag, so we need to walk the branch */
- branch = RCS_getbranch (rcs, tag, force_tag_match);
- free (tag);
- return branch;
- }
- else
- {
- Node *p;
-
- /* we have a revision tag, so make sure it exists */
- p = findnode (rcs->versions, tag);
- if (p != NULL)
- {
- /* We have found a numeric revision for the revision tag.
- To support expanding the RCS keyword Name, if
- SIMPLE_TAG is not NULL, tell the the caller that this
- is a simple tag which co will recognize. FIXME: Are
- there other cases in which we should set this? In
- particular, what if we expand RCS keywords internally
- without calling co? */
- if (simple_tag != NULL)
- *simple_tag = 1;
- return tag;
- }
- else
- {
- /* The revision wasn't there, so return the head or NULL */
- free (tag);
- if (force_tag_match)
- return NULL;
- else
- return RCS_head (rcs);
- }
- }
-}
-
-/*
- * Return a "magic" revision as a virtual branch off of REV for the RCS file.
- * A "magic" revision is one which is unique in the RCS file. By unique, I
- * mean we return a revision which:
- * - has a branch of 0 (see rcs.h RCS_MAGIC_BRANCH)
- * - has a revision component which is not an existing branch off REV
- * - has a revision component which is not an existing magic revision
- * - is an even-numbered revision, to avoid conflicts with vendor branches
- * The first point is what makes it "magic".
- *
- * As an example, if we pass in 1.37 as REV, we will look for an existing
- * branch called 1.37.2. If it did not exist, we would look for an
- * existing symbolic tag with a numeric part equal to 1.37.0.2. If that
- * didn't exist, then we know that the 1.37.2 branch can be reserved by
- * creating a symbolic tag with 1.37.0.2 as the numeric part.
- *
- * This allows us to fork development with very little overhead -- just a
- * symbolic tag is used in the RCS file. When a commit is done, a physical
- * branch is dynamically created to hold the new revision.
- *
- * Note: We assume that REV is an RCS revision and not a branch number.
- */
-static char *check_rev;
-char *
-RCS_magicrev (rcs, rev)
- RCSNode *rcs;
- char *rev;
-{
- int rev_num;
- char *xrev, *test_branch, *local_branch_num;
-
- xrev = xmalloc (strlen (rev) + 14); /* enough for .0.number */
- check_rev = xrev;
-
- local_branch_num = getenv("CVS_LOCAL_BRANCH_NUM");
- if (local_branch_num)
- {
- rev_num = atoi(local_branch_num);
- if (rev_num < 2)
- rev_num = 2;
- else
- rev_num &= ~1;
- }
- else
- rev_num = 2;
-
- /* only look at even numbered branches */
- for ( ; ; rev_num += 2)
- {
- /* see if the physical branch exists */
- (void) sprintf (xrev, "%s.%d", rev, rev_num);
- test_branch = RCS_getbranch (rcs, xrev, 1);
- if (test_branch != NULL) /* it did, so keep looking */
- {
- free (test_branch);
- continue;
- }
-
- /* now, create a "magic" revision */
- (void) sprintf (xrev, "%s.%d.%d", rev, RCS_MAGIC_BRANCH, rev_num);
-
- /* walk the symbols list to see if a magic one already exists */
- if (walklist (RCS_symbols(rcs), checkmagic_proc, NULL) != 0)
- continue;
-
- /* we found a free magic branch. Claim it as ours */
- return (xrev);
- }
-}
-
-/*
- * walklist proc to look for a match in the symbols list.
- * Returns 0 if the symbol does not match, 1 if it does.
- */
-static int
-checkmagic_proc (p, closure)
- Node *p;
- void *closure;
-{
- if (STREQ (check_rev, p->data))
- return (1);
- else
- return (0);
-}
-
-/*
- * Given an RCSNode, returns non-zero if the specified revision number
- * or symbolic tag resolves to a "branch" within the rcs file.
- *
- * FIXME: this is the same as RCS_nodeisbranch except for the special
- * case for handling a null rcsnode.
- */
-int
-RCS_isbranch (rcs, rev)
- RCSNode *rcs;
- const char *rev;
-{
- /* numeric revisions are easy -- even number of dots is a branch */
- if (isdigit ((unsigned char) *rev))
- return ((numdots (rev) & 1) == 0);
-
- /* assume a revision if you can't find the RCS info */
- if (rcs == NULL)
- return (0);
-
- /* now, look for a match in the symbols list */
- return (RCS_nodeisbranch (rcs, rev));
-}
-
-/*
- * Given an RCSNode, returns non-zero if the specified revision number
- * or symbolic tag resolves to a "branch" within the rcs file. We do
- * take into account any magic branches as well.
- */
-int
-RCS_nodeisbranch (rcs, rev)
- RCSNode *rcs;
- const char *rev;
-{
- int dots;
- char *version;
-
- assert (rcs != NULL);
-
- /* numeric revisions are easy -- even number of dots is a branch */
- if (isdigit ((unsigned char) *rev))
- return ((numdots (rev) & 1) == 0);
-
- version = translate_symtag (rcs, rev);
- if (version == NULL)
- return (0);
- dots = numdots (version);
- if ((dots & 1) == 0)
- {
- free (version);
- return (1);
- }
-
- /* got a symbolic tag match, but it's not a branch; see if it's magic */
- if (dots > 2)
- {
- char *magic;
- char *branch = strrchr (version, '.');
- char *cp = branch - 1;
- while (*cp != '.')
- cp--;
-
- /* see if we have .magic-branch. (".0.") */
- magic = xmalloc (strlen (version) + 1);
- (void) sprintf (magic, ".%d.", RCS_MAGIC_BRANCH);
- if (strncmp (magic, cp, strlen (magic)) == 0)
- {
- free (magic);
- free (version);
- return (1);
- }
- free (magic);
- }
- free (version);
- return (0);
-}
-
-/*
- * Returns a pointer to malloc'ed memory which contains the branch
- * for the specified *symbolic* tag. Magic branches are handled correctly.
- */
-char *
-RCS_whatbranch (rcs, rev)
- RCSNode *rcs;
- const char *rev;
-{
- char *version;
- int dots;
-
- /* assume no branch if you can't find the RCS info */
- if (rcs == NULL)
- return ((char *) NULL);
-
- /* now, look for a match in the symbols list */
- version = translate_symtag (rcs, rev);
- if (version == NULL)
- return ((char *) NULL);
- dots = numdots (version);
- if ((dots & 1) == 0)
- return (version);
-
- /* got a symbolic tag match, but it's not a branch; see if it's magic */
- if (dots > 2)
- {
- char *magic;
- char *branch = strrchr (version, '.');
- char *cp = branch++ - 1;
- while (*cp != '.')
- cp--;
-
- /* see if we have .magic-branch. (".0.") */
- magic = xmalloc (strlen (version) + 1);
- (void) sprintf (magic, ".%d.", RCS_MAGIC_BRANCH);
- if (strncmp (magic, cp, strlen (magic)) == 0)
- {
- /* yep. it's magic. now, construct the real branch */
- *cp = '\0'; /* turn it into a revision */
- (void) sprintf (magic, "%s.%s", version, branch);
- free (version);
- return (magic);
- }
- free (magic);
- }
- free (version);
- return ((char *) NULL);
-}
-
-/*
- * Get the head of the specified branch. If the branch does not exist,
- * return NULL or RCS_head depending on force_tag_match.
- * Returns NULL or a newly malloc'd string.
- */
-char *
-RCS_getbranch (rcs, tag, force_tag_match)
- RCSNode *rcs;
- const char *tag;
- int force_tag_match;
-{
- Node *p, *head;
- RCSVers *vn;
- char *xtag;
- char *nextvers;
- char *cp;
-
- /* make sure we have something to look at... */
- assert (rcs != NULL);
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- /* find out if the tag contains a dot, or is on the trunk */
- cp = strrchr (tag, '.');
-
- /* trunk processing is the special case */
- if (cp == NULL)
- {
- xtag = xmalloc (strlen (tag) + 1 + 1); /* +1 for an extra . */
- (void) strcpy (xtag, tag);
- (void) strcat (xtag, ".");
- for (cp = rcs->head; cp != NULL;)
- {
- if (strncmp (xtag, cp, strlen (xtag)) == 0)
- break;
- p = findnode (rcs->versions, cp);
- if (p == NULL)
- {
- free (xtag);
- if (force_tag_match)
- return (NULL);
- else
- return (RCS_head (rcs));
- }
- vn = p->data;
- cp = vn->next;
- }
- free (xtag);
- if (cp == NULL)
- {
- if (force_tag_match)
- return (NULL);
- else
- return (RCS_head (rcs));
- }
- return (xstrdup (cp));
- }
-
- /* if it had a `.', terminate the string so we have the base revision */
- *cp = '\0';
-
- /* look up the revision this branch is based on */
- p = findnode (rcs->versions, tag);
-
- /* put the . back so we have the branch again */
- *cp = '.';
-
- if (p == NULL)
- {
- /* if the base revision didn't exist, return head or NULL */
- if (force_tag_match)
- return (NULL);
- else
- return (RCS_head (rcs));
- }
-
- /* find the first element of the branch we are looking for */
- vn = p->data;
- if (vn->branches == NULL)
- return (NULL);
- xtag = xmalloc (strlen (tag) + 1 + 1); /* 1 for the extra '.' */
- (void) strcpy (xtag, tag);
- (void) strcat (xtag, ".");
- head = vn->branches->list;
- for (p = head->next; p != head; p = p->next)
- if (strncmp (p->key, xtag, strlen (xtag)) == 0)
- break;
- free (xtag);
-
- if (p == head)
- {
- /* we didn't find a match so return head or NULL */
- if (force_tag_match)
- return (NULL);
- else
- return (RCS_head (rcs));
- }
-
- /* now walk the next pointers of the branch */
- nextvers = p->key;
- do
- {
- p = findnode (rcs->versions, nextvers);
- if (p == NULL)
- {
- /* a link in the chain is missing - return head or NULL */
- if (force_tag_match)
- return (NULL);
- else
- return (RCS_head (rcs));
- }
- vn = p->data;
- nextvers = vn->next;
- } while (nextvers != NULL);
-
- /* we have the version in our hand, so go for it */
- return (xstrdup (vn->version));
-}
-
-/* Returns the head of the branch which REV is on. REV can be a
- branch tag or non-branch tag; symbolic or numeric.
-
- Returns a newly malloc'd string. Returns NULL if a symbolic name
- isn't found. */
-
-char *
-RCS_branch_head (rcs, rev)
- RCSNode *rcs;
- char *rev;
-{
- char *num;
- char *br;
- char *retval;
-
- assert (rcs != NULL);
-
- if (RCS_nodeisbranch (rcs, rev))
- return RCS_getbranch (rcs, rev, 1);
-
- if (isdigit ((unsigned char) *rev))
- num = xstrdup (rev);
- else
- {
- num = translate_symtag (rcs, rev);
- if (num == NULL)
- return NULL;
- }
- br = truncate_revnum (num);
- retval = RCS_getbranch (rcs, br, 1);
- free (br);
- free (num);
- return retval;
-}
-
-/* Get the branch point for a particular branch, that is the first
- revision on that branch. For example, RCS_getbranchpoint (rcs,
- "1.3.2") will normally return "1.3.2.1". TARGET may be either a
- branch number or a revision number; if a revnum, find the
- branchpoint of the branch to which TARGET belongs.
-
- Return RCS_head if TARGET is on the trunk or if the root node could
- not be found (this is sort of backwards from our behavior on a branch;
- the rationale is that the return value is a revision from which you
- can start walking the next fields and end up at TARGET).
- Return NULL on error. */
-
-static char *
-RCS_getbranchpoint (rcs, target)
- RCSNode *rcs;
- char *target;
-{
- char *branch, *bp;
- Node *vp;
- RCSVers *rev;
- int dots, isrevnum, brlen;
-
- dots = numdots (target);
- isrevnum = dots & 1;
-
- if (dots == 1)
- /* TARGET is a trunk revision; return rcs->head. */
- return (RCS_head (rcs));
-
- /* Get the revision number of the node at which TARGET's branch is
- rooted. If TARGET is a branch number, lop off the last field;
- if it's a revision number, lop off the last *two* fields. */
- branch = xstrdup (target);
- bp = strrchr (branch, '.');
- if (bp == NULL)
- error (1, 0, "%s: confused revision number %s",
- rcs->path, target);
- if (isrevnum)
- while (*--bp != '.')
- ;
- *bp = '\0';
-
- vp = findnode (rcs->versions, branch);
- if (vp == NULL)
- {
- error (0, 0, "%s: can't find branch point %s", rcs->path, target);
- free (branch);
- return NULL;
- }
- rev = vp->data;
-
- *bp++ = '.';
- while (*bp && *bp != '.')
- ++bp;
- brlen = bp - branch;
-
- vp = rev->branches->list->next;
- while (vp != rev->branches->list)
- {
- /* BRANCH may be a genuine branch number, e.g. `1.1.3', or
- maybe a full revision number, e.g. `1.1.3.6'. We have
- found our branch point if the first BRANCHLEN characters
- of the revision number match, *and* if the following
- character is a dot. */
- if (strncmp (vp->key, branch, brlen) == 0 && vp->key[brlen] == '.')
- break;
- vp = vp->next;
- }
-
- free (branch);
- if (vp == rev->branches->list)
- {
- error (0, 0, "%s: can't find branch point %s", rcs->path, target);
- return NULL;
- }
- else
- return (xstrdup (vp->key));
-}
-
-/*
- * Get the head of the RCS file. If branch is set, this is the head of the
- * branch, otherwise the real head.
- * Returns NULL or a newly malloc'd string.
- */
-char *
-RCS_head (rcs)
- RCSNode *rcs;
-{
- /* make sure we have something to look at... */
- assert (rcs != NULL);
-
- /*
- * NOTE: we call getbranch with force_tag_match set to avoid any
- * possibility of recursion
- */
- if (rcs->branch)
- return (RCS_getbranch (rcs, rcs->branch, 1));
- else
- return (xstrdup (rcs->head));
-}
-
-/*
- * Get the most recent revision, based on the supplied date, but use some
- * funky stuff and follow the vendor branch maybe
- */
-char *
-RCS_getdate (rcs, date, force_tag_match)
- RCSNode *rcs;
- const char *date;
- int force_tag_match;
-{
- char *cur_rev = NULL;
- char *retval = NULL;
- Node *p;
- RCSVers *vers = NULL;
-
- /* make sure we have something to look at... */
- assert (rcs != NULL);
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- /* if the head is on a branch, try the branch first */
- if (rcs->branch != NULL)
- {
- retval = RCS_getdatebranch (rcs, date, rcs->branch);
- if (retval != NULL)
- return (retval);
- }
-
- /* otherwise if we have a trunk, try it */
- if (rcs->head)
- {
- p = findnode (rcs->versions, rcs->head);
- if (p == NULL)
- {
- error (0, 0, "%s: head revision %s doesn't exist", rcs->path,
- rcs->head);
- }
- while (p != NULL)
- {
- /* if the date of this one is before date, take it */
- vers = p->data;
- if (RCS_datecmp (vers->date, date) <= 0)
- {
- cur_rev = vers->version;
- break;
- }
-
- /* if there is a next version, find the node */
- if (vers->next != NULL)
- p = findnode (rcs->versions, vers->next);
- else
- p = (Node *) NULL;
- }
- }
- else
- error (0, 0, "%s: no head revision", rcs->path);
-
- /*
- * at this point, either we have the revision we want, or we have the
- * first revision on the trunk (1.1?) in our hands, or we've come up
- * completely empty
- */
-
- /* if we found what we're looking for, and it's not 1.1 return it */
- if (cur_rev != NULL)
- {
- if (! STREQ (cur_rev, "1.1"))
- return (xstrdup (cur_rev));
-
- /* This is 1.1; if the date of 1.1 is not the same as that for the
- 1.1.1.1 version, then return 1.1. This happens when 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. */
- p = findnode (rcs->versions, "1.1.1.1");
- if (p)
- {
- char *date_1_1 = vers->date;
-
- assert (p->data != NULL);
-
- vers = p->data;
- if (RCS_datecmp (vers->date, date_1_1) != 0)
- return xstrdup ("1.1");
- }
- }
-
- /* look on the vendor branch */
- retval = RCS_getdatebranch (rcs, date, CVSBRANCH);
-
- /*
- * if we found a match, return it; otherwise, we return the first
- * revision on the trunk or NULL depending on force_tag_match and the
- * date of the first rev
- */
- if (retval != NULL)
- return (retval);
-
- if (vers && (!force_tag_match || RCS_datecmp (vers->date, date) <= 0))
- return xstrdup (vers->version);
- else
- return NULL;
-}
-
-
-
-/*
- * Look up the last element on a branch that was put in before the specified
- * date (return the rev or NULL)
- */
-static char *
-RCS_getdatebranch (rcs, date, branch)
- RCSNode *rcs;
- const char *date;
- const char *branch;
-{
- char *cur_rev = NULL;
- char *cp;
- char *xbranch, *xrev;
- Node *p;
- RCSVers *vers;
-
- /* look up the first revision on the branch */
- xrev = xstrdup (branch);
- cp = strrchr (xrev, '.');
- if (cp == NULL)
- {
- free (xrev);
- return (NULL);
- }
- *cp = '\0'; /* turn it into a revision */
-
- assert (rcs != NULL);
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- p = findnode (rcs->versions, xrev);
- free (xrev);
- if (p == NULL)
- return (NULL);
- vers = p->data;
-
- /* Tentatively use this revision, if it is early enough. */
- if (RCS_datecmp (vers->date, date) <= 0)
- cur_rev = vers->version;
-
- /* If no branches list, return now. This is what happens if the branch
- is a (magic) branch with no revisions yet. */
- if (vers->branches == NULL)
- return xstrdup (cur_rev);
-
- /* walk the branches list looking for the branch number */
- xbranch = xmalloc (strlen (branch) + 1 + 1); /* +1 for the extra dot */
- (void) strcpy (xbranch, branch);
- (void) strcat (xbranch, ".");
- for (p = vers->branches->list->next; p != vers->branches->list; p = p->next)
- if (strncmp (p->key, xbranch, strlen (xbranch)) == 0)
- break;
- free (xbranch);
- if (p == vers->branches->list)
- {
- /* This is what happens if the branch is a (magic) branch with
- no revisions yet. Similar to the case where vers->branches ==
- NULL, except here there was a another branch off the same
- branchpoint. */
- return xstrdup (cur_rev);
- }
-
- p = findnode (rcs->versions, p->key);
-
- /* walk the next pointers until you find the end, or the date is too late */
- while (p != NULL)
- {
- vers = p->data;
- if (RCS_datecmp (vers->date, date) <= 0)
- cur_rev = vers->version;
- else
- break;
-
- /* if there is a next version, find the node */
- if (vers->next != NULL)
- p = findnode (rcs->versions, vers->next);
- else
- p = (Node *) NULL;
- }
-
- /* Return whatever we found, which may be NULL. */
- return xstrdup (cur_rev);
-}
-
-
-
-/*
- * Compare two dates in RCS format. Beware the change in format on January 1,
- * 2000, when years go from 2-digit to full format.
- */
-int
-RCS_datecmp (date1, date2)
- const char *date1, *date2;
-{
- int length_diff = strlen (date1) - strlen (date2);
-
- return length_diff ? length_diff : strcmp (date1, date2);
-}
-
-
-
-/* Look up revision REV in RCS and return the date specified for the
- revision minus FUDGE seconds (FUDGE will generally be one, so that the
- logically previous revision will be found later, or zero, if we want
- the exact date).
-
- The return value is the date being returned as a time_t, or (time_t)-1
- on error (previously was documented as zero on error; I haven't checked
- the callers to make sure that they really check for (time_t)-1, but
- the latter is what this function really returns). If DATE is non-NULL,
- then it must point to MAXDATELEN characters, and we store the same
- return value there in DATEFORM format. */
-time_t
-RCS_getrevtime (rcs, rev, date, fudge)
- RCSNode *rcs;
- const char *rev;
- char *date;
- int fudge;
-{
- char tdate[MAXDATELEN];
- struct tm xtm, *ftm;
- time_t revdate = 0;
- Node *p;
- RCSVers *vers;
-
- /* make sure we have something to look at... */
- assert (rcs != NULL);
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- /* look up the revision */
- p = findnode (rcs->versions, rev);
- if (p == NULL)
- return (-1);
- vers = p->data;
-
- /* split up the date */
- if (sscanf (vers->date, SDATEFORM, &xtm.tm_year, &xtm.tm_mon,
- &xtm.tm_mday, &xtm.tm_hour, &xtm.tm_min, &xtm.tm_sec) != 6)
- error (1, 0, "%s: invalid date for revision %s (%s)", rcs->path,
- rev, vers->date);
-
- /* If the year is from 1900 to 1999, RCS files contain only two
- digits, and sscanf gives us a year from 0-99. If the year is
- 2000+, RCS files contain all four digits and we subtract 1900,
- because the tm_year field should contain years since 1900. */
-
- if (xtm.tm_year >= 100 && xtm.tm_year < 2000)
- error (0, 0, "%s: non-standard date format for revision %s (%s)",
- rcs->path, rev, vers->date);
- if (xtm.tm_year >= 1900)
- xtm.tm_year -= 1900;
-
- /* put the date in a form getdate can grok */
- (void) sprintf (tdate, "%d/%d/%d GMT %d:%d:%d", xtm.tm_mon,
- xtm.tm_mday, xtm.tm_year + 1900, xtm.tm_hour,
- xtm.tm_min, xtm.tm_sec);
-
- /* turn it into seconds since the epoch */
- revdate = get_date (tdate, (struct timeb *) NULL);
- if (revdate != (time_t) -1)
- {
- revdate -= fudge; /* remove "fudge" seconds */
- if (date)
- {
- /* put an appropriate string into ``date'' if we were given one */
- ftm = gmtime (&revdate);
- (void) sprintf (date, DATEFORM,
- ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
- ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
- ftm->tm_min, ftm->tm_sec);
- }
- }
- return revdate;
-}
-
-List *
-RCS_getlocks (rcs)
- RCSNode *rcs;
-{
- assert(rcs != NULL);
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- if (rcs->locks_data) {
- rcs->locks = getlist ();
- do_locks (rcs->locks, rcs->locks_data);
- free(rcs->locks_data);
- rcs->locks_data = NULL;
- }
-
- return rcs->locks;
-}
-
-List *
-RCS_symbols(rcs)
- RCSNode *rcs;
-{
- assert(rcs != NULL);
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- if (rcs->symbols_data) {
- rcs->symbols = getlist ();
- do_symbols (rcs->symbols, rcs->symbols_data);
- free(rcs->symbols_data);
- rcs->symbols_data = NULL;
- }
-
- return rcs->symbols;
-}
-
-/*
- * Return the version associated with a particular symbolic tag.
- * Returns NULL or a newly malloc'd string.
- */
-static char *
-translate_symtag (rcs, tag)
- RCSNode *rcs;
- const char *tag;
-{
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- if (rcs->symbols != NULL)
- {
- Node *p;
-
- /* The symbols have already been converted into a list. */
- p = findnode (rcs->symbols, tag);
- if (p == NULL)
- return NULL;
-
- return xstrdup (p->data);
- }
-
- if (rcs->symbols_data != NULL)
- {
- size_t len;
- char *cp, *last;
-
- /* Look through the RCS symbols information. This is like
- do_symbols, but we don't add the information to a list. In
- most cases, we will only be called once for this file, so
- generating the list is unnecessary overhead. */
-
- len = strlen (tag);
- cp = rcs->symbols_data;
- /* Keeping track of LAST below isn't strictly necessary, now that tags
- * should be parsed for validity before they are accepted, but tags
- * with spaces used to cause the code below to loop indefintely, so
- * I have corrected for that. Now, in the event that I missed
- * something, the server cannot be hung. -DRP
- */
- last = NULL;
- while ((cp = strchr (cp, tag[0])) != NULL)
- {
- if (cp == last) break;
- if ((cp == rcs->symbols_data || whitespace (cp[-1]))
- && strncmp (cp, tag, len) == 0
- && cp[len] == ':')
- {
- char *v, *r;
-
- /* We found the tag. Return the version number. */
-
- cp += len + 1;
- v = cp;
- while (! whitespace (*cp) && *cp != '\0')
- ++cp;
- r = xmalloc (cp - v + 1);
- strncpy (r, v, cp - v);
- r[cp - v] = '\0';
- return r;
- }
-
- while (! whitespace (*cp) && *cp != '\0')
- ++cp;
- if (*cp == '\0')
- break;
- last = cp;
- }
- }
-
- return NULL;
-}
-
-/*
- * The argument ARG is the getopt remainder of the -k option specified on the
- * command line. This function returns malloc'ed space that can be used
- * directly in calls to RCS V5, with the -k flag munged correctly.
- */
-char *
-RCS_check_kflag (arg)
- const char *arg;
-{
- static const char *const keyword_usage[] =
- {
- "%s %s: invalid RCS keyword expansion mode\n",
- "Valid expansion modes include:\n",
- " -kkv\tGenerate keywords using the default form.\n",
- " -kkvl\tLike -kkv, except locker's name inserted.\n",
- " -kk\tGenerate only keyword names in keyword strings.\n",
- " -kv\tGenerate only keyword values in keyword strings.\n",
- " -ko\tGenerate the old keyword string (no changes from checked in file).\n",
- " -kb\tGenerate binary file unmodified (merges not allowed) (RCS 5.7).\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL,
- };
- /* Big enough to hold any of the strings from kflags. */
- char karg[10];
- char const *const *cpp = NULL;
-
- if (arg)
- {
- for (cpp = kflags; *cpp != NULL; cpp++)
- {
- if (STREQ (arg, *cpp))
- break;
- }
- }
-
- if (arg == NULL || *cpp == NULL)
- {
- usage (keyword_usage);
- }
-
- (void) sprintf (karg, "-k%s", *cpp);
- return (xstrdup (karg));
-}
-
-/*
- * Do some consistency checks on the symbolic tag... These should equate
- * pretty close to what RCS checks, though I don't know for certain.
- */
-void
-RCS_check_tag (tag)
- const char *tag;
-{
- char *invalid = "$,.:;@"; /* invalid RCS tag characters */
- const char *cp;
-
- /*
- * The first character must be an alphabetic letter. The remaining
- * characters cannot be non-visible graphic characters, and must not be
- * in the set of "invalid" RCS identifier characters.
- */
- if (isalpha ((unsigned char) *tag))
- {
- for (cp = tag; *cp; cp++)
- {
- if (!isgraph ((unsigned char) *cp))
- error (1, 0, "tag `%s' has non-visible graphic characters",
- tag);
- if (strchr (invalid, *cp))
- error (1, 0, "tag `%s' must not contain the characters `%s'",
- tag, invalid);
- }
- }
- else
- error (1, 0, "tag `%s' must start with a letter", tag);
-}
-
-/*
- * TRUE if argument has valid syntax for an RCS revision or
- * branch number. All characters must be digits or dots, first
- * and last characters must be digits, and no two consecutive
- * characters may be dots.
- *
- * Intended for classifying things, so this function doesn't
- * call error.
- */
-int
-RCS_valid_rev (rev)
- char *rev;
-{
- char last, c;
- last = *rev++;
- if (!isdigit ((unsigned char) last))
- return 0;
- while ((c = *rev++)) /* Extra parens placate -Wall gcc option */
- {
- if (c == '.')
- {
- if (last == '.')
- return 0;
- continue;
- }
- last = c;
- if (!isdigit ((unsigned char) c))
- return 0;
- }
- if (!isdigit ((unsigned char) last))
- return 0;
- return 1;
-}
-
-/*
- * Return true if RCS revision with TAG is a dead revision.
- */
-int
-RCS_isdead (rcs, tag)
- RCSNode *rcs;
- const char *tag;
-{
- Node *p;
- RCSVers *version;
-
- assert (rcs != NULL);
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- p = findnode (rcs->versions, tag);
- if (p == NULL)
- return (0);
-
- version = p->data;
- return (version->dead);
-}
-
-/* Return the RCS keyword expansion mode. For example "b" for binary.
- Returns a pointer into storage which is allocated and freed along with
- the rest of the RCS information; the caller should not modify this
- storage. Returns NULL if the RCS file does not specify a keyword
- expansion mode; for all other errors, die with a fatal error. */
-char *
-RCS_getexpand (rcs)
- RCSNode *rcs;
-{
- /* Since RCS_parsercsfile_i now reads expand, don't need to worry
- about RCS_reparsercsfile. */
- assert (rcs != NULL);
- return rcs->expand;
-}
-
-/* Set keyword expansion mode to EXPAND. For example "b" for binary. */
-void
-RCS_setexpand (rcs, expand)
- RCSNode *rcs;
- const char *expand;
-{
- /* Since RCS_parsercsfile_i now reads expand, don't need to worry
- about RCS_reparsercsfile. */
- assert (rcs != NULL);
- if (rcs->expand != NULL)
- free (rcs->expand);
- rcs->expand = xstrdup (expand);
-}
-
-/* RCS keywords, and a matching enum. */
-struct rcs_keyword
-{
- const char *string;
- size_t len;
- int expandit;
-};
-#define KEYWORD_INIT(s) (s), sizeof (s) - 1
-static struct rcs_keyword keywords[] =
-{
- { KEYWORD_INIT ("Author"), 1 },
- { KEYWORD_INIT ("Date"), 1 },
- { KEYWORD_INIT ("CVSHeader"), 1 },
- { KEYWORD_INIT ("Header"), 1 },
- { KEYWORD_INIT ("Id"), 1 },
- { KEYWORD_INIT ("Locker"), 1 },
- { KEYWORD_INIT ("Log"), 1 },
- { KEYWORD_INIT ("Name"), 1 },
- { KEYWORD_INIT ("RCSfile"), 1 },
- { KEYWORD_INIT ("Revision"), 1 },
- { KEYWORD_INIT ("Source"), 1 },
- { KEYWORD_INIT ("State"), 1 },
- { NULL, 0, 0 },
- { NULL, 0, 0 }
-};
-enum keyword
-{
- KEYWORD_AUTHOR = 0,
- KEYWORD_DATE,
- KEYWORD_CVSHEADER,
- KEYWORD_HEADER,
- KEYWORD_ID,
- KEYWORD_LOCKER,
- KEYWORD_LOG,
- KEYWORD_NAME,
- KEYWORD_RCSFILE,
- KEYWORD_REVISION,
- KEYWORD_SOURCE,
- KEYWORD_STATE,
- KEYWORD_LOCALID
-};
-enum keyword keyword_local = KEYWORD_ID;
-
-/* Convert an RCS date string into a readable string. This is like
- the RCS date2str function. */
-
-static char *
-printable_date (rcs_date)
- const char *rcs_date;
-{
- int year, mon, mday, hour, min, sec;
- char buf[100];
-
- (void) sscanf (rcs_date, SDATEFORM, &year, &mon, &mday, &hour, &min,
- &sec);
- if (year < 1900)
- year += 1900;
- sprintf (buf, "%04d%c%02d%c%02d %02d:%02d:%02d",
- year, datesep, mon, datesep, mday, hour, min, sec);
- return xstrdup (buf);
-}
-
-/* Escape the characters in a string so that it can be included in an
- RCS value. */
-
-static char *
-escape_keyword_value (value, free_value)
- const char *value;
- int *free_value;
-{
- char *ret, *t;
- const char *s;
-
- for (s = value; *s != '\0'; s++)
- {
- char c;
-
- c = *s;
- if (c == '\t'
- || c == '\n'
- || c == '\\'
- || c == ' '
- || c == '$')
- {
- break;
- }
- }
-
- if (*s == '\0')
- {
- *free_value = 0;
- return (char *) value;
- }
-
- ret = xmalloc (strlen (value) * 4 + 1);
- *free_value = 1;
-
- for (s = value, t = ret; *s != '\0'; s++, t++)
- {
- switch (*s)
- {
- default:
- *t = *s;
- break;
- case '\t':
- *t++ = '\\';
- *t = 't';
- break;
- case '\n':
- *t++ = '\\';
- *t = 'n';
- break;
- case '\\':
- *t++ = '\\';
- *t = '\\';
- break;
- case ' ':
- *t++ = '\\';
- *t++ = '0';
- *t++ = '4';
- *t = '0';
- break;
- case '$':
- *t++ = '\\';
- *t++ = '0';
- *t++ = '4';
- *t = '4';
- break;
- }
- }
-
- *t = '\0';
-
- return ret;
-}
-
-/* Expand RCS keywords in the memory buffer BUF of length LEN. This
- applies to file RCS and version VERS. If NAME is not NULL, and is
- not a numeric revision, then it is the symbolic tag used for the
- checkout. EXPAND indicates how to expand the keywords. This
- function sets *RETBUF and *RETLEN to the new buffer and length.
- This function may modify the buffer BUF. If BUF != *RETBUF, then
- RETBUF is a newly allocated buffer. */
-
-static void
-expand_keywords (rcs, ver, name, log, loglen, expand, buf, len, retbuf, retlen)
- RCSNode *rcs;
- RCSVers *ver;
- const char *name;
- const char *log;
- size_t loglen;
- enum kflag expand;
- char *buf;
- size_t len;
- char **retbuf;
- size_t *retlen;
-{
- struct expand_buffer
- {
- struct expand_buffer *next;
- char *data;
- size_t len;
- int free_data;
- } *ebufs = NULL;
- struct expand_buffer *ebuf_last = NULL;
- size_t ebuf_len = 0;
- char *locker;
- char *srch, *srch_next;
- size_t srch_len;
-
- if (expand == KFLAG_O || expand == KFLAG_B)
- {
- *retbuf = buf;
- *retlen = len;
- return;
- }
-
- /* If we are using -kkvl, dig out the locker information if any. */
- locker = NULL;
- if (expand == KFLAG_KVL)
- {
- Node *lock;
- lock = findnode (RCS_getlocks(rcs), ver->version);
- if (lock != NULL)
- locker = xstrdup (lock->data);
- }
-
- /* RCS keywords look like $STRING$ or $STRING: VALUE$. */
- srch = buf;
- srch_len = len;
- while ((srch_next = memchr (srch, '$', srch_len)) != NULL)
- {
- char *s, *send;
- size_t slen;
- const struct rcs_keyword *keyword;
- enum keyword kw;
- char *value;
- int free_value;
- char *sub;
- size_t sublen;
-
- srch_len -= (srch_next + 1) - srch;
- srch = srch_next + 1;
-
- /* Look for the first non alphabetic character after the '$'. */
- send = srch + srch_len;
- for (s = srch; s < send; s++)
- if (! isalpha ((unsigned char) *s))
- break;
-
- /* If the first non alphabetic character is not '$' or ':',
- then this is not an RCS keyword. */
- if (s == send || (*s != '$' && *s != ':'))
- continue;
-
- /* See if this is one of the keywords. */
- slen = s - srch;
- for (keyword = keywords; keyword->string != NULL; keyword++)
- {
- if (keyword->expandit
- && keyword->len == slen
- && strncmp (keyword->string, srch, slen) == 0)
- {
- break;
- }
- }
- if (keyword->string == NULL)
- continue;
-
- kw = (enum keyword) (keyword - keywords);
-
- /* If the keyword ends with a ':', then the old value consists
- of the characters up to the next '$'. If there is no '$'
- before the end of the line, though, then this wasn't an RCS
- keyword after all. */
- if (*s == ':')
- {
- for (; s < send; s++)
- if (*s == '$' || *s == '\n')
- break;
- if (s == send || *s != '$')
- continue;
- }
-
- /* At this point we must replace the string from SRCH to S
- with the expansion of the keyword KW. */
-
- /* Get the value to use. */
- free_value = 0;
- if (expand == KFLAG_K)
- value = NULL;
- else
- {
- switch (kw)
- {
- default:
- abort ();
-
- case KEYWORD_AUTHOR:
- value = ver->author;
- break;
-
- case KEYWORD_DATE:
- value = printable_date (ver->date);
- free_value = 1;
- break;
-
- case KEYWORD_CVSHEADER:
- case KEYWORD_HEADER:
- case KEYWORD_ID:
- case KEYWORD_LOCALID:
- {
- const char *path;
- int free_path;
- char *date;
- char *old_path;
-
- old_path = NULL;
- if (kw == KEYWORD_HEADER ||
- (kw == KEYWORD_LOCALID &&
- keyword_local == KEYWORD_HEADER))
- path = rcs->path;
- else if (kw == KEYWORD_CVSHEADER ||
- (kw == KEYWORD_LOCALID &&
- keyword_local == KEYWORD_CVSHEADER))
- path = getfullCVSname(rcs->path, &old_path);
- else
- path = last_component (rcs->path);
- path = escape_keyword_value (path, &free_path);
- date = printable_date (ver->date);
- value = xmalloc (strlen (path)
- + strlen (ver->version)
- + strlen (date)
- + strlen (ver->author)
- + strlen (ver->state)
- + (locker == NULL ? 0 : strlen (locker))
- + 20);
-
- sprintf (value, "%s %s %s %s %s%s%s",
- path, ver->version, date, ver->author,
- ver->state,
- locker != NULL ? " " : "",
- locker != NULL ? locker : "");
- if (free_path)
- /* If free_path is set then we know we allocated path
- * and we can discard the const.
- */
- free ((char *)path);
- if (old_path)
- free (old_path);
- free (date);
- free_value = 1;
- }
- break;
-
- case KEYWORD_LOCKER:
- value = locker;
- break;
-
- case KEYWORD_LOG:
- case KEYWORD_RCSFILE:
- value = escape_keyword_value (last_component (rcs->path),
- &free_value);
- break;
-
- case KEYWORD_NAME:
- if (name != NULL && ! isdigit ((unsigned char) *name))
- value = (char *) name;
- else
- value = NULL;
- break;
-
- case KEYWORD_REVISION:
- value = ver->version;
- break;
-
- case KEYWORD_SOURCE:
- value = escape_keyword_value (rcs->path, &free_value);
- break;
-
- case KEYWORD_STATE:
- value = ver->state;
- break;
- }
- }
-
- sub = xmalloc (keyword->len
- + (value == NULL ? 0 : strlen (value))
- + 10);
- if (expand == KFLAG_V)
- {
- /* Decrement SRCH and increment S to remove the $
- characters. */
- --srch;
- ++srch_len;
- ++s;
- sublen = 0;
- }
- else
- {
- strcpy (sub, keyword->string);
- sublen = strlen (keyword->string);
- if (expand != KFLAG_K)
- {
- sub[sublen] = ':';
- sub[sublen + 1] = ' ';
- sublen += 2;
- }
- }
- if (value != NULL)
- {
- strcpy (sub + sublen, value);
- sublen += strlen (value);
- }
- if (expand != KFLAG_V && expand != KFLAG_K)
- {
- sub[sublen] = ' ';
- ++sublen;
- sub[sublen] = '\0';
- }
-
- if (free_value)
- free (value);
-
- /* The Log keyword requires special handling. This behaviour
- is taken from RCS 5.7. The special log message is what RCS
- uses for ci -k. */
- if (kw == KEYWORD_LOG
- && (sizeof "checked in with -k by " <= loglen
- || log == NULL
- || strncmp (log, "checked in with -k by ",
- sizeof "checked in with -k by " - 1) != 0))
- {
- char *start;
- char *leader;
- size_t leader_len, leader_sp_len;
- const char *logend;
- const char *snl;
- int cnl;
- char *date;
- const char *sl;
-
- /* We are going to insert the trailing $ ourselves, before
- the log message, so we must remove it from S, if we
- haven't done so already. */
- if (expand != KFLAG_V)
- ++s;
-
- /* CVS never has empty log messages, but old RCS files might. */
- if (log == NULL)
- log = "";
-
- /* Find the start of the line. */
- start = srch;
- while (start > buf && start[-1] != '\n')
- --start;
-
- /* Copy the start of the line to use as a comment leader. */
- leader_len = srch - start;
- if (expand != KFLAG_V)
- --leader_len;
- leader = xmalloc (leader_len);
- memcpy (leader, start, leader_len);
- leader_sp_len = leader_len;
- while (leader_sp_len > 0 && leader[leader_sp_len - 1] == ' ')
- --leader_sp_len;
-
- /* RCS does some checking for an old style of Log here,
- but we don't bother. RCS issues a warning if it
- changes anything. */
-
- /* Count the number of newlines in the log message so that
- we know how many copies of the leader we will need. */
- cnl = 0;
- logend = log + loglen;
- for (snl = log; snl < logend; snl++)
- if (*snl == '\n')
- ++cnl;
-
- /* If the log message did not end in a newline, increment
- * the newline count so we have space for the extra leader.
- * Failure to do so results in a buffer overrun.
- */
- if (loglen && snl[-1] != '\n')
- ++cnl;
-
- date = printable_date (ver->date);
- sub = xrealloc (sub,
- (sublen
- + sizeof "Revision"
- + strlen (ver->version)
- + strlen (date)
- + strlen (ver->author)
- + loglen
- /* Use CNL + 2 below: One leader for each log
- * line, plus the Revision/Author/Date line,
- * plus a trailing blank line.
- */
- + (cnl + 2) * leader_len
- + 20));
- if (expand != KFLAG_V)
- {
- sub[sublen] = '$';
- ++sublen;
- }
- sub[sublen] = '\n';
- ++sublen;
- memcpy (sub + sublen, leader, leader_len);
- sublen += leader_len;
- sprintf (sub + sublen, "Revision %s %s %s\n",
- ver->version, date, ver->author);
- sublen += strlen (sub + sublen);
- free (date);
-
- sl = log;
- while (sl < logend)
- {
- if (*sl == '\n')
- {
- memcpy (sub + sublen, leader, leader_sp_len);
- sublen += leader_sp_len;
- sub[sublen] = '\n';
- ++sublen;
- ++sl;
- }
- else
- {
- const char *slnl;
-
- memcpy (sub + sublen, leader, leader_len);
- sublen += leader_len;
- for (slnl = sl; slnl < logend && *slnl != '\n'; ++slnl)
- ;
- if (slnl < logend)
- ++slnl;
- memcpy (sub + sublen, sl, slnl - sl);
- sublen += slnl - sl;
- if (slnl == logend && slnl[-1] != '\n')
- {
- /* There was no EOL at the end of the log message. Add
- * one.
- */
- sub[sublen] = '\n';
- ++sublen;
- }
- sl = slnl;
- }
- }
-
- memcpy (sub + sublen, leader, leader_sp_len);
- sublen += leader_sp_len;
-
- free (leader);
- }
-
- /* Now SUB contains a string which is to replace the string
- from SRCH to S. SUBLEN is the length of SUB. */
-
- if (srch + sublen == s)
- {
- memcpy (srch, sub, sublen);
- free (sub);
- }
- else
- {
- struct expand_buffer *ebuf;
-
- /* We need to change the size of the buffer. We build a
- list of expand_buffer structures. Each expand_buffer
- structure represents a portion of the final output. We
- concatenate them back into a single buffer when we are
- done. This minimizes the number of potentially large
- buffer copies we must do. */
-
- if (ebufs == NULL)
- {
- ebufs = (struct expand_buffer *) xmalloc (sizeof *ebuf);
- ebufs->next = NULL;
- ebufs->data = buf;
- ebufs->free_data = 0;
- ebuf_len = srch - buf;
- ebufs->len = ebuf_len;
- ebuf_last = ebufs;
- }
- else
- {
- assert (srch >= ebuf_last->data);
- assert (srch <= ebuf_last->data + ebuf_last->len);
- ebuf_len -= ebuf_last->len - (srch - ebuf_last->data);
- ebuf_last->len = srch - ebuf_last->data;
- }
-
- ebuf = (struct expand_buffer *) xmalloc (sizeof *ebuf);
- ebuf->data = sub;
- ebuf->len = sublen;
- ebuf->free_data = 1;
- ebuf->next = NULL;
- ebuf_last->next = ebuf;
- ebuf_last = ebuf;
- ebuf_len += sublen;
-
- ebuf = (struct expand_buffer *) xmalloc (sizeof *ebuf);
- ebuf->data = s;
- ebuf->len = srch_len - (s - srch);
- ebuf->free_data = 0;
- ebuf->next = NULL;
- ebuf_last->next = ebuf;
- ebuf_last = ebuf;
- ebuf_len += srch_len - (s - srch);
- }
-
- srch_len -= (s - srch);
- srch = s;
- }
-
- if (locker != NULL)
- free (locker);
-
- if (ebufs == NULL)
- {
- *retbuf = buf;
- *retlen = len;
- }
- else
- {
- char *ret;
-
- ret = xmalloc (ebuf_len);
- *retbuf = ret;
- *retlen = ebuf_len;
- while (ebufs != NULL)
- {
- struct expand_buffer *next;
-
- memcpy (ret, ebufs->data, ebufs->len);
- ret += ebufs->len;
- if (ebufs->free_data)
- free (ebufs->data);
- next = ebufs->next;
- free (ebufs);
- ebufs = next;
- }
- }
-}
-
-
-
-/* Check out a revision from an RCS file.
-
- If PFN is not NULL, then ignore WORKFILE and SOUT. Call PFN zero
- or more times with the contents of the file. CALLERDAT is passed,
- uninterpreted, to PFN. (The current code will always call PFN
- exactly once for a non empty file; however, the current code
- assumes that it can hold the entire file contents in memory, which
- is not a good assumption, and might change in the future).
-
- Otherwise, if WORKFILE is not NULL, check out the revision to
- WORKFILE. However, if WORKFILE is not NULL, and noexec is set,
- then don't do anything.
-
- Otherwise, if WORKFILE is NULL, check out the revision to SOUT. If
- SOUT is RUN_TTY, then write the contents of the revision to
- standard output. When using SOUT, the output is generally a
- temporary file; don't bother to get the file modes correct. When
- NOEXEC is set, WORKFILEs are not written but SOUTs are.
-
- REV is the numeric revision to check out. It may be NULL, which
- means to check out the head of the default branch.
-
- If NAMETAG is not NULL, and is not a numeric revision, then it is
- the tag that should be used when expanding the RCS Name keyword.
-
- OPTIONS is a string such as "-kb" or "-kv" for keyword expansion
- options. It may be NULL to use the default expansion mode of the
- file, typically "-kkv".
-
- On an error which prevented checking out the file, either print a
- nonfatal error and return 1, or give a fatal error. On success,
- return 0. */
-
-/* This function mimics the behavior of `rcs co' almost exactly. The
- chief difference is in its support for preserving file ownership,
- permissions, and special files across checkin and checkout -- see
- comments in RCS_checkin for some issues about this. -twp */
-
-int
-RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
- RCSNode *rcs;
- const char *workfile;
- const char *rev;
- const char *nametag;
- const char *options;
- const char *sout;
- RCSCHECKOUTPROC pfn;
- void *callerdat;
-{
- int free_rev = 0;
- enum kflag expand;
- FILE *fp;
- FILE *ofp = NULL;
- struct stat sb;
- struct rcsbuffer rcsbuf;
- char *key;
- char *value;
- size_t len;
- int free_value = 0;
- char *log = NULL;
- size_t loglen = 0;
- Node *vp = NULL;
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- uid_t rcs_owner = (uid_t) -1;
- gid_t rcs_group = (gid_t) -1;
- mode_t rcs_mode;
- int change_rcs_owner_or_group = 0;
- int change_rcs_mode = 0;
- int special_file = 0;
- unsigned long devnum_long;
- dev_t devnum = 0;
-#endif
-
- if (trace)
- {
- (void) fprintf (stderr, "%s-> RCS_checkout (%s, %s, %s, %s, %s)\n",
-#ifdef SERVER_SUPPORT
- server_active ? "S" : " ",
-#else
- "",
-#endif
- rcs->path,
- rev != NULL ? rev : "",
- nametag != NULL ? nametag : "",
- options != NULL ? options : "",
- (pfn != NULL ? "(function)"
- : (workfile != NULL
- ? workfile
- : (sout != RUN_TTY ? sout : "(stdout)"))));
- }
-
- assert (rev == NULL || isdigit ((unsigned char) *rev));
-
- if (noexec && !server_active && workfile != NULL)
- return 0;
-
- assert (sout == RUN_TTY || workfile == NULL);
- assert (pfn == NULL || (sout == RUN_TTY && workfile == NULL));
-
- /* Some callers, such as Checkin or remove_file, will pass us a
- branch. */
- if (rev != NULL && (numdots (rev) & 1) == 0)
- {
- rev = RCS_getbranch (rcs, rev, 1);
- if (rev == NULL)
- error (1, 0, "internal error: bad branch tag in checkout");
- free_rev = 1;
- }
-
- if (rev == NULL || STREQ (rev, rcs->head))
- {
- int gothead;
-
- /* We want the head revision. Try to read it directly. */
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, &fp, &rcsbuf);
- else
- rcsbuf_cache_open (rcs, rcs->delta_pos, &fp, &rcsbuf);
-
- gothead = 0;
- if (! rcsbuf_getrevnum (&rcsbuf, &key))
- error (1, 0, "unexpected EOF reading %s", rcs->path);
-
- if (!STREQ (rcs->head, key))
- error (1, 0, "Expected head revision %s, found %s.",
- rcs->head, key);
-
- while (rcsbuf_getkey (&rcsbuf, &key, &value))
- {
- if (STREQ (key, "log"))
- {
- if (log)
- {
- error (0, 0,
-"Duplicate log keyword found for head revision in RCS file.");
- free (log);
- }
- log = rcsbuf_valcopy (&rcsbuf, value, 0, &loglen);
- }
- else if (STREQ (key, "text"))
- {
- gothead = 1;
- break;
- }
- }
-
- if (! gothead)
- {
- error (0, 0, "internal error: cannot find head text");
- if (free_rev)
- /* It's okay to discard the const when free_rev is set, because
- * we know we allocated it in this function.
- */
- free ((char *)rev);
- return 1;
- }
-
- rcsbuf_valpolish (&rcsbuf, value, 0, &len);
-
- if (fstat (fileno (fp), &sb) < 0)
- error (1, errno, "cannot fstat %s", rcs->path);
-
- rcsbuf_cache (rcs, &rcsbuf);
- }
- else
- {
- struct rcsbuffer *rcsbufp;
-
- /* It isn't the head revision of the trunk. We'll need to
- walk through the deltas. */
-
- fp = NULL;
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, &fp, &rcsbuf);
-
- if (fp == NULL)
- {
- /* If RCS_deltas didn't close the file, we could use fstat
- here too. Probably should change it thusly.... */
- if (stat (rcs->path, &sb) < 0)
- error (1, errno, "cannot stat %s", rcs->path);
- rcsbufp = NULL;
- }
- else
- {
- if (fstat (fileno (fp), &sb) < 0)
- error (1, errno, "cannot fstat %s", rcs->path);
- rcsbufp = &rcsbuf;
- }
-
- RCS_deltas (rcs, fp, rcsbufp, rev, RCS_FETCH, &value, &len,
- &log, &loglen);
- free_value = 1;
- }
-
- /* If OPTIONS is NULL or the empty string, then the old code would
- invoke the RCS co program with no -k option, which means that
- co would use the string we have stored in rcs->expand. */
- if ((options == NULL || options[0] == '\0') && rcs->expand == NULL)
- expand = KFLAG_KV;
- else
- {
- const char *ouroptions;
- const char * const *cpp;
-
- if (options != NULL && options[0] != '\0')
- {
- assert (options[0] == '-' && options[1] == 'k');
- ouroptions = options + 2;
- }
- else
- ouroptions = rcs->expand;
-
- for (cpp = kflags; *cpp != NULL; cpp++)
- if (STREQ (*cpp, ouroptions))
- break;
-
- if (*cpp != NULL)
- expand = (enum kflag) (cpp - kflags);
- else
- {
- error (0, 0,
- "internal error: unsupported substitution string -k%s",
- ouroptions);
- expand = KFLAG_KV;
- }
- }
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- /* Handle special files and permissions, if that is desired. */
- if (preserve_perms)
- {
- RCSVers *vers;
- Node *info;
-
- vp = findnode (rcs->versions, rev == NULL ? rcs->head : rev);
- if (vp == NULL)
- error (1, 0, "internal error: no revision information for %s",
- rev == NULL ? rcs->head : rev);
- vers = vp->data;
-
- /* First we look for symlinks, which are simplest to handle. */
- info = findnode (vers->other_delta, "symlink");
- if (info != NULL)
- {
- char *dest;
-
- if (pfn != NULL || (workfile == NULL && sout == RUN_TTY))
- error (1, 0, "symbolic link %s:%s cannot be piped",
- rcs->path, vers->version);
- if (workfile == NULL)
- dest = sout;
- else
- dest = workfile;
-
- /* Remove `dest', just in case. It's okay to get ENOENT here,
- since we just want the file not to be there. (TODO: decide
- whether it should be considered an error for `dest' to exist
- at this point. If so, the unlink call should be removed and
- `symlink' should signal the error. -twp) */
- if (CVS_UNLINK (dest) < 0 && !existence_error (errno))
- error (1, errno, "cannot remove %s", dest);
- if (symlink (info->data, dest) < 0)
- error (1, errno, "cannot create symbolic link from %s to %s",
- dest, (char *)info->data);
- if (free_value)
- free (value);
- if (free_rev)
- /* It's okay to discard the const when free_rev is set, because
- * we know we allocated it in this function.
- */
- free ((char *)rev);
- return 0;
- }
-
- /* Next, we look at this file's hardlinks field, and see whether
- it is linked to any other file that has been checked out.
- If so, we don't do anything else -- just link it to that file.
-
- If we are checking out a file to a pipe or temporary storage,
- none of this should matter. Hence the `workfile != NULL'
- wrapper around the whole thing. -twp */
-
- if (workfile != NULL)
- {
- List *links = vers->hardlinks;
- if (links != NULL)
- {
- Node *uptodate_link;
-
- /* For each file in the hardlinks field, check to see
- if it exists, and if so, if it has been checked out
- this iteration. When walklist returns, uptodate_link
- should point to a hardlist node representing a file
- in `links' which has recently been checked out, or
- NULL if no file in `links' has yet been checked out. */
-
- uptodate_link = NULL;
- (void) walklist (links, find_checkedout_proc, &uptodate_link);
- dellist (&links);
-
- /* If we've found a file that `workfile' is supposed to be
- linked to, and it has been checked out since CVS was
- invoked, then simply link workfile to that file and return.
-
- If one of these conditions is not met, then
- workfile is the first one in its hardlink group to
- be checked out, and we must continue with a full
- checkout. */
-
- if (uptodate_link != NULL)
- {
- struct hardlink_info *hlinfo = uptodate_link->data;
-
- if (link (uptodate_link->key, workfile) < 0)
- error (1, errno, "cannot link %s to %s",
- workfile, uptodate_link->key);
- hlinfo->checked_out = 1; /* probably unnecessary */
- if (free_value)
- free (value);
- if (free_rev)
- /* It's okay to discard the const when free_rev is set,
- * because we know we allocated it in this function.
- */
- free ((char *)rev);
- return 0;
- }
- }
- }
-
- info = findnode (vers->other_delta, "owner");
- if (info != NULL)
- {
- change_rcs_owner_or_group = 1;
- rcs_owner = (uid_t) strtoul (info->data, NULL, 10);
- }
- info = findnode (vers->other_delta, "group");
- if (info != NULL)
- {
- change_rcs_owner_or_group = 1;
- rcs_group = (gid_t) strtoul (info->data, NULL, 10);
- }
- info = findnode (vers->other_delta, "permissions");
- if (info != NULL)
- {
- change_rcs_mode = 1;
- rcs_mode = (mode_t) strtoul (info->data, NULL, 8);
- }
- info = findnode (vers->other_delta, "special");
- if (info != NULL)
- {
- /* If the size of `devtype' changes, fix the sscanf call also */
- char devtype[16];
-
- if (sscanf (info->data, "%15s %lu",
- devtype, &devnum_long) < 2)
- error (1, 0, "%s:%s has bad `special' newphrase %s",
- workfile, vers->version, (char *)info->data);
- devnum = devnum_long;
- if (STREQ (devtype, "character"))
- special_file = S_IFCHR;
- else if (STREQ (devtype, "block"))
- special_file = S_IFBLK;
- else
- error (0, 0, "%s is a special file of unsupported type `%s'",
- workfile, (char *)info->data);
- }
- }
-#endif /* PRESERVE_PERMISSIONS_SUPPORT */
-
- if (expand != KFLAG_O && expand != KFLAG_B)
- {
- char *newvalue;
-
- /* Don't fetch the delta node again if we already have it. */
- if (vp == NULL)
- {
- vp = findnode (rcs->versions, rev == NULL ? rcs->head : rev);
- if (vp == NULL)
- error (1, 0, "internal error: no revision information for %s",
- rev == NULL ? rcs->head : rev);
- }
-
- expand_keywords (rcs, vp->data, nametag, log, loglen,
- expand, value, len, &newvalue, &len);
-
- if (newvalue != value)
- {
- if (free_value)
- free (value);
- value = newvalue;
- free_value = 1;
- }
- }
-
- if (free_rev)
- /* It's okay to discard the const when free_rev is set, because
- * we know we allocated it in this function.
- */
- free ((char *)rev);
-
- if (log != NULL)
- {
- free (log);
- log = NULL;
- }
-
- if (pfn != NULL)
- {
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- if (special_file)
- error (1, 0, "special file %s cannot be piped to anything",
- rcs->path);
-#endif
- /* The PFN interface is very simple to implement right now, as
- we always have the entire file in memory. */
- if (len != 0)
- pfn (callerdat, value, len);
- }
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- else if (special_file)
- {
-# ifdef HAVE_MKNOD
- char *dest;
-
- /* Can send either to WORKFILE or to SOUT, as long as SOUT is
- not RUN_TTY. */
- dest = workfile;
- if (dest == NULL)
- {
- if (sout == RUN_TTY)
- error (1, 0, "special file %s cannot be written to stdout",
- rcs->path);
- dest = sout;
- }
-
- /* Unlink `dest', just in case. It's okay if this provokes a
- ENOENT error. */
- if (CVS_UNLINK (dest) < 0 && existence_error (errno))
- error (1, errno, "cannot remove %s", dest);
- if (mknod (dest, special_file, devnum) < 0)
- error (1, errno, "could not create special file %s",
- dest);
-# else
- error (1, 0,
-"cannot create %s: unable to create special files on this system",
-workfile);
-# endif
- }
-#endif
- else
- {
- /* Not a special file: write to WORKFILE or SOUT. */
- if (workfile == NULL)
- {
- if (sout == RUN_TTY)
- ofp = stdout;
- else
- {
- /* Symbolic links should be removed before replacement, so that
- `fopen' doesn't follow the link and open the wrong file. */
- if (islink (sout))
- if (unlink_file (sout) < 0)
- error (1, errno, "cannot remove %s", sout);
- ofp = CVS_FOPEN (sout, expand == KFLAG_B ? "wb" : "w");
- if (ofp == NULL)
- error (1, errno, "cannot open %s", sout);
- }
- }
- else
- {
- /* Output is supposed to go to WORKFILE, so we should open that
- file. Symbolic links should be removed first (see above). */
- if (islink (workfile))
- if (unlink_file (workfile) < 0)
- error (1, errno, "cannot remove %s", workfile);
-
- ofp = CVS_FOPEN (workfile, expand == KFLAG_B ? "wb" : "w");
-
- /* If the open failed because the existing workfile was not
- writable, try to chmod the file and retry the open. */
- if (ofp == NULL && errno == EACCES
- && isfile (workfile) && !iswritable (workfile))
- {
- xchmod (workfile, 1);
- ofp = CVS_FOPEN (workfile, expand == KFLAG_B ? "wb" : "w");
- }
-
- if (ofp == NULL)
- {
- error (0, errno, "cannot open %s", workfile);
- if (free_value)
- free (value);
- return 1;
- }
- }
-
- if (workfile == NULL && sout == RUN_TTY)
- {
- if (expand == KFLAG_B)
- cvs_output_binary (value, len);
- else
- {
- /* cvs_output requires the caller to check for zero
- length. */
- if (len > 0)
- cvs_output (value, len);
- }
- }
- else
- {
- /* NT 4.0 is said to have trouble writing 2099999 bytes
- (for example) in a single fwrite. So break it down
- (there is no need to be writing that much at once
- anyway; it is possible that LARGEST_FWRITE should be
- somewhat larger for good performance, but for testing I
- want to start with a small value until/unless a bigger
- one proves useful). */
-#define LARGEST_FWRITE 8192
- size_t nleft = len;
- size_t nstep = (len < LARGEST_FWRITE ? len : LARGEST_FWRITE);
- char *p = value;
-
- while (nleft > 0)
- {
- if (fwrite (p, 1, nstep, ofp) != nstep)
- {
- error (0, errno, "cannot write %s",
- (workfile != NULL
- ? workfile
- : (sout != RUN_TTY ? sout : "stdout")));
- if (free_value)
- free (value);
- return 1;
- }
- p += nstep;
- nleft -= nstep;
- if (nleft < nstep)
- nstep = nleft;
- }
- }
- }
-
- if (free_value)
- free (value);
-
- if (workfile != NULL)
- {
- int ret;
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- if (!special_file && fclose (ofp) < 0)
- {
- error (0, errno, "cannot close %s", workfile);
- return 1;
- }
-
- if (change_rcs_owner_or_group)
- {
- if (chown (workfile, rcs_owner, rcs_group) < 0)
- error (0, errno, "could not change owner or group of %s",
- workfile);
- }
-
- ret = chmod (workfile,
- change_rcs_mode
- ? rcs_mode
- : sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH));
-#else
- if (fclose (ofp) < 0)
- {
- error (0, errno, "cannot close %s", workfile);
- return 1;
- }
-
- ret = chmod (workfile,
- sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH));
-#endif
- if (ret < 0)
- {
- error (0, errno, "cannot change mode of file %s",
- workfile);
- }
- }
- else if (sout != RUN_TTY)
- {
- if (
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- !special_file &&
-#endif
- fclose (ofp) < 0)
- {
- error (0, errno, "cannot close %s", sout);
- return 1;
- }
- }
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- /* If we are in the business of preserving hardlinks, then
- mark this file as having been checked out. */
- if (preserve_perms && workfile != NULL)
- update_hardlink_info (workfile);
-#endif
-
- return 0;
-}
-
-static RCSVers *RCS_findlock_or_tip PROTO ((RCSNode *rcs));
-
-/* Find the delta currently locked by the user. From the `ci' man page:
-
- "If rev is omitted, ci tries to derive the new revision
- number from the caller's last lock. If the caller has
- locked the tip revision of a branch, the new revision is
- appended to that branch. The new revision number is
- obtained by incrementing the tip revision number. If the
- caller locked a non-tip revision, a new branch is started
- at that revision by incrementing the highest branch number
- at that revision. The default initial branch and level
- numbers are 1.
-
- If rev is omitted and the caller has no lock, but owns the
- file and locking is not set to strict, then the revision
- is appended to the default branch (normally the trunk; see
- the -b option of rcs(1))."
-
- RCS_findlock_or_tip finds the unique revision locked by the caller
- and returns its delta node. If the caller has not locked any
- revisions (and is permitted to commit to an unlocked delta, as
- described above), return the tip of the default branch. */
-
-static RCSVers *
-RCS_findlock_or_tip (rcs)
- RCSNode *rcs;
-{
- char *user = getcaller();
- Node *lock, *p;
- List *locklist;
- char *defaultrev = NULL;
-
- /* Find unique delta locked by caller. This code is very similar
- to the code in RCS_unlock -- perhaps it could be abstracted
- into a RCS_findlock function. */
- locklist = RCS_getlocks (rcs);
- lock = NULL;
- for (p = locklist->list->next; p != locklist->list; p = p->next)
- {
- if (STREQ (p->data, user))
- {
- if (lock != NULL)
- {
- error (0, 0, "\
-%s: multiple revisions locked by %s; please specify one", rcs->path, user);
- return NULL;
- }
- lock = p;
- }
- }
-
- if (lock != NULL)
- {
- /* Found an old lock, but check that the revision still exists. */
- p = findnode (rcs->versions, lock->key);
- if (p == NULL)
- {
- error (0, 0, "%s: can't unlock nonexistent revision %s",
- rcs->path,
- lock->key);
- return NULL;
- }
- return p->data;
- }
-
- /* No existing lock. The RCS rule is that this is an error unless
- locking is nonstrict AND the file is owned by the current
- user. Trying to determine the latter is a portability nightmare
- in the face of NT, VMS, AFS, and other systems with non-unix-like
- ideas of users and owners. In the case of CVS, we should never get
- here (as long as the traditional behavior of making sure to call
- RCS_lock persists). Anyway, we skip the RCS error checks
- and just return the default branch or head. The reasoning is that
- those error checks are to make users lock before a checkin, and we do
- that in other ways if at all anyway (e.g. rcslock.pl). */
-
- defaultrev = RCS_getbranch (rcs, rcs->branch, 0);
- p = findnode (rcs->versions, defaultrev);
- if (defaultrev != NULL)
- free (defaultrev);
- if (!p)
- {
- error (0, 0, "RCS file `%s' does not contain its default revision.",
- rcs->path);
- return NULL;
- }
-
- return p->data;
-}
-
-/* Revision number string, R, must contain a `.'.
- Return a newly-malloc'd copy of the prefix of R up
- to but not including the final `.'. */
-
-static char *
-truncate_revnum (r)
- const char *r;
-{
- size_t len;
- char *new_r;
- char *dot = strrchr (r, '.');
-
- assert (dot);
- len = dot - r;
- new_r = xmalloc (len + 1);
- memcpy (new_r, r, len);
- *(new_r + len) = '\0';
- return new_r;
-}
-
-/* Revision number string, R, must contain a `.'.
- R must be writable. Replace the rightmost `.' in R with
- the NUL byte and return a pointer to that NUL byte. */
-
-static char *
-truncate_revnum_in_place (r)
- char *r;
-{
- char *dot = strrchr (r, '.');
- assert (dot);
- *dot = '\0';
- return dot;
-}
-
-/* Revision number strings, R and S, must each contain a `.'.
- R and S must be writable and must have the same number of dots.
- Truncate R and S for the comparison, then restored them to their
- original state.
- Return the result (see compare_revnums) of comparing R and S
- ignoring differences in any component after the rightmost `.'. */
-
-static int
-compare_truncated_revnums (r, s)
- char *r;
- char *s;
-{
- char *r_dot = truncate_revnum_in_place (r);
- char *s_dot = truncate_revnum_in_place (s);
- int cmp;
-
- assert (numdots (r) == numdots (s));
-
- cmp = compare_revnums (r, s);
-
- *r_dot = '.';
- *s_dot = '.';
-
- return cmp;
-}
-
-/* Return a malloc'd copy of the string representing the highest branch
- number on BRANCHNODE. If there are no branches on BRANCHNODE, return NULL.
- FIXME: isn't the max rev always the last one?
- If so, we don't even need a loop. */
-
-static char *max_rev PROTO ((const RCSVers *));
-
-static char *
-max_rev (branchnode)
- const RCSVers *branchnode;
-{
- Node *head;
- Node *bp;
- char *max;
-
- if (branchnode->branches == NULL)
- {
- return NULL;
- }
-
- max = NULL;
- head = branchnode->branches->list;
- for (bp = head->next; bp != head; bp = bp->next)
- {
- if (max == NULL || compare_truncated_revnums (max, bp->key) < 0)
- {
- max = bp->key;
- }
- }
- assert (max);
-
- return truncate_revnum (max);
-}
-
-/* Create BRANCH in RCS's delta tree. BRANCH may be either a branch
- number or a revision number. In the former case, create the branch
- with the specified number; in the latter case, create a new branch
- rooted at node BRANCH with a higher branch number than any others.
- Return the number of the tip node on the new branch. */
-
-static char *
-RCS_addbranch (rcs, branch)
- RCSNode *rcs;
- const char *branch;
-{
- char *branchpoint, *newrevnum;
- Node *nodep, *bp;
- Node *marker;
- RCSVers *branchnode;
-
- assert (branch);
-
- /* Append to end by default. */
- marker = NULL;
-
- branchpoint = xstrdup (branch);
- if ((numdots (branchpoint) & 1) == 0)
- {
- truncate_revnum_in_place (branchpoint);
- }
-
- /* Find the branch rooted at BRANCHPOINT. */
- nodep = findnode (rcs->versions, branchpoint);
- if (nodep == NULL)
- {
- error (0, 0, "%s: can't find branch point %s", rcs->path, branchpoint);
- free (branchpoint);
- return NULL;
- }
- free (branchpoint);
- branchnode = nodep->data;
-
- /* If BRANCH was a full branch number, make sure it is higher than MAX. */
- if ((numdots (branch) & 1) == 1)
- {
- if (branchnode->branches == NULL)
- {
- /* We have to create the first branch on this node, which means
- appending ".2" to the revision number. */
- newrevnum = (char *) xmalloc (strlen (branch) + 3);
- strcpy (newrevnum, branch);
- strcat (newrevnum, ".2");
- }
- else
- {
- char *max = max_rev (branchnode);
- assert (max);
- newrevnum = increment_revnum (max);
- free (max);
- }
- }
- else
- {
- newrevnum = xstrdup (branch);
-
- if (branchnode->branches != NULL)
- {
- Node *head;
- Node *bp;
-
- /* Find the position of this new branch in the sorted list
- of branches. */
- head = branchnode->branches->list;
- for (bp = head->next; bp != head; bp = bp->next)
- {
- char *dot;
- int found_pos;
-
- /* The existing list must be sorted on increasing revnum. */
- assert (bp->next == head
- || compare_truncated_revnums (bp->key,
- bp->next->key) < 0);
- dot = truncate_revnum_in_place (bp->key);
- found_pos = (compare_revnums (branch, bp->key) < 0);
- *dot = '.';
-
- if (found_pos)
- {
- break;
- }
- }
- marker = bp;
- }
- }
-
- newrevnum = (char *) xrealloc (newrevnum, strlen (newrevnum) + 3);
- strcat (newrevnum, ".1");
-
- /* Add this new revision number to BRANCHPOINT's branches list. */
- if (branchnode->branches == NULL)
- branchnode->branches = getlist();
- bp = getnode();
- bp->key = xstrdup (newrevnum);
-
- /* Append to the end of the list by default, that is, just before
- the header node, `list'. */
- if (marker == NULL)
- marker = branchnode->branches->list;
-
- {
- int fail;
- fail = insert_before (branchnode->branches, marker, bp);
- assert (!fail);
- }
-
- return newrevnum;
-}
-
-/* Check in to RCSFILE with revision REV (which must be greater than
- the largest revision) and message MESSAGE (which is checked for
- legality). If FLAGS & RCS_FLAGS_DEAD, check in a dead revision.
- If FLAGS & RCS_FLAGS_QUIET, tell ci to be quiet. If FLAGS &
- RCS_FLAGS_MODTIME, use the working file's modification time for the
- checkin time. WORKFILE is the working file to check in from, or
- NULL to use the usual RCS rules for deriving it from the RCSFILE.
- If FLAGS & RCS_FLAGS_KEEPFILE, don't unlink the working file;
- unlinking the working file is standard RCS behavior, but is rarely
- appropriate for CVS.
-
- This function should almost exactly mimic the behavior of `rcs ci'. The
- principal point of difference is the support here for preserving file
- ownership and permissions in the delta nodes. This is not a clean
- solution -- precisely because it diverges from RCS's behavior -- but
- it doesn't seem feasible to do this anywhere else in the code. [-twp]
-
- Return value is -1 for error (and errno is set to indicate the
- error), positive for error (and an error message has been printed),
- or zero for success. */
-
-int
-RCS_checkin (rcs, workfile_in, message, rev, citime, flags)
- RCSNode *rcs;
- const char *workfile_in;
- const char *message;
- const char *rev;
- time_t citime;
- int flags;
-{
- RCSVers *delta, *commitpt;
- Deltatext *dtext;
- Node *nodep;
- char *tmpfile, *changefile;
- int dargc = 0;
- size_t darg_allocated = 0;
- char **dargv = NULL;
- size_t bufsize;
- int status, checkin_quiet;
- struct tm *ftm;
- time_t modtime;
- int adding_branch = 0;
- char *workfile = xstrdup (workfile_in);
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- struct stat sb;
-#endif
-
- commitpt = NULL;
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- /* Get basename of working file. Is there a library function to
- do this? I couldn't find one. -twp */
- if (workfile == NULL)
- {
- char *p;
- int extlen = strlen (RCSEXT);
- assert (rcs->path);
- workfile = xstrdup (last_component (rcs->path));
- p = workfile + (strlen (workfile) - extlen);
- assert (strncmp (p, RCSEXT, extlen) == 0);
- *p = '\0';
- }
-
- /* If the filename is a symbolic link, follow it and replace it
- with the destination of the link. We need to do this before
- calling rcs_internal_lockfile, or else we won't put the lock in
- the right place. */
- resolve_symlink (&(rcs->path));
-
- checkin_quiet = flags & RCS_FLAGS_QUIET;
- if (!checkin_quiet)
- {
- cvs_output (rcs->path, 0);
- cvs_output (" <-- ", 7);
- cvs_output (workfile, 0);
- cvs_output ("\n", 1);
- }
-
- /* Create new delta node. */
- delta = (RCSVers *) xmalloc (sizeof (RCSVers));
- memset (delta, 0, sizeof (RCSVers));
- delta->author = xstrdup (getcaller ());
- if (flags & RCS_FLAGS_MODTIME)
- {
- struct stat ws;
- if (stat (workfile, &ws) < 0)
- {
- error (1, errno, "cannot stat %s", workfile);
- }
- modtime = ws.st_mtime;
- }
- else if (flags & RCS_FLAGS_USETIME)
- modtime = citime;
- else
- (void) time (&modtime);
- ftm = gmtime (&modtime);
- delta->date = (char *) xmalloc (MAXDATELEN);
- (void) sprintf (delta->date, DATEFORM,
- ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
- ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
- ftm->tm_min, ftm->tm_sec);
- if (flags & RCS_FLAGS_DEAD)
- {
- delta->state = xstrdup (RCSDEAD);
- delta->dead = 1;
- }
- else
- delta->state = xstrdup ("Exp");
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- /* If permissions should be preserved on this project, then
- save the permission info. */
- if (preserve_perms)
- {
- Node *np;
- char buf[64]; /* static buffer should be safe: see usage. -twp */
-
- delta->other_delta = getlist();
-
- if (CVS_LSTAT (workfile, &sb) < 0)
- error (1, errno, "cannot lstat %s", workfile);
-
- if (S_ISLNK (sb.st_mode))
- {
- np = getnode();
- np->type = RCSFIELD;
- np->key = xstrdup ("symlink");
- np->data = xreadlink (workfile);
- addnode (delta->other_delta, np);
- }
- else
- {
- (void) sprintf (buf, "%u", sb.st_uid);
- np = getnode();
- np->type = RCSFIELD;
- np->key = xstrdup ("owner");
- np->data = xstrdup (buf);
- addnode (delta->other_delta, np);
-
- (void) sprintf (buf, "%u", sb.st_gid);
- np = getnode();
- np->type = RCSFIELD;
- np->key = xstrdup ("group");
- np->data = xstrdup (buf);
- addnode (delta->other_delta, np);
-
- (void) sprintf (buf, "%o", sb.st_mode & 07777);
- np = getnode();
- np->type = RCSFIELD;
- np->key = xstrdup ("permissions");
- np->data = xstrdup (buf);
- addnode (delta->other_delta, np);
-
- /* Save device number. */
- switch (sb.st_mode & S_IFMT)
- {
- case S_IFREG: break;
- case S_IFCHR:
- case S_IFBLK:
-# ifdef HAVE_STRUCT_STAT_ST_RDEV
- np = getnode();
- np->type = RCSFIELD;
- np->key = xstrdup ("special");
- sprintf (buf, "%s %lu",
- ((sb.st_mode & S_IFMT) == S_IFCHR
- ? "character" : "block"),
- (unsigned long) sb.st_rdev);
- np->data = xstrdup (buf);
- addnode (delta->other_delta, np);
-# else
- error (0, 0,
-"can't preserve %s: unable to save device files on this system",
-workfile);
-# endif
- break;
-
- default:
- error (0, 0, "special file %s has unknown type", workfile);
- }
-
- /* Save hardlinks. */
- delta->hardlinks = list_linked_files_on_disk (workfile);
- }
- }
-#endif
-
- /* Create a new deltatext node. */
- dtext = (Deltatext *) xmalloc (sizeof (Deltatext));
- memset (dtext, 0, sizeof (Deltatext));
-
- dtext->log = make_message_rcslegal (message);
-
- /* If the delta tree is empty, then there's nothing to link the
- new delta into. So make a new delta tree, snarf the working
- file contents, and just write the new RCS file. */
- if (rcs->head == NULL)
- {
- char *newrev;
- FILE *fout;
-
- /* Figure out what the first revision number should be. */
- if (rev == NULL || *rev == '\0')
- newrev = xstrdup ("1.1");
- else if (numdots (rev) == 0)
- {
- newrev = (char *) xmalloc (strlen (rev) + 3);
- strcpy (newrev, rev);
- strcat (newrev, ".1");
- }
- else
- newrev = xstrdup (rev);
-
- /* Don't need to xstrdup NEWREV because it's already dynamic, and
- not used for anything else. (Don't need to free it, either.) */
- rcs->head = newrev;
- delta->version = xstrdup (newrev);
- nodep = getnode();
- nodep->type = RCSVERS;
- nodep->delproc = rcsvers_delproc;
- nodep->data = delta;
- nodep->key = delta->version;
- (void) addnode (rcs->versions, nodep);
-
- dtext->version = xstrdup (newrev);
- bufsize = 0;
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- if (preserve_perms && !S_ISREG (sb.st_mode))
- /* Pretend file is empty. */
- bufsize = 0;
- else
-#endif
- get_file (workfile, workfile,
- rcs->expand != NULL && STREQ (rcs->expand, "b") ? "rb" : "r",
- &dtext->text, &bufsize, &dtext->len);
-
- if (!checkin_quiet)
- {
- cvs_output ("initial revision: ", 0);
- cvs_output (rcs->head, 0);
- cvs_output ("\n", 1);
- }
-
- /* We are probably about to invalidate any cached file. */
- rcsbuf_cache_close ();
-
- fout = rcs_internal_lockfile (rcs->path);
- RCS_putadmin (rcs, fout);
- RCS_putdtree (rcs, rcs->head, fout);
- RCS_putdesc (rcs, fout);
- rcs->delta_pos = ftell (fout);
- if (rcs->delta_pos == -1)
- error (1, errno, "cannot ftell for %s", rcs->path);
- putdeltatext (fout, dtext);
- rcs_internal_unlockfile (fout, rcs->path);
-
- if ((flags & RCS_FLAGS_KEEPFILE) == 0)
- {
- if (unlink_file (workfile) < 0)
- /* FIXME-update-dir: message does not include update_dir. */
- error (0, errno, "cannot remove %s", workfile);
- }
-
- if (!checkin_quiet)
- cvs_output ("done\n", 5);
-
- status = 0;
- goto checkin_done;
- }
-
- /* Derive a new revision number. From the `ci' man page:
-
- "If rev is a revision number, it must be higher than the
- latest one on the branch to which rev belongs, or must
- start a new branch.
-
- If rev is a branch rather than a revision number, the new
- revision is appended to that branch. The level number is
- obtained by incrementing the tip revision number of that
- branch. If rev indicates a non-existing branch, that
- branch is created with the initial revision numbered
- rev.1."
-
- RCS_findlock_or_tip handles the case where REV is omitted.
- RCS 5.7 also permits REV to be "$" or to begin with a dot, but
- we do not address those cases -- every routine that calls
- RCS_checkin passes it a numeric revision. */
-
- if (rev == NULL || *rev == '\0')
- {
- /* Figure out where the commit point is by looking for locks.
- If the commit point is at the tip of a branch (or is the
- head of the delta tree), then increment its revision number
- to obtain the new revnum. Otherwise, start a new
- branch. */
- commitpt = RCS_findlock_or_tip (rcs);
- if (commitpt == NULL)
- {
- status = 1;
- goto checkin_done;
- }
- else if (commitpt->next == NULL
- || STREQ (commitpt->version, rcs->head))
- delta->version = increment_revnum (commitpt->version);
- else
- delta->version = RCS_addbranch (rcs, commitpt->version);
- }
- else
- {
- /* REV is either a revision number or a branch number. Find the
- tip of the target branch. */
- char *branch, *tip, *newrev, *p;
- int dots, isrevnum;
-
- assert (isdigit ((unsigned char) *rev));
-
- newrev = xstrdup (rev);
- dots = numdots (newrev);
- isrevnum = dots & 1;
-
- branch = xstrdup (rev);
- if (isrevnum)
- {
- p = strrchr (branch, '.');
- *p = '\0';
- }
-
- /* Find the tip of the target branch. If we got a one- or two-digit
- revision number, this will be the head of the tree. Exception:
- if rev is a single-field revision equal to the branch number of
- the trunk (usually "1") then we want to treat it like an ordinary
- branch revision. */
- if (dots == 0)
- {
- tip = xstrdup (rcs->head);
- assert (tip != NULL);
- if (atoi (tip) != atoi (branch))
- {
- newrev = (char *) xrealloc (newrev, strlen (newrev) + 3);
- strcat (newrev, ".1");
- dots = isrevnum = 1;
- }
- }
- else if (dots == 1)
- tip = xstrdup (rcs->head);
- else
- tip = RCS_getbranch (rcs, branch, 1);
-
- /* If the branch does not exist, and we were supplied an exact
- revision number, signal an error. Otherwise, if we were
- given only a branch number, create it and set COMMITPT to
- the branch point. */
- if (tip == NULL)
- {
- if (isrevnum)
- {
- error (0, 0, "%s: can't find branch point %s",
- rcs->path, branch);
- free (branch);
- free (newrev);
- status = 1;
- goto checkin_done;
- }
- delta->version = RCS_addbranch (rcs, branch);
- if (!delta->version)
- {
- free (branch);
- free (newrev);
- status = 1;
- goto checkin_done;
- }
- adding_branch = 1;
- p = strrchr (branch, '.');
- *p = '\0';
- tip = xstrdup (branch);
- }
- else
- {
- if (isrevnum)
- {
- /* NEWREV must be higher than TIP. */
- if (compare_revnums (tip, newrev) >= 0)
- {
- error (0, 0,
- "%s: revision %s too low; must be higher than %s",
- rcs->path,
- newrev, tip);
- free (branch);
- free (newrev);
- free (tip);
- status = 1;
- goto checkin_done;
- }
- delta->version = xstrdup (newrev);
- }
- else
- /* Just increment the tip number to get the new revision. */
- delta->version = increment_revnum (tip);
- }
-
- nodep = findnode (rcs->versions, tip);
- commitpt = nodep->data;
-
- free (branch);
- free (newrev);
- free (tip);
- }
-
- assert (delta->version != NULL);
-
- /* If COMMITPT is locked by us, break the lock. If it's locked
- by someone else, signal an error. */
- nodep = findnode (RCS_getlocks (rcs), commitpt->version);
- if (nodep != NULL)
- {
- if (! STREQ (nodep->data, delta->author))
- {
- /* If we are adding a branch, then leave the old lock around.
- That is sensible in the sense that when adding a branch,
- we don't need to use the lock to tell us where to check
- in. It is fishy in the sense that if it is our own lock,
- we break it. However, this is the RCS 5.7 behavior (at
- the end of addbranch in ci.c in RCS 5.7, it calls
- removelock only if it is our own lock, not someone
- else's). */
-
- if (!adding_branch)
- {
- error (0, 0, "%s: revision %s locked by %s",
- rcs->path,
- nodep->key, (char *)nodep->data);
- status = 1;
- goto checkin_done;
- }
- }
- else
- delnode (nodep);
- }
-
- dtext->version = xstrdup (delta->version);
-
- /* Obtain the change text for the new delta. If DELTA is to be the
- new head of the tree, then its change text should be the contents
- of the working file, and LEAFNODE's change text should be a diff.
- Else, DELTA's change text should be a diff between LEAFNODE and
- the working file. */
-
- tmpfile = cvs_temp_name();
- status = RCS_checkout (rcs, NULL, commitpt->version, NULL,
- ((rcs->expand != NULL
- && STREQ (rcs->expand, "b"))
- ? "-kb"
- : "-ko"),
- tmpfile,
- (RCSCHECKOUTPROC)0, NULL);
- if (status != 0)
- error (1, 0,
- "could not check out revision %s of `%s'",
- commitpt->version, rcs->path);
-
- bufsize = 0;
- changefile = cvs_temp_name();
-
- /* Diff options should include --binary if the RCS file has -kb set
- in its `expand' field. */
- run_add_arg_p (&dargc, &darg_allocated, &dargv, "-a");
- run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n");
- if (rcs->expand && STREQ (rcs->expand, "b"))
- run_add_arg_p (&dargc, &darg_allocated, &dargv, "--binary");
-
- if (STREQ (commitpt->version, rcs->head) &&
- numdots (delta->version) == 1)
- {
- /* If this revision is being inserted on the trunk, the change text
- for the new delta should be the contents of the working file ... */
- bufsize = 0;
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- if (preserve_perms && !S_ISREG (sb.st_mode))
- /* Pretend file is empty. */
- ;
- else
-#endif
- get_file (workfile, workfile,
- rcs->expand != NULL && STREQ (rcs->expand, "b") ? "rb" : "r",
- &dtext->text, &bufsize, &dtext->len);
-
- /* ... and the change text for the old delta should be a diff. */
- commitpt->text = (Deltatext *) xmalloc (sizeof (Deltatext));
- memset (commitpt->text, 0, sizeof (Deltatext));
-
- bufsize = 0;
- switch (diff_exec (workfile, tmpfile, NULL, NULL,
- dargc, dargv, changefile))
- {
- case 0:
- case 1:
- break;
- case -1:
- /* FIXME-update-dir: message does not include update_dir. */
- error (1, errno, "error diffing %s", workfile);
- break;
- default:
- /* FIXME-update-dir: message does not include update_dir. */
- error (1, 0, "error diffing %s", workfile);
- break;
- }
-
- /* OK, the text file case here is really dumb. Logically
- speaking we want diff to read the files in text mode,
- convert them to the canonical form found in RCS files
- (which, we hope at least, is independent of OS--always
- bare linefeeds), and then work with change texts in that
- format. However, diff_exec both generates change
- texts and produces output for user purposes (e.g. patch.c),
- and there is no way to distinguish between the two cases.
- So we actually implement the text file case by writing the
- change text as a text file, then reading it as a text file.
- This should cause no harm, but doesn't strike me as
- immensely clean. */
- get_file (changefile, changefile,
- rcs->expand != NULL && STREQ (rcs->expand, "b") ? "rb" : "r",
- &commitpt->text->text, &bufsize, &commitpt->text->len);
-
- /* If COMMITPT->TEXT->TEXT is NULL, it means that CHANGEFILE
- was empty and that there are no differences between revisions.
- In that event, we want to force RCS_rewrite to write an empty
- string for COMMITPT's change text. Leaving the change text
- field set NULL won't work, since that means "preserve the original
- change text for this delta." */
- if (commitpt->text->text == NULL)
- {
- commitpt->text->text = xstrdup ("");
- commitpt->text->len = 0;
- }
- }
- else
- {
- /* This file is not being inserted at the head, but on a side
- branch somewhere. Make a diff from the previous revision
- to the working file. */
- switch (diff_exec (tmpfile, workfile, NULL, NULL,
- dargc, dargv, changefile))
- {
- case 0:
- case 1:
- break;
- case -1:
- /* FIXME-update-dir: message does not include update_dir. */
- error (1, errno, "error diffing %s", workfile);
- break;
- default:
- /* FIXME-update-dir: message does not include update_dir. */
- error (1, 0, "error diffing %s", workfile);
- break;
- }
- /* See the comment above, at the other get_file invocation,
- regarding binary vs. text. */
- get_file (changefile, changefile,
- rcs->expand != NULL && STREQ (rcs->expand, "b") ? "rb" : "r",
- &dtext->text, &bufsize,
- &dtext->len);
- if (dtext->text == NULL)
- {
- dtext->text = xstrdup ("");
- dtext->len = 0;
- }
- }
-
- run_arg_free_p (dargc, dargv);
- free (dargv);
-
- /* Update DELTA linkage. It is important not to do this before
- the very end of RCS_checkin; if an error arises that forces
- us to abort checking in, we must not have malformed deltas
- partially linked into the tree.
-
- If DELTA and COMMITPT are on different branches, do nothing --
- DELTA is linked to the tree through COMMITPT->BRANCHES, and we
- don't want to change `next' pointers.
-
- Otherwise, if the nodes are both on the trunk, link DELTA to
- COMMITPT; otherwise, link COMMITPT to DELTA. */
-
- if (numdots (commitpt->version) == numdots (delta->version))
- {
- if (STREQ (commitpt->version, rcs->head))
- {
- delta->next = rcs->head;
- rcs->head = xstrdup (delta->version);
- }
- else
- commitpt->next = xstrdup (delta->version);
- }
-
- /* Add DELTA to RCS->VERSIONS. */
- if (rcs->versions == NULL)
- rcs->versions = getlist();
- nodep = getnode();
- nodep->type = RCSVERS;
- nodep->delproc = rcsvers_delproc;
- nodep->data = delta;
- nodep->key = delta->version;
- (void) addnode (rcs->versions, nodep);
-
- /* Write the new RCS file, inserting the new delta at COMMITPT. */
- if (!checkin_quiet)
- {
- cvs_output ("new revision: ", 14);
- cvs_output (delta->version, 0);
- cvs_output ("; previous revision: ", 21);
- cvs_output (commitpt->version, 0);
- cvs_output ("\n", 1);
- }
-
- RCS_rewrite (rcs, dtext, commitpt->version);
-
- if ((flags & RCS_FLAGS_KEEPFILE) == 0)
- {
- if (unlink_file (workfile) < 0)
- /* FIXME-update-dir: message does not include update_dir. */
- error (1, errno, "cannot remove %s", workfile);
- }
- if (unlink_file (tmpfile) < 0)
- error (0, errno, "cannot remove %s", tmpfile);
- free (tmpfile);
- if (unlink_file (changefile) < 0)
- error (0, errno, "cannot remove %s", changefile);
- free (changefile);
-
- if (!checkin_quiet)
- cvs_output ("done\n", 5);
-
- checkin_done:
- free (workfile);
-
- if (commitpt != NULL && commitpt->text != NULL)
- {
- freedeltatext (commitpt->text);
- commitpt->text = NULL;
- }
-
- freedeltatext (dtext);
- if (status != 0)
- {
- /* If delta has not been added to a List, then freeing the Node key
- * won't free delta->version.
- */
- if (delta->version) free (delta->version);
- free_rcsvers_contents (delta);
- }
-
- return status;
-}
-
-
-
-/* This structure is passed between RCS_cmp_file and cmp_file_buffer. */
-struct cmp_file_data
-{
- const char *filename;
- FILE *fp;
- int different;
-};
-
-/* Compare the contents of revision REV1 of RCS file RCS with the
- contents of REV2 if given, otherwise, compare with the contents of
- the file FILENAME. OPTIONS is a string for the keyword
- expansion options. Return 0 if the contents of the revision are
- the same as the contents of the file, 1 if they are different. */
-int
-RCS_cmp_file (rcs, rev1, rev1_cache, rev2, options, filename)
- RCSNode *rcs;
- const char *rev1;
- char **rev1_cache;
- const char *rev2;
- const char *options;
- const char *filename;
-{
- int binary;
-
- if (options != NULL && options[0] != '\0')
- binary = STREQ (options, "-kb");
- else
- {
- char *expand;
-
- expand = RCS_getexpand (rcs);
- if (expand != NULL && STREQ (expand, "b"))
- binary = 1;
- else
- binary = 0;
- }
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- /* If CVS is to deal properly with special files (when
- PreservePermissions is on), the best way is to check out the
- revision to a temporary file and call `xcmp' on the two disk
- files. xcmp needs to handle non-regular files properly anyway,
- so calling it simplifies RCS_cmp_file. We *could* just yank
- the delta node out of the version tree and look for device
- numbers, but writing to disk and calling xcmp is a better
- abstraction (therefore probably more robust). -twp */
-
- if (preserve_perms)
- {
- char *tmp;
- int retcode;
-
- tmp = cvs_temp_name();
- retcode = RCS_checkout(rcs, NULL, rev, NULL, options, tmp, NULL, NULL);
- if (retcode != 0)
- return 1;
-
- retcode = xcmp (tmp, filename);
- if (CVS_UNLINK (tmp) < 0)
- error (0, errno, "cannot remove %s", tmp);
- free (tmp);
- return retcode;
- }
- else
-#endif
- {
- FILE *fp;
- struct cmp_file_data data;
- const char *use_file1;
- char *tmpfile = NULL;
-
- if (rev2 != NULL)
- {
- /* Open & cache rev1 */
- tmpfile = cvs_temp_name();
- if (RCS_checkout (rcs, NULL, rev1, NULL, options, tmpfile,
- (RCSCHECKOUTPROC)0, NULL))
- error (1, errno,
- "cannot check out revision %s of %s",
- rev1, rcs->path);
- use_file1 = tmpfile;
- if (rev1_cache != NULL)
- *rev1_cache = tmpfile;
- }
- else
- use_file1 = filename;
-
- fp = CVS_FOPEN (use_file1, binary ? FOPEN_BINARY_READ : "r");
- if (fp == NULL)
- /* FIXME-update-dir: should include update_dir in message. */
- error (1, errno, "cannot open file %s for comparing", use_file1);
-
- data.filename = use_file1;
- data.fp = fp;
- data.different = 0;
-
- if (RCS_checkout (rcs, (char *)NULL, rev2 ? rev2 : rev1,
- (char *)NULL, options, RUN_TTY, cmp_file_buffer,
- (void *)&data ))
- error (1, errno,
- "cannot check out revision %s of %s",
- rev2 ? rev2 : rev1, rcs->path);
-
- /* If we have not yet found a difference, make sure that we are at
- the end of the file. */
- if (!data.different)
- {
- if (getc (fp) != EOF)
- data.different = 1;
- }
-
- fclose (fp);
- if (rev1_cache == NULL && tmpfile)
- {
- if (CVS_UNLINK (tmpfile ) < 0)
- error (0, errno, "cannot remove %s", tmpfile);
- free (tmpfile);
- }
-
- return data.different;
- }
-}
-
-
-
-/* This is a subroutine of RCS_cmp_file. It is passed to
- RCS_checkout. */
-#define CMP_BUF_SIZE (8 * 1024)
-
-static void
-cmp_file_buffer (callerdat, buffer, len)
- void *callerdat;
- const char *buffer;
- size_t len;
-{
- struct cmp_file_data *data = (struct cmp_file_data *)callerdat;
- char *filebuf;
-
- /* If we've already found a difference, we don't need to check
- further. */
- if (data->different)
- return;
-
- filebuf = xmalloc (len > CMP_BUF_SIZE ? CMP_BUF_SIZE : len);
-
- while (len > 0)
- {
- size_t checklen;
-
- checklen = len > CMP_BUF_SIZE ? CMP_BUF_SIZE : len;
- if (fread (filebuf, 1, checklen, data->fp) != checklen)
- {
- if (ferror (data->fp))
- error (1, errno, "cannot read file %s for comparing",
- data->filename);
- data->different = 1;
- free (filebuf);
- return;
- }
-
- if (memcmp (filebuf, buffer, checklen) != 0)
- {
- data->different = 1;
- free (filebuf);
- return;
- }
-
- buffer += checklen;
- len -= checklen;
- }
-
- free (filebuf);
-}
-
-
-
-/* For RCS file RCS, make symbolic tag TAG point to revision REV.
- This validates that TAG is OK for a user to use. Return value is
- -1 for error (and errno is set to indicate the error), positive for
- error (and an error message has been printed), or zero for success. */
-
-int
-RCS_settag (rcs, tag, rev)
- RCSNode *rcs;
- const char *tag;
- const char *rev;
-{
- List *symbols;
- Node *node;
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- /* FIXME: This check should be moved to RCS_check_tag. There is no
- reason for it to be here. */
- if (STREQ (tag, TAG_BASE)
- || STREQ (tag, TAG_HEAD))
- {
- /* Print the name of the tag might be considered redundant
- with the caller, which also prints it. Perhaps this helps
- clarify why the tag name is considered reserved, I don't
- know. */
- error (0, 0, "Attempt to add reserved tag name %s", tag);
- return 1;
- }
-
- /* A revision number of NULL means use the head or default branch.
- If rev is not NULL, it may be a symbolic tag or branch number;
- expand it to the correct numeric revision or branch head. */
- if (rev == NULL)
- rev = rcs->branch ? rcs->branch : rcs->head;
-
- /* At this point rcs->symbol_data may not have been parsed.
- Calling RCS_symbols will force it to be parsed into a list
- which we can easily manipulate. */
- symbols = RCS_symbols (rcs);
- if (symbols == NULL)
- {
- symbols = getlist ();
- rcs->symbols = symbols;
- }
- node = findnode (symbols, tag);
- if (node != NULL)
- {
- free (node->data);
- node->data = xstrdup (rev);
- }
- else
- {
- node = getnode ();
- node->key = xstrdup (tag);
- node->data = xstrdup (rev);
- (void) addnode_at_front (symbols, node);
- }
-
- return 0;
-}
-
-/* Delete the symbolic tag TAG from the RCS file RCS. Return 0 if
- the tag was found (and removed), or 1 if it was not present. (In
- either case, the tag will no longer be in RCS->SYMBOLS.) */
-
-int
-RCS_deltag (rcs, tag)
- RCSNode *rcs;
- const char *tag;
-{
- List *symbols;
- Node *node;
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- symbols = RCS_symbols (rcs);
- if (symbols == NULL)
- return 1;
-
- node = findnode (symbols, tag);
- if (node == NULL)
- return 1;
-
- delnode (node);
-
- return 0;
-}
-
-/* Set the default branch of RCS to REV. */
-
-int
-RCS_setbranch (rcs, rev)
- RCSNode *rcs;
- const char *rev;
-{
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- if (rev && ! *rev)
- rev = NULL;
-
- if (rev == NULL && rcs->branch == NULL)
- return 0;
- if (rev != NULL && rcs->branch != NULL && STREQ (rev, rcs->branch))
- return 0;
-
- if (rcs->branch != NULL)
- free (rcs->branch);
- rcs->branch = xstrdup (rev);
-
- return 0;
-}
-
-/* Lock revision REV. LOCK_QUIET is 1 to suppress output. FIXME:
- Most of the callers only call us because RCS_checkin still tends to
- like a lock (a relic of old behavior inherited from the RCS ci
- program). If we clean this up, only "cvs admin -l" will still need
- to call RCS_lock. */
-
-/* FIXME-twp: if a lock owned by someone else is broken, should this
- send mail to the lock owner? Prompt user? It seems like such an
- obscure situation for CVS as almost not worth worrying much
- about. */
-
-int
-RCS_lock (rcs, rev, lock_quiet)
- RCSNode *rcs;
- const char *rev;
- int lock_quiet;
-{
- List *locks;
- Node *p;
- char *user;
- char *xrev = NULL;
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- locks = RCS_getlocks (rcs);
- if (locks == NULL)
- locks = rcs->locks = getlist();
- user = getcaller();
-
- /* A revision number of NULL means lock the head or default branch. */
- if (rev == NULL)
- xrev = RCS_head (rcs);
- else
- xrev = RCS_gettag (rcs, rev, 1, (int *) NULL);
-
- /* Make sure that the desired revision exists. Technically,
- we can update the locks list without even checking this,
- but RCS 5.7 did this. And it can't hurt. */
- if (xrev == NULL || findnode (rcs->versions, xrev) == NULL)
- {
- if (!lock_quiet)
- error (0, 0, "%s: revision %s absent", rcs->path, rev);
- free (xrev);
- return 1;
- }
-
- /* Is this rev already locked? */
- p = findnode (locks, xrev);
- if (p != NULL)
- {
- if (STREQ (p->data, user))
- {
- /* We already own the lock on this revision, so do nothing. */
- free (xrev);
- return 0;
- }
-
-#if 0
- /* Well, first of all, "rev" below should be "xrev" to avoid
- core dumps. But more importantly, should we really be
- breaking the lock unconditionally? What CVS 1.9 does (via
- RCS) is to prompt "Revision 1.1 is already locked by fred.
- Do you want to break the lock? [ny](n): ". Well, we don't
- want to interact with the user (certainly not at the
- server/protocol level, and probably not in the command-line
- client), but isn't it more sensible to give an error and
- let the user run "cvs admin -u" if they want to break the
- lock? */
-
- /* Break the lock. */
- if (!lock_quiet)
- {
- cvs_output (rev, 0);
- cvs_output (" unlocked\n", 0);
- }
- delnode (p);
-#else
- error (1, 0, "Revision %s is already locked by %s", xrev, (char *)p->data);
-#endif
- }
-
- /* Create a new lock. */
- p = getnode();
- p->key = xrev; /* already xstrdupped */
- p->data = xstrdup (getcaller());
- (void) addnode_at_front (locks, p);
-
- if (!lock_quiet)
- {
- cvs_output (xrev, 0);
- cvs_output (" locked\n", 0);
- }
-
- return 0;
-}
-
-/* Unlock revision REV. UNLOCK_QUIET is 1 to suppress output. FIXME:
- Like RCS_lock, this can become a no-op if we do the checkin
- ourselves.
-
- If REV is not null and is locked by someone else, break their
- lock and notify them. It is an open issue whether RCS_unlock
- queries the user about whether or not to break the lock. */
-
-int
-RCS_unlock (rcs, rev, unlock_quiet)
- RCSNode *rcs;
- char *rev;
- int unlock_quiet;
-{
- Node *lock;
- List *locks;
- char *user;
- char *xrev = NULL;
-
- user = getcaller();
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- /* If rev is NULL, unlock the revision held by the caller; if more
- than one, make the user specify the revision explicitly. This
- differs from RCS which unlocks the latest revision (first in
- rcs->locks) held by the caller. */
- if (rev == NULL)
- {
- Node *p;
-
- /* No-ops: attempts to unlock an empty tree or an unlocked file. */
- if (rcs->head == NULL)
- {
- if (!unlock_quiet)
- cvs_outerr ("can't unlock an empty tree\n", 0);
- return 0;
- }
-
- locks = RCS_getlocks (rcs);
- if (locks == NULL)
- {
- if (!unlock_quiet)
- cvs_outerr ("No locks are set.\n", 0);
- return 0;
- }
-
- lock = NULL;
- for (p = locks->list->next; p != locks->list; p = p->next)
- {
- if (STREQ (p->data, user))
- {
- if (lock != NULL)
- {
- if (!unlock_quiet)
- error (0, 0, "\
-%s: multiple revisions locked by %s; please specify one", rcs->path, user);
- return 1;
- }
- lock = p;
- }
- }
- if (lock == NULL)
- {
- if (!unlock_quiet)
- error (0, 0, "No locks are set for %s.\n", user);
- return 0; /* no lock found, ergo nothing to do */
- }
- xrev = xstrdup (lock->key);
- }
- else
- {
- xrev = RCS_gettag (rcs, rev, 1, (int *) NULL);
- if (xrev == NULL)
- {
- error (0, 0, "%s: revision %s absent", rcs->path, rev);
- return 1;
- }
- }
-
- lock = findnode (RCS_getlocks (rcs), xrev);
- if (lock == NULL)
- {
- /* This revision isn't locked. */
- free (xrev);
- return 0;
- }
-
- if (! STREQ (lock->data, user))
- {
- /* If the revision is locked by someone else, notify
- them. Note that this shouldn't ever happen if RCS_unlock
- is called with a NULL revision, since that means "whatever
- revision is currently locked by the caller." */
- char *repos, *workfile;
- if (!unlock_quiet)
- error (0, 0, "\
-%s: revision %s locked by %s; breaking lock", rcs->path, xrev, (char *)lock->data);
- repos = xstrdup (rcs->path);
- workfile = strrchr (repos, '/');
- *workfile++ = '\0';
- notify_do ('C', workfile, user, NULL, NULL, repos);
- free (repos);
- }
-
- delnode (lock);
- if (!unlock_quiet)
- {
- cvs_output (xrev, 0);
- cvs_output (" unlocked\n", 0);
- }
-
- free (xrev);
- return 0;
-}
-
-/* Add USER to the access list of RCS. Do nothing if already present.
- FIXME-twp: check syntax of USER to make sure it's a valid id. */
-
-void
-RCS_addaccess (rcs, user)
- RCSNode *rcs;
- char *user;
-{
- char *access, *a;
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- if (rcs->access == NULL)
- rcs->access = xstrdup (user);
- else
- {
- access = xstrdup (rcs->access);
- for (a = strtok (access, " "); a != NULL; a = strtok (NULL, " "))
- {
- if (STREQ (a, user))
- {
- free (access);
- return;
- }
- }
- free (access);
- rcs->access = (char *) xrealloc
- (rcs->access, strlen (rcs->access) + strlen (user) + 2);
- strcat (rcs->access, " ");
- strcat (rcs->access, user);
- }
-}
-
-/* Remove USER from the access list of RCS. */
-
-void
-RCS_delaccess (rcs, user)
- RCSNode *rcs;
- char *user;
-{
- char *p, *s;
- int ulen;
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- if (rcs->access == NULL)
- return;
-
- if (user == NULL)
- {
- free (rcs->access);
- rcs->access = NULL;
- return;
- }
-
- p = rcs->access;
- ulen = strlen (user);
- while (p != NULL)
- {
- if (strncmp (p, user, ulen) == 0 && (p[ulen] == '\0' || p[ulen] == ' '))
- break;
- p = strchr (p, ' ');
- if (p != NULL)
- ++p;
- }
-
- if (p == NULL)
- return;
-
- s = p + ulen;
- while (*s != '\0')
- *p++ = *s++;
- *p = '\0';
-}
-
-char *
-RCS_getaccess (rcs)
- RCSNode *rcs;
-{
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- return rcs->access;
-}
-
-static int findtag PROTO ((Node *, void *));
-
-/* Return a nonzero value if the revision specified by ARG is found. */
-
-static int
-findtag (node, arg)
- Node *node;
- void *arg;
-{
- char *rev = (char *)arg;
-
- if (STREQ (node->data, rev))
- return 1;
- else
- return 0;
-}
-
-static int findmagictag PROTO ((Node *, void *));
-
-/* Return a nonzero value if a magic tag rooted at ARG is found. */
-
-static int
-findmagictag (node, arg)
- Node *node;
- void *arg;
-{
- char *rev = (char *)arg;
- size_t len = strlen (rev);
-
- if (strncmp (node->data, rev, len) == 0 &&
- strncmp ((char *)node->data + len, ".0.", 3) == 0)
- return 1;
- else
- return 0;
-}
-
-/* Delete revisions between REV1 and REV2. The changes between the two
- revisions must be collapsed, and the result stored in the revision
- immediately preceding the lower one. Return 0 for successful completion,
- 1 otherwise.
-
- Solution: check out the revision preceding REV1 and the revision
- following REV2. Use call_diff to find aggregate diffs between
- these two revisions, and replace the delta text for the latter one
- with the new aggregate diff. Alternatively, we could write a
- function that takes two change texts and combines them to produce a
- new change text, without checking out any revs or calling diff. It
- would be hairy, but so, so cool.
-
- If INCLUSIVE is set, then TAG1 and TAG2, if non-NULL, tell us to
- delete that revision as well (cvs admin -o tag1:tag2). If clear,
- delete up to but not including that revision (cvs admin -o tag1::tag2).
- This does not affect TAG1 or TAG2 being NULL; the meaning of the start
- point in ::tag2 and :tag2 is the same and likewise for end points. */
-
-int
-RCS_delete_revs (rcs, tag1, tag2, inclusive)
- RCSNode *rcs;
- char *tag1;
- char *tag2;
- int inclusive;
-{
- char *next;
- Node *nodep;
- RCSVers *revp = NULL;
- RCSVers *beforep;
- int status, found;
- int save_noexec;
-
- char *branchpoint = NULL;
- char *rev1 = NULL;
- char *rev2 = NULL;
- int rev1_inclusive = inclusive;
- int rev2_inclusive = inclusive;
- char *before = NULL;
- char *after = NULL;
- char *beforefile = NULL;
- char *afterfile = NULL;
- char *outfile = NULL;
-
- if (tag1 == NULL && tag2 == NULL)
- return 0;
-
- /* Assume error status until everything is finished. */
- status = 1;
-
- /* Make sure both revisions exist. */
- if (tag1 != NULL)
- {
- rev1 = RCS_gettag (rcs, tag1, 1, NULL);
- if (rev1 == NULL || (nodep = findnode (rcs->versions, rev1)) == NULL)
- {
- error (0, 0, "%s: Revision %s doesn't exist.", rcs->path, tag1);
- goto delrev_done;
- }
- }
- if (tag2 != NULL)
- {
- rev2 = RCS_gettag (rcs, tag2, 1, NULL);
- if (rev2 == NULL || (nodep = findnode (rcs->versions, rev2)) == NULL)
- {
- error (0, 0, "%s: Revision %s doesn't exist.", rcs->path, tag2);
- goto delrev_done;
- }
- }
-
- /* If rev1 is on the trunk and rev2 is NULL, rev2 should be
- RCS->HEAD. (*Not* RCS_head(rcs), which may return rcs->branch
- instead.) We need to check this special case early, in order
- to make sure that rev1 and rev2 get ordered correctly. */
- if (rev2 == NULL && numdots (rev1) == 1)
- {
- rev2 = xstrdup (rcs->head);
- rev2_inclusive = 1;
- }
-
- if (rev2 == NULL)
- rev2_inclusive = 1;
-
- if (rev1 != NULL && rev2 != NULL)
- {
- /* A range consisting of a branch number means the latest revision
- on that branch. */
- if (RCS_isbranch (rcs, rev1) && STREQ (rev1, rev2))
- {
- char *tmp = RCS_getbranch (rcs, rev1, 0);
- free (rev1);
- free (rev2);
- rev1 = rev2 = tmp;
- }
- else
- {
- /* Make sure REV1 and REV2 are ordered correctly (in the
- same order as the next field). For revisions on the
- trunk, REV1 should be higher than REV2; for branches,
- REV1 should be lower. */
- /* Shouldn't we just be giving an error in the case where
- the user specifies the revisions in the wrong order
- (that is, always swap on the trunk, never swap on a
- branch, in the non-error cases)? It is not at all
- clear to me that users who specify -o 1.4:1.2 really
- meant to type -o 1.2:1.4, and the out of order usage
- has never been documented, either by cvs.texinfo or
- rcs(1). */
- char *temp;
- int temp_inclusive;
- if (numdots (rev1) == 1)
- {
- if (compare_revnums (rev1, rev2) <= 0)
- {
- temp = rev2;
- rev2 = rev1;
- rev1 = temp;
-
- temp_inclusive = rev2_inclusive;
- rev2_inclusive = rev1_inclusive;
- rev1_inclusive = temp_inclusive;
- }
- }
- else if (compare_revnums (rev1, rev2) > 0)
- {
- temp = rev2;
- rev2 = rev1;
- rev1 = temp;
-
- temp_inclusive = rev2_inclusive;
- rev2_inclusive = rev1_inclusive;
- rev1_inclusive = temp_inclusive;
- }
- }
- }
-
- /* Basically the same thing; make sure that the ordering is what we
- need. */
- if (rev1 == NULL)
- {
- assert (rev2 != NULL);
- if (numdots (rev2) == 1)
- {
- /* Swap rev1 and rev2. */
- int temp_inclusive;
-
- rev1 = rev2;
- rev2 = NULL;
-
- temp_inclusive = rev2_inclusive;
- rev2_inclusive = rev1_inclusive;
- rev1_inclusive = temp_inclusive;
- }
- }
-
- /* Put the revision number preceding the first one to delete into
- BEFORE (where "preceding" means according to the next field).
- If the first revision to delete is the first revision on its
- branch (e.g. 1.3.2.1), BEFORE should be the node on the trunk
- at which the branch is rooted. If the first revision to delete
- is the head revision of the trunk, set BEFORE to NULL.
-
- Note that because BEFORE may not be on the same branch as REV1,
- it is not very handy for navigating the revision tree. It's
- most useful just for checking out the revision preceding REV1. */
- before = NULL;
- branchpoint = RCS_getbranchpoint (rcs, rev1 != NULL ? rev1 : rev2);
- if (rev1 == NULL)
- {
- rev1 = xstrdup (branchpoint);
- if (numdots (branchpoint) > 1)
- {
- char *bp;
- bp = strrchr (branchpoint, '.');
- while (*--bp != '.')
- ;
- *bp = '\0';
- /* Note that this is exclusive, always, because the inclusive
- flag doesn't affect the meaning when rev1 == NULL. */
- before = xstrdup (branchpoint);
- *bp = '.';
- }
- }
- else if (! STREQ (rev1, branchpoint))
- {
- /* Walk deltas from BRANCHPOINT on, looking for REV1. */
- nodep = findnode (rcs->versions, branchpoint);
- revp = nodep->data;
- while (revp->next != NULL && ! STREQ (revp->next, rev1))
- {
- revp = nodep->data;
- nodep = findnode (rcs->versions, revp->next);
- }
- if (revp->next == NULL)
- {
- error (0, 0, "%s: Revision %s doesn't exist.", rcs->path, rev1);
- goto delrev_done;
- }
- if (rev1_inclusive)
- before = xstrdup (revp->version);
- else
- {
- before = rev1;
- nodep = findnode (rcs->versions, before);
- rev1 = xstrdup (((RCSVers *)nodep->data)->next);
- }
- }
- else if (!rev1_inclusive)
- {
- before = rev1;
- nodep = findnode (rcs->versions, before);
- rev1 = xstrdup (((RCSVers *)nodep->data)->next);
- }
- else if (numdots (branchpoint) > 1)
- {
- /* Example: rev1 is "1.3.2.1", branchpoint is "1.3.2.1".
- Set before to "1.3". */
- char *bp;
- bp = strrchr (branchpoint, '.');
- while (*--bp != '.')
- ;
- *bp = '\0';
- before = xstrdup (branchpoint);
- *bp = '.';
- }
-
- /* If any revision between REV1 and REV2 is locked or is a branch point,
- we can't delete that revision and must abort. */
- after = NULL;
- next = rev1;
- found = 0;
- while (!found && next != NULL)
- {
- nodep = findnode (rcs->versions, next);
- revp = nodep->data;
-
- if (rev2 != NULL)
- found = STREQ (revp->version, rev2);
- next = revp->next;
-
- if ((!found && next != NULL) || rev2_inclusive || rev2 == NULL)
- {
- if (findnode (RCS_getlocks (rcs), revp->version))
- {
- error (0, 0, "%s: can't remove locked revision %s",
- rcs->path,
- revp->version);
- goto delrev_done;
- }
- if (revp->branches != NULL)
- {
- error (0, 0, "%s: can't remove branch point %s",
- rcs->path,
- revp->version);
- goto delrev_done;
- }
-
- /* Doing this only for the :: syntax is for compatibility.
- See cvs.texinfo for somewhat more discussion. */
- if (!inclusive &&
- (walklist (RCS_symbols (rcs), findtag, revp->version) ||
- walklist (RCS_symbols (rcs), findmagictag, revp->version)))
- {
- /* We don't print which file this happens to on the theory
- that the caller will print the name of the file in a
- more useful fashion (fullname not rcs->path). */
- error (0, 0, "cannot remove revision %s because it has tags",
- revp->version);
- goto delrev_done;
- }
-
- /* It's misleading to print the `deleting revision' output
- here, since we may not actually delete these revisions.
- But that's how RCS does it. Bleah. Someday this should be
- moved to the point where the revs are actually marked for
- deletion. -twp */
- cvs_output ("deleting revision ", 0);
- cvs_output (revp->version, 0);
- cvs_output ("\n", 1);
- }
- }
-
- if (rev2 == NULL)
- ;
- else if (found)
- {
- if (rev2_inclusive)
- after = xstrdup (next);
- else
- after = xstrdup (revp->version);
- }
- else if (!inclusive)
- {
- /* In the case of an empty range, for example 1.2::1.2 or
- 1.2::1.3, we want to just do nothing. */
- status = 0;
- goto delrev_done;
- }
- else
- {
- /* This looks fishy in the cases where tag1 == NULL or tag2 == NULL.
- Are those cases really impossible? */
- assert (tag1 != NULL);
- assert (tag2 != NULL);
-
- error (0, 0, "%s: invalid revision range %s:%s", rcs->path,
- tag1, tag2);
- goto delrev_done;
- }
-
- if (after == NULL && before == NULL)
- {
- /* The user is trying to delete all revisions. While an
- RCS file without revisions makes sense to RCS (e.g. the
- state after "rcs -i"), CVS has never been able to cope with
- it. So at least for now we just make this an error.
-
- We don't include rcs->path in the message since "cvs admin"
- already printed "RCS file:" and the name. */
- error (1, 0, "attempt to delete all revisions");
- }
-
- /* The conditionals at this point get really hairy. Here is the
- general idea:
-
- IF before != NULL and after == NULL
- THEN don't check out any revisions, just delete them
- IF before == NULL and after != NULL
- THEN only check out after's revision, and use it for the new deltatext
- ELSE
- check out both revisions and diff -n them. This could use
- RCS_exec_rcsdiff with some changes, like being able
- to suppress diagnostic messages and to direct output. */
-
- if (after != NULL)
- {
- char *diffbuf;
- size_t bufsize, len;
-
-#if defined (WOE32) && !defined (__CYGWIN32__)
- /* FIXME: This is an awful kludge, but at least until I have
- time to work on it a little more and test it, I'd rather
- give a fatal error than corrupt the file. I think that we
- need to use "-kb" and "--binary" and "rb" to get_file
- (probably can do it always, not just for binary files, if
- we are consistent between the RCS_checkout and the diff). */
- {
- char *expand = RCS_getexpand (rcs);
- if (expand != NULL && STREQ (expand, "b"))
- error (1, 0,
- "admin -o not implemented yet for binary on this system");
- }
-#endif /* WOE32 */
-
- afterfile = cvs_temp_name();
- status = RCS_checkout (rcs, NULL, after, NULL, "-ko", afterfile,
- (RCSCHECKOUTPROC)0, NULL);
- if (status > 0)
- goto delrev_done;
-
- if (before == NULL)
- {
- /* We are deleting revisions from the head of the tree,
- so must create a new head. */
- diffbuf = NULL;
- bufsize = 0;
- get_file (afterfile, afterfile, "r", &diffbuf, &bufsize, &len);
-
- save_noexec = noexec;
- noexec = 0;
- if (unlink_file (afterfile) < 0)
- error (0, errno, "cannot remove %s", afterfile);
- noexec = save_noexec;
-
- free (afterfile);
- afterfile = NULL;
-
- free (rcs->head);
- rcs->head = xstrdup (after);
- }
- else
- {
- int dargc = 0;
- size_t darg_allocated = 0;
- char **dargv = NULL;
-
- beforefile = cvs_temp_name();
- status = RCS_checkout (rcs, NULL, before, NULL, "-ko", beforefile,
- (RCSCHECKOUTPROC)0, NULL);
- if (status > 0)
- goto delrev_done;
-
- outfile = cvs_temp_name();
- run_add_arg_p (&dargc, &darg_allocated, &dargv, "-a");
- run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n");
- status = diff_exec (beforefile, afterfile, NULL, NULL,
- dargc, dargv, outfile);
- run_arg_free_p (dargc, dargv);
- free (dargv);
-
- if (status == 2)
- {
- /* Not sure we need this message; will diff_exec already
- have printed an error? */
- error (0, 0, "%s: could not diff", rcs->path);
- status = 1;
- goto delrev_done;
- }
-
- diffbuf = NULL;
- bufsize = 0;
- get_file (outfile, outfile, "r", &diffbuf, &bufsize, &len);
- }
-
- /* Save the new change text in after's delta node. */
- nodep = findnode (rcs->versions, after);
- revp = nodep->data;
-
- assert (revp->text == NULL);
-
- revp->text = (Deltatext *) xmalloc (sizeof (Deltatext));
- memset ((Deltatext *) revp->text, 0, sizeof (Deltatext));
- revp->text->version = xstrdup (revp->version);
- revp->text->text = diffbuf;
- revp->text->len = len;
-
- /* If DIFFBUF is NULL, it means that OUTFILE is empty and that
- there are no differences between the two revisions. In that
- case, we want to force RCS_copydeltas to write an empty string
- for the new change text (leaving the text field set NULL
- means "preserve the original change text for this delta," so
- we don't want that). */
- if (revp->text->text == NULL)
- revp->text->text = xstrdup ("");
- }
-
- /* Walk through the revisions (again) to mark each one as
- outdated. (FIXME: would it be safe to use the `dead' field for
- this? Doubtful.) */
- for (next = rev1;
- next != NULL && (after == NULL || ! STREQ (next, after));
- next = revp->next)
- {
- nodep = findnode (rcs->versions, next);
- revp = nodep->data;
- revp->outdated = 1;
- }
-
- /* Update delta links. If BEFORE == NULL, we're changing the
- head of the tree and don't need to update any `next' links. */
- if (before != NULL)
- {
- /* If REV1 is the first node on its branch, then BEFORE is its
- root node (on the trunk) and we have to update its branches
- list. Otherwise, BEFORE is on the same branch as AFTER, and
- we can just change BEFORE's `next' field to point to AFTER.
- (This should be safe: since findnode manages its lists via
- the `hashnext' and `hashprev' fields, rather than `next' and
- `prev', mucking with `next' and `prev' should not corrupt the
- delta tree's internal structure. Much. -twp) */
-
- if (rev1 == NULL)
- /* beforep's ->next field already should be equal to after,
- which I think is always NULL in this case. */
- ;
- else if (STREQ (rev1, branchpoint))
- {
- nodep = findnode (rcs->versions, before);
- revp = nodep->data;
- nodep = revp->branches->list->next;
- while (nodep != revp->branches->list &&
- ! STREQ (nodep->key, rev1))
- nodep = nodep->next;
- assert (nodep != revp->branches->list);
- if (after == NULL)
- delnode (nodep);
- else
- {
- free (nodep->key);
- nodep->key = xstrdup (after);
- }
- }
- else
- {
- nodep = findnode (rcs->versions, before);
- beforep = nodep->data;
- free (beforep->next);
- beforep->next = xstrdup (after);
- }
- }
-
- status = 0;
-
- delrev_done:
- if (rev1 != NULL)
- free (rev1);
- if (rev2 && rev2 != rev1)
- free (rev2);
- if (branchpoint != NULL)
- free (branchpoint);
- if (before != NULL)
- free (before);
- if (after != NULL)
- free (after);
-
- save_noexec = noexec;
- noexec = 0;
- if (beforefile != NULL)
- {
- if (unlink_file (beforefile) < 0)
- error (0, errno, "cannot remove %s", beforefile);
- free (beforefile);
- }
- if (afterfile != NULL)
- {
- if (unlink_file (afterfile) < 0)
- error (0, errno, "cannot remove %s", afterfile);
- free (afterfile);
- }
- if (outfile != NULL)
- {
- if (unlink_file (outfile) < 0)
- error (0, errno, "cannot remove %s", outfile);
- free (outfile);
- }
- noexec = save_noexec;
-
- return status;
-}
-
-/*
- * TRUE if there exists a symbolic tag "tag" in file.
- */
-int
-RCS_exist_tag (rcs, tag)
- RCSNode *rcs;
- char *tag;
-{
-
- assert (rcs != NULL);
-
- if (findnode (RCS_symbols (rcs), tag))
- return 1;
- return 0;
-
-}
-
-/*
- * TRUE if RCS revision number "rev" exists.
- * This includes magic branch revisions, not found in rcs->versions,
- * but only in rcs->symbols, requiring a list walk to find them.
- * Take advantage of list walk callback function already used by
- * RCS_delete_revs, above.
- */
-int
-RCS_exist_rev (rcs, rev)
- RCSNode *rcs;
- char *rev;
-{
-
- assert (rcs != NULL);
-
- if (rcs->flags & PARTIAL)
- RCS_reparsercsfile (rcs, (FILE **) NULL, (struct rcsbuffer *) NULL);
-
- if (findnode(rcs->versions, rev) != 0)
- return 1;
-
- if (walklist (RCS_symbols(rcs), findtag, rev) != 0)
- return 1;
-
- return 0;
-
-}
-
-
-/* RCS_deltas and friends. Processing of the deltas in RCS files. */
-
-struct line
-{
- /* Text of this line. Part of the same malloc'd block as the struct
- line itself (we probably should use the "struct hack" (char text[1])
- and save ourselves sizeof (char *) bytes). Does not include \n;
- instead has_newline indicates the presence or absence of \n. */
- char *text;
- /* Length of this line, not counting \n if has_newline is true. */
- size_t len;
- /* Version in which it was introduced. */
- RCSVers *vers;
- /* Nonzero if this line ends with \n. This will always be true
- except possibly for the last line. */
- int has_newline;
- /* Number of pointers to this struct line. */
- int refcount;
-};
-
-struct linevector
-{
- /* How many lines in use for this linevector? */
- unsigned int nlines;
- /* How many lines allocated for this linevector? */
- unsigned int lines_alloced;
- /* Pointer to array containing a pointer to each line. */
- struct line **vector;
-};
-
-static void linevector_init PROTO ((struct linevector *));
-
-/* Initialize *VEC to be a linevector with no lines. */
-static void
-linevector_init (vec)
- struct linevector *vec;
-{
- vec->lines_alloced = 0;
- vec->nlines = 0;
- vec->vector = NULL;
-}
-
-static int linevector_add PROTO ((struct linevector *vec, const char *text,
- size_t len, RCSVers *vers,
- unsigned int pos));
-
-/* Given some text TEXT, add each of its lines to VEC before line POS
- (where line 0 is the first line). The last line in TEXT may or may
- not be \n terminated.
- Set the version for each of the new lines to VERS. This
- function returns non-zero for success. It returns zero if the line
- number is out of range.
-
- Each of the lines in TEXT are copied to space which is managed with
- the linevector (and freed by linevector_free). So the caller doesn't
- need to keep TEXT around after the call to this function. */
-static int
-linevector_add (vec, text, len, vers, pos)
- struct linevector *vec;
- const char *text;
- size_t len;
- RCSVers *vers;
- unsigned int pos;
-{
- const char *textend;
- unsigned int i;
- unsigned int nnew;
- const char *p;
- const char *nextline_text;
- size_t nextline_len;
- int nextline_newline;
- struct line *q;
-
- if (len == 0)
- return 1;
-
- textend = text + len;
-
- /* Count the number of lines we will need to add. */
- nnew = 1;
- for (p = text; p < textend; ++p)
- if (*p == '\n' && p + 1 < textend)
- ++nnew;
-
- /* Expand VEC->VECTOR if needed. */
- if (vec->nlines + nnew >= vec->lines_alloced)
- {
- if (vec->lines_alloced == 0)
- vec->lines_alloced = 10;
- while (vec->nlines + nnew >= vec->lines_alloced)
- vec->lines_alloced *= 2;
- vec->vector = xrealloc (vec->vector,
- vec->lines_alloced * sizeof (*vec->vector));
- }
-
- /* Make room for the new lines in VEC->VECTOR. */
- for (i = vec->nlines + nnew - 1; i >= pos + nnew; --i)
- vec->vector[i] = vec->vector[i - nnew];
-
- if (pos > vec->nlines)
- return 0;
-
- /* Actually add the lines, to VEC->VECTOR. */
- i = pos;
- nextline_text = text;
- nextline_newline = 0;
- for (p = text; p < textend; ++p)
- if (*p == '\n')
- {
- nextline_newline = 1;
- if (p + 1 == textend)
- /* If there are no characters beyond the last newline, we
- don't consider it another line. */
- break;
- nextline_len = p - nextline_text;
- q = (struct line *) xmalloc (sizeof (struct line) + nextline_len);
- q->vers = vers;
- q->text = (char *)q + sizeof (struct line);
- q->len = nextline_len;
- q->has_newline = nextline_newline;
- q->refcount = 1;
- memcpy (q->text, nextline_text, nextline_len);
- vec->vector[i++] = q;
-
- nextline_text = (char *)p + 1;
- nextline_newline = 0;
- }
- nextline_len = p - nextline_text;
- q = (struct line *) xmalloc (sizeof (struct line) + nextline_len);
- q->vers = vers;
- q->text = (char *)q + sizeof (struct line);
- q->len = nextline_len;
- q->has_newline = nextline_newline;
- q->refcount = 1;
- memcpy (q->text, nextline_text, nextline_len);
- vec->vector[i] = q;
-
- vec->nlines += nnew;
-
- return 1;
-}
-
-static void linevector_copy PROTO ((struct linevector *, struct linevector *));
-
-/* Copy FROM to TO, copying the vectors but not the lines pointed to. */
-static void
-linevector_copy (to, from)
- struct linevector *to;
- struct linevector *from;
-{
- unsigned int ln;
-
- for (ln = 0; ln < to->nlines; ++ln)
- {
- if (--to->vector[ln]->refcount == 0)
- free (to->vector[ln]);
- }
- if (from->nlines > to->lines_alloced)
- {
- if (to->lines_alloced == 0)
- to->lines_alloced = 10;
- while (from->nlines > to->lines_alloced)
- to->lines_alloced *= 2;
- to->vector = (struct line **)
- xrealloc (to->vector, to->lines_alloced * sizeof (*to->vector));
- }
- memcpy (to->vector, from->vector,
- from->nlines * sizeof (*to->vector));
- to->nlines = from->nlines;
- for (ln = 0; ln < to->nlines; ++ln)
- ++to->vector[ln]->refcount;
-}
-
-static void linevector_free PROTO ((struct linevector *));
-
-/* Free storage associated with linevector. */
-static void
-linevector_free (vec)
- struct linevector *vec;
-{
- unsigned int ln;
-
- if (vec->vector != NULL)
- {
- for (ln = 0; ln < vec->nlines; ++ln)
- if (vec->vector[ln] && --vec->vector[ln]->refcount == 0)
- free (vec->vector[ln]);
-
- free (vec->vector);
- }
-}
-
-static char *month_printname PROTO ((char *));
-
-/* Given a textual string giving the month (1-12), terminated with any
- character not recognized by atoi, return the 3 character name to
- print it with. I do not think it is a good idea to change these
- strings based on the locale; they are standard abbreviations (for
- example in rfc822 mail messages) which should be widely understood.
- Returns a pointer into static readonly storage. */
-static char *
-month_printname (month)
- char *month;
-{
- static const char *const months[] =
- {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
- int mnum;
-
- mnum = atoi (month);
- if (mnum < 1 || mnum > 12)
- return "???";
- return (char *)months[mnum - 1];
-}
-
-static int
-apply_rcs_changes PROTO ((struct linevector *, const char *, size_t,
- const char *, RCSVers *, RCSVers *));
-
-/* Apply changes to the line vector LINES. DIFFBUF is a buffer of
- * length DIFFLEN holding the change text from an RCS file (the output
- * of diff -n). NAME is used in error messages. The VERS field of
- * any line added is set to ADDVERS. The VERS field of any line
- * deleted is set to DELVERS, unless DELVERS is NULL, in which case
- * the VERS field of deleted lines is unchanged.
- *
- * RETURNS
- * Non-zero if the change text is applied successfully to ORIG_LINES.
- *
- * If the change text does not appear to apply to ORIG_LINES (e.g., a
- * line number is invalid), this function will return zero and ORIG_LINES
- * will remain unmolested.
- *
- * ERRORS
- * If the change text is improperly formatted (e.g., it is not the output
- * of diff -n), the function calls error with a status of 1, causing the
- * program to exit.
- */
-static int
-apply_rcs_changes (orig_lines, diffbuf, difflen, name, addvers, delvers)
- struct linevector *orig_lines;
- const char *diffbuf;
- size_t difflen;
- const char *name;
- RCSVers *addvers;
- RCSVers *delvers;
-{
- const char *p;
- const char *q;
- int op;
- /* The RCS format throws us for a loop in that the deltafrags (if
- we define a deltafrag as an add or a delete) need to be applied
- in reverse order. So we stick them into a linked list. */
- struct deltafrag {
- enum {FRAG_ADD, FRAG_DELETE} type;
- unsigned long pos;
- unsigned long nlines;
- const char *new_lines;
- size_t len;
- struct deltafrag *next;
- };
- struct deltafrag *dfhead;
- struct deltafrag **dftail;
- struct deltafrag *df;
- unsigned long numlines, lastmodline, offset;
- struct linevector lines;
- int err;
-
- dfhead = NULL;
- dftail = &dfhead;
- numlines = orig_lines->nlines; /* start with init # of lines */
- for (p = diffbuf; p != NULL && p < diffbuf + difflen; )
- {
- op = *p++;
- if (op != 'a' && op != 'd')
- /* Can't just skip over the deltafrag, because the value
- of op determines the syntax. */
- error (1, 0, "unrecognized operation '\\x%x' in %s",
- op, name);
- *dftail = df = xmalloc (sizeof *df);
- *(dftail = &df->next) = NULL;
-
- df->pos = strtoul (p, (char **) &q, 10);
-
- if (p == q)
- error (1, 0, "number expected in %s", name);
- p = q;
- if (*p++ != ' ')
- error (1, 0, "space expected in %s", name);
- df->nlines = strtoul (p, (char **) &q, 10);
- if (p == q)
- error (1, 0, "number expected in %s", name);
- p = q;
- if (*p++ != '\012')
- error (1, 0, "linefeed expected in %s", name);
-
- if (op == 'a')
- {
- unsigned int i;
-
- df->type = FRAG_ADD;
- i = df->nlines;
- /* The text we want is the number of lines specified, or
- until the end of the value, whichever comes first (it
- will be the former except in the case where we are
- adding a line which does not end in newline). */
- for (q = p; i != 0; ++q)
- if (*q == '\n')
- --i;
- else if (q == diffbuf + difflen)
- {
- if (i != 1)
- error (1, 0, "premature end of change in %s", name);
- else
- break;
- }
-
- /* Stash away a pointer to the text we are adding. */
- df->new_lines = p;
- df->len = q - p;
-
- p = q;
- numlines += df->nlines;
- }
- else
- {
- /* Correct for the fact that line numbers in RCS files
- start with 1. */
- --df->pos;
-
- assert (op == 'd');
- df->type = FRAG_DELETE;
- numlines -= df->nlines;
- }
- }
-
- /* New temp data structure to hold new org before
- copy back into original structure. */
- lines.nlines = lines.lines_alloced = numlines;
- lines.vector = xmalloc (numlines * sizeof *lines.vector);
-
- /* We changed the list order to first to last -- so the
- list never gets larger than the size numlines. */
- lastmodline = 0;
-
- /* offset created when adding/removing lines
- between new and original structure */
- offset = 0;
- err = 0;
- for (df = dfhead; df != NULL; )
- {
- unsigned int ln;
- unsigned long deltaend;
-
- if (df->pos > orig_lines->nlines)
- err = 1;
-
- /* On error, just free the rest of the list. */
- if (!err)
- {
- /* Here we need to get to the line where the next insert will
- begin, which is DF->pos in ORIG_LINES. We will fill up to
- DF->pos - OFFSET in LINES with original items. */
- for (deltaend = df->pos - offset;
- lastmodline < deltaend;
- lastmodline++)
- {
- /* we need to copy from the orig structure into new one */
- lines.vector[lastmodline] =
- orig_lines->vector[lastmodline + offset];
- lines.vector[lastmodline]->refcount++;
- }
-
- switch (df->type)
- {
- case FRAG_ADD:
- {
- const char *textend, *p;
- const char *nextline_text;
- struct line *q;
- int nextline_newline;
- size_t nextline_len;
-
- textend = df->new_lines + df->len;
- nextline_newline = 0;
- nextline_text = df->new_lines;
- for (p = df->new_lines; p < textend; ++p)
- {
- if (*p == '\n')
- {
- nextline_newline = 1;
- if (p + 1 == textend)
- {
- /* If there are no characters beyond the
- last newline, we don't consider it
- another line. */
- break;
- }
-
- nextline_len = p - nextline_text;
- q = xmalloc (sizeof *q + nextline_len);
- q->vers = addvers;
- q->text = (char *)(q + 1);
- q->len = nextline_len;
- q->has_newline = nextline_newline;
- q->refcount = 1;
- memcpy (q->text, nextline_text, nextline_len);
- lines.vector[lastmodline++] = q;
- offset--;
-
- nextline_text = (char *)p + 1;
- nextline_newline = 0;
- }
- }
- nextline_len = p - nextline_text;
- q = xmalloc (sizeof *q + nextline_len);
- q->vers = addvers;
- q->text = (char *)(q + 1);
- q->len = nextline_len;
- q->has_newline = nextline_newline;
- q->refcount = 1;
- memcpy (q->text, nextline_text, nextline_len);
- lines.vector[lastmodline++] = q;
-
- /* For each line we add the offset between the #'s
- decreases. */
- offset--;
- break;
- }
-
- case FRAG_DELETE:
- /* we are removing this many lines from the source. */
- offset += df->nlines;
-
- if (df->pos + df->nlines > orig_lines->nlines)
- err = 1;
- else if (delvers)
- for (ln = df->pos; ln < df->pos + df->nlines; ++ln)
- if (orig_lines->vector[ln]->refcount > 1)
- /* Annotate needs this but, since the original
- * vector is disposed of before returning from
- * this function, we only need keep track if
- * there are multiple references.
- */
- orig_lines->vector[ln]->vers = delvers;
- break;
- }
- }
-
- df = df->next;
- free (dfhead);
- dfhead = df;
- }
-
- if (err)
- {
- /* No reason to try and move a half-mutated and known invalid
- * text into the output buffer.
- */
- linevector_free (&lines);
- }
- else
- {
- /* add the rest of the remaining lines to the data vector */
- for (; lastmodline < numlines; lastmodline++)
- {
- /* we need to copy from the orig structure into new one */
- lines.vector[lastmodline] = orig_lines->vector[lastmodline
- + offset];
- lines.vector[lastmodline]->refcount++;
- }
-
- /* Move the lines vector to the original structure for output,
- * first deleting the old.
- */
- linevector_free (orig_lines);
- orig_lines->vector = lines.vector;
- orig_lines->lines_alloced = numlines;
- orig_lines->nlines = lines.nlines;
- }
-
- return !err;
-}
-
-/* Apply an RCS change text to a buffer. The function name starts
- with rcs rather than RCS because this does not take an RCSNode
- argument. NAME is used in error messages. TEXTBUF is the text
- buffer to change, and TEXTLEN is the size. DIFFBUF and DIFFLEN are
- the change buffer and size. The new buffer is returned in *RETBUF
- and *RETLEN. The new buffer is allocated by xmalloc.
-
- Return 1 for success. On failure, call error and return 0. */
-
-int
-rcs_change_text (name, textbuf, textlen, diffbuf, difflen, retbuf, retlen)
- const char *name;
- char *textbuf;
- size_t textlen;
- const char *diffbuf;
- size_t difflen;
- char **retbuf;
- size_t *retlen;
-{
- struct linevector lines;
- int ret;
-
- *retbuf = NULL;
- *retlen = 0;
-
- linevector_init (&lines);
-
- if (! linevector_add (&lines, textbuf, textlen, NULL, 0))
- error (1, 0, "cannot initialize line vector");
-
- if (! apply_rcs_changes (&lines, diffbuf, difflen, name, NULL, NULL))
- {
- error (0, 0, "invalid change text in %s", name);
- ret = 0;
- }
- else
- {
- char *p;
- size_t n;
- unsigned int ln;
-
- n = 0;
- for (ln = 0; ln < lines.nlines; ++ln)
- /* 1 for \n */
- n += lines.vector[ln]->len + 1;
-
- p = xmalloc (n);
- *retbuf = p;
-
- for (ln = 0; ln < lines.nlines; ++ln)
- {
- memcpy (p, lines.vector[ln]->text, lines.vector[ln]->len);
- p += lines.vector[ln]->len;
- if (lines.vector[ln]->has_newline)
- *p++ = '\n';
- }
-
- *retlen = p - *retbuf;
- assert (*retlen <= n);
-
- ret = 1;
- }
-
- linevector_free (&lines);
-
- return ret;
-}
-
-/* Walk the deltas in RCS to get to revision VERSION.
-
- If OP is RCS_ANNOTATE, then write annotations using cvs_output.
-
- If OP is RCS_FETCH, then put the contents of VERSION into a
- newly-malloc'd array and put a pointer to it in *TEXT. Each line
- is \n terminated; the caller is responsible for converting text
- files if desired. The total length is put in *LEN.
-
- If FP is non-NULL, it should be a file descriptor open to the file
- RCS with file position pointing to the deltas. We close the file
- when we are done.
-
- If LOG is non-NULL, then *LOG is set to the log message of VERSION,
- and *LOGLEN is set to the length of the log message.
-
- On error, give a fatal error. */
-
-void
-RCS_deltas (rcs, fp, rcsbuf, version, op, text, len, log, loglen)
- RCSNode *rcs;
- FILE *fp;
- struct rcsbuffer *rcsbuf;
- const char *version;
- enum rcs_delta_op op;
- char **text;
- size_t *len;
- char **log;
- size_t *loglen;
-{
- struct rcsbuffer rcsbuf_local;
- char *branchversion;
- char *cpversion;
- char *key;
- char *value;
- size_t vallen;
- RCSVers *vers;
- RCSVers *prev_vers;
- RCSVers *trunk_vers;
- char *next;
- int ishead, isnext, isversion, onbranch;
- Node *node;
- struct linevector headlines;
- struct linevector curlines;
- struct linevector trunklines;
- int foundhead;
-
- assert (version);
-
- if (fp == NULL)
- {
- rcsbuf_cache_open (rcs, rcs->delta_pos, &fp, &rcsbuf_local);
- rcsbuf = &rcsbuf_local;
- }
-
- assert (rcsbuf);
-
- if (log) *log = NULL;
-
- ishead = 1;
- vers = NULL;
- prev_vers = NULL;
- trunk_vers = NULL;
- next = NULL;
- onbranch = 0;
- foundhead = 0;
-
- linevector_init (&curlines);
- linevector_init (&headlines);
- linevector_init (&trunklines);
-
- /* We set BRANCHVERSION to the version we are currently looking
- for. Initially, this is the version on the trunk from which
- VERSION branches off. If VERSION is not a branch, then
- BRANCHVERSION is just VERSION. */
- branchversion = xstrdup (version);
- cpversion = strchr (branchversion, '.');
- if (cpversion != NULL)
- cpversion = strchr (cpversion + 1, '.');
- if (cpversion != NULL)
- *cpversion = '\0';
-
- do {
- if (! rcsbuf_getrevnum (rcsbuf, &key))
- error (1, 0, "unexpected EOF reading RCS file %s", rcs->path);
-
- /* look up the revision */
- node = findnode (rcs->versions, key);
- if (!node)
- error (1, 0,
- "Delta text %s without revision information in `%s'.",
- key, rcs->path);
-
- if (next != NULL && ! STREQ (next, key))
- {
- /* This is not the next version we need. It is a branch
- version which we want to ignore. */
- isnext = 0;
- isversion = 0;
- }
- else
- {
- isnext = 1;
-
- /* Stash the previous version. */
- prev_vers = vers;
-
- vers = node->data;
- next = vers->next;
-
- /* Compare key and trunkversion now, because key points to
- storage controlled by rcsbuf_getkey. */
- if (STREQ (branchversion, key))
- isversion = 1;
- else
- isversion = 0;
- }
-
- while (1)
- {
- if (! rcsbuf_getkey (rcsbuf, &key, &value))
- error (1, 0, "%s does not appear to be a valid rcs file",
- rcs->path);
-
- if (log != NULL
- && isversion
- && STREQ (key, "log")
- && STREQ (branchversion, version))
- {
- if (*log != NULL)
- {
- error (0, 0, "Duplicate `log' keyword in RCS file (`%s').",
- rcs->path);
- free (*log);
- }
- *log = rcsbuf_valcopy (rcsbuf, value, 0, loglen);
- }
-
- if (STREQ (key, "text"))
- {
- rcsbuf_valpolish (rcsbuf, value, 0, &vallen);
- if (ishead)
- {
- if (! linevector_add (&curlines, value, vallen, NULL, 0))
- error (1, 0, "invalid rcs file %s", rcs->path);
-
- ishead = 0;
- }
- else if (isnext)
- {
- if (! apply_rcs_changes (&curlines, value, vallen,
- rcs->path,
- onbranch ? vers : NULL,
- onbranch ? NULL : prev_vers))
- error (1, 0, "invalid change text in %s", rcs->path);
- }
- break;
- }
- }
-
- if (isversion)
- {
- /* This is either the version we want, or it is the
- branchpoint to the version we want. */
- if (STREQ (branchversion, version))
- {
- /* This is the version we want. */
- linevector_copy (&headlines, &curlines);
- foundhead = 1;
- if (onbranch)
- {
- /* We have found this version by tracking up a
- branch. Restore back to the lines we saved
- when we left the trunk, and continue tracking
- down the trunk. */
- onbranch = 0;
- vers = trunk_vers;
- next = vers->next;
- linevector_copy (&curlines, &trunklines);
- }
- }
- else
- {
- Node *p;
-
- /* We need to look up the branch. */
- onbranch = 1;
-
- if (numdots (branchversion) < 2)
- {
- unsigned int ln;
-
- /* We are leaving the trunk; save the current
- lines so that we can restore them when we
- continue tracking down the trunk. */
- trunk_vers = vers;
- linevector_copy (&trunklines, &curlines);
-
- /* Reset the version information we have
- accumulated so far. It only applies to the
- changes from the head to this version. */
- for (ln = 0; ln < curlines.nlines; ++ln)
- curlines.vector[ln]->vers = NULL;
- }
-
- /* The next version we want is the entry on
- VERS->branches which matches this branch. For
- example, suppose VERSION is 1.21.4.3 and
- BRANCHVERSION was 1.21. Then we look for an entry
- starting with "1.21.4" and we'll put it (probably
- 1.21.4.1) in NEXT. We'll advance BRANCHVERSION by
- two dots (in this example, to 1.21.4.3). */
-
- if (vers->branches == NULL)
- error (1, 0, "missing expected branches in %s",
- rcs->path);
- if (!cpversion)
- error (1, 0, "Invalid revision number in `%s'.",
- rcs->path);
- *cpversion = '.';
- ++cpversion;
- cpversion = strchr (cpversion, '.');
- if (cpversion == NULL)
- error (1, 0, "version number confusion in %s",
- rcs->path);
- for (p = vers->branches->list->next;
- p != vers->branches->list;
- p = p->next)
- if (strncmp (p->key, branchversion,
- cpversion - branchversion) == 0)
- break;
- if (p == vers->branches->list)
- error (1, 0, "missing expected branch in %s",
- rcs->path);
-
- next = p->key;
-
- cpversion = strchr (cpversion + 1, '.');
- if (cpversion != NULL)
- *cpversion = '\0';
- }
- }
- if (op == RCS_FETCH && foundhead)
- break;
- } while (next != NULL);
-
- free (branchversion);
-
- rcsbuf_cache (rcs, rcsbuf);
-
- if (! foundhead)
- error (1, 0, "could not find desired version %s in %s",
- version, rcs->path);
-
- /* Now print out or return the data we have just computed. */
- switch (op)
- {
- case RCS_ANNOTATE:
- {
- unsigned int ln;
-
- for (ln = 0; ln < headlines.nlines; ++ln)
- {
- char *buf;
- /* Period which separates year from month in date. */
- char *ym;
- /* Period which separates month from day in date. */
- char *md;
- RCSVers *prvers;
-
- prvers = headlines.vector[ln]->vers;
- if (prvers == NULL)
- prvers = vers;
-
- buf = xmalloc (strlen (prvers->version) + 24);
- sprintf (buf, "%-12s (%-8.8s ",
- prvers->version,
- prvers->author);
- cvs_output (buf, 0);
- free (buf);
-
- /* Now output the date. */
- ym = strchr (prvers->date, '.');
- if (ym == NULL)
- {
- /* ??- is an ANSI trigraph. The ANSI way to
- avoid it is \? but some pre ANSI compilers
- complain about the unrecognized escape
- sequence. Of course string concatenation
- ("??" "-???") is also an ANSI-ism. Testing
- __STDC__ seems to be a can of worms, since
- compilers do all kinds of things with it. */
- cvs_output ("??", 0);
- cvs_output ("-???", 0);
- cvs_output ("-??", 0);
- }
- else
- {
- md = strchr (ym + 1, '.');
- if (md == NULL)
- cvs_output ("??", 0);
- else
- cvs_output (md + 1, 2);
-
- cvs_output ("-", 1);
- cvs_output (month_printname (ym + 1), 0);
- cvs_output ("-", 1);
- /* Only output the last two digits of the year. Our output
- lines are long enough as it is without printing the
- century. */
- cvs_output (ym - 2, 2);
- }
- cvs_output ("): ", 0);
- if (headlines.vector[ln]->len != 0)
- cvs_output (headlines.vector[ln]->text,
- headlines.vector[ln]->len);
- cvs_output ("\n", 1);
- }
- }
- break;
- case RCS_FETCH:
- {
- char *p;
- size_t n;
- unsigned int ln;
-
- assert (text != NULL);
- assert (len != NULL);
-
- n = 0;
- for (ln = 0; ln < headlines.nlines; ++ln)
- /* 1 for \n */
- n += headlines.vector[ln]->len + 1;
- p = xmalloc (n);
- *text = p;
- for (ln = 0; ln < headlines.nlines; ++ln)
- {
- memcpy (p, headlines.vector[ln]->text,
- headlines.vector[ln]->len);
- p += headlines.vector[ln]->len;
- if (headlines.vector[ln]->has_newline)
- *p++ = '\n';
- }
- *len = p - *text;
- assert (*len <= n);
- }
- break;
- }
-
- linevector_free (&curlines);
- linevector_free (&headlines);
- linevector_free (&trunklines);
-
- return;
-}
-
-/* Read the information for a single delta from the RCS buffer RCSBUF,
- whose name is RCSFILE. *KEYP and *VALP are either NULL, or the
- first key/value pair to read, as set by rcsbuf_getkey. Return NULL
- if there are no more deltas. Store the key/value pair which
- terminated the read in *KEYP and *VALP. */
-
-static RCSVers *
-getdelta (rcsbuf, rcsfile, keyp, valp)
- struct rcsbuffer *rcsbuf;
- char *rcsfile;
- char **keyp;
- char **valp;
-{
- RCSVers *vnode;
- char *key, *value, *cp;
- Node *kv;
-
- /* Get revision number if it wasn't passed in. This uses
- rcsbuf_getkey because it doesn't croak when encountering
- unexpected input. As a result, we have to play unholy games
- with `key' and `value'. */
- if (*keyp != NULL)
- {
- key = *keyp;
- value = *valp;
- }
- else
- {
- if (! rcsbuf_getkey (rcsbuf, &key, &value))
- error (1, 0, "%s: unexpected EOF", rcsfile);
- }
-
- /* Make sure that it is a revision number and not a cabbage
- or something. */
- for (cp = key;
- (isdigit ((unsigned char) *cp) || *cp == '.') && *cp != '\0';
- cp++)
- /* do nothing */ ;
- /* Note that when comparing with RCSDATE, we are not massaging
- VALUE from the string found in the RCS file. This is OK since
- we know exactly what to expect. */
- if (*cp != '\0' || strncmp (RCSDATE, value, (sizeof RCSDATE) - 1) != 0)
- {
- *keyp = key;
- *valp = value;
- return NULL;
- }
-
- vnode = (RCSVers *) xmalloc (sizeof (RCSVers));
- memset (vnode, 0, sizeof (RCSVers));
-
- vnode->version = xstrdup (key);
-
- /* Grab the value of the date from value. Note that we are not
- massaging VALUE from the string found in the RCS file. */
- cp = value + (sizeof RCSDATE) - 1; /* skip the "date" keyword */
- while (whitespace (*cp)) /* take space off front of value */
- cp++;
-
- vnode->date = xstrdup (cp);
-
- /* Get author field. */
- if (! rcsbuf_getkey (rcsbuf, &key, &value))
- {
- error (1, 0, "unexpected end of file reading %s", rcsfile);
- }
- if (! STREQ (key, "author"))
- error (1, 0, "\
-unable to parse %s; `author' not in the expected place", rcsfile);
- vnode->author = rcsbuf_valcopy (rcsbuf, value, 0, (size_t *) NULL);
-
- /* Get state field. */
- if (! rcsbuf_getkey (rcsbuf, &key, &value))
- {
- error (1, 0, "unexpected end of file reading %s", rcsfile);
- }
- if (! STREQ (key, "state"))
- error (1, 0, "\
-unable to parse %s; `state' not in the expected place", rcsfile);
- vnode->state = rcsbuf_valcopy (rcsbuf, value, 0, (size_t *) NULL);
- /* The value is optional, according to rcsfile(5). */
- if (value != NULL && STREQ (value, RCSDEAD))
- {
- vnode->dead = 1;
- }
-
- /* Note that "branches" and "next" are in fact mandatory, according
- to doc/RCSFILES. */
-
- /* fill in the branch list (if any branches exist) */
- if (! rcsbuf_getkey (rcsbuf, &key, &value))
- {
- error (1, 0, "unexpected end of file reading %s", rcsfile);
- }
- if (STREQ (key, RCSDESC))
- {
- *keyp = key;
- *valp = value;
- /* Probably could/should be a fatal error. */
- error (0, 0, "warning: 'branches' keyword missing from %s", rcsfile);
- return vnode;
- }
- if (value != (char *) NULL)
- {
- vnode->branches = getlist ();
- /* Note that we are not massaging VALUE from the string found
- in the RCS file. */
- do_branches (vnode->branches, value);
- }
-
- /* fill in the next field if there is a next revision */
- if (! rcsbuf_getkey (rcsbuf, &key, &value))
- {
- error (1, 0, "unexpected end of file reading %s", rcsfile);
- }
- if (STREQ (key, RCSDESC))
- {
- *keyp = key;
- *valp = value;
- /* Probably could/should be a fatal error. */
- error (0, 0, "warning: 'next' keyword missing from %s", rcsfile);
- return vnode;
- }
- if (value != (char *) NULL)
- vnode->next = rcsbuf_valcopy (rcsbuf, value, 0, (size_t *) NULL);
-
- /*
- * XXX - this is where we put the symbolic link stuff???
- * (into newphrases in the deltas).
- */
- while (1)
- {
- if (! rcsbuf_getkey (rcsbuf, &key, &value))
- error (1, 0, "unexpected end of file reading %s", rcsfile);
-
- /* The `desc' keyword is the end of the deltas. */
- if (strcmp (key, RCSDESC) == 0)
- break;
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
-
- /* The `hardlinks' value is a group of words, which must
- be parsed separately and added as a list to vnode->hardlinks. */
- if (strcmp (key, "hardlinks") == 0)
- {
- char *word;
-
- vnode->hardlinks = getlist();
- while ((word = rcsbuf_valword (rcsbuf, &value)) != NULL)
- {
- Node *n = getnode();
- n->key = word;
- addnode (vnode->hardlinks, n);
- }
- continue;
- }
-#endif
-
- /* Enable use of repositories created by certain obsolete
- versions of CVS. This code should remain indefinately;
- there is no procedure for converting old repositories, and
- checking for it is harmless. */
- if (STREQ (key, RCSDEAD))
- {
- vnode->dead = 1;
- if (vnode->state != NULL)
- free (vnode->state);
- vnode->state = xstrdup (RCSDEAD);
- continue;
- }
- /* if we have a new revision number, we're done with this delta */
- for (cp = key;
- (isdigit ((unsigned char) *cp) || *cp == '.') && *cp != '\0';
- cp++)
- /* do nothing */ ;
- /* Note that when comparing with RCSDATE, we are not massaging
- VALUE from the string found in the RCS file. This is OK
- since we know exactly what to expect. */
- if (*cp == '\0' && strncmp (RCSDATE, value, strlen (RCSDATE)) == 0)
- break;
-
- /* At this point, key and value represent a user-defined field
- in the delta node. */
- if (vnode->other_delta == NULL)
- vnode->other_delta = getlist ();
- kv = getnode ();
- kv->type = rcsbuf_valcmp (rcsbuf) ? RCSCMPFLD : RCSFIELD;
- kv->key = xstrdup (key);
- kv->data = rcsbuf_valcopy (rcsbuf, value, kv->type == RCSFIELD,
- (size_t *) NULL);
- if (addnode (vnode->other_delta, kv) != 0)
- {
- /* Complaining about duplicate keys in newphrases seems
- questionable, in that we don't know what they mean and
- doc/RCSFILES has no prohibition on several newphrases
- with the same key. But we can't store more than one as
- long as we store them in a List *. */
- error (0, 0, "warning: duplicate key `%s' in RCS file `%s'",
- key, rcsfile);
- freenode (kv);
- }
- }
-
- /* Return the key which caused us to fail back to the caller. */
- *keyp = key;
- *valp = value;
-
- return vnode;
-}
-
-static void
-freedeltatext (d)
- Deltatext *d;
-{
- if (d->version != NULL)
- free (d->version);
- if (d->log != NULL)
- free (d->log);
- if (d->text != NULL)
- free (d->text);
- if (d->other != (List *) NULL)
- dellist (&d->other);
- free (d);
-}
-
-static Deltatext *
-RCS_getdeltatext (rcs, fp, rcsbuf)
- RCSNode *rcs;
- FILE *fp;
- struct rcsbuffer *rcsbuf;
-{
- char *num;
- char *key, *value;
- Node *p;
- Deltatext *d;
-
- /* Get the revision number. */
- if (! rcsbuf_getrevnum (rcsbuf, &num))
- {
- /* If num == NULL, it means we reached EOF naturally. That's
- fine. */
- if (num == NULL)
- return NULL;
- else
- error (1, 0, "%s: unexpected EOF", rcs->path);
- }
-
- p = findnode (rcs->versions, num);
- if (!p)
- error (1, 0,
- "Delta text %s without revision information in `%s'.",
- num, rcs->path);
-
- d = (Deltatext *) xmalloc (sizeof (Deltatext));
- d->version = xstrdup (num);
-
- /* Get the log message. */
- if (! rcsbuf_getkey (rcsbuf, &key, &value))
- error (1, 0, "%s, delta %s: unexpected EOF", rcs->path, num);
- if (! STREQ (key, "log"))
- error (1, 0, "%s, delta %s: expected `log', got `%s'",
- rcs->path, num, key);
- d->log = rcsbuf_valcopy (rcsbuf, value, 0, (size_t *) NULL);
-
- /* Get random newphrases. */
- d->other = getlist();
- while (1)
- {
- if (! rcsbuf_getkey (rcsbuf, &key, &value))
- error (1, 0, "%s, delta %s: unexpected EOF", rcs->path, num);
-
- if (STREQ (key, "text"))
- break;
-
- p = getnode();
- p->type = rcsbuf_valcmp (rcsbuf) ? RCSCMPFLD : RCSFIELD;
- p->key = xstrdup (key);
- p->data = rcsbuf_valcopy (rcsbuf, value, p->type == RCSFIELD,
- (size_t *) NULL);
- if (addnode (d->other, p) < 0)
- {
- error (0, 0, "warning: %s, delta %s: duplicate field `%s'",
- rcs->path, num, key);
- }
- }
-
- /* Get the change text. We already know that this key is `text'. */
- d->text = rcsbuf_valcopy (rcsbuf, value, 0, &d->len);
-
- return d;
-}
-
-/* RCS output functions, for writing RCS format files from RCSNode
- structures.
-
- For most of this work, RCS 5.7 uses an `aprintf' function which aborts
- program upon error. Instead, these functions check the output status
- of the stream right before closing it, and aborts if an error condition
- is found. The RCS solution is probably the better one: it produces
- more overhead, but will produce a clearer diagnostic in the case of
- catastrophic error. In either case, however, the repository will probably
- not get corrupted. */
-
-static int
-putsymbol_proc (symnode, fparg)
- Node *symnode;
- void *fparg;
-{
- FILE *fp = (FILE *) fparg;
-
- /* A fiddly optimization: this code used to just call fprintf, but
- in an old repository with hundreds of tags this can get called
- hundreds of thousands of times when doing a cvs tag. Since
- tagging is a relatively common operation, and using putc and
- fputs is just as comprehensible, the change is worthwhile. */
- putc ('\n', fp);
- putc ('\t', fp);
- fputs (symnode->key, fp);
- putc (':', fp);
- fputs (symnode->data, fp);
- return 0;
-}
-
-static int putlock_proc PROTO ((Node *, void *));
-
-/* putlock_proc is like putsymbol_proc, but key and data are reversed. */
-
-static int
-putlock_proc (symnode, fp)
- Node *symnode;
- void *fp;
-{
- return fprintf ((FILE *) fp, "\n\t%s:%s", (char *)symnode->data, symnode->key);
-}
-
-static int
-putrcsfield_proc (node, vfp)
- Node *node;
- void *vfp;
-{
- FILE *fp = (FILE *) vfp;
-
- /* Some magic keys used internally by CVS start with `;'. Skip them. */
- if (node->key[0] == ';')
- return 0;
-
- fprintf (fp, "\n%s\t", node->key);
- if (node->data != NULL)
- {
- /* If the field's value contains evil characters,
- it must be stringified. */
- /* FIXME: This does not quite get it right. "7jk8f" is not a legal
- value for a value in a newpharse, according to doc/RCSFILES,
- because digits are not valid in an "id". We might do OK by
- always writing strings (enclosed in @@). Would be nice to
- explicitly mention this one way or another in doc/RCSFILES.
- A case where we are wrong in a much more clear-cut way is that
- we let through non-graphic characters such as whitespace and
- control characters. */
-
- if (node->type == RCSCMPFLD || strpbrk (node->data, "$,.:;@") == NULL)
- fputs (node->data, fp);
- else
- {
- putc ('@', fp);
- expand_at_signs (node->data, (off_t) strlen (node->data), fp);
- putc ('@', fp);
- }
- }
-
- /* desc, log and text fields should not be terminated with semicolon;
- all other fields should be. */
- if (! STREQ (node->key, "desc") &&
- ! STREQ (node->key, "log") &&
- ! STREQ (node->key, "text"))
- {
- putc (';', fp);
- }
- return 0;
-}
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
-
-/* Save a filename in a `hardlinks' RCS field. NODE->KEY will contain
- a full pathname, but currently only basenames are stored in the RCS
- node. Assume that the filename includes nasty characters and
- @-escape it. */
-
-static int
-puthardlink_proc (node, vfp)
- Node *node;
- void *vfp;
-{
- FILE *fp = (FILE *) vfp;
- char *basename = strrchr (node->key, '/');
-
- if (basename == NULL)
- basename = node->key;
- else
- ++basename;
-
- putc ('\t', fp);
- putc ('@', fp);
- (void) expand_at_signs (basename, strlen (basename), fp);
- putc ('@', fp);
-
- return 0;
-}
-
-#endif
-
-/* Output the admin node for RCS into stream FP. */
-
-static void
-RCS_putadmin (rcs, fp)
- RCSNode *rcs;
- FILE *fp;
-{
- fprintf (fp, "%s\t%s;\n", RCSHEAD, rcs->head ? rcs->head : "");
- if (rcs->branch)
- fprintf (fp, "%s\t%s;\n", RCSBRANCH, rcs->branch);
-
- fputs ("access", fp);
- if (rcs->access)
- {
- char *p, *s;
- s = xstrdup (rcs->access);
- for (p = strtok (s, " \n\t"); p != NULL; p = strtok (NULL, " \n\t"))
- fprintf (fp, "\n\t%s", p);
- free (s);
- }
- fputs (";\n", fp);
-
- fputs (RCSSYMBOLS, fp);
- /* If we haven't had to convert the symbols to a list yet, don't
- force a conversion now; just write out the string. */
- if (rcs->symbols == NULL && rcs->symbols_data != NULL)
- {
- fputs ("\n\t", fp);
- fputs (rcs->symbols_data, fp);
- }
- else
- walklist (RCS_symbols (rcs), putsymbol_proc, (void *) fp);
- fputs (";\n", fp);
-
- fputs ("locks", fp);
- if (rcs->locks_data)
- fprintf (fp, "\t%s", rcs->locks_data);
- else if (rcs->locks)
- walklist (rcs->locks, putlock_proc, (void *) fp);
- if (rcs->strict_locks)
- fprintf (fp, "; strict");
- fputs (";\n", fp);
-
- if (rcs->comment)
- {
- fprintf (fp, "comment\t@");
- expand_at_signs (rcs->comment, (off_t) strlen (rcs->comment), fp);
- fputs ("@;\n", fp);
- }
- if (rcs->expand && ! STREQ (rcs->expand, "kv"))
- fprintf (fp, "%s\t@%s@;\n", RCSEXPAND, rcs->expand);
-
- walklist (rcs->other, putrcsfield_proc, (void *) fp);
-
- putc ('\n', fp);
-}
-
-static void
-putdelta (vers, fp)
- RCSVers *vers;
- FILE *fp;
-{
- Node *bp, *start;
-
- /* Skip if no revision was supplied, or if it is outdated (cvs admin -o) */
- if (vers == NULL || vers->outdated)
- return;
-
- fprintf (fp, "\n%s\n%s\t%s;\t%s %s;\t%s %s;\nbranches",
- vers->version,
- RCSDATE, vers->date,
- "author", vers->author,
- "state", vers->state ? vers->state : "");
-
- if (vers->branches != NULL)
- {
- start = vers->branches->list;
- for (bp = start->next; bp != start; bp = bp->next)
- fprintf (fp, "\n\t%s", bp->key);
- }
-
- fprintf (fp, ";\nnext\t%s;", vers->next ? vers->next : "");
-
- walklist (vers->other_delta, putrcsfield_proc, fp);
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- if (vers->hardlinks)
- {
- fprintf (fp, "\nhardlinks");
- walklist (vers->hardlinks, puthardlink_proc, fp);
- putc (';', fp);
- }
-#endif
- putc ('\n', fp);
-}
-
-static void
-RCS_putdtree (rcs, rev, fp)
- RCSNode *rcs;
- char *rev;
- FILE *fp;
-{
- RCSVers *versp;
- Node *p, *branch;
-
- /* Previously, this function used a recursive implementation, but
- if the trunk has a huge number of revisions and the program
- stack is not big, a stack overflow could occur, so this
- nonrecursive version was developed to be more safe. */
- Node *branchlist, *onebranch;
- List *branches;
- List *onebranchlist;
-
- if (rev == NULL)
- return;
-
- branches = getlist();
-
- for (; rev != NULL;)
- {
- /* Find the delta node for this revision. */
- p = findnode (rcs->versions, rev);
- if (p == NULL)
- {
- error (1, 0,
- "error parsing repository file %s, file may be corrupt.",
- rcs->path);
- }
-
- versp = p->data;
-
- /* Print the delta node and go for its `next' node. This
- prints the trunk. If there are any branches printed on this
- revision, mark we have some. */
- putdelta (versp, fp);
- /* Store branch information into branch list so to write its
- trunk afterwards */
- if (versp->branches != NULL)
- {
- branch = getnode();
- branch->data = versp->branches;
-
- addnode(branches, branch);
- }
-
- rev = versp->next;
- }
-
- /* If there are any branches printed on this revision,
- print those trunks as well. */
- branchlist = branches->list;
- for (branch = branchlist->next;
- branch != branchlist;
- branch = branch->next)
- {
- onebranchlist = (List *)(branch->data);
- onebranch = onebranchlist->list;
- for (p = onebranch->next; p != onebranch; p = p->next)
- RCS_putdtree (rcs, p->key, fp);
-
- branch->data = NULL; /* so to prevent its freeing on dellist */
- }
-
- dellist(&branches);
-}
-
-static void
-RCS_putdesc (rcs, fp)
- RCSNode *rcs;
- FILE *fp;
-{
- fprintf (fp, "\n\n%s\n@", RCSDESC);
- if (rcs->desc != NULL)
- {
- off_t len = (off_t) strlen (rcs->desc);
- if (len > 0)
- {
- expand_at_signs (rcs->desc, len, fp);
- if (rcs->desc[len-1] != '\n')
- putc ('\n', fp);
- }
- }
- fputs ("@\n", fp);
-}
-
-static void
-putdeltatext (fp, d)
- FILE *fp;
- Deltatext *d;
-{
- fprintf (fp, "\n\n%s\nlog\n@", d->version);
- if (d->log != NULL)
- {
- int loglen = strlen (d->log);
- expand_at_signs (d->log, (off_t) loglen, fp);
- if (d->log[loglen-1] != '\n')
- putc ('\n', fp);
- }
- putc ('@', fp);
-
- walklist (d->other, putrcsfield_proc, fp);
-
- fputs ("\ntext\n@", fp);
- if (d->text != NULL)
- expand_at_signs (d->text, (off_t) d->len, fp);
- fputs ("@\n", fp);
-}
-
-/* TODO: the whole mechanism for updating deltas is kludgey... more
- sensible would be to supply all the necessary info in a `newdeltatext'
- field for RCSVers nodes. -twp */
-
-/* Copy delta text nodes from FIN to FOUT. If NEWDTEXT is non-NULL, it
- is a new delta text node, and should be added to the tree at the
- node whose revision number is INSERTPT. (Note that trunk nodes are
- written in decreasing order, and branch nodes are written in
- increasing order.) */
-
-static void
-RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt)
- RCSNode *rcs;
- FILE *fin;
- struct rcsbuffer *rcsbufin;
- FILE *fout;
- Deltatext *newdtext;
- char *insertpt;
-{
- int actions;
- RCSVers *dadmin;
- Node *np;
- int insertbefore, found;
- char *bufrest;
- int nls;
- size_t buflen;
- char buf[8192];
- int got;
-
- /* Count the number of versions for which we have to do some
- special operation. */
- actions = walklist (rcs->versions, count_delta_actions, (void *) NULL);
-
- /* Make a note of whether NEWDTEXT should be inserted
- before or after its INSERTPT. */
- insertbefore = (newdtext != NULL && numdots (newdtext->version) == 1);
-
- while (actions != 0 || newdtext != NULL)
- {
- Deltatext *dtext;
-
- dtext = RCS_getdeltatext (rcs, fin, rcsbufin);
-
- /* We shouldn't hit EOF here, because that would imply that
- some action was not taken, or that we could not insert
- NEWDTEXT. */
- if (dtext == NULL)
- error (1, 0, "internal error: EOF too early in RCS_copydeltas");
-
- found = (insertpt != NULL && STREQ (dtext->version, insertpt));
- if (found && insertbefore)
- {
- putdeltatext (fout, newdtext);
- newdtext = NULL;
- insertpt = NULL;
- }
-
- np = findnode (rcs->versions, dtext->version);
- if (!np)
- error (1, 0,
- "Delta text %s without revision information in `%s'.",
- dtext->version, rcs->path);
-
- dadmin = np->data;
-
- /* If this revision has been outdated, just skip it. */
- if (dadmin->outdated)
- {
- freedeltatext (dtext);
- --actions;
- continue;
- }
-
- /* Update the change text for this delta. New change text
- data may come from cvs admin -m, cvs admin -o, or cvs ci. */
- if (dadmin->text != NULL)
- {
- if (dadmin->text->log != NULL || dadmin->text->text != NULL)
- --actions;
- if (dadmin->text->log != NULL)
- {
- free (dtext->log);
- dtext->log = dadmin->text->log;
- dadmin->text->log = NULL;
- }
- if (dadmin->text->text != NULL)
- {
- free (dtext->text);
- dtext->text = dadmin->text->text;
- dtext->len = dadmin->text->len;
- dadmin->text->text = NULL;
- }
- }
- putdeltatext (fout, dtext);
- freedeltatext (dtext);
-
- if (found && !insertbefore)
- {
- putdeltatext (fout, newdtext);
- newdtext = NULL;
- insertpt = NULL;
- }
- }
-
- /* Copy the rest of the file directly, without bothering to
- interpret it. The caller will handle error checking by calling
- ferror.
-
- We just wrote a newline to the file, either in putdeltatext or
- in the caller. However, we may not have read the corresponding
- newline from the file, because rcsbuf_getkey returns as soon as
- it finds the end of the '@' string for the desc or text key.
- Therefore, we may read three newlines when we should really
- only write two, and we check for that case here. This is not
- an semantically important issue; we only do it to make our RCS
- files look traditional. */
-
- nls = 3;
-
- rcsbuf_get_buffered (rcsbufin, &bufrest, &buflen);
- if (buflen > 0)
- {
- if (bufrest[0] != '\n'
- || strncmp (bufrest, "\n\n\n", buflen < 3 ? buflen : 3) != 0)
- {
- nls = 0;
- }
- else
- {
- if (buflen < 3)
- nls -= buflen;
- else
- {
- ++bufrest;
- --buflen;
- nls = 0;
- }
- }
-
- fwrite (bufrest, 1, buflen, fout);
- }
- if (!rcsbufin->mmapped)
- {
- /* This bit isn't necessary when using mmap since the entire file
- * will already be available via the RCS buffer. Besides, the
- * mmap code doesn't always keep the file pointer up to date, so
- * this adds some data twice.
- */
- while ((got = fread (buf, 1, sizeof buf, fin)) != 0)
- {
- if (nls > 0
- && got >= nls
- && buf[0] == '\n'
- && strncmp (buf, "\n\n\n", nls) == 0)
- {
- fwrite (buf + 1, 1, got - 1, fout);
- }
- else
- {
- fwrite (buf, 1, got, fout);
- }
-
- nls = 0;
- }
- }
-}
-
-/* A helper procedure for RCS_copydeltas. This is called via walklist
- to count the number of RCS revisions for which some special action
- is required. */
-
-static int
-count_delta_actions (np, ignore)
- Node *np;
- void *ignore;
-{
- RCSVers *dadmin = np->data;
-
- if (dadmin->outdated)
- return 1;
-
- if (dadmin->text != NULL
- && (dadmin->text->log != NULL || dadmin->text->text != NULL))
- {
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Clean up temporary files
- */
-RETSIGTYPE
-rcs_cleanup ()
-{
- /* Note that the checks for existence_error are because we are
- called from a signal handler, so we don't know whether the
- files got created. */
-
- /* FIXME: Do not perform buffered I/O from an interrupt handler like
- this (via error). However, I'm leaving the error-calling code there
- in the hope that on the rare occasion the error call is actually made
- (e.g., a fluky I/O error or permissions problem prevents the deletion
- of a just-created file) reentrancy won't be an issue. */
- if (rcs_lockfile != NULL)
- {
- char *tmp = rcs_lockfile;
- rcs_lockfile = NULL;
- if (rcs_lockfd >= 0)
- {
- if (close (rcs_lockfd) != 0)
- error (0, errno, "error closing lock file %s", tmp);
- rcs_lockfd = -1;
- }
- if (unlink_file (tmp) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", tmp);
- }
-}
-
-/* RCS_internal_lockfile and RCS_internal_unlockfile perform RCS-style
- locking on the specified RCSFILE: for a file called `foo,v', open
- for writing a file called `,foo,'.
-
- Note that we what do here is quite different from what RCS does.
- RCS creates the ,foo, file before it reads the RCS file (if it
- knows that it will be writing later), so that it actually serves as
- a lock. We don't; instead we rely on CVS writelocks. This means
- that if someone is running RCS on the file at the same time they
- are running CVS on it, they might lose (we read the file,
- then RCS writes it, then we write it, clobbering the
- changes made by RCS). I believe the current sentiment about this
- is "well, don't do that".
-
- A concern has been expressed about whether adopting the RCS
- strategy would slow us down. I don't think so, since we need to
- write the ,foo, file anyway (unless perhaps if O_EXCL is slower or
- something).
-
- These do not perform quite the same function as the RCS -l option
- for locking files: they are intended to prevent competing RCS
- processes from stomping all over each other's laundry. Hence,
- they are `internal' locking functions.
-
- If there is an error, give a fatal error; if we return we always
- return a non-NULL value. */
-
-static FILE *
-rcs_internal_lockfile (rcsfile)
- char *rcsfile;
-{
- struct stat rstat;
- FILE *fp;
- static int first_call = 1;
-
- if (first_call)
- {
- first_call = 0;
- /* clean up if we get a signal */
-#ifdef SIGABRT
- (void) SIG_register (SIGABRT, rcs_cleanup);
-#endif
-#ifdef SIGHUP
- (void) SIG_register (SIGHUP, rcs_cleanup);
-#endif
-#ifdef SIGINT
- (void) SIG_register (SIGINT, rcs_cleanup);
-#endif
-#ifdef SIGQUIT
- (void) SIG_register (SIGQUIT, rcs_cleanup);
-#endif
-#ifdef SIGPIPE
- (void) SIG_register (SIGPIPE, rcs_cleanup);
-#endif
-#ifdef SIGTERM
- (void) SIG_register (SIGTERM, rcs_cleanup);
-#endif
- }
-
- /* Get the lock file name: `,file,' for RCS file `file,v'. */
- assert (rcs_lockfile == NULL);
- assert (rcs_lockfd < 0);
- rcs_lockfile = rcs_lockfilename (rcsfile);
-
- /* Use the existing RCS file mode, or read-only if this is a new
- file. (Really, this is a lie -- if this is a new file,
- RCS_checkin uses the permissions from the working copy. For
- actually creating the file, we use 0444 as a safe default mode.) */
- if (stat (rcsfile, &rstat) < 0)
- {
- if (existence_error (errno))
- rstat.st_mode = S_IRUSR | S_IRGRP | S_IROTH;
- else
- error (1, errno, "cannot stat %s", rcsfile);
- }
-
- /* Try to open exclusively. POSIX.1 guarantees that O_EXCL|O_CREAT
- guarantees an exclusive open. According to the RCS source, with
- NFS v2 we must also throw in O_TRUNC and use an open mask that makes
- the file unwriteable. For extensive justification, see the comments for
- rcswriteopen() in rcsedit.c, in RCS 5.7. This is kind of pointless
- in the CVS case; see comment at the start of this file concerning
- general ,foo, file strategy.
-
- There is some sentiment that with NFSv3 and such, that one can
- rely on O_EXCL these days. This might be true for unix (I
- don't really know), but I am still pretty skeptical in the case
- of the non-unix systems. */
- rcs_lockfd = open (rcs_lockfile,
- OPEN_BINARY | O_WRONLY | O_CREAT | O_EXCL | O_TRUNC,
- S_IRUSR | S_IRGRP | S_IROTH);
-
- if (rcs_lockfd < 0)
- {
- error (1, errno, "could not open lock file `%s'", rcs_lockfile);
- }
-
- /* Force the file permissions, and return a stream object. */
- /* Because we change the modes later, we don't worry about
- this in the non-HAVE_FCHMOD case. */
-#ifdef HAVE_FCHMOD
- if (fchmod (rcs_lockfd, rstat.st_mode) < 0)
- error (1, errno, "cannot change mode for %s", rcs_lockfile);
-#endif
- fp = fdopen (rcs_lockfd, FOPEN_BINARY_WRITE);
- if (fp == NULL)
- error (1, errno, "cannot fdopen %s", rcs_lockfile);
-
- return fp;
-}
-
-static void
-rcs_internal_unlockfile (fp, rcsfile)
- FILE *fp;
- char *rcsfile;
-{
- assert (rcs_lockfile != NULL);
- assert (rcs_lockfd >= 0);
-
- /* Abort if we could not write everything successfully to LOCKFILE.
- This is not a great error-handling mechanism, but should prevent
- corrupting the repository. */
-
- if (ferror (fp))
- /* Using errno here may well be misleanding since the most recent
- call that set errno may not have anything whatsoever to do with
- the error that set the flag, but it's better than nothing. The
- real solution is to check each call to fprintf rather than waiting
- until the end like this. */
- error (1, errno, "error writing to lock file %s", rcs_lockfile);
-
- /* Flush and sync the file, or the user may be told the commit completed,
- * while a server crash/power failure could still cause the data to be
- * lost.
- *
- * Invoking rename(",<file>," , "<file>,v") on Linux and almost all UNIXs
- * only flushes the inode for the target file to disk, it does not
- * guarantee flush of the kernel buffers allocated for the ,<file>,.
- * Depending upon the load on the machine, the Linux kernel's flush daemon
- * process may not flush for a while. In the meantime the CVS transaction
- * could have been declared committed to the end CVS user (CVS process has
- * returned the final "OK"). If the machine crashes prior to syncing the
- * changes to disk, the committed transaction can be lost.
- */
- if (fflush (fp) != 0)
- error (1, errno, "error flushing file `%s' to kernel buffers",
- rcs_lockfile);
-#ifdef HAVE_FSYNC
- if (fsync (rcs_lockfd) < 0)
- error (1, errno, "error fsyncing file `%s'", rcs_lockfile);
-#endif
-
- if (fclose (fp) == EOF)
- error (1, errno, "error closing lock file %s", rcs_lockfile);
- rcs_lockfd = -1;
-
- rename_file (rcs_lockfile, rcsfile);
-
- {
- /* Use a temporary to make sure there's no interval
- (after rcs_lockfile has been freed but before it's set to NULL)
- during which the signal handler's use of rcs_lockfile would
- reference freed memory. */
- char *tmp = rcs_lockfile;
- rcs_lockfile = NULL;
- free (tmp);
- }
-}
-
-static char *
-rcs_lockfilename (rcsfile)
- const char *rcsfile;
-{
- char *lockfile, *lockp;
- const char *rcsbase, *rcsp, *rcsend;
- int rcslen;
-
- /* Create the lockfile name. */
- rcslen = strlen (rcsfile);
- lockfile = (char *) xmalloc (rcslen + 10);
- rcsbase = last_component (rcsfile);
- rcsend = rcsfile + rcslen - sizeof(RCSEXT);
- for (lockp = lockfile, rcsp = rcsfile; rcsp < rcsbase; ++rcsp)
- *lockp++ = *rcsp;
- *lockp++ = ',';
- while (rcsp <= rcsend)
- *lockp++ = *rcsp++;
- *lockp++ = ',';
- *lockp = '\0';
-
- return lockfile;
-}
-
-/* Rewrite an RCS file. The basic idea here is that the caller should
- first call RCS_reparsercsfile, then munge the data structures as
- desired (via RCS_delete_revs, RCS_settag, &c), then call RCS_rewrite. */
-
-void
-RCS_rewrite (rcs, newdtext, insertpt)
- RCSNode *rcs;
- Deltatext *newdtext;
- char *insertpt;
-{
- FILE *fin, *fout;
- struct rcsbuffer rcsbufin;
-
- assert (rcs);
-
- if (noexec)
- return;
-
- /* Make sure we're operating on an actual file and not a symlink. */
- resolve_symlink (&(rcs->path));
-
- fout = rcs_internal_lockfile (rcs->path);
-
- RCS_putadmin (rcs, fout);
- RCS_putdtree (rcs, rcs->head, fout);
- RCS_putdesc (rcs, fout);
-
- /* Open the original RCS file and seek to the first delta text. */
- rcsbuf_cache_open (rcs, rcs->delta_pos, &fin, &rcsbufin);
-
- /* Update delta_pos to the current position in the output file.
- Do NOT move these statements: they must be done after fin has
- been positioned at the old delta_pos, but before any delta
- texts have been written to fout.
- */
- rcs->delta_pos = ftell (fout);
- if (rcs->delta_pos == -1)
- error (1, errno, "cannot ftell in RCS file %s", rcs->path);
-
- RCS_copydeltas (rcs, fin, &rcsbufin, fout, newdtext, insertpt);
-
- /* We don't want to call rcsbuf_cache here, since we're about to
- delete the file. */
- rcsbuf_close (&rcsbufin);
- if (ferror (fin))
- /* The only case in which using errno here would be meaningful
- is if we happen to have left errno unmolested since the call
- which produced the error (e.g. fread). That is pretty
- fragile even if it happens to sometimes be true. The real
- solution is to make sure that all the code which reads
- from fin checks for errors itself (some does, some doesn't). */
- error (0, 0, "warning: ferror set while rewriting RCS file `%s'", rcs->path);
- if (fclose (fin) < 0)
- error (0, errno, "warning: closing RCS file `%s'", rcs->path);
-
- rcs_internal_unlockfile (fout, rcs->path);
-}
-
-/* Abandon changes to an RCS file. */
-
-void
-RCS_abandon (rcs)
- RCSNode *rcs;
-{
- free_rcsnode_contents (rcs);
- rcs->symbols_data = NULL;
- rcs->expand = NULL;
- rcs->access = NULL;
- rcs->locks_data = NULL;
- rcs->comment = NULL;
- rcs->desc = NULL;
- rcs->flags |= PARTIAL;
-}
-
-/*
- * For a given file with full pathname PATH and revision number REV,
- * produce a file label suitable for passing to diff. The default
- * file label as used by RCS 5.7 looks like this:
- *
- * FILENAME <tab> YYYY/MM/DD <sp> HH:MM:SS <tab> REVNUM
- *
- * The date and time used are the revision's last checkin date and time.
- * If REV is NULL, use the working copy's mtime instead.
- *
- * /dev/null is not statted but assumed to have been created on the Epoch.
- * At least using the POSIX.2 definition of patch, this should cause creation
- * of files on platforms such as Windoze where the null IO device isn't named
- * /dev/null to be parsed by patch properly.
- */
-char *
-make_file_label (path, rev, rcs)
- const char *path;
- const char *rev;
- RCSNode *rcs;
-{
- char datebuf[MAXDATELEN + 1];
- char *label;
-
- label = (char *) xmalloc (strlen (path)
- + (rev == NULL ? 0 : strlen (rev) + 1)
- + MAXDATELEN
- + 2);
-
- if (rev)
- {
- char date[MAXDATELEN + 1];
- /* revs cannot be attached to /dev/null ... duh. */
- assert (strcmp(DEVNULL, path));
- RCS_getrevtime (rcs, rev, datebuf, 0);
- (void) date_to_internet (date, datebuf);
- (void) sprintf (label, "-L%s\t%s\t%s", path, date, rev);
- }
- else
- {
- struct stat sb;
- struct tm *wm;
-
- if (strcmp(DEVNULL, path))
- {
- const char *file = last_component (path);
- if (CVS_STAT (file, &sb) < 0)
- /* Assume that if the stat fails,then the later read for the
- * diff will too.
- */
- error (1, errno, "could not get info for `%s'", path);
- wm = gmtime (&sb.st_mtime);
- }
- else
- {
- time_t t = 0;
- wm = gmtime(&t);
- }
-
- (void) tm_to_internet (datebuf, wm);
- (void) sprintf (label, "-L%s\t%s", path, datebuf);
- }
- return label;
-}
-
-void
-RCS_setlocalid (arg)
- const char *arg;
-{
- char *copy, *next, *key;
-
- copy = xstrdup(arg);
- next = copy;
- key = strtok(next, "=");
-
- keywords[KEYWORD_LOCALID].string = xstrdup(key);
- keywords[KEYWORD_LOCALID].len = strlen(key);
- keywords[KEYWORD_LOCALID].expandit = 1;
-
- /* options? */
- while (key = strtok(NULL, ",")) {
- if (!strcmp(key, keywords[KEYWORD_ID].string))
- keyword_local = KEYWORD_ID;
- else if (!strcmp(key, keywords[KEYWORD_HEADER].string))
- keyword_local = KEYWORD_HEADER;
- else if (!strcmp(key, keywords[KEYWORD_CVSHEADER].string))
- keyword_local = KEYWORD_CVSHEADER;
- else
- error(1, 0, "Unknown LocalId mode: %s", key);
- }
- free(copy);
-}
-
-void
-RCS_setincexc (arg)
- const char *arg;
-{
- char *key;
- char *copy, *next;
- int include = 0;
- struct rcs_keyword *keyword;
-
- copy = xstrdup(arg);
- next = copy;
- switch (*next++) {
- case 'e':
- include = 0;
- break;
- case 'i':
- include = 1;
- break;
- default:
- free(copy);
- return;
- }
-
- if (include)
- for (keyword = keywords; keyword->string != NULL; keyword++)
- {
- keyword->expandit = 0;
- }
-
- key = strtok(next, ",");
- while (key) {
- for (keyword = keywords; keyword->string != NULL; keyword++) {
- if (strcmp (keyword->string, key) == 0)
- keyword->expandit = include;
- }
- key = strtok(NULL, ",");
- }
- free(copy);
- return;
-}
-
-#define ATTIC "/" CVSATTIC
-static char *
-getfullCVSname(CVSname, pathstore)
- char *CVSname, **pathstore;
-{
- if (current_parsed_root->directory) {
- int rootlen;
- char *c = NULL;
- int alen = sizeof(ATTIC) - 1;
-
- *pathstore = xstrdup(CVSname);
- if ((c = strrchr(*pathstore, '/')) != NULL) {
- if (c - *pathstore >= alen) {
- if (!strncmp(c - alen, ATTIC, alen)) {
- while (*c != '\0') {
- *(c - alen) = *c;
- c++;
- }
- *(c - alen) = '\0';
- }
- }
- }
-
- rootlen = strlen(current_parsed_root->directory);
- if (!strncmp(*pathstore, current_parsed_root->directory, rootlen) &&
- (*pathstore)[rootlen] == '/')
- CVSname = (*pathstore + rootlen + 1);
- else
- CVSname = (*pathstore);
- }
- return CVSname;
-}
diff --git a/contrib/cvs/src/rcs.h b/contrib/cvs/src/rcs.h
deleted file mode 100644
index 08b8a5f0698a..000000000000
--- a/contrib/cvs/src/rcs.h
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * RCS source control definitions needed by rcs.c and friends
- *
- * $FreeBSD$
- */
-
-/* Strings which indicate a conflict if they occur at the start of a line. */
-#define RCS_MERGE_PAT_1 "<<<<<<< "
-#define RCS_MERGE_PAT_2 "=======\n"
-#define RCS_MERGE_PAT_3 ">>>>>>> "
-
-#define RCSEXT ",v"
-#define RCSPAT "*,v"
-#define RCSHEAD "head"
-#define RCSBRANCH "branch"
-#define RCSSYMBOLS "symbols"
-#define RCSDATE "date"
-#define RCSDESC "desc"
-#define RCSEXPAND "expand"
-
-/* Used by the version of death support which resulted from old
- versions of CVS (e.g. 1.5 if you define DEATH_SUPPORT and not
- DEATH_STATE). Only a hacked up RCS (used by those old versions of
- CVS) will put this into RCS files. Considered obsolete. */
-#define RCSDEAD "dead"
-
-#define DATEFORM "%02d.%02d.%02d.%02d.%02d.%02d"
-#define SDATEFORM "%d.%d.%d.%d.%d.%d"
-
-/*
- * Opaque structure definitions used by RCS specific lookup routines
- */
-#define VALID 0x1 /* flags field contains valid data */
-#define INATTIC 0x2 /* RCS file is located in the Attic */
-#define PARTIAL 0x4 /* RCS file not completly parsed */
-
-/* All the "char *" fields in RCSNode, Deltatext, and RCSVers are
- '\0'-terminated (except "text" in Deltatext). This means that we
- can't deal with fields containing '\0', which is a limitation that
- RCS does not have. Would be nice to fix this some day. */
-
-struct rcsnode
-{
- /* Reference count for this structure. Used to deal with the
- fact that there might be a pointer from the Vers_TS or might
- not. Callers who increment this field are responsible for
- calling freercsnode when they are done with their reference. */
- int refcount;
-
- /* Flags (INATTIC, PARTIAL, &c), see above. */
- int flags;
-
- /* File name of the RCS file. This is not necessarily the name
- as specified by the user, but it is a name which can be passed to
- system calls and a name which is OK to print in error messages
- (the various names might differ in case). */
- char *path;
-
- /* Value for head keyword from RCS header, or NULL if empty. */
- char *head;
-
- /* Value for branch keyword from RCS header, or NULL if omitted. */
- char *branch;
-
- /* Raw data on symbolic revisions. The first time that RCS_symbols is
- called, we parse these into ->symbols, and free ->symbols_data. */
- char *symbols_data;
-
- /* Value for expand keyword from RCS header, or NULL if omitted. */
- char *expand;
-
- /* List of nodes, the key of which is the symbolic name and the data
- of which is the numeric revision that it corresponds to (malloc'd). */
- List *symbols;
-
- /* List of nodes (type RCSVERS), the key of which the numeric revision
- number, and the data of which is an RCSVers * for the revision. */
- List *versions;
-
- /* Value for access keyword from RCS header, or NULL if empty.
- FIXME: RCS_delaccess would also seem to use "" for empty. We
- should pick one or the other. */
- char *access;
-
- /* Raw data on locked revisions. The first time that RCS_getlocks is
- called, we parse these into ->locks, and free ->locks_data. */
- char *locks_data;
-
- /* List of nodes, the key of which is the numeric revision and the
- data of which is the user that it corresponds to (malloc'd). */
- List *locks;
-
- /* Set for the strict keyword from the RCS header. */
- int strict_locks;
-
- /* Value for the comment keyword from RCS header (comment leader), or
- NULL if omitted. */
- char *comment;
-
- /* Value for the desc field in the RCS file, or NULL if empty. */
- char *desc;
-
- /* File offset of the first deltatext node, so we can seek there. */
- long delta_pos;
-
- /* Newphrases from the RCS header. List of nodes, the key of which
- is the "id" which introduces the newphrase, and the value of which
- is the value from the newphrase. */
- List *other;
-};
-
-typedef struct rcsnode RCSNode;
-
-struct deltatext {
- char *version;
-
- /* Log message, or NULL if we do not intend to change the log message
- (that is, RCS_copydeltas should just use the log message from the
- file). */
- char *log;
-
- /* Change text, or NULL if we do not intend to change the change text
- (that is, RCS_copydeltas should just use the change text from the
- file). Note that it is perfectly legal to have log be NULL and
- text non-NULL, or vice-versa. */
- char *text;
- size_t len;
-
- /* Newphrase fields from deltatext nodes. FIXME: duplicates the
- other field in the rcsversnode, I think. */
- List *other;
-};
-typedef struct deltatext Deltatext;
-
-struct rcsversnode
-{
- /* Duplicate of the key by which this structure is indexed. */
- char *version;
-
- char *date;
- char *author;
- char *state;
- char *next;
- int dead;
- int outdated;
- Deltatext *text;
- List *branches;
- /* Newphrase fields from deltatext nodes. Also contains ";add" and
- ";delete" magic fields (see rcs.c, log.c). I think this is
- only used by log.c (where it looks up "log"). Duplicates the
- other field in struct deltatext, I think. */
- List *other;
- /* Newphrase fields from delta nodes. */
- List *other_delta;
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- /* Hard link information for each revision. */
- List *hardlinks;
-#endif
-};
-typedef struct rcsversnode RCSVers;
-
-/*
- * CVS reserves all even-numbered branches for its own use. "magic" branches
- * (see rcs.c) are contained as virtual revision numbers (within symbolic
- * tags only) off the RCS_MAGIC_BRANCH, which is 0. CVS also reserves the
- * ".1" branch for vendor revisions. So, if you do your own branching, you
- * should limit your use to odd branch numbers starting at 3.
- */
-#define RCS_MAGIC_BRANCH 0
-
-/* The type of a function passed to RCS_checkout. */
-typedef void (*RCSCHECKOUTPROC) PROTO ((void *, const char *, size_t));
-
-#ifdef __STDC__
-struct rcsbuffer;
-#endif
-
-/* What RCS_deltas is supposed to do. */
-enum rcs_delta_op {RCS_ANNOTATE, RCS_FETCH};
-
-/*
- * exported interfaces
- */
-RCSNode *RCS_parse PROTO((const char *file, const char *repos));
-RCSNode *RCS_parsercsfile PROTO((const char *rcsfile));
-void RCS_fully_parse PROTO((RCSNode *));
-void RCS_reparsercsfile PROTO((RCSNode *, FILE **, struct rcsbuffer *));
-extern int RCS_setattic PROTO ((RCSNode *, int));
-
-char *RCS_check_kflag PROTO((const char *arg));
-char *RCS_getdate PROTO((RCSNode * rcs, const char *date,
- int force_tag_match));
-char *RCS_gettag PROTO((RCSNode * rcs, const char *symtag, int force_tag_match,
- int *simple_tag));
-int RCS_exist_rev PROTO((RCSNode *rcs, char *rev));
-int RCS_exist_tag PROTO((RCSNode *rcs, char *tag));
-char *RCS_tag2rev PROTO((RCSNode *rcs, char *tag));
-char *RCS_getversion PROTO((RCSNode * rcs, const char *tag, const char *date,
- int force_tag_match, int *simple_tag));
-char *RCS_magicrev PROTO((RCSNode *rcs, char *rev));
-int RCS_isbranch PROTO((RCSNode *rcs, const char *rev));
-int RCS_nodeisbranch PROTO((RCSNode *rcs, const char *tag));
-char *RCS_whatbranch PROTO((RCSNode *rcs, const char *tag));
-char *RCS_head PROTO((RCSNode * rcs));
-int RCS_datecmp PROTO((const char *date1, const char *date2));
-time_t RCS_getrevtime PROTO((RCSNode * rcs, const char *rev, char *date,
- int fudge));
-List *RCS_symbols PROTO((RCSNode *rcs));
-void RCS_check_tag PROTO((const char *tag));
-int RCS_valid_rev PROTO ((char *rev));
-List *RCS_getlocks PROTO((RCSNode *rcs));
-void freercsnode PROTO((RCSNode ** rnodep));
-char *RCS_getbranch PROTO((RCSNode * rcs, const char *tag,
- int force_tag_match));
-char *RCS_branch_head PROTO ((RCSNode *rcs, char *rev));
-
-int RCS_isdead PROTO((RCSNode *, const char *));
-char *RCS_getexpand PROTO ((RCSNode *));
-void RCS_setexpand PROTO ((RCSNode *, const char *));
-int RCS_checkout PROTO ((RCSNode *, const char *, const char *, const char *,
- const char *, const char *, RCSCHECKOUTPROC, void *));
-int RCS_checkin PROTO ((RCSNode *rcs, const char *workfile,
- const char *message, const char *rev, time_t citime,
- int flags));
-int RCS_cmp_file PROTO((RCSNode *, const char *, char **, const char *,
- const char *, const char *));
-int RCS_settag PROTO ((RCSNode *, const char *, const char *));
-int RCS_deltag PROTO ((RCSNode *, const char *));
-int RCS_setbranch PROTO((RCSNode *, const char *));
-int RCS_lock PROTO ((RCSNode *, const char *, int));
-int RCS_unlock PROTO ((RCSNode *, char *, int));
-int RCS_delete_revs PROTO ((RCSNode *, char *, char *, int));
-void RCS_addaccess PROTO ((RCSNode *, char *));
-void RCS_delaccess PROTO ((RCSNode *, char *));
-char *RCS_getaccess PROTO ((RCSNode *));
-RETSIGTYPE rcs_cleanup PROTO ((void));
-void RCS_rewrite PROTO ((RCSNode *, Deltatext *, char *));
-void RCS_abandon PROTO ((RCSNode *));
-int rcs_change_text PROTO ((const char *, char *, size_t, const char *,
- size_t, char **, size_t *));
-void RCS_deltas PROTO ((RCSNode *, FILE *, struct rcsbuffer *, const char *,
- enum rcs_delta_op, char **, size_t *,
- char **, size_t *));
-void RCS_setincexc PROTO ((const char *arg));
-void RCS_setlocalid PROTO ((const char *arg));
-char *make_file_label PROTO ((const char *, const char *, RCSNode *));
-
-extern int datesep;
-extern int preserve_perms;
-
-/* From import.c. */
-extern int add_rcs_file PROTO ((const char *, const char *, const char *,
- const char *, const char *, const char *,
- const char *, int, char **, const char *,
- size_t, FILE *));
diff --git a/contrib/cvs/src/rcscmds.c b/contrib/cvs/src/rcscmds.c
deleted file mode 100644
index 18182ffce86c..000000000000
--- a/contrib/cvs/src/rcscmds.c
+++ /dev/null
@@ -1,628 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * The functions in this file provide an interface for performing
- * operations directly on RCS files.
- *
- * $FreeBSD$
- */
-
-#include "cvs.h"
-#include <assert.h>
-#include <stdio.h>
-#include "diffrun.h"
-
-/* This file, rcs.h, and rcs.c, together sometimes known as the "RCS
- library", are intended to define our interface to RCS files.
-
- Whether there will also be a version of RCS which uses this
- library, or whether the library will be packaged for uses beyond
- CVS or RCS (many people would like such a thing) is an open
- question. Some considerations:
-
- 1. An RCS library for CVS must have the capabilities of the
- existing CVS code which accesses RCS files. In particular, simple
- approaches will often be slow.
-
- 2. An RCS library should not use code from the current RCS
- (5.7 and its ancestors). The code has many problems. Too few
- comments, too many layers of abstraction, too many global variables
- (the correct number for a library is zero), too much intricately
- interwoven functionality, and too many clever hacks. Paul Eggert,
- the current RCS maintainer, agrees.
-
- 3. More work needs to be done in terms of separating out the RCS
- library from the rest of CVS (for example, cvs_output should be
- replaced by a callback, and the declarations should be centralized
- into rcs.h, and probably other such cleanups).
-
- 4. To be useful for RCS and perhaps for other uses, the library
- may need features beyond those needed by CVS.
-
- 5. Any changes to the RCS file format *must* be compatible. Many,
- many tools (not just CVS and RCS) can at least import this format.
- RCS and CVS must preserve the current ability to import/export it
- (preferably improved--magic branches are currently a roadblock).
- See doc/RCSFILES in the CVS distribution for documentation of this
- file format.
-
- On a related note, see the comments at diff_exec, later in this file,
- for more on the diff library. */
-
-static void RCS_output_diff_options PROTO ((int, char *const *, const char *,
- const char *, const char *));
-
-
-/* Stuff to deal with passing arguments the way libdiff.a wants to deal
- with them. This is a crufty interface; there is no good reason for it
- to resemble a command line rather than something closer to "struct
- log_data" in log.c. */
-
-/* First call call_diff_setup to setup any initial arguments. The
- argument will be parsed into whitespace separated words and added
- to the global call_diff_argv list.
-
- Then, optionally, call call_diff_add_arg for each additional argument
- that you'd like to pass to the diff library.
-
- Finally, call call_diff or call_diff3 to produce the diffs. */
-
-static char **call_diff_argv;
-static int call_diff_argc;
-static size_t call_diff_argc_allocated;
-
-static void call_diff_add_arg PROTO ((const char *));
-static void call_diff_setup PROTO ((const char *prog,
- int argc, char * const *argv));
-static int call_diff PROTO ((const char *out));
-static int call_diff3 PROTO ((char *out));
-
-static void call_diff_write_output PROTO((const char *, size_t));
-static void call_diff_flush_output PROTO((void));
-static void call_diff_write_stdout PROTO((const char *));
-static void call_diff_error PROTO((const char *, const char *, const char *));
-
-
-
-static void
-call_diff_add_arg (s)
- const char *s;
-{
- run_add_arg_p (&call_diff_argc, &call_diff_argc_allocated, &call_diff_argv,
- s);
-}
-
-
-
-/* VARARGS */
-static void
-call_diff_setup (prog, argc, argv)
- const char *prog;
- int argc;
- char * const *argv;
-{
- int i;
-
- /* clean out any malloc'ed values from call_diff_argv */
- run_arg_free_p (call_diff_argc, call_diff_argv);
- call_diff_argc = 0;
-
- /* put each word into call_diff_argv, allocating it as we go */
- call_diff_add_arg (prog);
- for (i = 0; i < argc; i++)
- call_diff_add_arg (argv[i]);
-}
-
-
-/* Callback function for the diff library to write data to the output
- file. This is used when we are producing output to stdout. */
-
-static void
-call_diff_write_output (text, len)
- const char *text;
- size_t len;
-{
- if (len > 0)
- cvs_output (text, len);
-}
-
-/* Call back function for the diff library to flush the output file.
- This is used when we are producing output to stdout. */
-
-static void
-call_diff_flush_output ()
-{
- cvs_flushout ();
-}
-
-/* Call back function for the diff library to write to stdout. */
-
-static void
-call_diff_write_stdout (text)
- const char *text;
-{
- cvs_output (text, 0);
-}
-
-/* Call back function for the diff library to write to stderr. */
-
-static void
-call_diff_error (format, a1, a2)
- const char *format;
- const char *a1;
- const char *a2;
-{
- /* FIXME: Should we somehow indicate that this error is coming from
- the diff library? */
- error (0, 0, format, a1, a2);
-}
-
-/* This set of callback functions is used if we are sending the diff
- to stdout. */
-
-static struct diff_callbacks call_diff_stdout_callbacks =
-{
- call_diff_write_output,
- call_diff_flush_output,
- call_diff_write_stdout,
- call_diff_error
-};
-
-/* This set of callback functions is used if we are sending the diff
- to a file. */
-
-static struct diff_callbacks call_diff_file_callbacks =
-{
- (void (*) PROTO((const char *, size_t))) NULL,
- (void (*) PROTO((void))) NULL,
- call_diff_write_stdout,
- call_diff_error
-};
-
-
-
-static int
-call_diff (out)
- const char *out;
-{
- call_diff_add_arg (NULL);
-
- if (out == RUN_TTY)
- return diff_run (call_diff_argc, call_diff_argv, NULL,
- &call_diff_stdout_callbacks);
- else
- return diff_run (call_diff_argc, call_diff_argv, out,
- &call_diff_file_callbacks);
-}
-
-
-
-static int
-call_diff3 (out)
- char *out;
-{
- if (out == RUN_TTY)
- return diff3_run (call_diff_argc, call_diff_argv, NULL,
- &call_diff_stdout_callbacks);
- else
- return diff3_run (call_diff_argc, call_diff_argv, out,
- &call_diff_file_callbacks);
-}
-
-
-
-/* Merge revisions REV1 and REV2. */
-
-int
-RCS_merge(rcs, path, workfile, options, rev1, rev2)
- RCSNode *rcs;
- const char *path;
- const char *workfile;
- const char *options;
- const char *rev1;
- const char *rev2;
-{
- char *xrev1, *xrev2;
- char *tmp1, *tmp2;
- char *diffout = NULL;
- int retval;
-
- if (options != NULL && options[0] != '\0')
- assert (options[0] == '-' && options[1] == 'k');
-
- cvs_output ("RCS file: ", 0);
- cvs_output (rcs->path, 0);
- cvs_output ("\n", 1);
-
- /* Calculate numeric revision numbers from rev1 and rev2 (may be
- symbolic). */
- xrev1 = RCS_gettag (rcs, rev1, 0, NULL);
- xrev2 = RCS_gettag (rcs, rev2, 0, NULL);
- assert (xrev1 && xrev2);
-
- /* Check out chosen revisions. The error message when RCS_checkout
- fails is not very informative -- it is taken verbatim from RCS 5.7,
- and relies on RCS_checkout saying something intelligent upon failure. */
- cvs_output ("retrieving revision ", 0);
- cvs_output (xrev1, 0);
- cvs_output ("\n", 1);
-
- tmp1 = cvs_temp_name();
- if (RCS_checkout (rcs, NULL, xrev1, rev1, options, tmp1,
- (RCSCHECKOUTPROC)0, NULL))
- {
- cvs_outerr ("rcsmerge: co failed\n", 0);
- error_exit();
- }
-
- cvs_output ("retrieving revision ", 0);
- cvs_output (xrev2, 0);
- cvs_output ("\n", 1);
-
- tmp2 = cvs_temp_name();
- if (RCS_checkout (rcs, NULL, xrev2, rev2, options, tmp2,
- (RCSCHECKOUTPROC)0, NULL))
- {
- cvs_outerr ("rcsmerge: co failed\n", 0);
- error_exit();
- }
-
- /* Merge changes. */
- cvs_output ("Merging differences between ", 0);
- cvs_output (xrev1, 0);
- cvs_output (" and ", 0);
- cvs_output (xrev2, 0);
- cvs_output (" into ", 0);
- cvs_output (workfile, 0);
- cvs_output ("\n", 1);
-
- /* Remember that the first word in the `call_diff_setup' string is used now
- only for diagnostic messages -- CVS no longer forks to run diff3. */
- diffout = cvs_temp_name();
- call_diff_setup ("diff3", 0, NULL);
- call_diff_add_arg ("-E");
- call_diff_add_arg ("-am");
-
- call_diff_add_arg ("-L");
- call_diff_add_arg (workfile);
- call_diff_add_arg ("-L");
- call_diff_add_arg (xrev1);
- call_diff_add_arg ("-L");
- call_diff_add_arg (xrev2);
-
- call_diff_add_arg ("--");
- call_diff_add_arg (workfile);
- call_diff_add_arg (tmp1);
- call_diff_add_arg (tmp2);
-
- retval = call_diff3 (diffout);
-
- if (retval == 1)
- cvs_outerr ("rcsmerge: warning: conflicts during merge\n", 0);
- else if (retval == 2)
- error_exit();
-
- if (diffout)
- copy_file (diffout, workfile);
-
- /* Clean up. */
- {
- int save_noexec = noexec;
- noexec = 0;
- if (unlink_file (tmp1) < 0)
- {
- if (!existence_error (errno))
- error (0, errno, "cannot remove temp file %s", tmp1);
- }
- free (tmp1);
- if (unlink_file (tmp2) < 0)
- {
- if (!existence_error (errno))
- error (0, errno, "cannot remove temp file %s", tmp2);
- }
- free (tmp2);
- if (diffout)
- {
- if (unlink_file (diffout) < 0)
- {
- if (!existence_error (errno))
- error (0, errno, "cannot remove temp file %s", diffout);
- }
- free (diffout);
- }
- free (xrev1);
- free (xrev2);
- noexec = save_noexec;
- }
-
- return retval;
-}
-
-/* Diff revisions and/or files. OPTS controls the format of the diff
- (it contains options such as "-w -c", &c), or "" for the default.
- OPTIONS controls keyword expansion, as a string starting with "-k",
- or "" to use the default. REV1 is the first revision to compare
- against; it must be non-NULL. If REV2 is non-NULL, compare REV1
- and REV2; if REV2 is NULL compare REV1 with the file in the working
- directory, whose name is WORKFILE. LABEL1 and LABEL2 are default
- file labels, and (if non-NULL) should be added as -L options
- to diff. Output goes to stdout.
-
- Return value is 0 for success, -1 for a failure which set errno,
- or positive for a failure which printed a message on stderr.
-
- This used to exec rcsdiff, but now calls RCS_checkout and diff_exec.
-
- An issue is what timezone is used for the dates which appear in the
- diff output. rcsdiff uses the -z flag, which is not presently
- processed by CVS diff, but I'm not sure exactly how hard to worry
- about this--any such features are undocumented in the context of
- CVS, and I'm not sure how important to users. */
-int
-RCS_exec_rcsdiff (rcsfile, diff_argc, diff_argv, options, rev1, rev1_cache,
- rev2, label1, label2, workfile)
- RCSNode *rcsfile;
- int diff_argc;
- char * const *diff_argv;
- const char *options;
- const char *rev1;
- const char *rev1_cache;
- const char *rev2;
- const char *label1;
- const char *label2;
- const char *workfile;
-{
- char *tmpfile1 = NULL;
- char *tmpfile2 = NULL;
- const char *use_file1, *use_file2;
- int status, retval;
-
-
- cvs_output ("\
-===================================================================\n\
-RCS file: ", 0);
- cvs_output (rcsfile->path, 0);
- cvs_output ("\n", 1);
-
- /* Historically, `cvs diff' has expanded the $Name keyword to the
- empty string when checking out revisions. This is an accident,
- but no one has considered the issue thoroughly enough to determine
- what the best behavior is. Passing NULL for the `nametag' argument
- preserves the existing behavior. */
-
- cvs_output ("retrieving revision ", 0);
- cvs_output (rev1, 0);
- cvs_output ("\n", 1);
-
- if (rev1_cache != NULL)
- use_file1 = rev1_cache;
- else
- {
- tmpfile1 = cvs_temp_name();
- status = RCS_checkout (rcsfile, NULL, rev1, NULL, options, tmpfile1,
- (RCSCHECKOUTPROC)0, NULL);
- if (status > 0)
- {
- retval = status;
- goto error_return;
- }
- else if (status < 0)
- {
- error( 0, errno,
- "cannot check out revision %s of %s", rev1, rcsfile->path );
- retval = 1;
- goto error_return;
- }
- use_file1 = tmpfile1;
- }
-
- if (rev2 == NULL)
- {
- assert (workfile != NULL);
- use_file2 = workfile;
- }
- else
- {
- tmpfile2 = cvs_temp_name ();
- cvs_output ("retrieving revision ", 0);
- cvs_output (rev2, 0);
- cvs_output ("\n", 1);
- status = RCS_checkout (rcsfile, NULL, rev2, NULL, options,
- tmpfile2, (RCSCHECKOUTPROC)0, NULL);
- if (status > 0)
- {
- retval = status;
- goto error_return;
- }
- else if (status < 0)
- {
- error (0, errno,
- "cannot check out revision %s of %s", rev2, rcsfile->path);
- return 1;
- }
- use_file2 = tmpfile2;
- }
-
- RCS_output_diff_options (diff_argc, diff_argv, rev1, rev2, workfile);
- status = diff_exec (use_file1, use_file2, label1, label2,
- diff_argc, diff_argv, RUN_TTY);
- if (status >= 0)
- {
- retval = status;
- goto error_return;
- }
- else if (status < 0)
- {
- error (0, errno,
- "cannot diff %s and %s", use_file1, use_file2);
- retval = 1;
- goto error_return;
- }
-
- error_return:
- {
- /* Call CVS_UNLINK() below rather than unlink_file to avoid the check
- * for noexec.
- */
- if( tmpfile1 != NULL )
- {
- if( CVS_UNLINK( tmpfile1 ) < 0 )
- {
- if( !existence_error( errno ) )
- error( 0, errno, "cannot remove temp file %s", tmpfile1 );
- }
- free( tmpfile1 );
- }
- if( tmpfile2 != NULL )
- {
- if( CVS_UNLINK( tmpfile2 ) < 0 )
- {
- if( !existence_error( errno ) )
- error( 0, errno, "cannot remove temp file %s", tmpfile2 );
- }
- free (tmpfile2);
- }
- }
-
- return retval;
-}
-
-
-
-/* Show differences between two files. This is the start of a diff library.
-
- Some issues:
-
- * Should option parsing be part of the library or the caller? The
- former allows the library to add options without changing the callers,
- but it causes various problems. One is that something like --brief really
- wants special handling in CVS, and probably the caller should retain
- some flexibility in this area. Another is online help (the library could
- have some feature for providing help, but how does that interact with
- the help provided by the caller directly?). Another is that as things
- stand currently, there is no separate namespace for diff options versus
- "cvs diff" options like -l (that is, if the library adds an option which
- conflicts with a CVS option, it is trouble).
-
- * This isn't required for a first-cut diff library, but if there
- would be a way for the caller to specify the timestamps that appear
- in the diffs (rather than the library getting them from the files),
- that would clean up the kludgy utime() calls in patch.c.
-
- Show differences between FILE1 and FILE2. Either one can be
- DEVNULL to indicate a nonexistent file (same as an empty file
- currently, I suspect, but that may be an issue in and of itself).
- OPTIONS is a list of diff options, or "" if none. At a minimum,
- CVS expects that -c (update.c, patch.c) and -n (update.c) will be
- supported. Other options, like -u, --speed-large-files, &c, will
- be specified if the user specified them.
-
- OUT is a filename to send the diffs to, or RUN_TTY to send them to
- stdout. Error messages go to stderr. Return value is 0 for
- success, -1 for a failure which set errno, 1 for success (and some
- differences were found), or >1 for a failure which printed a
- message on stderr. */
-
-int
-diff_exec (file1, file2, label1, label2, dargc, dargv, out)
- const char *file1;
- const char *file2;
- const char *label1;
- const char *label2;
- int dargc;
- char * const *dargv;
- const char *out;
-{
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- /* If either file1 or file2 are special files, pretend they are
- /dev/null. Reason: suppose a file that represents a block
- special device in one revision becomes a regular file. CVS
- must find the `difference' between these files, but a special
- file contains no data useful for calculating this metric. The
- safe thing to do is to treat the special file as an empty file,
- thus recording the regular file's full contents. Doing so will
- create extremely large deltas at the point of transition
- between device files and regular files, but this is probably
- very rare anyway.
-
- There may be ways around this, but I think they are fraught
- with danger. -twp */
-
- if (preserve_perms &&
- strcmp (file1, DEVNULL) != 0 &&
- strcmp (file2, DEVNULL) != 0)
- {
- struct stat sb1, sb2;
-
- if (CVS_LSTAT (file1, &sb1) < 0)
- error (1, errno, "cannot get file information for %s", file1);
- if (CVS_LSTAT (file2, &sb2) < 0)
- error (1, errno, "cannot get file information for %s", file2);
-
- if (!S_ISREG (sb1.st_mode) && !S_ISDIR (sb1.st_mode))
- file1 = DEVNULL;
- if (!S_ISREG (sb2.st_mode) && !S_ISDIR (sb2.st_mode))
- file2 = DEVNULL;
- }
-#endif
-
- /* The first arg to call_diff_setup is used only for error reporting. */
- call_diff_setup ("diff", dargc, dargv);
- if (label1)
- call_diff_add_arg (label1);
- if (label2)
- call_diff_add_arg (label2);
- call_diff_add_arg ("--");
- call_diff_add_arg (file1);
- call_diff_add_arg (file2);
-
- return call_diff (out);
-}
-
-/* Print the options passed to DIFF, in the format used by rcsdiff.
- The rcsdiff code that produces this output is extremely hairy, and
- it is not clear how rcsdiff decides which options to print and
- which not to print. The code below reproduces every rcsdiff run
- that I have seen. */
-
-static void
-RCS_output_diff_options (diff_argc, diff_argv, rev1, rev2, workfile)
- int diff_argc;
- char * const *diff_argv;
- const char *rev1;
- const char *rev2;
- const char *workfile;
-{
- int i;
-
- cvs_output ("diff", 0);
- for (i = 0; i < diff_argc; i++)
- {
- cvs_output (" ", 1);
- cvs_output (diff_argv[i], 0);
- }
- cvs_output (" -r", 3);
- cvs_output (rev1, 0);
-
- if (rev2)
- {
- cvs_output (" -r", 3);
- cvs_output (rev2, 0);
- }
- else
- {
- assert (workfile != NULL);
- cvs_output (" ", 1);
- cvs_output (workfile, 0);
- }
- cvs_output ("\n", 1);
-}
diff --git a/contrib/cvs/src/recurse.c b/contrib/cvs/src/recurse.c
deleted file mode 100644
index fb865a9807cb..000000000000
--- a/contrib/cvs/src/recurse.c
+++ /dev/null
@@ -1,1299 +0,0 @@
-/*
- * Copyright (C) 1986-2008 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * General recursion handler
- *
- */
-
-#include "cvs.h"
-#include "savecwd.h"
-#include "fileattr.h"
-#include "edit.h"
-#include <assert.h>
-
-static int do_dir_proc PROTO((Node * p, void *closure));
-static int do_file_proc PROTO((Node * p, void *closure));
-static void addlist PROTO((List ** listp, char *key));
-static int unroll_files_proc PROTO((Node *p, void *closure));
-static void addfile PROTO((List **listp, char *dir, char *file));
-
-static char *update_dir;
-static char *repository = NULL;
-static List *filelist = NULL; /* holds list of files on which to operate */
-static List *dirlist = NULL; /* holds list of directories on which to operate */
-
-struct recursion_frame {
- FILEPROC fileproc;
- FILESDONEPROC filesdoneproc;
- DIRENTPROC direntproc;
- DIRLEAVEPROC dirleaveproc;
- void *callerdat;
- Dtype flags;
- int which;
- int aflag;
- int locktype;
- int dosrcs;
- char *repository; /* Keep track of repository for rtag */
-};
-
-static int do_recursion PROTO ((struct recursion_frame *frame));
-
-/* I am half tempted to shove a struct file_info * into the struct
- recursion_frame (but then we would need to modify or create a
- recursion_frame for each file), or shove a struct recursion_frame *
- into the struct file_info (more tempting, although it isn't completely
- clear that the struct file_info should contain info about recursion
- processor internals). So instead use this struct. */
-
-struct frame_and_file {
- struct recursion_frame *frame;
- struct file_info *finfo;
-};
-
-/* Similarly, we need to pass the entries list to do_dir_proc. */
-
-struct frame_and_entries {
- struct recursion_frame *frame;
- List *entries;
-};
-
-
-/* Start a recursive command.
-
- Command line arguments (ARGC, ARGV) dictate the directories and
- files on which we operate. In the special case of no arguments, we
- default to ".". */
-int
-start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
- argc, argv, local, which, aflag, locktype,
- update_preload, dosrcs, repository_in)
- FILEPROC fileproc;
- FILESDONEPROC filesdoneproc;
- DIRENTPROC direntproc;
- DIRLEAVEPROC dirleaveproc;
- void *callerdat;
-
- int argc;
- char **argv;
- int local;
-
- /* This specifies the kind of recursion. There are several cases:
-
- 1. W_LOCAL is not set but W_REPOS or W_ATTIC is. The current
- directory when we are called must be the repository and
- recursion proceeds according to what exists in the repository.
-
- 2a. W_LOCAL is set but W_REPOS and W_ATTIC are not. The
- current directory when we are called must be the working
- directory. Recursion proceeds according to what exists in the
- working directory, never (I think) consulting any part of the
- repository which does not correspond to the working directory
- ("correspond" == Name_Repository).
-
- 2b. W_LOCAL is set and so is W_REPOS or W_ATTIC. This is the
- weird one. The current directory when we are called must be
- the working directory. We recurse through working directories,
- but we recurse into a directory if it is exists in the working
- directory *or* it exists in the repository. If a directory
- does not exist in the working directory, the direntproc must
- either tell us to skip it (R_SKIP_ALL), or must create it (I
- think those are the only two cases). */
- int which;
-
- int aflag;
- int locktype;
- char *update_preload;
- int dosrcs;
- /* Keep track of the repository string. This is only for the remote mode,
- * specifically, r* commands (rtag, rdiff, co, ...) where xgetwd() was
- * used to locate the repository. Things would break when xgetwd() was
- * used with a symlinked repository because xgetwd() would return the true
- * path and in some cases this would cause the path to be printed as other
- * than the user specified in error messages and in other cases some of
- * CVS's security assertions would fail.
- */
- char *repository_in;
-{
- int i, err = 0;
-#ifdef CLIENT_SUPPORT
- List *args_to_send_when_finished = NULL;
-#endif
- List *files_by_dir = NULL;
- struct recursion_frame frame;
-
- frame.fileproc = fileproc;
- frame.filesdoneproc = filesdoneproc;
- frame.direntproc = direntproc;
- frame.dirleaveproc = dirleaveproc;
- frame.callerdat = callerdat;
- frame.flags = local ? R_SKIP_DIRS : R_PROCESS;
- frame.which = which;
- frame.aflag = aflag;
- frame.locktype = locktype;
- frame.dosrcs = dosrcs;
-
- /* If our repository_in has a trailing "/.", remove it before storing it
- * for do_recursion().
- *
- * FIXME: This is somewhat of a hack in the sense that many of our callers
- * painstakingly compute and add the trailing '.' we now remove.
- */
- while (repository_in && strlen (repository_in) >= 2
- && repository_in[strlen (repository_in) - 2] == '/'
- && repository_in[strlen (repository_in) - 1] == '.')
- {
- /* Beware the case where the string is exactly "/." or "//.".
- * Paths with a leading "//" are special on some early UNIXes.
- */
- if (strlen (repository_in) == 2 || strlen (repository_in) == 3)
- repository_in[strlen (repository_in) - 1] = '\0';
- else
- repository_in[strlen (repository_in) - 2] = '\0';
- }
- frame.repository = repository_in;
-
- expand_wild (argc, argv, &argc, &argv);
-
- if (update_preload == NULL)
- update_dir = xstrdup ("");
- else
- update_dir = xstrdup (update_preload);
-
- /* clean up from any previous calls to start_recursion */
- if (repository)
- {
- free (repository);
- repository = (char *) NULL;
- }
- if (filelist)
- dellist (&filelist); /* FIXME-krp: no longer correct. */
- if (dirlist)
- dellist (&dirlist);
-
-#ifdef SERVER_SUPPORT
- if (server_active)
- {
- for (i = 0; i < argc; ++i)
- server_pathname_check (argv[i]);
- }
-#endif
-
- if (argc == 0)
- {
- int just_subdirs = (which & W_LOCAL) && !isdir (CVSADM);
-
-#ifdef CLIENT_SUPPORT
- if (!just_subdirs
- && CVSroot_cmdline == NULL
- && current_parsed_root->isremote)
- {
- cvsroot_t *root = Name_Root (NULL, update_dir);
- if (root)
- {
- if (strcmp (root->original, current_parsed_root->original))
- /* We're skipping this directory because it is for
- * a different root. Therefore, we just want to
- * do the subdirectories only. Processing files would
- * cause a working directory from one repository to be
- * processed against a different repository, which could
- * cause all kinds of spurious conflicts and such.
- *
- * Question: what about the case of "cvs update foo"
- * where we process foo/bar and not foo itself? That
- * seems to be handled somewhere (else) but why should
- * it be a separate case? Needs investigation... */
- just_subdirs = 1;
- free_cvsroot_t (root);
- }
- }
-#endif
-
- /*
- * There were no arguments, so we'll probably just recurse. The
- * exception to the rule is when we are called from a directory
- * without any CVS administration files. That has always meant to
- * process each of the sub-directories, so we pretend like we were
- * called with the list of sub-dirs of the current dir as args
- */
- if (just_subdirs)
- {
- dirlist = Find_Directories ((char *) NULL, W_LOCAL, (List *) NULL);
- /* If there are no sub-directories, there is a certain logic in
- favor of doing nothing, but in fact probably the user is just
- confused about what directory they are in, or whether they
- cvs add'd a new directory. In the case of at least one
- sub-directory, at least when we recurse into them we
- notice (hopefully) whether they are under CVS control. */
- if (list_isempty (dirlist))
- {
- if (update_dir[0] == '\0')
- error (0, 0, "in directory .:");
- else
- error (0, 0, "in directory %s:", update_dir);
- error (1, 0,
- "there is no version here; run '%s checkout' first",
- program_name);
- }
-#ifdef CLIENT_SUPPORT
- else if (current_parsed_root->isremote && server_started)
- {
- /* In the the case "cvs update foo bar baz", a call to
- send_file_names in update.c will have sent the
- appropriate "Argument" commands to the server. In
- this case, that won't have happened, so we need to
- do it here. While this example uses "update", this
- generalizes to other commands. */
-
- /* This is the same call to Find_Directories as above.
- FIXME: perhaps it would be better to write a
- function that duplicates a list. */
- args_to_send_when_finished = Find_Directories ((char *) NULL,
- W_LOCAL,
- (List *) NULL);
- }
-#endif
- }
- else
- addlist (&dirlist, ".");
-
- goto do_the_work;
- }
-
-
- /*
- * There were arguments, so we have to handle them by hand. To do
- * that, we set up the filelist and dirlist with the arguments and
- * call do_recursion. do_recursion recognizes the fact that the
- * lists are non-null when it starts and doesn't update them.
- *
- * explicitly named directories are stored in dirlist.
- * explicitly named files are stored in filelist.
- * other possibility is named entities whicha are not currently in
- * the working directory.
- */
-
- for (i = 0; i < argc; i++)
- {
- /* if this argument is a directory, then add it to the list of
- directories. */
-
- if (!wrap_name_has (argv[i], WRAP_TOCVS) && isdir (argv[i]))
- {
- strip_trailing_slashes (argv[i]);
- addlist (&dirlist, argv[i]);
- }
- else
- {
- /* otherwise, split argument into directory and component names. */
- char *dir;
- char *comp;
- char *file_to_try;
-
- /* Now break out argv[i] into directory part (DIR) and file part (COMP).
- DIR and COMP will each point to a newly malloc'd string. */
- dir = xstrdup (argv[i]);
- /* Its okay to discard the const below - we know we just allocated
- * dir ourselves.
- */
- comp = (char *)last_component (dir);
- if (comp == dir)
- {
- /* no dir component. What we have is an implied "./" */
- dir = xstrdup(".");
- }
- else
- {
- char *p = comp;
-
- p[-1] = '\0';
- comp = xstrdup (p);
- }
-
- /* if this argument exists as a file in the current
- working directory tree, then add it to the files list. */
-
- if (!(which & W_LOCAL))
- {
- /* If doing rtag, we've done a chdir to the repository. */
- file_to_try = xmalloc (strlen (argv[i]) + sizeof (RCSEXT) + 5);
- sprintf (file_to_try, "%s%s", argv[i], RCSEXT);
- }
- else
- file_to_try = xstrdup (argv[i]);
-
- if (isfile (file_to_try))
- addfile (&files_by_dir, dir, comp);
- else if (isdir (dir))
- {
- if ((which & W_LOCAL) && isdir (CVSADM) &&
- !current_parsed_root->isremote)
- {
- /* otherwise, look for it in the repository. */
- char *tmp_update_dir;
- char *repos;
- char *reposfile;
-
- tmp_update_dir = xmalloc (strlen (update_dir)
- + strlen (dir)
- + 5);
- strcpy (tmp_update_dir, update_dir);
-
- if (*tmp_update_dir != '\0')
- (void) strcat (tmp_update_dir, "/");
-
- (void) strcat (tmp_update_dir, dir);
-
- /* look for it in the repository. */
- repos = Name_Repository (dir, tmp_update_dir);
- reposfile = xmalloc (strlen (repos)
- + strlen (comp)
- + 5);
- (void) sprintf (reposfile, "%s/%s", repos, comp);
- free (repos);
-
- if (!wrap_name_has (comp, WRAP_TOCVS) && isdir (reposfile))
- addlist (&dirlist, argv[i]);
- else
- addfile (&files_by_dir, dir, comp);
-
- free (tmp_update_dir);
- free (reposfile);
- }
- else
- addfile (&files_by_dir, dir, comp);
- }
- else
- error (1, 0, "no such directory `%s'", dir);
-
- free (file_to_try);
- free (dir);
- free (comp);
- }
- }
-
- /* At this point we have looped over all named arguments and built
- a coupla lists. Now we unroll the lists, setting up and
- calling do_recursion. */
-
- err += walklist (files_by_dir, unroll_files_proc, (void *) &frame);
- dellist(&files_by_dir);
-
- /* then do_recursion on the dirlist. */
- if (dirlist != NULL)
- {
- do_the_work:
- err += do_recursion (&frame);
- }
-
- /* Free the data which expand_wild allocated. */
- free_names (&argc, argv);
-
- free (update_dir);
- update_dir = NULL;
-
-#ifdef CLIENT_SUPPORT
- if (args_to_send_when_finished != NULL)
- {
- /* FIXME (njc): in the multiroot case, we don't want to send
- argument commands for those top-level directories which do
- not contain any subdirectories which have files checked out
- from current_parsed_root->original. If we do, and two repositories
- have a module with the same name, nasty things could happen.
-
- This is hard. Perhaps we should send the Argument commands
- later in this procedure, after we've had a chance to notice
- which directores we're using (after do_recursion has been
- called once). This means a _lot_ of rewriting, however.
-
- What we need to do for that to happen is descend the tree
- and construct a list of directories which are checked out
- from current_cvsroot. Now, we eliminate from the list all
- of those directories which are immediate subdirectories of
- another directory in the list. To say that the opposite
- way, we keep the directories which are not immediate
- subdirectories of any other in the list. Here's a picture:
-
- a
- / \
- B C
- / \
- D e
- / \
- F G
- / \
- H I
-
- The node in capitals are those directories which are
- checked out from current_cvsroot. We want the list to
- contain B, C, F, and G. D, H, and I are not included,
- because their parents are also checked out from
- current_cvsroot.
-
- The algorithm should be:
-
- 1) construct a tree of all directory names where each
- element contains a directory name and a flag which notes if
- that directory is checked out from current_cvsroot
-
- a0
- / \
- B1 C1
- / \
- D1 e0
- / \
- F1 G1
- / \
- H1 I1
-
- 2) Recursively descend the tree. For each node, recurse
- before processing the node. If the flag is zero, do
- nothing. If the flag is 1, check the node's parent. If
- the parent's flag is one, change the current entry's flag
- to zero.
-
- a0
- / \
- B1 C1
- / \
- D0 e0
- / \
- F1 G1
- / \
- H0 I0
-
- 3) Walk the tree and spit out "Argument" commands to tell
- the server which directories to munge.
-
- Yuck. It's not clear this is worth spending time on, since
- we might want to disable cvs commands entirely from
- directories that do not have CVSADM files...
-
- Anyways, the solution as it stands has modified server.c
- (dirswitch) to create admin files [via server.c
- (create_adm_p)] in all path elements for a client's
- "Directory xxx" command, which forces the server to descend
- and serve the files there. client.c (send_file_names) has
- also been modified to send only those arguments which are
- appropriate to current_parsed_root->original.
-
- */
-
- /* Construct a fake argc/argv pair. */
-
- int our_argc = 0, i;
- char **our_argv = NULL;
-
- if (! list_isempty (args_to_send_when_finished))
- {
- Node *head, *p;
-
- head = args_to_send_when_finished->list;
-
- /* count the number of nodes */
- i = 0;
- for (p = head->next; p != head; p = p->next)
- i++;
- our_argc = i;
-
- /* create the argument vector */
- our_argv = (char **) xmalloc (sizeof (char *) * our_argc);
-
- /* populate it */
- i = 0;
- for (p = head->next; p != head; p = p->next)
- our_argv[i++] = xstrdup (p->key);
- }
-
- /* We don't want to expand widcards, since we've just created
- a list of directories directly from the filesystem. */
- send_file_names (our_argc, our_argv, 0);
-
- /* Free our argc/argv. */
- if (our_argv != NULL)
- {
- for (i = 0; i < our_argc; i++)
- free (our_argv[i]);
- free (our_argv);
- }
-
- dellist (&args_to_send_when_finished);
- }
-#endif
-
- return (err);
-}
-
-/*
- * Implement the recursive policies on the local directory. This may be
- * called directly, or may be called by start_recursion
- */
-static int
-do_recursion (frame)
- struct recursion_frame *frame;
-{
- int err = 0;
- int dodoneproc = 1;
- char *srepository = NULL;
- List *entries = NULL;
- int locktype;
- int process_this_directory = 1;
-
- /* do nothing if told */
- if (frame->flags == R_SKIP_ALL)
- return (0);
-
- locktype = noexec ? CVS_LOCK_NONE : frame->locktype;
-
- /* The fact that locks are not active here is what makes us fail to have
- the
-
- If someone commits some changes in one cvs command,
- then an update by someone else will either get all the
- changes, or none of them.
-
- property (see node Concurrency in cvs.texinfo).
-
- The most straightforward fix would just to readlock the whole
- tree before starting an update, but that means that if a commit
- gets blocked on a big update, it might need to wait a *long*
- time.
-
- A more adequate fix would be a two-pass design for update,
- checkout, etc. The first pass would go through the repository,
- with the whole tree readlocked, noting what versions of each
- file we want to get. The second pass would release all locks
- (except perhaps short-term locks on one file at a
- time--although I think RCS already deals with this) and
- actually get the files, specifying the particular versions it wants.
-
- This could be sped up by separating out the data needed for the
- first pass into a separate file(s)--for example a file
- attribute for each file whose value contains the head revision
- for each branch. The structure should be designed so that
- commit can relatively quickly update the information for a
- single file or a handful of files (file attributes, as
- implemented in Jan 96, are probably acceptable; improvements
- would be possible such as branch attributes which are in
- separate files for each branch). */
-
-#if defined(SERVER_SUPPORT) && defined(SERVER_FLOWCONTROL)
- /*
- * Now would be a good time to check to see if we need to stop
- * generating data, to give the buffers a chance to drain to the
- * remote client. We should not have locks active at this point,
- * but if there are writelocks around, we cannot pause here. */
- if (server_active && locktype != CVS_LOCK_WRITE)
- server_pause_check();
-#endif
-
- /* Check the value in CVSADM_ROOT and see if it's in the list. If
- not, add it to our lists of CVS/Root directories and do not
- process the files in this directory. Otherwise, continue as
- usual. THIS_ROOT might be NULL if we're doing an initial
- checkout -- check before using it. The default should be that
- we process a directory's contents and only skip those contents
- if a CVS/Root file exists.
-
- If we're running the server, we want to process all
- directories, since we're guaranteed to have only one CVSROOT --
- our own. */
-
- /* If -d was specified, it should override CVS/Root.
-
- In the single-repository case, it is long-standing CVS behavior
- and makes sense - the user might want another access method,
- another server (which mounts the same repository), &c.
-
- In the multiple-repository case, -d overrides all CVS/Root
- files. That is the only plausible generalization I can
- think of. */
- if (CVSroot_cmdline == NULL && !server_active)
- {
- cvsroot_t *this_root = Name_Root ((char *) NULL, update_dir);
- if (this_root != NULL)
- {
- if (findnode (root_directories, this_root->original))
- {
- process_this_directory = !strcmp (current_parsed_root->original,
- this_root->original);
- free_cvsroot_t (this_root);
- }
- else
- {
- /* Add it to our list. */
-
- Node *n = getnode ();
- n->type = NT_UNKNOWN;
- n->key = xstrdup (this_root->original);
- n->data = this_root;
-
- if (addnode (root_directories, n))
- error (1, 0, "cannot add new CVSROOT %s",
- this_root->original);
-
- process_this_directory = 0;
- }
- }
- }
-
- /*
- * Fill in repository with the current repository
- */
- if (frame->which & W_LOCAL)
- {
- if (isdir (CVSADM))
- {
- repository = Name_Repository ((char *) NULL, update_dir);
- srepository = repository; /* remember what to free */
- }
- else
- repository = NULL;
- }
- else
- {
- repository = frame->repository;
- assert (repository != NULL);
- }
-
- fileattr_startdir (repository);
-
- /*
- * The filesdoneproc needs to be called for each directory where files
- * processed, or each directory that is processed by a call where no
- * directories were passed in. In fact, the only time we don't want to
- * call back the filesdoneproc is when we are processing directories that
- * were passed in on the command line (or in the special case of `.' when
- * we were called with no args
- */
- if (dirlist != NULL && filelist == NULL)
- dodoneproc = 0;
-
- /*
- * If filelist or dirlist is already set, we don't look again. Otherwise,
- * find the files and directories
- */
- if (filelist == NULL && dirlist == NULL)
- {
- /* both lists were NULL, so start from scratch */
- if (frame->fileproc != NULL && frame->flags != R_SKIP_FILES)
- {
- int lwhich = frame->which;
-
- /* be sure to look in the attic if we have sticky tags/date */
- if ((lwhich & W_ATTIC) == 0)
- if (isreadable (CVSADM_TAG))
- lwhich |= W_ATTIC;
-
- /* In the !(which & W_LOCAL) case, we filled in repository
- earlier in the function. In the (which & W_LOCAL) case,
- the Find_Names function is going to look through the
- Entries file. If we do not have a repository, that
- does not make sense, so we insist upon having a
- repository at this point. Name_Repository will give a
- reasonable error message. */
- if (repository == NULL)
- {
- Name_Repository ((char *) NULL, update_dir);
- assert (!"Not reached. Please report this problem to <"
- PACKAGE_BUGREPORT ">");
- }
-
- /* find the files and fill in entries if appropriate */
- if (process_this_directory)
- {
- filelist = Find_Names (repository, lwhich, frame->aflag,
- &entries);
- if (filelist == NULL)
- {
- error (0, 0, "skipping directory %s", update_dir);
- /* Note that Find_Directories and the filesdoneproc
- in particular would do bad things ("? foo.c" in
- the case of some filesdoneproc's). */
- goto skip_directory;
- }
- }
- }
-
- /* find sub-directories if we will recurse */
- if (frame->flags != R_SKIP_DIRS)
- dirlist = Find_Directories (
- process_this_directory ? repository : NULL,
- frame->which, entries);
- }
- else
- {
- /* something was passed on the command line */
- if (filelist != NULL && frame->fileproc != NULL)
- {
- /* we will process files, so pre-parse entries */
- if (frame->which & W_LOCAL)
- entries = Entries_Open (frame->aflag, NULL);
- }
- }
-
- /* process the files (if any) */
- if (process_this_directory && filelist != NULL && frame->fileproc)
- {
- struct file_info finfo_struct;
- struct frame_and_file frfile;
-
- /* read lock it if necessary */
- if (repository)
- {
- if (locktype == CVS_LOCK_READ)
- {
- if (Reader_Lock (repository) != 0)
- error (1, 0, "read lock failed - giving up");
- }
- else if (locktype == CVS_LOCK_WRITE)
- lock_dir_for_write (repository);
- }
-
-#ifdef CLIENT_SUPPORT
- /* For the server, we handle notifications in a completely different
- place (server_notify). For local, we can't do them here--we don't
- have writelocks in place, and there is no way to get writelocks
- here. */
- if (current_parsed_root->isremote)
- cvs_notify_check (repository, update_dir);
-#endif /* CLIENT_SUPPORT */
-
- finfo_struct.repository = repository;
- finfo_struct.update_dir = update_dir;
- finfo_struct.entries = entries;
- /* do_file_proc will fill in finfo_struct.file. */
-
- frfile.finfo = &finfo_struct;
- frfile.frame = frame;
-
- /* process the files */
- err += walklist (filelist, do_file_proc, &frfile);
-
- /* unlock it */
- if (/* We only lock the repository above when repository is set */
- repository
- /* and when asked for a read or write lock. */
- && locktype != CVS_LOCK_NONE)
- Lock_Cleanup ();
-
- /* clean up */
- dellist (&filelist);
- }
-
- /* call-back files done proc (if any) */
- if (process_this_directory && dodoneproc && frame->filesdoneproc != NULL)
- err = frame->filesdoneproc (frame->callerdat, err, repository,
- update_dir[0] ? update_dir : ".",
- entries);
-
- skip_directory:
- fileattr_write ();
- fileattr_free ();
-
- /* process the directories (if necessary) */
- if (dirlist != NULL)
- {
- struct frame_and_entries frent;
-
- frent.frame = frame;
- frent.entries = entries;
- err += walklist (dirlist, do_dir_proc, (void *) &frent);
- }
-#if 0
- else if (frame->dirleaveproc != NULL)
- err += frame->dirleaveproc (frame->callerdat, ".", err, ".");
-#endif
- dellist (&dirlist);
-
- if (entries)
- {
- Entries_Close (entries);
- entries = NULL;
- }
-
- /* free the saved copy of the pointer if necessary */
- if (srepository)
- {
- free (srepository);
- }
- repository = (char *) NULL;
-
- return err;
-}
-
-
-
-/*
- * Process each of the files in the list with the callback proc
- */
-static int
-do_file_proc (p, closure)
- Node *p;
- void *closure;
-{
- struct frame_and_file *frfile = (struct frame_and_file *)closure;
- struct file_info *finfo = frfile->finfo;
- int ret;
- char *tmp;
-
- finfo->file = p->key;
- tmp = xmalloc (strlen (finfo->file)
- + strlen (finfo->update_dir)
- + 2);
- tmp[0] = '\0';
- if (finfo->update_dir[0] != '\0')
- {
- strcat (tmp, finfo->update_dir);
- strcat (tmp, "/");
- }
- strcat (tmp, finfo->file);
-
- if (frfile->frame->dosrcs && repository)
- {
- finfo->rcs = RCS_parse (finfo->file, repository);
-
- /* OK, without W_LOCAL the error handling becomes relatively
- simple. The file names came from readdir() on the
- repository and so we know any ENOENT is an error
- (e.g. symlink pointing to nothing). Now, the logic could
- be simpler - since we got the name from readdir, we could
- just be calling RCS_parsercsfile. */
- if (finfo->rcs == NULL
- && !(frfile->frame->which & W_LOCAL))
- {
- error (0, 0, "could not read RCS file for %s", tmp);
- free (tmp);
- cvs_flushout ();
- return 0;
- }
- }
- else
- finfo->rcs = (RCSNode *) NULL;
- finfo->fullname = tmp;
- ret = frfile->frame->fileproc (frfile->frame->callerdat, finfo);
-
- freercsnode(&finfo->rcs);
- free (tmp);
-
- /* Allow the user to monitor progress with tail -f. Doing this once
- per file should be no big deal, but we don't want the performance
- hit of flushing on every line like previous versions of CVS. */
- cvs_flushout ();
-
- return ret;
-}
-
-
-
-/*
- * Process each of the directories in the list (recursing as we go)
- */
-static int
-do_dir_proc (p, closure)
- Node *p;
- void *closure;
-{
- struct frame_and_entries *frent = (struct frame_and_entries *) closure;
- struct recursion_frame *frame = frent->frame;
- struct recursion_frame xframe;
- char *dir = p->key;
- char *newrepos;
- List *sdirlist;
- char *srepository;
- Dtype dir_return = R_PROCESS;
- int stripped_dot = 0;
- int err = 0;
- struct saved_cwd cwd;
- char *saved_update_dir;
- int process_this_directory = 1;
-
- if (fncmp (dir, CVSADM) == 0)
- {
- /* This seems to most often happen when users (beginning users,
- generally), try "cvs ci *" or something similar. On that
- theory, it is possible that we should just silently skip the
- CVSADM directories, but on the other hand, using a wildcard
- like this isn't necessarily a practice to encourage (it operates
- only on files which exist in the working directory, unlike
- regular CVS recursion). */
-
- /* FIXME-reentrancy: printed_cvs_msg should be in a "command
- struct" or some such, so that it gets cleared for each new
- command (this is possible using the remote protocol and a
- custom-written client). The struct recursion_frame is not
- far back enough though, some commands (commit at least)
- will call start_recursion several times. An alternate solution
- would be to take this whole check and move it to a new function
- validate_arguments or some such that all the commands call
- and which snips the offending directory from the argc,argv
- vector. */
- static int printed_cvs_msg = 0;
- if (!printed_cvs_msg)
- {
- error (0, 0, "warning: directory %s specified in argument",
- dir);
- error (0, 0, "\
-but CVS uses %s for its own purposes; skipping %s directory",
- CVSADM, dir);
- printed_cvs_msg = 1;
- }
- return 0;
- }
-
- saved_update_dir = update_dir;
- update_dir = xmalloc (strlen (saved_update_dir)
- + strlen (dir)
- + 5);
- strcpy (update_dir, saved_update_dir);
-
- /* set up update_dir - skip dots if not at start */
- if (strcmp (dir, ".") != 0)
- {
- if (update_dir[0] != '\0')
- {
- (void) strcat (update_dir, "/");
- (void) strcat (update_dir, dir);
- }
- else
- (void) strcpy (update_dir, dir);
-
- /*
- * Here we need a plausible repository name for the sub-directory. We
- * create one by concatenating the new directory name onto the
- * previous repository name. The only case where the name should be
- * used is in the case where we are creating a new sub-directory for
- * update -d and in that case the generated name will be correct.
- */
- if (repository == NULL)
- newrepos = xstrdup ("");
- else
- {
- newrepos = xmalloc (strlen (repository) + strlen (dir) + 5);
- sprintf (newrepos, "%s/%s", repository, dir);
- }
- }
- else
- {
- if (update_dir[0] == '\0')
- (void) strcpy (update_dir, dir);
-
- if (repository == NULL)
- newrepos = xstrdup ("");
- else
- newrepos = xstrdup (repository);
- }
-
- /* Check to see that the CVSADM directory, if it exists, seems to be
- well-formed. It can be missing files if the user hit ^C in the
- middle of a previous run. We want to (a) make this a nonfatal
- error, and (b) make sure we print which directory has the
- problem.
-
- Do this before the direntproc, so that (1) the direntproc
- doesn't have to guess/deduce whether we will skip the directory
- (e.g. send_dirent_proc and whether to send the directory), and
- (2) so that the warm fuzzy doesn't get printed if we skip the
- directory. */
- if (frame->which & W_LOCAL)
- {
- char *cvsadmdir;
-
- cvsadmdir = xmalloc (strlen (dir)
- + sizeof (CVSADM_REP)
- + sizeof (CVSADM_ENT)
- + 80);
-
- strcpy (cvsadmdir, dir);
- strcat (cvsadmdir, "/");
- strcat (cvsadmdir, CVSADM);
- if (isdir (cvsadmdir))
- {
- strcpy (cvsadmdir, dir);
- strcat (cvsadmdir, "/");
- strcat (cvsadmdir, CVSADM_REP);
- if (!isfile (cvsadmdir))
- {
- /* Some commands like update may have printed "? foo" but
- if we were planning to recurse, and don't on account of
- CVS/Repository, we want to say why. */
- error (0, 0, "ignoring %s (%s missing)", update_dir,
- CVSADM_REP);
- dir_return = R_SKIP_ALL;
- }
-
- /* Likewise for CVS/Entries. */
- if (dir_return != R_SKIP_ALL)
- {
- strcpy (cvsadmdir, dir);
- strcat (cvsadmdir, "/");
- strcat (cvsadmdir, CVSADM_ENT);
- if (!isfile (cvsadmdir))
- {
- /* Some commands like update may have printed "? foo" but
- if we were planning to recurse, and don't on account of
- CVS/Repository, we want to say why. */
- error (0, 0, "ignoring %s (%s missing)", update_dir,
- CVSADM_ENT);
- dir_return = R_SKIP_ALL;
- }
- }
- }
- free (cvsadmdir);
- }
-
- /* Only process this directory if the root matches. This nearly
- duplicates code in do_recursion. */
-
- /* If -d was specified, it should override CVS/Root.
-
- In the single-repository case, it is long-standing CVS behavior
- and makes sense - the user might want another access method,
- another server (which mounts the same repository), &c.
-
- In the multiple-repository case, -d overrides all CVS/Root
- files. That is the only plausible generalization I can
- think of. */
- if (CVSroot_cmdline == NULL && !server_active)
- {
- cvsroot_t *this_root = Name_Root (dir, update_dir);
- if (this_root != NULL)
- {
- if (findnode (root_directories, this_root->original))
- {
- process_this_directory = !strcmp (current_parsed_root->original,
- this_root->original);
- free_cvsroot_t (this_root);
- }
- else
- {
- /* Add it to our list. */
-
- Node *n = getnode ();
- n->type = NT_UNKNOWN;
- n->key = xstrdup (this_root->original);
- n->data = this_root;
-
- if (addnode (root_directories, n))
- error (1, 0, "cannot add new CVSROOT %s",
- this_root->original);
-
- process_this_directory = 0;
- }
- }
- }
-
- /* call-back dir entry proc (if any) */
- if (dir_return == R_SKIP_ALL)
- ;
- else if (frame->direntproc != NULL)
- {
- /* If we're doing the actual processing, call direntproc.
- Otherwise, assume that we need to process this directory
- and recurse. FIXME. */
-
- if (process_this_directory)
- dir_return = frame->direntproc (frame->callerdat, dir, newrepos,
- update_dir, frent->entries);
- else
- dir_return = R_PROCESS;
- }
- else
- {
- /* Generic behavior. I don't see a reason to make the caller specify
- a direntproc just to get this. */
- if ((frame->which & W_LOCAL) && !isdir (dir))
- dir_return = R_SKIP_ALL;
- }
-
- free (newrepos);
-
- /* only process the dir if the return code was 0 */
- if (dir_return != R_SKIP_ALL)
- {
- /* save our current directory and static vars */
- if (save_cwd (&cwd))
- error_exit ();
- sdirlist = dirlist;
- srepository = repository;
- dirlist = NULL;
-
- /* cd to the sub-directory */
- if (CVS_CHDIR (dir) < 0)
- error (1, errno, "could not chdir to %s", dir);
-
- /* honor the global SKIP_DIRS (a.k.a. local) */
- if (frame->flags == R_SKIP_DIRS)
- dir_return = R_SKIP_DIRS;
-
- /* remember if the `.' will be stripped for subsequent dirs */
- if (strcmp (update_dir, ".") == 0)
- {
- update_dir[0] = '\0';
- stripped_dot = 1;
- }
-
- /* make the recursive call */
- xframe = *frame;
- xframe.flags = dir_return;
- /* Keep track of repository, really just for r* commands (rtag, rdiff,
- * co, ...) to tag_check_valid, since all the other commands use
- * CVS/Repository to figure it out per directory.
- */
- if (repository)
- {
- if (strcmp (dir, ".") == 0)
- xframe.repository = xstrdup (repository);
- else
- {
- xframe.repository = xmalloc (strlen (repository)
- + strlen (dir)
- + 2);
- sprintf (xframe.repository, "%s/%s", repository, dir);
- }
- }
- else
- xframe.repository = NULL;
- err += do_recursion (&xframe);
- if (xframe.repository)
- {
- free (xframe.repository);
- xframe.repository = NULL;
- }
-
- /* put the `.' back if necessary */
- if (stripped_dot)
- (void) strcpy (update_dir, ".");
-
- /* call-back dir leave proc (if any) */
- if (process_this_directory && frame->dirleaveproc != NULL)
- err = frame->dirleaveproc (frame->callerdat, dir, err, update_dir,
- frent->entries);
-
- /* get back to where we started and restore state vars */
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- free_cwd (&cwd);
- dirlist = sdirlist;
- repository = srepository;
- }
-
- free (update_dir);
- update_dir = saved_update_dir;
-
- return err;
-}
-
-/*
- * Add a node to a list allocating the list if necessary.
- */
-static void
-addlist (listp, key)
- List **listp;
- char *key;
-{
- Node *p;
-
- if (*listp == NULL)
- *listp = getlist ();
- p = getnode ();
- p->type = FILES;
- p->key = xstrdup (key);
- if (addnode (*listp, p) != 0)
- freenode (p);
-}
-
-static void
-addfile (listp, dir, file)
- List **listp;
- char *dir;
- char *file;
-{
- Node *n;
- List *fl;
-
- /* add this dir. */
- addlist (listp, dir);
-
- n = findnode (*listp, dir);
- if (n == NULL)
- {
- error (1, 0, "can't find recently added dir node `%s' in start_recursion.",
- dir);
- }
-
- n->type = DIRS;
- fl = n->data;
- addlist (&fl, file);
- n->data = fl;
- return;
-}
-
-static int
-unroll_files_proc (p, closure)
- Node *p;
- void *closure;
-{
- Node *n;
- struct recursion_frame *frame = (struct recursion_frame *) closure;
- int err = 0;
- List *save_dirlist;
- char *save_update_dir = NULL;
- struct saved_cwd cwd;
-
- /* if this dir was also an explicitly named argument, then skip
- it. We'll catch it later when we do dirs. */
- n = findnode (dirlist, p->key);
- if (n != NULL)
- return (0);
-
- /* otherwise, call dorecusion for this list of files. */
- filelist = p->data;
- p->data = NULL;
- save_dirlist = dirlist;
- dirlist = NULL;
-
- if (strcmp(p->key, ".") != 0)
- {
- if (save_cwd (&cwd))
- error_exit ();
- if ( CVS_CHDIR (p->key) < 0)
- error (1, errno, "could not chdir to %s", p->key);
-
- save_update_dir = update_dir;
- update_dir = xmalloc (strlen (save_update_dir)
- + strlen (p->key)
- + 5);
- strcpy (update_dir, save_update_dir);
-
- if (*update_dir != '\0')
- (void) strcat (update_dir, "/");
-
- (void) strcat (update_dir, p->key);
- }
-
- err += do_recursion (frame);
-
- if (save_update_dir != NULL)
- {
- free (update_dir);
- update_dir = save_update_dir;
-
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- free_cwd (&cwd);
- }
-
- dirlist = save_dirlist;
- if (filelist)
- dellist (&filelist);
- return(err);
-}
diff --git a/contrib/cvs/src/release.c b/contrib/cvs/src/release.c
deleted file mode 100644
index 27a16c08753c..000000000000
--- a/contrib/cvs/src/release.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 1994-2005 The Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-/*
- * Release: "cancel" a checkout in the history log.
- *
- * - Enter a line in the history log indicating the "release". - If asked to,
- * delete the local working directory.
- */
-
-#include "cvs.h"
-#include "savecwd.h"
-#include "getline.h"
-
-static const char *const release_usage[] =
-{
- "Usage: %s %s [-d] directories...\n",
- "\t-d\tDelete the given directory.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-#ifdef SERVER_SUPPORT
-static int release_server PROTO ((int argc, char **argv));
-
-/* This is the server side of cvs release. */
-static int
-release_server (argc, argv)
- int argc;
- char **argv;
-{
- int i;
-
- /* Note that we skip argv[0]. */
- for (i = 1; i < argc; ++i)
- history_write ('F', argv[i], "", argv[i], "");
- return 0;
-}
-
-#endif /* SERVER_SUPPORT */
-
-/* There are various things to improve about this implementation:
-
- 1. Using run_popen to run "cvs update" could be replaced by a
- fairly simple start_recursion/classify_file loop--a win for
- portability, performance, and cleanliness. In particular, there is
- no particularly good way to find the right "cvs".
-
- 2. The fact that "cvs update" contacts the server slows things down;
- it undermines the case for using "cvs release" rather than "rm -rf".
- However, for correctly printing "? foo" and correctly handling
- CVSROOTADM_IGNORE, we currently need to contact the server. (One
- idea for how to fix this is to stash a copy of CVSROOTADM_IGNORE in
- the working directories; see comment at base_* in entries.c for a
- few thoughts on that).
-
- 3. Would be nice to take processing things on the client side one step
- further, and making it like edit/unedit in terms of working well if
- disconnected from the network, and then sending a delayed
- notification.
-
- 4. Having separate network turnarounds for the "Notify" request
- which we do as part of unedit, and for the "release" itself, is slow
- and unnecessary. */
-
-int
-release (argc, argv)
- int argc;
- char **argv;
-{
- FILE *fp;
- int i, c;
- char *line = NULL;
- size_t line_allocated = 0;
- char *update_cmd;
- char *thisarg;
- int arg_start_idx;
- int err = 0;
- short delete_flag = 0;
- struct saved_cwd cwd;
-
-#ifdef SERVER_SUPPORT
- if (server_active)
- return release_server (argc, argv);
-#endif
-
- /* Everything from here on is client or local. */
- if (argc == -1)
- usage (release_usage);
- optind = 0;
- while ((c = getopt (argc, argv, "+Qdq")) != -1)
- {
- switch (c)
- {
- case 'Q':
- case 'q':
- error (1, 0,
- "-q or -Q must be specified before \"%s\"",
- cvs_cmd_name);
- break;
- case 'd':
- delete_flag++;
- break;
- case '?':
- default:
- usage (release_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- /* 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. Be sure to add authentication and
- encryption if we are using them currently, else our child process may
- not be able to communicate with the server. */
- update_cmd = xmalloc (strlen (program_path)
- + strlen (current_parsed_root->original)
- + 1 + 3 + 3 + 16 + 1);
- sprintf (update_cmd, "%s %s%s-n -q -d %s update",
- program_path,
-#if defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT)
- cvsauthenticate ? "-a " : "",
- cvsencrypt ? "-x " : "",
-#else
- "", "",
-#endif
- current_parsed_root->original);
-
-#ifdef CLIENT_SUPPORT
- /* Start the server; we'll close it after looping. */
- if (current_parsed_root->isremote)
- {
- start_server ();
- ign_setup ();
- }
-#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++)
- {
- thisarg = argv[i];
-
- if (isdir (thisarg))
- {
- if (CVS_CHDIR (thisarg) < 0)
- {
- if (!really_quiet)
- error (0, errno, "can't chdir to: %s", thisarg);
- continue;
- }
- if (!isdir (CVSADM))
- {
- if (!really_quiet)
- error (0, 0, "no repository directory: %s", thisarg);
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- continue;
- }
- }
- else
- {
- if (!really_quiet)
- error (0, 0, "no such directory: %s", thisarg);
- continue;
- }
-
- if (!really_quiet)
- {
- int line_length, status;
-
- /* The "release" command piggybacks on "update", which
- does the real work of finding out if anything is not
- up-to-date with the repository. Then "release" prompts
- the user, telling her how many files have been
- modified, and asking if she still wants to do the
- release. */
- fp = run_popen (update_cmd, "r");
- if (fp == NULL)
- error (1, 0, "cannot run command %s", update_cmd);
-
- c = 0;
-
- while ((line_length = getline (&line, &line_allocated, fp)) >= 0)
- {
- if (strchr ("MARCZ", *line))
- c++;
- (void) fputs (line, stdout);
- }
- if (line_length < 0 && !feof (fp))
- error (0, errno, "cannot read from subprocess");
-
- /* If the update exited with an error, then we just want to
- complain and go on to the next arg. Especially, we do
- not want to delete the local copy, since it's obviously
- not what the user thinks it is. */
- status = pclose (fp);
- if (status != 0)
- {
- error (0, 0, "unable to release `%s' (%d)", thisarg, status);
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- continue;
- }
-
- printf ("You have [%d] altered files in this repository.\n",
- c);
- printf ("Are you sure you want to release %sdirectory `%s': ",
- delete_flag ? "(and delete) " : "", thisarg);
- c = !yesno ();
- if (c) /* "No" */
- {
- (void) fprintf (stderr, "** `%s' aborted by user choice.\n",
- cvs_cmd_name);
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- continue;
- }
- }
-
- /* Note: client.c doesn't like to have other code
- changing the current directory on it. So a fair amount
- of effort is needed to make sure it doesn't get confused
- about the directory and (for example) overwrite
- CVS/Entries file in the wrong directory. See release-17
- through release-23. */
-
- if (restore_cwd (&cwd, NULL))
- error_exit ();
-
- if (1
-#ifdef CLIENT_SUPPORT
- && !(current_parsed_root->isremote
- && (!supported_request ("noop")
- || !supported_request ("Notify")))
-#endif
- )
- {
- int argc = 2;
- char *argv[3];
- argv[0] = "dummy";
- argv[1] = thisarg;
- argv[2] = NULL;
- err += unedit (argc, argv);
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- }
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- send_to_server ("Argument ", 0);
- send_to_server (thisarg, 0);
- send_to_server ("\012", 1);
- send_to_server ("release\012", 0);
- }
- else
-#endif /* CLIENT_SUPPORT */
- {
- history_write ('F', thisarg, "", thisarg, ""); /* F == Free */
- }
-
- 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 (current_parsed_root->isremote)
- {
- /* FIXME:
- * Is there a good reason why get_server_responses() isn't
- * responsible for restoring its initial directory itself when
- * finished?
- */
- err += get_server_responses ();
-
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- }
-#endif /* CLIENT_SUPPORT */
- }
-
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- free_cwd (&cwd);
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- /* Unfortunately, client.c doesn't offer a way to close
- the connection without waiting for responses. The extra
- network turnaround here is quite unnecessary other than
- that.... */
- send_to_server ("noop\012", 0);
- err += get_responses_and_close ();
- }
-#endif /* CLIENT_SUPPORT */
-
- free (update_cmd);
- if (line != NULL)
- free (line);
- return err;
-}
diff --git a/contrib/cvs/src/remove.c b/contrib/cvs/src/remove.c
deleted file mode 100644
index a09cfd475493..000000000000
--- a/contrib/cvs/src/remove.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Remove a File
- *
- * Removes entries from the present version. The entries will be removed from
- * the RCS repository upon the next "commit".
- *
- * "remove" accepts no options, only file names that are to be removed. The
- * file must not exist in the current directory for "remove" to work
- * correctly.
- */
-
-#include "cvs.h"
-
-#ifdef CLIENT_SUPPORT
-static int remove_force_fileproc PROTO ((void *callerdat,
- struct file_info *finfo));
-#endif
-static int remove_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-static Dtype remove_dirproc PROTO ((void *callerdat, const char *dir,
- const char *repos, const char *update_dir,
- List *entries));
-
-static int force;
-static int local;
-static int removed_files;
-static int existing_files;
-
-static const char *const remove_usage[] =
-{
- "Usage: %s %s [-flR] [files...]\n",
- "\t-f\tDelete the file before removing it.\n",
- "\t-l\tProcess this directory only (not recursive).\n",
- "\t-R\tProcess directories recursively.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-int
-cvsremove (argc, argv)
- int argc;
- char **argv;
-{
- int c, err;
-
- if (argc == -1)
- usage (remove_usage);
-
- optind = 0;
- while ((c = getopt (argc, argv, "+flR")) != -1)
- {
- switch (c)
- {
- case 'f':
- force = 1;
- break;
- case 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case '?':
- default:
- usage (remove_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- wrap_setup ();
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote) {
- /* Call expand_wild so that the local removal of files will
- work. It's ok to do it always because we have to send the
- file names expanded anyway. */
- expand_wild (argc, argv, &argc, &argv);
-
- if (force)
- {
- if (!noexec)
- {
- start_recursion (remove_force_fileproc, (FILESDONEPROC) NULL,
- (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL,
- (void *) NULL, argc, argv, local, W_LOCAL,
- 0, CVS_LOCK_NONE, (char *) NULL, 0,
- (char *) NULL);
- }
- /* else FIXME should probably act as if the file doesn't exist
- in doing the following checks. */
- }
-
- start_server ();
- ign_setup ();
- if (local)
- send_arg("-l");
- send_arg ("--");
- /* FIXME: Can't we set SEND_NO_CONTENTS here? Needs investigation. */
- send_files (argc, argv, local, 0, 0);
- send_file_names (argc, argv, 0);
- free_names (&argc, argv);
- send_to_server ("remove\012", 0);
- return get_responses_and_close ();
- }
-#endif
-
- /* start the recursion processor */
- err = start_recursion (remove_fileproc, (FILESDONEPROC) NULL,
- remove_dirproc, (DIRLEAVEPROC) NULL, NULL,
- argc, argv,
- local, W_LOCAL, 0, CVS_LOCK_READ, (char *) NULL, 1,
- (char *) NULL);
-
- if (removed_files && !really_quiet)
- error (0, 0, "use '%s commit' to remove %s permanently", program_name,
- (removed_files == 1) ? "this file" : "these files");
-
- if (existing_files)
- error (0, 0,
- ((existing_files == 1) ?
- "%d file exists; remove it first" :
- "%d files exist; remove them first"),
- existing_files);
-
- return (err);
-}
-
-#ifdef CLIENT_SUPPORT
-
-/*
- * This is called via start_recursion if we are running as the client
- * and the -f option was used. We just physically remove the file.
- */
-
-/*ARGSUSED*/
-static int
-remove_force_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- if (CVS_UNLINK (finfo->file) < 0 && ! existence_error (errno))
- error (0, errno, "unable to remove %s", finfo->fullname);
- return 0;
-}
-
-#endif
-
-/*
- * remove the file, only if it has already been physically removed
- */
-/* ARGSUSED */
-static int
-remove_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- Vers_TS *vers;
-
- if (force)
- {
- if (!noexec)
- {
- if ( CVS_UNLINK (finfo->file) < 0 && ! existence_error (errno))
- {
- error (0, errno, "unable to remove %s", finfo->fullname);
- }
- }
- /* else FIXME should probably act as if the file doesn't exist
- in doing the following checks. */
- }
-
- vers = Version_TS (finfo, NULL, NULL, NULL, 0, 0);
-
- if (vers->ts_user != NULL)
- {
- existing_files++;
- if (!quiet)
- error (0, 0, "file `%s' still in working directory",
- finfo->fullname);
- }
- else if (vers->vn_user == NULL)
- {
- if (!quiet)
- error (0, 0, "nothing known about `%s'", finfo->fullname);
- }
- else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
- {
- char *fname;
-
- /*
- * It's a file that has been added, but not commited yet. So,
- * remove the ,t file for it and scratch it from the
- * entries file. */
- Scratch_Entry (finfo->entries, finfo->file);
- fname = xmalloc (strlen (finfo->file)
- + sizeof (CVSADM)
- + sizeof (CVSEXT_LOG)
- + 10);
- (void) sprintf (fname, "%s/%s%s", CVSADM, finfo->file, CVSEXT_LOG);
- 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);
-
-#ifdef SERVER_SUPPORT
- if (server_active)
- server_checked_in (finfo->file, finfo->update_dir, finfo->repository);
-#endif
- free (fname);
- }
- else if (vers->vn_user[0] == '-')
- {
- if (!quiet)
- error (0, 0, "file `%s' already scheduled for removal",
- finfo->fullname);
- }
- 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
- arise out of parallel development are one thing, but conflicts
- that arise from sticky tags are quite another.
-
- I would have thought that non-branch sticky tags should be the
- same but at least now, removing a file with a non-branch sticky
- tag means to delete the tag from the file. I'm not sure that
- is a good behavior, but until it is changed, we need to allow
- it. */
- error (0, 0, "\
-cannot remove file `%s' which has a numeric sticky tag of `%s'",
- finfo->fullname, vers->tag);
- }
- else if (vers->date != NULL)
- {
- /* Commit will just give an error, and so there seems to be
- little reason to allow the remove. */
- error (0, 0, "\
-cannot remove file `%s' which has a sticky date of `%s'",
- finfo->fullname, vers->date);
- }
- else
- {
- char *fname;
-
- /* Re-register it with a negative version number. */
- fname = xmalloc (strlen (vers->vn_user) + 5);
- (void) strcpy (fname, "-");
- (void) strcat (fname, vers->vn_user);
- Register (finfo->entries, finfo->file, fname, vers->ts_rcs, vers->options,
- vers->tag, vers->date, vers->ts_conflict);
- if (!quiet)
- error (0, 0, "scheduling `%s' for removal", finfo->fullname);
- removed_files++;
-
-#ifdef SERVER_SUPPORT
- if (server_active)
- server_checked_in (finfo->file, finfo->update_dir, finfo->repository);
-#endif
- free (fname);
- }
-
- freevers_ts (&vers);
- return (0);
-}
-
-/*
- * Print a warm fuzzy message
- */
-/* ARGSUSED */
-static Dtype
-remove_dirproc (callerdat, dir, repos, update_dir, entries)
- void *callerdat;
- const char *dir;
- const char *repos;
- const char *update_dir;
- List *entries;
-{
- if (!quiet)
- error (0, 0, "Removing %s", update_dir);
- return (R_PROCESS);
-}
diff --git a/contrib/cvs/src/repos.c b/contrib/cvs/src/repos.c
deleted file mode 100644
index 202d92d5e8a2..000000000000
--- a/contrib/cvs/src/repos.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- */
-
-#include <assert.h>
-#include "cvs.h"
-#include "getline.h"
-
-/* Determine the name of the RCS repository for directory DIR in the
- current working directory, or for the current working directory
- itself if DIR is NULL. Returns the name in a newly-malloc'd
- string. On error, gives a fatal error and does not return.
- UPDATE_DIR is the path from where cvs was invoked (for use in error
- messages), and should contain DIR as its last component.
- UPDATE_DIR can be NULL to signify the directory in which cvs was
- invoked. */
-
-char *
-Name_Repository (dir, update_dir)
- const char *dir;
- const char *update_dir;
-{
- FILE *fpin;
- const char *xupdate_dir;
- char *repos = NULL;
- size_t repos_allocated = 0;
- char *tmp;
- char *cp;
-
- if (update_dir && *update_dir)
- xupdate_dir = update_dir;
- else
- xupdate_dir = ".";
-
- if (dir != NULL)
- {
- tmp = xmalloc (strlen (dir) + sizeof (CVSADM_REP) + 10);
- (void) sprintf (tmp, "%s/%s", dir, CVSADM_REP);
- }
- else
- tmp = xstrdup (CVSADM_REP);
-
- /*
- * The assumption here is that the repository is always contained in the
- * first line of the "Repository" file.
- */
- fpin = CVS_FOPEN (tmp, "r");
-
- if (fpin == NULL)
- {
- int save_errno = errno;
- char *cvsadm;
-
- if (dir != NULL)
- {
- cvsadm = xmalloc (strlen (dir) + sizeof (CVSADM) + 10);
- (void) sprintf (cvsadm, "%s/%s", dir, CVSADM);
- }
- else
- cvsadm = xstrdup (CVSADM);
-
- if (!isdir (cvsadm))
- {
- error (0, 0, "in directory %s:", xupdate_dir);
- error (1, 0, "there is no version here; do '%s checkout' first",
- program_name);
- }
- free (cvsadm);
-
- if (existence_error (save_errno))
- {
- /* FIXME: This is a very poorly worded error message. It
- occurs at least in the case where the user manually
- creates a directory named CVS, so the error message
- should be more along the lines of "CVS directory found
- without administrative files; use CVS to create the CVS
- directory, or rename it to something else if the
- intention is to store something besides CVS
- administrative files". */
- error (0, 0, "in directory %s:", xupdate_dir);
- error (1, 0, "*PANIC* administration files missing");
- }
-
- error (1, save_errno, "cannot open %s", tmp);
- }
-
- if (getline (&repos, &repos_allocated, fpin) < 0)
- {
- /* FIXME: should be checking for end of file separately. */
- error (0, 0, "in directory %s:", xupdate_dir);
- error (1, errno, "cannot read %s", CVSADM_REP);
- }
- if (fclose (fpin) < 0)
- error (0, errno, "cannot close %s", tmp);
- free (tmp);
-
- if ((cp = strrchr (repos, '\n')) != NULL)
- *cp = '\0'; /* strip the newline */
-
- /*
- * If this is a relative repository pathname, turn it into an absolute
- * one by tacking on the CVSROOT environment variable. If the CVSROOT
- * environment variable is not set, die now.
- */
- if (! isabsolute(repos))
- {
- char *newrepos;
-
- if (current_parsed_root == NULL)
- {
- error (0, 0, "in directory %s:", xupdate_dir);
- error (0, 0, "must set the CVSROOT environment variable\n");
- error (0, 0, "or specify the '-d' option to %s.", program_name);
- error (1, 0, "illegal repository setting");
- }
- if (pathname_levels (repos) > 0)
- {
- error (0, 0, "in directory %s:", xupdate_dir);
- error (0, 0, "`..'-relative repositories are not supported.");
- error (1, 0, "illegal source repository");
- }
- newrepos = xmalloc (strlen (current_parsed_root->directory)
- + strlen (repos) + 2);
- sprintf (newrepos, "%s/%s", current_parsed_root->directory, repos);
- free (repos);
- repos = newrepos;
- }
-
- Sanitize_Repository_Name (repos);
-
- return repos;
-}
-
-
-
-/*
- * Return a pointer to the repository name relative to CVSROOT from a
- * possibly fully qualified repository
- */
-const char *
-Short_Repository (repository)
- const char *repository;
-{
- if (repository == NULL)
- return NULL;
-
- /* If repository matches CVSroot at the beginning, strip off CVSroot */
- /* And skip leading '/' in rep, in case CVSroot ended with '/'. */
- if (strncmp (current_parsed_root->directory, repository,
- strlen (current_parsed_root->directory)) == 0)
- {
- const char *rep = repository + strlen (current_parsed_root->directory);
- return (*rep == '/') ? rep+1 : rep;
- }
- else
- return repository;
-}
-
-
-
-/* Sanitize the repository name (in place) by removing trailing
- * slashes and a trailing "." if present. It should be safe for
- * callers to use strcat and friends to create repository names.
- * Without this check, names like "/path/to/repos/./foo" and
- * "/path/to/repos//foo" would be created. For example, one
- * significant case is the CVSROOT-detection code in commit.c. It
- * decides whether or not it needs to rebuild the administrative file
- * database by doing a string compare. If we've done a `cvs co .' to
- * get the CVSROOT files, "/path/to/repos/./CVSROOT" and
- * "/path/to/repos/CVSROOT" are the arguments that are compared!
- *
- * This function ends up being called from the same places as
- * strip_path, though what it does is much more conservative. Many
- * comments about this operation (which was scattered around in
- * several places in the source code) ran thus:
- *
- * ``repository ends with "/."; omit it. This sort of thing used
- * to be taken care of by strip_path. Now we try to be more
- * selective. I suspect that it would be even better to push it
- * back further someday, so that the trailing "/." doesn't get into
- * repository in the first place, but we haven't taken things that
- * far yet.'' --Jim Kingdon (recurse.c, 07-Sep-97)
- */
-
-void
-Sanitize_Repository_Name (repository)
- char *repository;
-{
- size_t len;
-
- assert (repository != NULL);
-
- strip_trailing_slashes (repository);
-
- len = strlen (repository);
- if (len >= 2
- && repository[len - 1] == '.'
- && ISDIRSEP (repository[len - 2]))
- {
- repository[len - 2] = '\0';
- }
-}
diff --git a/contrib/cvs/src/root.c b/contrib/cvs/src/root.c
deleted file mode 100644
index 44d1f9a9bb4e..000000000000
--- a/contrib/cvs/src/root.c
+++ /dev/null
@@ -1,864 +0,0 @@
-/*
- * Copyright (C) 1986-2008 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Poritons Copyright (c) 1992, Mark D. Baushke
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Name of Root
- *
- * Determine the path to the CVSROOT and set "Root" accordingly.
- */
-
-#include "cvs.h"
-#include <assert.h>
-#include "getline.h"
-
-/* Printable names for things in the current_parsed_root->method enum variable.
- Watch out if the enum is changed in cvs.h! */
-
-const char method_names[][16] = {
- "undefined", "local", "server (rsh)", "pserver",
- "kserver", "gserver", "ext", "extssh", "fork"
-};
-
-#ifndef DEBUG
-
-cvsroot_t *
-Name_Root (dir, update_dir)
- const char *dir;
- const char *update_dir;
-{
- FILE *fpin;
- cvsroot_t *ret;
- const char *xupdate_dir;
- char *root = NULL;
- size_t root_allocated = 0;
- char *tmp;
- char *cvsadm;
- char *cp;
- int len;
-
- if (update_dir && *update_dir)
- xupdate_dir = update_dir;
- else
- xupdate_dir = ".";
-
- if (dir != NULL)
- {
- cvsadm = xmalloc (strlen (dir) + sizeof (CVSADM) + 10);
- (void) sprintf (cvsadm, "%s/%s", dir, CVSADM);
- tmp = xmalloc (strlen (dir) + sizeof (CVSADM_ROOT) + 10);
- (void) sprintf (tmp, "%s/%s", dir, CVSADM_ROOT);
- }
- else
- {
- cvsadm = xstrdup (CVSADM);
- tmp = xstrdup (CVSADM_ROOT);
- }
-
- /*
- * Do not bother looking for a readable file if there is no cvsadm
- * directory present.
- *
- * It is possible that not all repositories will have a CVS/Root
- * file. This is ok, but the user will need to specify -d
- * /path/name or have the environment variable CVSROOT set in
- * order to continue. */
- if ((!isdir (cvsadm)) || (!isreadable (tmp)))
- {
- ret = NULL;
- goto out;
- }
-
- /*
- * The assumption here is that the CVS Root is always contained in the
- * first line of the "Root" file.
- */
- fpin = open_file (tmp, "r");
-
- if ((len = getline (&root, &root_allocated, fpin)) < 0)
- {
- int saved_errno = errno;
- /* FIXME: should be checking for end of file separately; errno
- is not set in that case. */
- error (0, 0, "in directory %s:", xupdate_dir);
- error (0, saved_errno, "cannot read %s", CVSADM_ROOT);
- error (0, 0, "please correct this problem");
- ret = NULL;
- goto out;
- }
- fclose (fpin);
- cp = root + len - 1;
- if (*cp == '\n')
- *cp = '\0'; /* strip the newline */
-
- /*
- * root now contains a candidate for CVSroot. It must be an
- * absolute pathname or specify a remote server.
- */
-
- ret = parse_cvsroot (root);
- if (ret == NULL)
- {
- error (0, 0, "in directory %s:", xupdate_dir);
- error (0, 0,
- "ignoring %s because it does not contain a valid root.",
- CVSADM_ROOT);
- goto out;
- }
-
- if (!ret->isremote && !isdir (ret->directory))
- {
- error (0, 0, "in directory %s:", xupdate_dir);
- error (0, 0,
- "ignoring %s because it specifies a non-existent repository %s",
- CVSADM_ROOT, root);
- free_cvsroot_t (ret);
- ret = NULL;
- goto out;
- }
-
-
- out:
- free (cvsadm);
- free (tmp);
- if (root != NULL)
- free (root);
- return ret;
-}
-
-
-
-/*
- * Write the CVS/Root file so that the environment variable CVSROOT
- * and/or the -d option to cvs will be validated or not necessary for
- * future work.
- */
-void
-Create_Root (dir, rootdir)
- const char *dir;
- const char *rootdir;
-{
- FILE *fout;
- char *tmp;
-
- if (noexec)
- return;
-
- /* record the current cvs root */
-
- if (rootdir != NULL)
- {
- if (dir != NULL)
- {
- tmp = xmalloc (strlen (dir) + sizeof (CVSADM_ROOT) + 10);
- (void) sprintf (tmp, "%s/%s", dir, CVSADM_ROOT);
- }
- else
- tmp = xstrdup (CVSADM_ROOT);
-
- fout = open_file (tmp, "w+");
- if (fprintf (fout, "%s\n", rootdir) < 0)
- error (1, errno, "write to %s failed", tmp);
- if (fclose (fout) == EOF)
- error (1, errno, "cannot close %s", tmp);
- free (tmp);
- }
-}
-
-#endif /* ! DEBUG */
-
-
-/* The root_allow_* stuff maintains a list of legal CVSROOT
- directories. Then we can check against them when a remote user
- hands us a CVSROOT directory. */
-
-static int root_allow_count;
-static char **root_allow_vector;
-static int root_allow_size;
-
-int
-root_allow_used ()
-{
- return root_allow_count;
-}
-
-void
-root_allow_add (arg)
- char *arg;
-{
- char *p;
-
- if (root_allow_size <= root_allow_count)
- {
- if (root_allow_size == 0)
- {
- root_allow_size = 1;
- root_allow_vector =
- (char **) xmalloc (root_allow_size * sizeof (char *));
- }
- else
- {
- root_allow_size *= 2;
- root_allow_vector =
- (char **) xrealloc (root_allow_vector,
- root_allow_size * sizeof (char *));
- }
-
- if (root_allow_vector == NULL)
- {
- no_memory:
- /* Strictly speaking, we're not supposed to output anything
- now. But we're about to exit(), give it a try. */
- printf ("E Fatal server error, aborting.\n\
-error ENOMEM Virtual memory exhausted.\n");
-
- error_exit ();
- }
- }
- p = xmalloc (strlen (arg) + 1);
- if (p == NULL)
- goto no_memory;
- strcpy (p, arg);
- root_allow_vector[root_allow_count++] = p;
-}
-
-void
-root_allow_free ()
-{
- if (root_allow_vector != NULL)
- free_names (&root_allow_count, root_allow_vector);
- root_allow_size = 0;
-}
-
-int
-root_allow_ok (arg)
- char *arg;
-{
- int i;
-
- if (root_allow_count == 0)
- {
- /* Probably someone upgraded from CVS before 1.9.10 to 1.9.10
- or later without reading the documentation about
- --allow-root. Printing an error here doesn't disclose any
- particularly useful information to an attacker because a
- CVS server configured in this way won't let *anyone* in. */
-
- /* Note that we are called from a context where we can spit
- back "error" rather than waiting for the next request which
- expects responses. */
- printf ("\
-error 0 Server configuration missing --allow-root in inetd.conf\n");
- error_exit ();
- }
-
- for (i = 0; i < root_allow_count; ++i)
- if (strcmp (root_allow_vector[i], arg) == 0)
- return 1;
- 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;
-
-
-
-/* FIXME - Deglobalize this. */
-cvsroot_t *current_parsed_root = NULL;
-
-
-
-/* allocate and initialize a cvsroot_t
- *
- * We must initialize the strings to NULL so we know later what we should
- * free
- *
- * Some of the other zeroes remain meaningful as, "never set, use default",
- * or the like
- */
-static cvsroot_t *
-new_cvsroot_t ()
-{
- cvsroot_t *newroot;
-
- /* gotta store it somewhere */
- newroot = xmalloc(sizeof(cvsroot_t));
-
- newroot->original = NULL;
- newroot->method = null_method;
- newroot->isremote = 0;
-#ifdef CLIENT_SUPPORT
- newroot->username = NULL;
- newroot->password = NULL;
- newroot->hostname = NULL;
- newroot->port = 0;
- newroot->directory = NULL;
- newroot->proxy_hostname = NULL;
- newroot->proxy_port = 0;
-#endif /* CLIENT_SUPPORT */
-
- return newroot;
-}
-
-
-
-/* Dispose of a cvsroot_t and its component parts */
-void
-free_cvsroot_t (root)
- cvsroot_t *root;
-{
- if (root->original != NULL)
- free (root->original);
- if (root->directory != NULL)
- free (root->directory);
-#ifdef CLIENT_SUPPORT
- if (root->username != NULL)
- free (root->username);
- if (root->password != NULL)
- {
- /* I like to be paranoid */
- memset (root->password, 0, strlen (root->password));
- free (root->password);
- }
- if (root->hostname != NULL)
- free (root->hostname);
- if (root->proxy_hostname != NULL)
- free (root->proxy_hostname);
-#endif /* CLIENT_SUPPORT */
- free (root);
-}
-
-
-
-/*
- * Parse a CVSROOT string to allocate and return a new cvsroot_t structure.
- * Valid specifications are:
- *
- * :(gserver|kserver|pserver):[[user][:password]@]host[:[port]]/path
- * [:(ext|server):][[user]@]host[:]/path
- * [:local:[e:]]/path
- * :fork:/path
- *
- * INPUTS
- * root_in C String containing the CVSROOT to be parsed.
- *
- * RETURNS
- * A pointer to a newly allocated cvsroot_t structure upon success and
- * NULL upon failure. The caller is responsible for disposing of
- * new structures with a call to free_cvsroot_t().
- *
- * NOTES
- * This would have been a lot easier to write in Perl.
- *
- * SEE ALSO
- * free_cvsroot_t()
- */
-cvsroot_t *
-parse_cvsroot (root_in)
- const char *root_in;
-{
- cvsroot_t *newroot; /* the new root to be returned */
- char *cvsroot_save; /* what we allocated so we can dispose
- * it when finished */
- char *firstslash; /* save where the path spec starts
- * while we parse
- * [[user][:password]@]host[:[port]]
- */
- char *cvsroot_copy, *p, *q; /* temporary pointers for parsing */
-#ifdef CLIENT_SUPPORT
- int check_hostname, no_port, no_password;
-#endif /* CLIENT_SUPPORT */
-
- assert (root_in);
-
- /* allocate some space */
- newroot = new_cvsroot_t();
-
- /* save the original string */
- newroot->original = xstrdup (root_in);
-
- /* and another copy we can munge while parsing */
- cvsroot_save = cvsroot_copy = xstrdup (root_in);
-
- if (*cvsroot_copy == ':')
- {
- char *method = ++cvsroot_copy;
-
- /* Access method specified, as in
- * "cvs -d :(gserver|kserver|pserver):[[user][:password]@]host[:[port]]/path",
- * "cvs -d [:(ext|server):][[user]@]host[:]/path",
- * "cvs -d :local:e:\path",
- * "cvs -d :fork:/path".
- * We need to get past that part of CVSroot before parsing the
- * rest of it.
- */
-
- if (! (p = strchr (method, ':')))
- {
- error (0, 0, "No closing `:' on method in CVSROOT.");
- goto error_exit;
- }
- *p = '\0';
- cvsroot_copy = ++p;
-
-#ifdef CLIENT_SUPPORT
- /* Look for method options, for instance, proxy, proxyport.
- * We don't handle these, but we like to try and warn the user that
- * they are being ignored.
- */
- if ((p = strchr (method, ';')) != NULL)
- {
- *p++ = '\0';
- if (!really_quiet)
- {
- error (0, 0,
-"WARNING: Ignoring method options found in CVSROOT: `%s'.",
- p);
- error (0, 0,
-"Use CVS version 1.12.7 or later to handle method options.");
- }
- }
-#endif /* CLIENT_SUPPORT */
-
- /* Now we have an access method -- see if it's valid. */
-
- if (strcmp (method, "local") == 0)
- newroot->method = local_method;
- else if (strcmp (method, "pserver") == 0)
- newroot->method = pserver_method;
- else if (strcmp (method, "kserver") == 0)
- newroot->method = kserver_method;
- else if (strcmp (method, "gserver") == 0)
- newroot->method = gserver_method;
- else if (strcmp (method, "server") == 0)
- newroot->method = server_method;
- else if (strcmp (method, "ext") == 0)
- newroot->method = ext_method;
- else if (strcmp (method, "extssh") == 0)
- newroot->method = extssh_method;
- else if (strcmp (method, "fork") == 0)
- newroot->method = fork_method;
- else
- {
- error (0, 0, "Unknown method (`%s') in CVSROOT.", method);
- goto error_exit;
- }
- }
- else
- {
- /* If the method isn't specified, assume EXT_METHOD if the string looks
- like a relative path and LOCAL_METHOD otherwise. */
-
- newroot->method = ((*cvsroot_copy != '/' && strchr (cvsroot_copy, '/'))
- ? ext_method
- : local_method);
- }
-
- newroot->isremote = (newroot->method != local_method);
-
- if ((newroot->method != local_method)
- && (newroot->method != fork_method))
- {
- /* split the string into [[user][:password]@]host[:[port]] & /path
- *
- * this will allow some characters such as '@' & ':' to remain unquoted
- * in the path portion of the spec
- */
- if ((p = strchr (cvsroot_copy, '/')) == NULL)
- {
- error (0, 0, "CVSROOT requires a path spec:");
- error (0, 0,
-":(gserver|kserver|pserver):[[user][:password]@]host[:[port]]/path");
- error (0, 0, "[:(ext|server):][[user]@]host[:]/path");
- goto error_exit;
- }
- firstslash = p; /* == NULL if '/' not in string */
- *p = '\0';
-
- /* Don't parse username, password, hostname, or port without client
- * support.
- */
-#ifdef CLIENT_SUPPORT
- /* Check to see if there is a username[:password] in the string. */
- if ((p = strchr (cvsroot_copy, '@')) != NULL)
- {
- *p = '\0';
- /* check for a password */
- if ((q = strchr (cvsroot_copy, ':')) != NULL)
- {
- *q = '\0';
- newroot->password = xstrdup (++q);
- /* Don't check for *newroot->password == '\0' since
- * a user could conceivably wish to specify a blank password
- *
- * (newroot->password == NULL means to use the
- * password from .cvspass)
- */
- }
-
- /* copy the username */
- if (*cvsroot_copy != '\0')
- /* a blank username is impossible, so leave it NULL in that
- * case so we know to use the default username
- */
- newroot->username = xstrdup (cvsroot_copy);
-
- cvsroot_copy = ++p;
- }
-
- /* now deal with host[:[port]] */
-
- /* the port */
- if ((p = strchr (cvsroot_copy, ':')) != NULL)
- {
- *p++ = '\0';
- if (strlen(p))
- {
- q = p;
- if (*q == '-') q++;
- while (*q)
- {
- if (!isdigit(*q++))
- {
- error (0, 0,
-"CVSROOT may only specify a positive, non-zero, integer port (not `%s').",
- p);
- error (0, 0,
- "Perhaps you entered a relative pathname?");
- goto error_exit;
- }
- }
- if ((newroot->port = atoi (p)) <= 0)
- {
- error (0, 0,
-"CVSROOT may only specify a positive, non-zero, integer port (not `%s').",
- p);
- error (0, 0, "Perhaps you entered a relative pathname?");
- goto error_exit;
- }
- }
- }
-
- /* copy host */
- if (*cvsroot_copy != '\0')
- /* blank hostnames are invalid, but for now leave the field NULL
- * and catch the error during the sanity checks later
- */
- newroot->hostname = xstrdup (cvsroot_copy);
-
- /* restore the '/' */
- cvsroot_copy = firstslash;
- *cvsroot_copy = '/';
-#endif /* CLIENT_SUPPORT */
- }
-
- /*
- * Parse the path for all methods.
- */
- /* Here & local_cvsroot() should be the only places this needs to be
- * called on a CVSROOT now. cvsroot->original is saved for error messages
- * and, otherwise, we want no trailing slashes.
- */
- Sanitize_Repository_Name( cvsroot_copy );
- newroot->directory = xstrdup(cvsroot_copy);
-
- /*
- * Do various sanity checks.
- */
-
-#if ! defined (CLIENT_SUPPORT) && ! defined (DEBUG)
- if (newroot->method != local_method)
- {
- error (0, 0, "CVSROOT is set for a remote access method but your");
- error (0, 0, "CVS executable doesn't support it.");
- goto error_exit;
- }
-#endif
-
-#if ! defined (SERVER_SUPPORT) && ! defined (DEBUG)
- if (newroot->method == fork_method)
- {
- error (0, 0, "CVSROOT is set to use the :fork: access method but your");
- error (0, 0, "CVS executable doesn't support it.");
- goto error_exit;
- }
-#endif
-
-#ifdef CLIENT_SUPPORT
- if (newroot->username && ! newroot->hostname)
- {
- error (0, 0, "Missing hostname in CVSROOT.");
- goto error_exit;
- }
-
- check_hostname = 0;
- no_password = 1;
- no_port = 0;
-#endif /* CLIENT_SUPPORT */
- switch (newroot->method)
- {
- case local_method:
-#ifdef CLIENT_SUPPORT
- if (newroot->username || newroot->hostname)
- {
- error (0, 0, "Can't specify hostname and username in CVSROOT");
- error (0, 0, "when using local access method.");
- goto error_exit;
- }
- no_port = 1;
- /* no_password already set */
-#endif /* CLIENT_SUPPORT */
- /* cvs.texinfo has always told people that CVSROOT must be an
- absolute pathname. Furthermore, attempts to use a relative
- pathname produced various errors (I couldn't get it to work),
- so there would seem to be little risk in making this a fatal
- error. */
- if (!isabsolute (newroot->directory))
- {
- error (0, 0, "CVSROOT must be an absolute pathname (not `%s')",
- newroot->directory);
- error (0, 0, "when using local access method.");
- goto error_exit;
- }
- break;
-#ifdef CLIENT_SUPPORT
- case fork_method:
- /* We want :fork: to behave the same as other remote access
- methods. Therefore, don't check to see that the repository
- name is absolute -- let the server do it. */
- if (newroot->username || newroot->hostname)
- {
- error (0, 0, "Can't specify hostname and username in CVSROOT");
- error (0, 0, "when using fork access method.");
- goto error_exit;
- }
- newroot->hostname = xstrdup("server"); /* for error messages */
- if (!isabsolute (newroot->directory))
- {
- error (0, 0, "CVSROOT must be an absolute pathname (not `%s')",
- newroot->directory);
- error (0, 0, "when using fork access method.");
- goto error_exit;
- }
- no_port = 1;
- /* no_password already set */
- break;
- case kserver_method:
-# ifndef HAVE_KERBEROS
- error (0, 0, "CVSROOT is set for a kerberos access method but your");
- error (0, 0, "CVS executable doesn't support it.");
- goto error_exit;
-# else
- check_hostname = 1;
- /* no_password already set */
- break;
-# endif
- case gserver_method:
-# ifndef HAVE_GSSAPI
- error (0, 0, "CVSROOT is set for a GSSAPI access method but your");
- error (0, 0, "CVS executable doesn't support it.");
- goto error_exit;
-# else
- check_hostname = 1;
- /* no_password already set */
- break;
-# endif
- case server_method:
- case ext_method:
- case extssh_method:
- no_port = 1;
- /* no_password already set */
- check_hostname = 1;
- break;
- case pserver_method:
- no_password = 0;
- check_hostname = 1;
- break;
-#endif /* CLIENT_SUPPORT */
- default:
- error (1, 0, "Invalid method found in parse_cvsroot");
- }
-
-#ifdef CLIENT_SUPPORT
- if (no_password && newroot->password)
- {
- error (0, 0, "CVSROOT password specification is only valid for");
- error (0, 0, "pserver connection method.");
- goto error_exit;
- }
-
- if (check_hostname && !newroot->hostname)
- {
- error (0, 0, "Didn't specify hostname in CVSROOT.");
- goto error_exit;
- }
-
- if (no_port && newroot->port)
- {
- error (0, 0, "CVSROOT port specification is only valid for gserver, kserver,");
- error (0, 0, "and pserver connection methods.");
- goto error_exit;
- }
-#endif /* CLIENT_SUPPORT */
-
- if (*newroot->directory == '\0')
- {
- error (0, 0, "Missing directory in CVSROOT.");
- goto error_exit;
- }
-
- /* Hooray! We finally parsed it! */
- free (cvsroot_save);
- return newroot;
-
-error_exit:
- free (cvsroot_save);
- free_cvsroot_t (newroot);
- return NULL;
-}
-
-
-
-#ifdef AUTH_CLIENT_SUPPORT
-/* Use root->username, root->hostname, root->port, and root->directory
- * to create a normalized CVSROOT fit for the .cvspass file
- *
- * username defaults to the result of getcaller()
- * port defaults to the result of get_cvs_port_number()
- *
- * FIXME - we could cache the canonicalized version of a root inside the
- * cvsroot_t, but we'd have to un'const the input here and stop expecting the
- * caller to be responsible for our return value
- */
-char *
-normalize_cvsroot (root)
- const cvsroot_t *root;
-{
- char *cvsroot_canonical;
- char *p, *hostname, *username;
- char port_s[64];
-
- assert (root && root->hostname && root->directory);
-
- /* get the appropriate port string */
- sprintf (port_s, "%d", get_cvs_port_number (root));
-
- /* use a lower case hostname since we know hostnames are case insensitive */
- /* Some logic says we should be tacking our domain name on too if it isn't
- * there already, but for now this works. Reverse->Forward lookups are
- * almost certainly too much since that would make CVS immune to some of
- * the DNS trickery that makes life easier for sysadmins when they want to
- * move a repository or the like
- */
- p = hostname = xstrdup(root->hostname);
- while (*p)
- {
- *p = tolower(*p);
- p++;
- }
-
- /* get the username string */
- username = root->username ? root->username : getcaller();
- cvsroot_canonical = xmalloc ( strlen(username)
- + strlen(hostname) + strlen(port_s)
- + strlen(root->directory) + 12);
- sprintf (cvsroot_canonical, ":pserver:%s@%s:%s%s",
- username, hostname, port_s, root->directory);
-
- free (hostname);
- return cvsroot_canonical;
-}
-#endif /* AUTH_CLIENT_SUPPORT */
-
-
-
-/* allocate and return a cvsroot_t structure set up as if we're using the local
- * repository DIR. */
-cvsroot_t *
-local_cvsroot (dir)
- const char *dir;
-{
- cvsroot_t *newroot = new_cvsroot_t();
-
- newroot->original = xstrdup(dir);
- newroot->method = local_method;
- newroot->directory = xstrdup(dir);
- /* Here and parse_cvsroot() should be the only places this needs to be
- * called on a CVSROOT now. cvsroot->original is saved for error messages
- * and, otherwise, we want no trailing slashes.
- */
- Sanitize_Repository_Name( newroot->directory );
- return newroot;
-}
-
-
-
-#ifdef DEBUG
-/* This is for testing the parsing function. Use
-
- gcc -I. -I.. -I../lib -DDEBUG root.c -o root
-
- to compile. */
-
-#include <stdio.h>
-
-char *program_name = "testing";
-char *cvs_cmd_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);
-}
-
-int
-isabsolute (dir)
- const char *dir;
-{
- return (dir && (*dir == '/'));
-}
-
-void
-main (argc, argv)
- int argc;
- char *argv[];
-{
- program_name = argv[0];
-
- if (argc != 2)
- {
- fprintf (stderr, "Usage: %s <CVSROOT>\n", program_name);
- exit (2);
- }
-
- if ((current_parsed_root = parse_cvsroot (argv[1])) == NULL)
- {
- fprintf (stderr, "%s: Parsing failed.\n", program_name);
- exit (1);
- }
- printf ("CVSroot: %s\n", argv[1]);
- printf ("current_parsed_root->method: %s\n", method_names[current_parsed_root->method]);
- printf ("current_parsed_root->username: %s\n",
- current_parsed_root->username ? current_parsed_root->username : "NULL");
- printf ("current_parsed_root->hostname: %s\n",
- current_parsed_root->hostname ? current_parsed_root->hostname : "NULL");
- printf ("current_parsed_root->directory: %s\n", current_parsed_root->directory);
-
- exit (0);
- /* NOTREACHED */
-}
-#endif
diff --git a/contrib/cvs/src/root.h b/contrib/cvs/src/root.h
deleted file mode 100644
index 089b69431e0d..000000000000
--- a/contrib/cvs/src/root.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS kit.
- */
-
-/* CVSroot data structures */
-
-/* Access method specified in CVSroot. */
-typedef enum {
- null_method,
- local_method,
- server_method,
- pserver_method,
- kserver_method,
- gserver_method,
- ext_method,
- extssh_method,
- fork_method
-} CVSmethod;
-extern const char method_names[][16]; /* change this in root.c if you change
- the enum above */
-
-typedef struct cvsroot_s {
- char *original; /* The complete source CVSroot string. */
- CVSmethod method; /* One of the enum values above. */
- char *directory; /* The directory name. */
- unsigned char isremote; /* Nonzero if we are doing remote access. */
-#ifdef CLIENT_SUPPORT
- char *username; /* The username or NULL if method == local. */
- char *password; /* The password or NULL if method == local. */
- char *hostname; /* The hostname or NULL if method == local. */
- int port; /* The port or zero if method == local. */
- char *proxy_hostname; /* The hostname of the proxy server, or NULL
- * when method == local or no proxy will be
- * used.
- */
- int proxy_port; /* The port of the proxy or zero, as above. */
-#endif /* CLIENT_SUPPORT */
-} cvsroot_t;
-
-cvsroot_t *Name_Root PROTO((const char *dir, const char *update_dir));
-void free_cvsroot_t PROTO((cvsroot_t *root_in));
-cvsroot_t *parse_cvsroot PROTO((const char *root));
-cvsroot_t *local_cvsroot PROTO((const char *dir));
-void Create_Root PROTO((const char *dir, const char *rootdir));
-void root_allow_add PROTO ((char *));
-void root_allow_free PROTO ((void));
-int root_allow_ok PROTO ((char *));
-int root_allow_used PROTO ((void));
diff --git a/contrib/cvs/src/run.c b/contrib/cvs/src/run.c
deleted file mode 100644
index 98ae911ce93f..000000000000
--- a/contrib/cvs/src/run.c
+++ /dev/null
@@ -1,578 +0,0 @@
-/* run.c --- routines for executing subprocesses.
-
- This file is part of GNU CVS.
-
- GNU CVS is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-#include "cvs.h"
-
-#ifndef HAVE_UNISTD_H
-extern int execvp PROTO((char *file, char **argv));
-#endif
-
-static void run_add_arg PROTO((const char *s));
-
-extern char *strtok ();
-
-/*
- * To exec a program under CVS, first call run_setup() to setup initial
- * arguments. The argument to run_setup will be parsed into whitespace
- * separated words and added to the global run_argv list.
- *
- * Then, optionally call run_arg() for each additional argument that you'd like
- * to pass to the executed program.
- *
- * Finally, call run_exec() to execute the program with the specified arguments.
- * The execvp() syscall will be used, so that the PATH is searched correctly.
- * File redirections can be performed in the call to run_exec().
- */
-static char **run_argv;
-static int run_argc;
-static size_t run_argc_allocated;
-
-
-
-void
-run_arg_free_p (int argc, char **argv)
-{
- int i;
- for (i = 0; i < argc; i++)
- free (argv[i]);
-}
-
-
-
-/* VARARGS */
-void
-run_setup (prog)
- const char *prog;
-{
- char *cp;
- char *run_prog;
-
- /* clean out any malloc'ed values from run_argv */
- run_arg_free_p (run_argc, run_argv);
- run_argc = 0;
-
- run_prog = xstrdup (prog);
-
- /* put each word into run_argv, allocating it as we go */
- for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t"))
- run_add_arg (cp);
- free (run_prog);
-}
-
-void
-run_arg (s)
- const char *s;
-{
- run_add_arg (s);
-}
-
-
-
-void
-run_add_arg_p (iargc, iarg_allocated, iargv, s)
- int *iargc;
- size_t *iarg_allocated;
- char ***iargv;
- const char *s;
-{
- /* allocate more argv entries if we've run out */
- if (*iargc >= *iarg_allocated)
- {
- *iarg_allocated += 50;
- *iargv = xrealloc (*iargv, *iarg_allocated * sizeof (char **));
- }
-
- if (s)
- (*iargv)[(*iargc)++] = xstrdup (s);
- else
- (*iargv)[*iargc] = NULL; /* not post-incremented on purpose! */
-}
-
-
-
-static void
-run_add_arg (s)
- const char *s;
-{
- run_add_arg_p (&run_argc, &run_argc_allocated, &run_argv, s);
-}
-
-
-
-int
-run_exec (stin, stout, sterr, flags)
- const char *stin;
- const char *stout;
- const char *sterr;
- int flags;
-{
- int shin, shout, sherr;
- int mode_out, mode_err;
- int status;
- int rc = -1;
- int rerrno = 0;
- int pid, w;
-
-#ifdef POSIX_SIGNALS
- sigset_t sigset_mask, sigset_omask;
- struct sigaction act, iact, qact;
-
-#else
-#ifdef BSD_SIGNALS
- int mask;
- struct sigvec vec, ivec, qvec;
-
-#else
- RETSIGTYPE (*istat) (), (*qstat) ();
-#endif
-#endif
-
- if (trace)
- {
-#ifdef SERVER_SUPPORT
- cvs_outerr (server_active ? "S" : " ", 1);
-#endif
- cvs_outerr ("-> system(", 0);
- run_print (stderr);
- cvs_outerr (")\n", 0);
- }
- if (noexec && (flags & RUN_REALLY) == 0)
- return 0;
-
- /* make sure that we are null terminated, since we didn't calloc */
- run_add_arg ((char *)0);
-
- /* setup default file descriptor numbers */
- shin = 0;
- shout = 1;
- sherr = 2;
-
- /* set the file modes for stdout and stderr */
- mode_out = mode_err = O_WRONLY | O_CREAT;
- mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC);
- mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC);
-
- if (stin && (shin = open (stin, O_RDONLY)) == -1)
- {
- rerrno = errno;
- error (0, errno, "cannot open %s for reading (prog %s)",
- stin, run_argv[0]);
- goto out0;
- }
- if (stout && (shout = open (stout, mode_out, 0666)) == -1)
- {
- rerrno = errno;
- error (0, errno, "cannot open %s for writing (prog %s)",
- stout, run_argv[0]);
- goto out1;
- }
- if (sterr && (flags & RUN_COMBINED) == 0)
- {
- if ((sherr = open (sterr, mode_err, 0666)) == -1)
- {
- rerrno = errno;
- error (0, errno, "cannot open %s for writing (prog %s)",
- sterr, run_argv[0]);
- goto out2;
- }
- }
-
- /* Make sure we don't flush this twice, once in the subprocess. */
- cvs_flushout();
- cvs_flusherr();
-
- /* The output files, if any, are now created. Do the fork and dups.
-
- 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
- pid = vfork ();
-#else
- pid = fork ();
-#endif
- if (pid == 0)
- {
- if (shin != 0)
- {
- (void) dup2 (shin, 0);
- (void) close (shin);
- }
- if (shout != 1)
- {
- (void) dup2 (shout, 1);
- (void) close (shout);
- }
- if (flags & RUN_COMBINED)
- (void) dup2 (1, 2);
- else if (sherr != 2)
- {
- (void) dup2 (sherr, 2);
- (void) close (sherr);
- }
-
-#ifdef SETXID_SUPPORT
- /*
- ** This prevents a user from creating a privileged shell
- ** from the text editor when the SETXID_SUPPORT option is selected.
- */
- if (!strcmp (run_argv[0], Editor) && setegid (getgid ()))
- {
- error (0, errno, "cannot set egid to gid");
- _exit (127);
- }
-#endif
-
- /* dup'ing is done. try to run it now */
- (void) execvp (run_argv[0], run_argv);
- error (0, errno, "cannot exec %s", run_argv[0]);
- _exit (127);
- }
- else if (pid == -1)
- {
- rerrno = errno;
- goto out;
- }
-
- /* the parent. Ignore some signals for now */
-#ifdef POSIX_SIGNALS
- if (flags & RUN_SIGIGNORE)
- {
- act.sa_handler = SIG_IGN;
- (void) sigemptyset (&act.sa_mask);
- act.sa_flags = 0;
- (void) sigaction (SIGINT, &act, &iact);
- (void) sigaction (SIGQUIT, &act, &qact);
- }
- else
- {
- (void) sigemptyset (&sigset_mask);
- (void) sigaddset (&sigset_mask, SIGINT);
- (void) sigaddset (&sigset_mask, SIGQUIT);
- (void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask);
- }
-#else
-#ifdef BSD_SIGNALS
- if (flags & RUN_SIGIGNORE)
- {
- memset ((char *)&vec, 0, sizeof (vec));
- vec.sv_handler = SIG_IGN;
- (void) sigvec (SIGINT, &vec, &ivec);
- (void) sigvec (SIGQUIT, &vec, &qvec);
- }
- else
- mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT));
-#else
- istat = signal (SIGINT, SIG_IGN);
- qstat = signal (SIGQUIT, SIG_IGN);
-#endif
-#endif
-
- /* wait for our process to die and munge return status */
-#ifdef POSIX_SIGNALS
- while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
- ;
-#else
- while ((w = wait (&status)) != pid)
- {
- if (w == -1 && errno != EINTR)
- break;
- }
-#endif
-
- if (w == -1)
- {
- rc = -1;
- rerrno = errno;
- }
-#ifndef VMS /* status is return status */
- else if (WIFEXITED (status))
- rc = WEXITSTATUS (status);
- else if (WIFSIGNALED (status))
- {
- if (WTERMSIG (status) == SIGPIPE)
- error (1, 0, "broken pipe");
- rc = 2;
- }
- else
- rc = 1;
-#else /* VMS */
- rc = WEXITSTATUS (status);
-#endif /* VMS */
-
- /* restore the signals */
-#ifdef POSIX_SIGNALS
- if (flags & RUN_SIGIGNORE)
- {
- (void) sigaction (SIGINT, &iact, (struct sigaction *)NULL);
- (void) sigaction (SIGQUIT, &qact, (struct sigaction *)NULL);
- }
- else
- (void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *)NULL);
-#else
-#ifdef BSD_SIGNALS
- if (flags & RUN_SIGIGNORE)
- {
- (void) sigvec (SIGINT, &ivec, (struct sigvec *)NULL);
- (void) sigvec (SIGQUIT, &qvec, (struct sigvec *)NULL);
- }
- else
- (void) sigsetmask (mask);
-#else
- (void) signal (SIGINT, istat);
- (void) signal (SIGQUIT, qstat);
-#endif
-#endif
-
- /* cleanup the open file descriptors */
- out:
- if (sterr)
- (void) close (sherr);
- else
- /* ensure things are received by the parent in the correct order
- * relative to the protocol pipe
- */
- cvs_flusherr();
- out2:
- if (stout)
- (void) close (shout);
- else
- /* ensure things are received by the parent in the correct order
- * relative to the protocol pipe
- */
- cvs_flushout();
- out1:
- if (stin)
- (void) close (shin);
-
- out0:
- if (rerrno)
- errno = rerrno;
- return rc;
-}
-
-
-
-void
-run_print (fp)
- FILE *fp;
-{
- int i;
- void (*outfn) PROTO ((const char *, size_t));
-
- if (fp == stderr)
- outfn = cvs_outerr;
- else if (fp == stdout)
- outfn = cvs_output;
- else
- {
- error (1, 0, "internal error: bad argument to run_print");
- /* Solely to placate gcc -Wall.
- FIXME: it'd be better to use a function named `fatal' that
- is known never to return. Then kludges wouldn't be necessary. */
- outfn = NULL;
- }
-
- for (i = 0; i < run_argc; i++)
- {
- (*outfn) ("'", 1);
- (*outfn) (run_argv[i], 0);
- (*outfn) ("'", 1);
- if (i != run_argc - 1)
- (*outfn) (" ", 1);
- }
-}
-
-/* Return value is NULL for error, or if noexec was set. If there was an
- error, return NULL and I'm not sure whether errno was set (the Red Hat
- Linux 4.1 popen manpage was kind of vague but discouraging; and the noexec
- case complicates this even aside from popen behavior). */
-
-FILE *
-run_popen (cmd, mode)
- const char *cmd;
- const char *mode;
-{
- if (trace)
- (void) fprintf (stderr, "%s-> run_popen(%s,%s)\n",
- CLIENT_SERVER_STR, cmd, mode);
- if (noexec)
- return (NULL);
-
- return (popen (cmd, mode));
-}
-
-
-
-/* Work around an OpenSSH problem: it can put its standard file
- descriptors into nonblocking mode, which will mess us up if we
- share file descriptions with it. The simplest workaround is
- to create an intervening process between OpenSSH and the
- actual stderr. */
-
-static void
-work_around_openssh_glitch (void)
-{
- pid_t pid;
- int stderr_pipe[2];
- struct stat sb;
-
- /* Do nothing unless stderr is a file that is affected by
- nonblocking mode. */
- if (!(fstat (STDERR_FILENO, &sb) == 0
- && (S_ISFIFO (sb.st_mode) || S_ISSOCK (sb.st_mode)
- || S_ISCHR (sb.st_mode) || S_ISBLK (sb.st_mode))))
- return;
-
- if (pipe (stderr_pipe) < 0)
- error (1, errno, "cannot create pipe");
- pid = fork ();
- if (pid < 0)
- error (1, errno, "cannot fork");
- if (pid != 0)
- {
- /* Still in child of original process. Act like "cat -u". */
- char buf[1 << 13];
- ssize_t inbytes;
- pid_t w;
- int status;
-
- if (close (stderr_pipe[1]) < 0)
- error (1, errno, "cannot close pipe");
-
- while ((inbytes = read (stderr_pipe[0], buf, sizeof buf)) != 0)
- {
- size_t outbytes = 0;
-
- if (inbytes < 0)
- {
- if (errno == EINTR)
- continue;
- error (1, errno, "reading from pipe");
- }
-
- do
- {
- ssize_t w = write (STDERR_FILENO,
- buf + outbytes, inbytes - outbytes);
- if (w < 0)
- {
- if (errno == EINTR)
- w = 0;
- if (w < 0)
- _exit (1);
- }
- outbytes += w;
- }
- while (inbytes != outbytes);
- }
-
- /* Done processing output from grandchild. Propagate
- its exit status back to the parent. */
- while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
- continue;
- if (w < 0)
- error (1, errno, "waiting for child");
- if (!WIFEXITED (status))
- {
- if (WIFSIGNALED (status))
- raise (WTERMSIG (status));
- error (1, errno, "child did not exit cleanly");
- }
- _exit (WEXITSTATUS (status));
- }
-
- /* Grandchild of original process. */
- if (close (stderr_pipe[0]) < 0)
- error (1, errno, "cannot close pipe");
-
- if (stderr_pipe[1] != STDERR_FILENO)
- {
- if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0)
- error (1, errno, "cannot dup2 pipe");
- if (close (stderr_pipe[1]) < 0)
- error (1, errno, "cannot close pipe");
- }
-}
-
-
-
-int
-piped_child (command, tofdp, fromfdp, fix_stderr)
- const char **command;
- int *tofdp;
- int *fromfdp;
- int fix_stderr;
-{
- int pid;
- int to_child_pipe[2];
- int from_child_pipe[2];
-
- if (pipe (to_child_pipe) < 0)
- error (1, errno, "cannot create pipe");
- if (pipe (from_child_pipe) < 0)
- error (1, errno, "cannot create pipe");
-
-#ifdef USE_SETMODE_BINARY
- setmode (to_child_pipe[0], O_BINARY);
- setmode (to_child_pipe[1], O_BINARY);
- setmode (from_child_pipe[0], O_BINARY);
- setmode (from_child_pipe[1], O_BINARY);
-#endif
-
- pid = fork ();
- if (pid < 0)
- error (1, errno, "cannot fork");
- if (pid == 0)
- {
- if (dup2 (to_child_pipe[0], STDIN_FILENO) < 0)
- error (1, errno, "cannot dup2 pipe");
- if (close (to_child_pipe[1]) < 0)
- error (1, errno, "cannot close pipe");
- if (close (from_child_pipe[0]) < 0)
- error (1, errno, "cannot close pipe");
- if (dup2 (from_child_pipe[1], STDOUT_FILENO) < 0)
- error (1, errno, "cannot dup2 pipe");
-
- if (fix_stderr)
- work_around_openssh_glitch ();
-
- /* Okay to cast out const below - execvp don't return nohow. */
- execvp ((char *)command[0], (char **)command);
- error (1, errno, "cannot exec %s", command[0]);
- }
- if (close (to_child_pipe[0]) < 0)
- error (1, errno, "cannot close pipe");
- if (close (from_child_pipe[1]) < 0)
- error (1, errno, "cannot close pipe");
-
- *tofdp = to_child_pipe[1];
- *fromfdp = from_child_pipe[0];
- return pid;
-}
-
-
-void
-close_on_exec (fd)
- int fd;
-{
-#ifdef F_SETFD
- if (fcntl (fd, F_SETFD, 1) == -1)
- error (1, errno, "can't set close-on-exec flag on %d", fd);
-#endif
-}
diff --git a/contrib/cvs/src/sanity.sh b/contrib/cvs/src/sanity.sh
deleted file mode 100755
index dbcae19759a5..000000000000
--- a/contrib/cvs/src/sanity.sh
+++ /dev/null
@@ -1,30254 +0,0 @@
-#! /bin/sh
-:
-# sanity.sh -- a growing testsuite for cvs.
-#
-# The copyright notice said: "Copyright (C) 1992, 1993 Cygnus Support"
-# I'm not adding new copyright notices for new years as our recent
-# practice has been to include copying terms without copyright notices.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# Original Author: K. Richard Pixley
-
-# usage:
-usage ()
-{
- echo "Usage: `basename $0` --help"
- echo "Usage: `basename $0` [-eklrv] [-f FROM-TEST] [-h HOSTNAME] CVS-TO-TEST [TESTS-TO-RUN...]"
-}
-
-exit_usage ()
-{
- usage 1>&2
- exit 2
-}
-
-exit_help ()
-{
- usage
- echo
- echo "-H|--help Display this text."
- echo "-e|--skipfail Treat tests that would otherwise be nonfatally skipped"
- echo " for reasons like missing tools as failures, exiting"
- echo " with an error message. Also treat warnings as"
- echo " failures."
- echo "-f FROM-TEST Run TESTS-TO-RUN, skipping all tests in the list before"
- echo " FROM-TEST."
- echo "-h HOSTNAME Use :ext:HOSTNAME to run remote tests rather than"
- echo " :fork:. Implies --remote and assumes that \$TESTDIR"
- echo " resolves to the same directory on both the client and"
- echo " the server."
- echo "-k|--keep Try to keep directories created by individual tests"
- echo " around, exiting after the first test which supports"
- echo " --keep."
- echo "-l|--link-root"
- echo " Test CVS using a symlink to a real CVSROOT."
- echo "-r|--remote Test remote instead of local cvs."
- echo "-v|--verbose List test names as they are executed."
- echo
- echo "CVS-TO-TEST The path to the CVS executable to be tested."
- echo "TESTS-TO-RUN The names of the tests to run (defaults to all tests)."
- exit 2
-}
-
-# See TODO list at end of file.
-
-# required to make this script work properly.
-unset CVSREAD
-
-# This will cause malloc to run slower but should also catch some common errors
-# when CVS is linked with glibc 2.x.
-MALLOC_CHECK_=2; export MALLOC_CHECK_
-
-# We want to invoke a predictable set of i18n behaviors, not whatever
-# the user running this script might have set.
-# In particular:
-# 'sort' and tabs and spaces (LC_COLLATE).
-# Messages from getopt (LC_MESSAGES) (in the future, CVS itself might
-# also alter its messages based on LC_MESSAGES).
-LANG=C
-export LANG
-LC_ALL=C
-export LC_ALL
-
-
-#
-# Initialize the test counts.
-#
-passed=0
-skipped=0
-warnings=0
-
-
-
-#
-# read our options
-#
-unset fromtest
-unset remotehost
-keep=false
-linkroot=false
-remote=false
-skipfail=false
-verbose=false
-while getopts ef:h:Hklrv-: option ; do
- # convert the long opts to short opts
- if test x$option = x-; then
- case "$OPTARG" in
- [hH]|[hH][eE]|[hH][eE][lL]|[hH][eE][lL][pP])
- option=H;
- OPTARG=
- ;;
- [kK]|[kK][eE]|[kK][eE][eE]|[kK][eE][eE][pP])
- option=k;
- OPTARG=
- ;;
- l|li|lin|link|link-|link-r]|link-ro|link-roo|link-root)
- option=l;
- OPTARG=
- ;;
- [rR]|[rR][eE]|[rR][eE][mM]|[rR][eE][mM][oO]|[rR][eE][mM][oO][tT]|[rR][eE][mM][oO][tT][eE])
- option=k;
- OPTARG=
- ;;
- s|sk|ski|skip|skipf|skipfa|skipfai|skipfail)
- option=e
- OPTARG=
- ;;
- v|ve|ver|verb|verbo|verbos|verbose)
- option=v
- OPTARG=
- ;;
- *)
- option=\?
- OPTARG=
- esac
- fi
- case "$option" in
- e)
- skipfail=:
- ;;
- f)
- fromtest="$OPTARG"
- ;;
- h)
- # Set a remotehost to run the remote tests on via :ext:
- # Implies `-r' and assumes that $TESTDIR resolves to the same
- # directory on the client and the server.
- remotehost="$OPTARG"
- remote=:
- ;;
- H)
- exit_help
- ;;
- k)
- # The -k (keep) option will eventually cause all the tests to
- # leave around the contents of the /tmp directory; right now only
- # some implement it. Not originally intended to be useful with
- # more than one test, but this should work if each test uses a
- # uniquely named dir (use the name of the test).
- keep=:
- ;;
- l)
- linkroot=:
- ;;
- r)
- remote=:
- ;;
- v)
- verbose=:
- ;;
- \?)
- exit_usage
- ;;
- esac
-done
-
-# boot the arguments we used above
-while test $OPTIND -gt 1 ; do
- shift
- OPTIND=`expr $OPTIND - 1`
-done
-
-# Use full path for CVS executable, so that CVS_SERVER gets set properly
-# for remote.
-case $1 in
-"")
- exit_usage
- ;;
-/*)
- testcvs=$1
- ;;
-*)
- testcvs=`pwd`/$1
- ;;
-esac
-shift
-
-# If $remotehost is set, warn if $TESTDIR isn't since we are pretty sure
-# that its default value of `/tmp/cvs-sanity' will not resolve to the same
-# directory on two different machines.
-if test -n "$remotehost" && test -z "$TESTDIR"; then
- echo "WARNING: CVS server hostname is set and \$TESTDIR is not. If" >&2
- echo "$remotehost is not the local machine, then it is unlikely that" >&2
- echo "the default value assigned to \$TESTDIR will resolve to the same" >&2
- echo "directory on both this client and the CVS server." >&2
-fi
-
-
-
-###
-### GUTS
-###
-
-# "debugger"
-#set -x
-
-echo 'This test should produce no other output than this message, and a final "OK".'
-echo '(Note that the test can take an hour or more to run and periodically stops'
-echo 'for as long as one minute. Do not assume there is a problem just because'
-echo 'nothing seems to happen for a long time. If you cannot live without'
-echo 'running status, use the -v option or try the command:'
-echo "\`tail -f check.log' from another window.)"
-
-# Regexp to match what CVS will call itself in output that it prints.
-# FIXME: we don't properly quote this--if the name contains . we'll
-# just spuriously match a few things; if the name contains other regexp
-# special characters we are probably in big trouble.
-PROG=`basename ${testcvs}`
-
-# Match the hostname
-hostname="[-_.a-zA-Z0-9]*"
-
-# Regexp to match the name of a temporary file (from cvs_temp_name).
-# This appears in certain diff output.
-tempname="[-a-zA-Z0-9/.%_]*"
-
-# Regexp to match a date in RFC822 format (as amended by RFC1123).
-RFCDATE="[a-zA-Z0-9 ][a-zA-Z0-9 ]* [0-9:][0-9:]* -0000"
-RFCDATE_EPOCH="1 Jan 1970 00:00:00 -0000"
-
-# Regexp to match a date in standard Unix format as used by rdiff
-# FIXCVS: There's no reason for rdiff to use a different date format
-# than diff does
-DATE="[a-zA-Z]* [a-zA-Z]* [ 1-3][0-9] [0-9:]* [0-9]*"
-
-# Which directories should Which and find_tool search for executables?
-SEARCHPATH=$PATH:/usr/local/bin:/usr/contrib/bin:/usr/contrib:/usr/gnu/bin:/local/bin:/local/gnu/bin:/gnu/bin:/sw/bin:/usr/pkg/bin
-
-# Do not assume that `type -p cmd` is portable
-# Usage: Which [-a] [-x|-f|-r] prog [$SEARCHPATH:/with/directories:/to/search]
-Which() {
- # Optional first argument for file type, defaults to -x.
- # Second argument is the file or directory to be found.
- # Third argument is the PATH to search.
- # By default, print only the first file that matches,
- # -a will cause all matches to be printed.
- notevery=:
- if [ "x$1" = "x-a" ]; then notevery=false; shift; fi
- case "$1" in
- -*) t=$1; shift ;;
- *) t=-x ;;
- esac
- case "$1" in
- # FIXME: Someday this may need to be fixed
- # to deal better with C:\some\path\to\ssh values...
- /*) test $t $1 && echo $1 ;;
- *) for d in `IFS=:; echo ${2-$SEARCHPATH}`
- do
- test $t $d/$1 && { echo $d/$1; if $notevery; then break; fi; }
- done
- ;;
- esac
-}
-
-
-# On cygwin32, we may not have /bin/sh.
-if test -r /bin/sh; then
- TESTSHELL="/bin/sh"
-else
- TESTSHELL=`Which -f sh`
- if test ! -r "$TESTSHELL"; then
- TESTSHELL="/bin/sh"
- fi
-fi
-
-# FIXME: try things (what things? checkins?) without -m.
-#
-# Some of these tests are written to expect -Q. But testing with
-# -Q is kind of bogus, it is not the way users actually use CVS (usually).
-# So new tests probably should invoke ${testcvs} directly, rather than ${CVS}.
-# and then they've obviously got to do something with the output....
-#
-CVS="${testcvs} -Q"
-
-LOGFILE=`pwd`/check.log
-
-# Save the previous log in case the person running the tests decides
-# they want to look at it. The extension ".plog" is chosen for consistency
-# with dejagnu.
-if test -f check.log; then
- mv check.log check.plog
-fi
-
-# Create the log file so check.log can be tailed almost immediately after
-# this script is started. Otherwise it can take up to a minute or two before
-# the log file gets created when $remotehost is specified on some systems,
-# which makes for a lot of failed `tail -f' attempts.
-touch check.log
-
-# Workaround any X11Forwarding by ssh. Otherwise this text:
-# Warning: No xauth data; using fake authentication data for X11 forwarding.
-# has been known to end up in the test results below
-# causing the test to fail.
-[ -n "$DISPLAY" ] && unset DISPLAY
-
-# The default value of /tmp/cvs-sanity for TESTDIR is dubious,
-# because it loses if two people/scripts try to run the tests
-# at the same time. Some possible solutions:
-# 1. Use /tmp/cvs-test$$. One disadvantage is that the old
-# cvs-test* directories would pile up, because they wouldn't
-# necessarily get removed.
-# 2. Have everyone/everything running the testsuite set
-# TESTDIR to some appropriate directory.
-# 3. Have the default value of TESTDIR be some variation of
-# `pwd`/cvs-sanity. The biggest problem here is that we have
-# been fairly careful to test that CVS prints in messages the
-# actual pathnames that we pass to it, rather than a different
-# pathname for the same directory, as may come out of `pwd`.
-# So this would be lost if everything was `pwd`-based. I suppose
-# if we wanted to get baroque we could start making symlinks
-# to ensure the two are different.
-: ${CVS_RSH=rsh}; export CVS_RSH
-if test -n "$remotehost"; then
- # We need to set $tmp on the server since $TMPDIR is compared against
- # messages generated by the server.
- tmp=`$CVS_RSH $remotehost 'cd /tmp; /bin/pwd || pwd' 2>/dev/null`
- if test $? != 0; then
- echo "$CVS_RSH $remotehost failed." >&2
- exit 1
- fi
-else
- tmp=`(cd /tmp; /bin/pwd || pwd) 2>/dev/null`
-fi
-
-# Now:
-# 1) Set TESTDIR if it's not set already
-# 2) Remove any old test remnants
-# 3) Create $TESTDIR
-# 4) Normalize TESTDIR with `cd && (/bin/pwd || pwd)`
-# (This will match CVS output later)
-: ${TESTDIR=$tmp/cvs-sanity}
-# clean any old remnants (we need the chmod because some tests make
-# directories read-only)
-if test -d ${TESTDIR}; then
- chmod -R a+wx ${TESTDIR}
- rm -rf ${TESTDIR}
-fi
-# These exits are important. The first time I tried this, if the `mkdir && cd`
-# failed then the build directory would get blown away. Some people probably
-# wouldn't appreciate that.
-mkdir ${TESTDIR} || exit 1
-cd ${TESTDIR} || exit 1
-# Ensure $TESTDIR is absolute
-if echo "${TESTDIR}" |grep '^[^/]'; then
- # Don't resolve this unless we have to. This keeps symlinks intact. This
- # is important at least when testing using -h $remotehost, because the same
- # value for $TESTDIR must resolve to the same directory on the client and
- # the server and we likely used Samba, and possibly symlinks, to do this.
- TESTDIR=`(/bin/pwd || pwd) 2>/dev/null`
-fi
-
-if test -z "${TESTDIR}" || echo "${TESTDIR}" |grep '^[^/]'; then
- echo "Unable to resolve TESTDIR to an absolute directory." >&2
- exit 1
-fi
-cd ${TESTDIR}
-
-# Now set $TMPDIR if the user hasn't overridden it.
-#
-# We use a $TMPDIR under $TESTDIR by default so that two tests may be run at
-# the same time without bumping heads without requiring the user to specify
-# more than $TESTDIR. See the test for leftover cvs-serv* directories near the
-# end of this script at the end of "The big loop".
-: ${TMPDIR=$TESTDIR/tmp}
-export TMPDIR
-if test -d $TMPDIR; then :; else
- mkdir $TMPDIR
-fi
-
-# Make sure various tools work the way we expect, or try to find
-# versions that do.
-: ${AWK=awk}
-: ${EXPR=expr}
-: ${ID=id}
-: ${TR=tr}
-
-# Keep track of tools that are found, but do NOT work as we hope
-# in order to avoid them in future
-badtools=
-set_bad_tool ()
-{
- badtools=$badtools:$1
-}
-is_bad_tool ()
-{
- case ":$badtools:" in *:$1:*) return 0 ;; *) return 1 ; esac
-}
-
-version_test ()
-{
- vercmd=$1
- verbad=:
- if RES=`$vercmd --version </dev/null 2>&1`; then
- if test "X$RES" != "X--version" && test "X$RES" != "X" ; then
- echo "$RES"
- verbad=false
- fi
- fi
- if $verbad; then
- echo "The command \`$vercmd' does not support the --version option."
- fi
- # It does not really matter that --version is not supported
- return 0
-}
-
-# Try to find a tool that satisfies all of the tests.
-# Usage: list:of:colon:separated:alternatives test1 test2 test3 test4...
-# Example: find_tool awk:gawk:nawk awk_tooltest1 awk_tooltest2
-find_tool ()
-{
- default_TOOL=$1
- echo find_tool: ${1+"$@"} >>$LOGFILE
- cmds="`IFS=:; echo $1`"; shift; tooltests="${1+$@}"
- if test -z "$tooltests"; then tooltests=version_test; fi
- clist=; for cmd in $cmds; do clist="$clist `Which -a $cmd`"; done
- # Make sure the default tool is just the first real command name
- for default_TOOL in $clist `IFS=:; echo $default_TOOL`; do break; done
- TOOL=""
- for trytool in $clist ; do
- pass=:
- for tooltest in $tooltests; do
- result=`eval $tooltest $trytool`
- rc=$?
- echo "Running $tooltest $trytool" >>$LOGFILE
- if test -n "$result"; then
- echo "$result" >>$LOGFILE
- fi
- if test "$rc" = "0"; then
- echo "PASS: $tooltest $trytool" >>$LOGFILE
- elif test "$rc" = "77"; then
- echo "MARGINAL: $tooltest $trytool; rc=$rc" >>$LOGFILE
- TOOL=$trytool
- pass=false
- else
- set_bad_tool $trytool
- echo "FAIL: $tooltest $trytool; rc=$rc" >>$LOGFILE
- pass=false
- fi
- done
- if $pass; then
- echo $trytool
- return 0
- fi
- done
- if test -n "$TOOL"; then
- echo "Notice: The default version of \`$default_TOOL' is defective." >>$LOGFILE
- echo "using \`$TOOL' and hoping for the best." >>$LOGFILE
- echo "Notice: The default version of \`$default_TOOL' is defective." >&2
- echo "using \`$TOOL' and hoping for the best." >&2
- echo $TOOL
- else
- echo $default_TOOL
- fi
-}
-
-id_tool_test ()
-{
- id=$1
- if $id -u >/dev/null 2>&1 && $id -un >/dev/null 2>&1; then
- return 0
- else
- echo "Running these tests requires an \`id' program that understands the"
- echo "-u and -n flags. Make sure that such an id (GNU, or many but not"
- echo "all vendor-supplied versions) is in your path."
- return 1
- fi
-}
-
-ID=`find_tool id version_test id_tool_test`
-echo "Using ID=$ID" >>$LOGFILE
-
-# You can't run CVS as root; print a nice error message here instead
-# of somewhere later, after making a mess.
-for pass in false :; do
- case "`$ID -u 2>/dev/null`" in
- "0")
- echo "Test suite does not work correctly when run as root" >&2
- exit 1
- ;;
-
- *)
- break
- ;;
- esac
-done
-
-# Cause NextStep 3.3 users to lose in a more graceful fashion.
-expr_tooltest1 ()
-{
-expr=$1
-if $expr 'abc
-def' : 'abc
-def' >/dev/null; then
- # good, it works
- return 0
-else
- echo 'Running these tests requires an "expr" program that can handle'
- echo 'multi-line patterns. Make sure that such an expr (GNU, or many but'
- echo 'not all vendor-supplied versions) is in your path.'
- return 1
-fi
-}
-
-# Warn SunOS, SysVr3.2, etc., users that they may be partially losing
-# if we can't find a GNU expr to ease their troubles...
-expr_tooltest2 ()
-{
-expr=$1
-if $expr 'a
-b' : 'a
-c' >/dev/null; then
- echo 'WARNING: you are using a version of expr that does not correctly'
- echo 'match multi-line patterns. Some tests may spuriously pass or fail.'
- echo 'You may wish to make sure GNU expr is in your path.'
- return 1
-else
- return 0
-fi
-}
-
-expr_create_bar ()
-{
-echo 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' >${TESTDIR}/foo
-cat ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo >${TESTDIR}/bar
-cat ${TESTDIR}/bar ${TESTDIR}/bar ${TESTDIR}/bar ${TESTDIR}/bar >${TESTDIR}/foo
-cat ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo ${TESTDIR}/foo >${TESTDIR}/bar
-rm -f ${TESTDIR}/foo
-}
-
-expr_tooltest3 ()
-{
-expr=$1
-# More SunOS lossage...
-test ! -f ${TESTDIR}/bar && expr_create_bar
-if $expr "`cat ${TESTDIR}/bar`" : "`cat ${TESTDIR}/bar`" >/dev/null; then
- : good, it works
-else
- echo 'WARNING: you are using a version of expr that does not correctly'
- echo 'match large patterns. Some tests may spuriously pass or fail.'
- echo 'You may wish to make sure GNU expr is in your path.'
- return 1
-fi
-if $expr "`cat ${TESTDIR}/bar`x" : "`cat ${TESTDIR}/bar`y" >/dev/null; then
- echo 'WARNING: you are using a version of expr that does not correctly'
- echo 'match large patterns. Some tests may spuriously pass or fail.'
- echo 'You may wish to make sure GNU expr is in your path.'
- return 1
-fi
-# good, it works
-return 0
-}
-
-# That we should have to do this is total bogosity, but GNU expr
-# version 1.9.4-1.12 uses the emacs definition of "$" instead of the unix
-# (e.g. SunOS 4.1.3 expr) one. Rumor has it this will be fixed in the
-# next release of GNU expr after 1.12 (but we still have to cater to the old
-# ones for some time because they are in many linux distributions).
-ENDANCHOR="$"
-expr_set_ENDANCHOR ()
-{
-expr=$1
-ENDANCHOR="$"
-if $expr 'abc
-def' : 'abc$' >/dev/null; then
- ENDANCHOR='\'\'
- echo "Notice: An ENDANCHOR of dollar does not work."
- echo "Using a workaround for GNU expr versions 1.9.4 thru 1.12"
-fi
-return 0
-}
-
-# Work around another GNU expr (version 1.10-1.12) bug/incompatibility.
-# "." doesn't appear to match a newline (it does with SunOS 4.1.3 expr).
-# Note that the workaround is not a complete equivalent of .* because
-# the first parenthesized expression in the regexp must match something
-# in order for expr to return a successful exit status.
-# Rumor has it this will be fixed in the
-# next release of GNU expr after 1.12 (but we still have to cater to the old
-# ones for some time because they are in many linux distributions).
-DOTSTAR='.*'
-expr_set_DOTSTAR ()
-{
-expr=$1
-DOTSTAR='.*'
-if $expr 'abc
-def' : "a${DOTSTAR}f" >/dev/null; then
- : good, it works
-else
- DOTSTAR='\(.\|
-\)*'
- echo "Notice: DOTSTAR changed from sane \`.*' value to \`$DOTSTAR\`"
- echo "to workaround GNU expr version 1.10 thru 1.12 bug where \`.'"
- echo "does not match a newline."
-fi
-return 0
-}
-
-# Now that we have DOTSTAR, make sure it works with big matches
-expr_tooltest_DOTSTAR ()
-{
-expr=$1
-test ! -f ${TESTDIR}/bar && expr_create_bar
-if $expr "`cat ${TESTDIR}/bar`" : "${DOTSTAR}xyzABC${DOTSTAR}$" >/dev/null; then
- # good, it works
- return 0
-else
- echo 'WARNING: you are using a version of expr that does not correctly'
- echo 'match large patterns. Some tests may spuriously pass or fail.'
- echo 'You may wish to make sure GNU expr is in your path.'
- return 77
-fi
-}
-
-# FreeBSD 5.2 and 6.1 support 'expr [-e] expression'
-# They get confused unless '--' is used before the expressions
-# when those expressions begin with a '-' character, such as the
-# output of an ls -l command. The EXPR_COMPAT environment variable may
-# be used to go back to the non-POSIX behavior as an alternative.
-# (GNU expr appears to accept the '--' argument and work correctly or
-# not have it and still get the results we want.)
-exprDASHDASH='false'
-expr_set_DASHDASH ()
-{
-expr=$1
-exprDASHDASH='false'
-# Not POSIX, but works on a lot of expr versions.
-if $expr "-rw-rw-r--" : "-rw-rw-r--" >/dev/null 2>&1; then
- # good, it works
- return 0
-else
- # Do things in the POSIX manner.
- if $expr -- "-rw-rw-r--" : "-rw-rw-r--" >/dev/null 2>&1; then
- exprDASHDASH=':'
- return 0
- else
- echo 'WARNING: Your $expr does not correctly handle'
- echo 'leading "-" characters in regular expressions to'
- echo 'be matched. You may wish to see if there is an'
- echo 'environment variable or other setting to allow'
- echo 'POSIX functionality to be enabled.'
- return 77
- fi
-fi
-}
-
-
-EXPR=`find_tool ${EXPR}:gexpr \
- version_test expr_tooltest1 expr_tooltest2 expr_tooltest3 \
-expr_set_ENDANCHOR expr_set_DOTSTAR expr_tooltest_DOTSTAR`
-
-# Set the ENDANCHOR and DOTSTAR for the chosen expr version.
-expr_set_ENDANCHOR ${EXPR} >/dev/null
-expr_tooltest_DOTSTAR ${EXPR} >/dev/null
-
-# Is $EXPR a POSIX or non-POSIX implementation
-# with regard to command-line arguments?
-expr_set_DASHDASH ${EXPR}
-$exprDASHDASH && EXPR="$EXPR --"
-
-echo "Using EXPR=$EXPR" >>$LOGFILE
-echo "Using ENDANCHOR=$ENDANCHOR" >>$LOGFILE
-echo "Using DOTSTAR=$DOTSTAR" >>$LOGFILE
-
-# Cleanup
-rm -f ${TESTDIR}/bar
-
-# Work around yet another GNU expr (version 1.10) bug/incompatibility.
-# "+" is a special character, yet for unix expr (e.g. SunOS 4.1.3)
-# it is not. I doubt that POSIX allows us to use \+ and assume it means
-# (non-special) +, so here is another workaround
-# Rumor has it this will be fixed in the
-# next release of GNU expr after 1.12 (but we still have to cater to the old
-# ones for some time because they are in many linux distributions).
-PLUS='+'
-if $EXPR 'a +b' : "a ${PLUS}b" >/dev/null; then
- : good, it works
-else
- PLUS='\+'
-fi
-
-# Likewise, for ?
-QUESTION='?'
-if $EXPR 'a?b' : "a${QUESTION}b" >/dev/null; then
- : good, it works
-else
- QUESTION='\?'
-fi
-
-# Now test the username to make sure it contains only valid characters
-username=`$ID -un`
-if $EXPR "${username}" : "${username}" >/dev/null; then
- : good, it works
-else
- echo "Test suite does not work correctly when run by a username" >&2
- echo "containing regular expression meta-characters." >&2
- exit 1
-fi
-
-# Only 8 characters of $username appear in some output.
-if test `echo $username |wc -c` -gt 8; then
- username8=`echo $username |sed 's/^\(........\).*/\1/'`
-else
- username8=$username
-fi
-
-# Rarely, we need to match any username, not just the name of the user
-# running this test.
-#
-# I'm not really sure what characters should be here. a-zA-Z obviously.
-# People complained when 0-9 were not allowed in usernames. Other than that
-# I'm not sure.
-anyusername="[-a-zA-Z0-9][-a-zA-Z0-9]*"
-
-# now make sure that tr works on NULs
-tr_tooltest1 ()
-{
-tr=$1
-if $EXPR `echo "123" | $tr '2' '\0'` : "123" >/dev/null 2>&1; then
- echo 'Warning: you are using a version of tr which does not correctly'
- echo 'handle NUL bytes. Some tests may spuriously pass or fail.'
- echo 'You may wish to make sure GNU tr is in your path.'
- return 77
-fi
-# good, it works
-return 0
-}
-
-TR=`find_tool ${TR}:gtr version_test tr_tooltest1`
-echo "Using TR=$TR" >>$LOGFILE
-
-# Awk testing
-
-awk_tooltest1 ()
-{
-awk=$1
-$awk 'BEGIN {printf("one\ntwo\nthree\nfour\nfive\nsix")}' </dev/null >abc
-if $EXPR "`cat abc`" : \
-'one
-two
-three
-four
-five
-six'; then
- rm abc
- return 0
-else
- rm abc
- echo "Notice: awk BEGIN clause or printf is not be working properly."
- return 1
-fi
-}
-
-# Format item %c check
-awk_tooltest2 ()
-{
-awk=$1
-$awk 'BEGIN { printf "%c%c%c", 2, 3, 4 }' </dev/null \
- | ${TR} '\002\003\004' '123' >abc
-if $EXPR "`cat abc`" : "123" ; then
- : good, found it
-else
- echo "Notice: awk format %c string may not be working properly."
- rm abc
- return 77
-fi
-rm abc
-return 0
-}
-
-AWK=`find_tool gawk:nawk:awk version_test awk_tooltest1 awk_tooltest2`
-echo "Using AWK=$AWK" >>$LOGFILE
-
-# Test that $1 works as a remote shell. If so, set $host, $CVS_RSH, &
-# $save_CVS_RSH to match and return 0. Otherwise, set $skipreason and return
-# 77.
-depends_on_rsh ()
-{
- host=${remotehost-"`hostname`"}
- result=`$1 $host 'echo test'`
- rc=$?
- if test $? != 0 || test "x$result" != "xtest"; then
- skipreason="\`$1 $host' failed rc=$rc result=$result"
- return 77
- fi
-
- save_CVS_RSH=$CVS_RSH
- CVS_RSH=$1; export CVS_RSH
- return 0
-}
-
-# Find a usable SSH. When a usable ssh is found, set $host, $CVS_RSH, and
-# $save_CVS_RSH and return 0. Otherwise, set $skipreason and return 77.
-depends_on_ssh ()
-{
- case "$CVS_RSH" in
- *ssh*|*putty*)
- tryssh=`Which $CVS_RSH`
- if [ ! -n "$tryssh" ]; then
- skipreason="Unable to find CVS_RSH=$CVS_RSH executable"
- return 77
- elif [ ! -x "$tryssh" ]; then
- skipreason="Unable to execute $tryssh program"
- return 77
- fi
- ;;
- *)
- # Look in the user's PATH for "ssh"
- tryssh=`Which ssh`
- if test ! -r "$tryssh"; then
- skipreason="Unable to find ssh program"
- return 77
- fi
- ;;
- esac
-
- depends_on_rsh "$tryssh"
- return $?
-}
-
-pass ()
-{
- echo "PASS: $1" >>${LOGFILE}
- passed=`expr $passed + 1`
-}
-
-# Like skip(), but don't fail when $skipfail is set.
-skip_always ()
-{
- echo "SKIP: $1${2+ ($2)}" >>$LOGFILE
- skipped=`expr $skipped + 1`
-}
-
-skip ()
-{
- if $skipfail; then
- fail "$1${2+ ($2)}"
- else
- echo "SKIP: $1${2+ ($2)}" >>$LOGFILE
- fi
- skipped=`expr $skipped + 1`
-}
-
-warn ()
-{
- if $skipfail; then
- fail "$1${2+ ($2)}"
- else
- echo "WARNING: $1${2+ ($2)}" >>$LOGFILE
- fi
- warnings=`expr $warnings + 1`
-}
-
-# Convenience function for skipping tests run only in local mode.
-localonly ()
-{
- skip_always $1 "only tested in local mode"
-}
-
-fail ()
-{
- echo "FAIL: $1" | tee -a ${LOGFILE}
- echo "*** Please see the \`TESTS' and \`check.log' files for more information." >&2
- # This way the tester can go and see what remnants were left
- exit 1
-}
-
-verify_tmp_empty ()
-{
- # Test our temp directory for cvs-serv* directories and cvsXXXXXX temp
- # files. We would like to not leave any behind.
- if $remote && ls $TMPDIR/cvs-serv* >/dev/null 2>&1; then
- # A true value means ls found files/directories with these names.
- # Give the server some time to finish, then retry.
- sleep 1
- if ls $TMPDIR/cvs-serv* >/dev/null 2>&1; then
- warn "$1" "Found cvs-serv* directories in $TMPDIR."
- # The above will exit if $skipfail
- rm -rf $TMPDIR/cvs-serv*
- fi
- fi
- if ls $TMPDIR/cvs?????? >/dev/null 2>&1; then
- # A true value means ls found files/directories with these names.
- warn "$1" "Found cvsXXXXXX temp files in $TMPDIR."
- # The above will exit if $skipfail
- rm -f ls $TMPDIR/cvs??????
- fi
-}
-
-# Restore changes to CVSROOT admin files.
-restore_adm ()
-{
- rm -rf $CVSROOT_DIRNAME/CVSROOT
- cp -Rp $TESTDIR/CVSROOT.save $CVSROOT_DIRNAME/CVSROOT
-}
-
-# See dotest and dotest_fail for explanation (this is the parts
-# of the implementation common to the two).
-dotest_internal ()
-{
- if $EXPR "`cat ${TESTDIR}/dotest.tmp`" : "$3${ENDANCHOR}" >/dev/null; then
- # Why, I hear you ask, do we write this to the logfile
- # even when the test passes? The reason is that the test
- # may give us the regexp which we were supposed to match,
- # but sometimes it may be useful to look at the exact
- # text which was output. For example, suppose one wants
- # to grep for a particular warning, and make _sure_ that
- # CVS never hits it (even in cases where the tests might
- # match it with .*). Or suppose one wants to see the exact
- # date format output in a certain case (where the test will
- # surely use a somewhat non-specific pattern).
- cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
- pass "$1"
- verify_tmp_empty "$1"
- # expr can't distinguish between "zero characters matched" and "no match",
- # so special-case it.
- elif test -z "$3" && test ! -s ${TESTDIR}/dotest.tmp; then
- pass "$1"
- verify_tmp_empty "$1"
- elif test x"$4" != x; then
- if $EXPR "`cat ${TESTDIR}/dotest.tmp`" : "$4${ENDANCHOR}" >/dev/null; then
- cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
- pass "$1"
- verify_tmp_empty "$1"
- else
- echo "** expected: " >>${LOGFILE}
- echo "$3" >>${LOGFILE}
- echo "$3" > ${TESTDIR}/dotest.ex1
- echo "** or: " >>${LOGFILE}
- echo "$4" >>${LOGFILE}
- echo "$4" > ${TESTDIR}/dotest.ex2
- echo "** got: " >>${LOGFILE}
- cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
- fail "$1"
- fi
- else
- echo "** expected: " >>${LOGFILE}
- echo "$3" >>${LOGFILE}
- echo "$3" > ${TESTDIR}/dotest.exp
- echo "** got: " >>${LOGFILE}
- cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
- fail "$1"
- fi
-}
-
-dotest_all_in_one ()
-{
- if $EXPR "`cat ${TESTDIR}/dotest.tmp`" : \
- "`cat ${TESTDIR}/dotest.exp`" >/dev/null; then
- return 0
- fi
- return 1
-}
-
-# WARNING: this won't work with REs that match newlines....
-#
-dotest_line_by_line ()
-{
- line=1
- while [ $line -le `wc -l <${TESTDIR}/dotest.tmp` ] ; do
- if $EXPR "`sed -n ${line}p ${TESTDIR}/dotest.tmp`" : \
- "`sed -n ${line}p ${TESTDIR}/dotest.exp`" >/dev/null; then
- :
- elif test -z "`sed -n ${line}p ${TESTDIR}/dotest.tmp`" &&
- test -z "`sed -n ${line}p ${TESTDIR}/dotest.exp`"; then
- :
- else
- echo "Line $line:" >> ${LOGFILE}
- echo "**** expected: " >>${LOGFILE}
- sed -n ${line}p ${TESTDIR}/dotest.exp >>${LOGFILE}
- echo "**** got: " >>${LOGFILE}
- sed -n ${line}p ${TESTDIR}/dotest.tmp >>${LOGFILE}
- unset line
- return 1
- fi
- line=`expr $line + 1`
- done
- unset line
- return 0
-}
-
-# If you are having trouble telling which line of a multi-line
-# expression is not being matched, replace calls to dotest_internal()
-# with calls to this function:
-#
-dotest_internal_debug ()
-{
- if test -z "$3"; then
- if test -s ${TESTDIR}/dotest.tmp; then
- echo "** expected: " >>${LOGFILE}
- echo "$3" >>${LOGFILE}
- echo "$3" > ${TESTDIR}/dotest.exp
- rm -f ${TESTDIR}/dotest.ex2
- echo "** got: " >>${LOGFILE}
- cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
- fail "$1"
- else
- pass "$1"
- verify_tmp_empty "$1"
- fi
- else
- echo "$3" > ${TESTDIR}/dotest.exp
- if dotest_line_by_line "$1" "$2"; then
- pass "$1"
- verify_tmp_empty "$1"
- else
- if test x"$4" != x; then
- mv ${TESTDIR}/dotest.exp ${TESTDIR}/dotest.ex1
- echo "$4" > ${TESTDIR}/dotest.exp
- if dotest_line_by_line "$1" "$2"; then
- pass "$1"
- verify_tmp_empty "$1"
- else
- mv ${TESTDIR}/dotest.exp ${TESTDIR}/dotest.ex2
- echo "** expected: " >>${LOGFILE}
- echo "$3" >>${LOGFILE}
- echo "** or: " >>${LOGFILE}
- echo "$4" >>${LOGFILE}
- echo "** got: " >>${LOGFILE}
- cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
- fail "$1"
- fi
- else
- echo "** expected: " >>${LOGFILE}
- echo "$3" >>${LOGFILE}
- echo "** got: " >>${LOGFILE}
- cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
- fail "$1"
- fi
- fi
- fi
-}
-
-# Usage:
-# dotest TESTNAME COMMAND OUTPUT [OUTPUT2]
-# TESTNAME is the name used in the log to identify the test.
-# COMMAND is the command to run; for the test to pass, it exits with
-# exitstatus zero.
-# OUTPUT is a regexp which is compared against the output (stdout and
-# stderr combined) from the test. It is anchored to the start and end
-# of the output, so should start or end with ".*" if that is what is desired.
-# Trailing newlines are stripped from the command's actual output before
-# matching against OUTPUT.
-# If OUTPUT2 is specified and the output matches it, then it is also
-# a pass (partial workaround for the fact that some versions of expr
-# lack \|).
-dotest ()
-{
- rm -f ${TESTDIR}/dotest.ex? 2>&1
- eval "$2" >${TESTDIR}/dotest.tmp 2>&1
- status=$?
- if test "$status" != 0; then
- cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
- echo "exit status was $status" >>${LOGFILE}
- fail "$1"
- fi
- dotest_internal "$@"
-}
-
-# Like dotest except only 2 args and result must exactly match stdin
-dotest_lit ()
-{
- rm -f ${TESTDIR}/dotest.ex? 2>&1
- eval "$2" >${TESTDIR}/dotest.tmp 2>&1
- status=$?
- if test "$status" != 0; then
- cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
- echo "exit status was $status" >>${LOGFILE}
- fail "$1"
- fi
- cat >${TESTDIR}/dotest.exp
- if cmp ${TESTDIR}/dotest.exp ${TESTDIR}/dotest.tmp >/dev/null 2>&1; then
- pass "$1"
- verify_tmp_empty "$1"
- else
- echo "** expected: " >>${LOGFILE}
- cat ${TESTDIR}/dotest.exp >>${LOGFILE}
- echo "** got: " >>${LOGFILE}
- cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
- fail "$1"
- fi
-}
-
-# Like dotest except exitstatus should be nonzero.
-dotest_fail ()
-{
- rm -f ${TESTDIR}/dotest.ex? 2>&1
- eval "$2" >${TESTDIR}/dotest.tmp 2>&1
- status=$?
- if test "$status" = 0; then
- cat ${TESTDIR}/dotest.tmp >>${LOGFILE}
- echo "exit status was $status" >>${LOGFILE}
- fail "$1"
- fi
- dotest_internal "$@"
-}
-
-# Like dotest except output is sorted.
-dotest_sort ()
-{
- rm -f ${TESTDIR}/dotest.ex? 2>&1
- eval "$2" >${TESTDIR}/dotest.tmp1 2>&1
- status=$?
- if test "$status" != 0; then
- cat ${TESTDIR}/dotest.tmp1 >>${LOGFILE}
- echo "exit status was $status" >>${LOGFILE}
- fail "$1"
- fi
- ${TR} ' ' ' ' < ${TESTDIR}/dotest.tmp1 | sort > ${TESTDIR}/dotest.tmp
- dotest_internal "$@"
-}
-
-# A function for fetching the timestamp of a revison of a file
-getrlogdate () {
- ${testcvs} -n rlog -N ${1+"$@"} |
- while read token value; do
- case "$token" in
- date:)
- echo $value | sed "s,;.*,,"
- break;
- ;;
- esac
- done
-}
-
-# Avoid picking up any stray .cvsrc, etc., from the user running the tests
-mkdir home
-HOME=${TESTDIR}/home; export HOME
-
-# Make sure this variable is not defined to anything that would
-# change the format of rcs dates. Otherwise people using e.g.,
-# RCSINIT=-zLT get lots of spurious failures.
-RCSINIT=; export RCSINIT
-
-# Remaining arguments are the names of tests to run.
-#
-# The testsuite is broken up into (hopefully manageably-sized)
-# independently runnable tests, so that one can quickly get a result
-# from a cvs or testsuite change, and to facilitate understanding the
-# tests.
-
-if test x"$*" = x; then
- # Basic/miscellaneous functionality
- tests="version basica basicb basicc basic1 deep basic2"
- tests="${tests} parseroot parseroot2 files spacefiles commit-readonly"
- tests="${tests} commit-add-missing"
- tests="$tests add-restricted"
- tests="${tests} status"
- # Branching, tagging, removing, adding, multiple directories
- tests="${tests} rdiff rdiff-short"
- tests="${tests} rdiff2 diff diffnl death death2 death-rtag"
- tests="${tests} rm-update-message rmadd rmadd2 rmadd3 resurrection"
- tests="${tests} dirs dirs2 branches branches2 tagc tagf "
- tests="${tests} tag-log tag-space"
- tests="${tests} rcslib multibranch import importb importc import-CVS"
- tests="$tests import-quirks"
- tests="${tests} update-p import-after-initial branch-after-import"
- tests="${tests} join join2 join3 join4 join5 join6 join7 join8 join9"
- tests="${tests} join-readonly-conflict join-admin join-admin-2"
- tests="${tests} join-rm"
- tests="${tests} new newb conflicts conflicts2 conflicts3 conflicts4"
- tests="${tests} clean"
- # Checking out various places (modules, checkout -d, &c)
- tests="${tests} modules modules2 modules3 modules4 modules5 modules6"
- tests="${tests} modules7 mkmodules co-d"
- tests="${tests} cvsadm emptydir abspath abspath2 toplevel toplevel2"
- tests="${tests} rstar-toplevel trailingslashes checkout_repository"
- # Log messages, error messages.
- tests="${tests} mflag editor errmsg1 errmsg2 adderrmsg opterrmsg"
- # Watches, binary files, history browsing, &c.
- tests="${tests} devcom devcom2 devcom3 watch4 watch5 watch6"
- tests="${tests} unedit-without-baserev"
- tests="${tests} ignore ignore-on-branch binfiles binfiles2 binfiles3"
- tests="${tests} mcopy binwrap binwrap2"
- tests="${tests} binwrap3 mwrap info taginfo config"
- tests="${tests} serverpatch log log2 logopt ann ann-id"
- # Repository Storage (RCS file format, CVS lock files, creating
- # a repository without "cvs init", &c).
- tests="${tests} crerepos crerepos-extssh rcs rcs2 rcs3 rcs4 rcs5 rcs6"
- tests="$tests lockfiles backuprecover"
- tests="${tests} sshstdio"
- # More history browsing, &c.
- tests="${tests} history"
- tests="${tests} big modes modes2 modes3 stamps"
- # PreservePermissions stuff: permissions, symlinks et al.
- # tests="${tests} perms symlinks symlinks2 hardlinks"
- # More tag and branch tests, keywords.
- tests="${tests} sticky keyword keywordlog keywordname keyword2"
- tests="${tests} head tagdate multibranch2 tag8k"
- # "cvs admin", reserved checkouts.
- tests="${tests} admin reserved"
- # Nuts and bolts of diffing/merging (diff library, &c)
- tests="${tests} diffmerge1 diffmerge2"
- # Release of multiple directories
- tests="${tests} release"
- tests="${tests} recase"
- # Multiple root directories and low-level protocol tests.
- tests="${tests} multiroot multiroot2 multiroot3 multiroot4"
- tests="$tests rmroot reposmv pserver server server2 server3"
- tests="$tests client client2"
- tests="${tests} dottedroot fork commit-d"
-else
- tests="$*"
-fi
-
-# Now check the -f argument for validity.
-if test -n "$fromtest"; then
- # Don't allow spaces - they are our delimiters in tests
- count=0
- for sub in $fromtest; do
- count=`expr $count + 1`
- done
- if test $count != 1; then
- echo "No such test \`$fromtest'." >&2
- exit 2
- fi
- # make sure it is in $tests
- case " $tests " in
- *" $fromtest "*)
- ;;
- *)
- echo "No such test \`$fromtest'." >&2
- exit 2
- ;;
- esac
-fi
-
-
-
-# a simple function to compare directory contents
-#
-# Returns: 0 for same, 1 for different
-#
-directory_cmp ()
-{
- OLDPWD=`pwd`
- DIR_1=$1
- DIR_2=$2
-
- cd $DIR_1
- find . -print | fgrep -v /CVS | sort > $TESTDIR/dc$$d1
-
- # go back where we were to avoid symlink hell...
- cd $OLDPWD
- cd $DIR_2
- find . -print | fgrep -v /CVS | sort > $TESTDIR/dc$$d2
-
- if diff $TESTDIR/dc$$d1 $TESTDIR/dc$$d2 >/dev/null 2>&1
- then
- :
- else
- return 1
- fi
- cd $OLDPWD
- while read a
- do
- if test -f $DIR_1/"$a" ; then
- cmp -s $DIR_1/"$a" $DIR_2/"$a"
- if test $? -ne 0 ; then
- return 1
- fi
- fi
- done < $TESTDIR/dc$$d1
- rm -f $TESTDIR/dc$$*
- return 0
-}
-
-
-
-#
-# The following 4 functions are used by the diffmerge1 test case. They set up,
-# respectively, the four versions of the files necessary:
-#
-# 1. Ancestor revisions.
-# 2. "Your" changes.
-# 3. "My" changes.
-# 4. Expected merge result.
-#
-
-# Create ancestor revisions for diffmerge1
-diffmerge_create_older_files() {
- # This test case was supplied by Noah Friedman:
- cat >testcase01 <<EOF
-// Button.java
-
-package random.application;
-
-import random.util.*;
-
-public class Button
-{
- /* Instantiates a Button with origin (0, 0) and zero width and height.
- * You must call an initializer method to properly initialize the Button.
- */
- public Button ()
- {
- super ();
-
- _titleColor = Color.black;
- _disabledTitleColor = Color.gray;
- _titleFont = Font.defaultFont ();
- }
-
- /* Convenience constructor for instantiating a Button with
- * bounds x, y, width, and height. Equivalent to
- * foo = new Button ();
- * foo.init (x, y, width, height);
- */
- public Button (int x, int y, int width, int height)
- {
- this ();
- init (x, y, width, height);
- }
-}
-EOF
-
- # This test case was supplied by Jacob Burckhardt:
- cat >testcase02 <<EOF
-a
-a
-a
-a
-a
-EOF
-
- # This test case was supplied by Karl Tomlinson who also wrote the
- # patch which lets CVS correctly handle this and several other cases:
- cat >testcase03 <<EOF
-x
-s
-a
-b
-s
-y
-EOF
-
- # This test case was supplied by Karl Tomlinson:
- cat >testcase04 <<EOF
-s
-x
-m
-m
-x
-s
-v
-s
-x
-m
-m
-x
-s
-EOF
-
- # This test case was supplied by Karl Tomlinson:
- cat >testcase05 <<EOF
-s
-x
-m
-m
-x
-x
-x
-x
-x
-x
-x
-x
-x
-x
-s
-s
-s
-s
-s
-s
-s
-s
-s
-s
-v
-EOF
-
- # This test case was supplied by Jacob Burckhardt:
- cat >testcase06 <<EOF
-g
-
-
-
-
-
-
-
-
-
-
-
-i
-EOF
-
- # This test is supposed to verify that the horizon lines are the same
- # for both 2-way diffs, but unfortunately, it does not fail with the
- # old version of cvs. However, Karl Tomlinson still thought it would
- # be good to test it anyway:
- cat >testcase07 <<EOF
-h
-f
-
-
-
-
-
-
-
-
-
-g
-r
-
-
-
-i
-
-
-
-
-
-
-
-
-
-
-i
-EOF
-
- # This test case was supplied by Jacob Burckhardt:
- cat >testcase08 <<EOF
-Both changes move this line to the end of the file.
-
-no
-changes
-here
-
-First change will delete this line.
-
-First change will also delete this line.
-
- no
- changes
- here
-
-Second change will change it here.
-
- no
- changes
- here
-EOF
-
- # This test case was supplied by Jacob Burckhardt. Note that I do not
- # think cvs has ever failed with this case, but I include it anyway,
- # since I think it is a hard case. It is hard because Peter Miller's
- # fmerge utility fails on it:
- cat >testcase09 <<EOF
-m
-a
-{
-}
-b
-{
-}
-EOF
-
- # This test case was supplied by Martin Dorey and simplified by Jacob
- # Burckhardt:
- cat >testcase10 <<EOF
-
- petRpY ( MtatRk );
- fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
-
- MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
- OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
-
- Bloke_GttpfIRte_MtpeaL ( &acI );
-MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
-{
- fV ( Y < 16 )
- {
- petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
- Y * jfle_Uecopd_MfJe_fY_Mectopk,
- jfle_Uecopd_MfJe_fY_Mectopk,
- nRVVep ) );
- }
- elke
- {
- petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
- ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
- jfle_Uecopd_MfJe_fY_Mectopk,
- nRVVep ) );
- }
-
-}
-
-
-/****************************************************************************
-* *
-* Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY ) *
-* *
-****************************************************************************/
-
-MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
-{
-MTGTXM MtatRk = Zy;
-
- MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
-
- petRpY ( MtatRk );
-
-}
- HfkQipfte ( waYdle, /* waYdle */
- waYdleFok, /* ZVVket VpoL ktapt oV dfkQ */
- (coYkt RfYt8*) nRVVep, /* nRVVep */
- 0, /* MRrepVlRoRk KfxoYfkL */
- beYgtz /* nEtek to Apfte */
- );
-
- petRpY ( Zy );
-}
-EOF
-}
-
-# Create "your" revisions for diffmerge1
-diffmerge_create_your_files() {
- # remove the Button() method
- cat >testcase01 <<\EOF
-// Button.java
-
-package random.application;
-
-import random.util.*;
-
-public class Button
-{
- /* Instantiates a Button with origin (0, 0) and zero width and height.
- * You must call an initializer method to properly initialize the Button.
- */
- public Button ()
- {
- super ();
-
- _titleColor = Color.black;
- _disabledTitleColor = Color.gray;
- _titleFont = Font.defaultFont ();
- }
-}
-EOF
-
- cat >testcase02 <<\EOF
-y
-a
-a
-a
-a
-EOF
-
- cat >testcase03 <<\EOF
-x
-s
-a
-b
-s
-b
-s
-y
-EOF
-
- cat >testcase04 <<\EOF
-s
-m
-s
-v
-s
-m
-s
-EOF
-
- cat >testcase05 <<\EOF
-v
-s
-m
-s
-s
-s
-s
-s
-s
-s
-s
-s
-s
-v
-EOF
-
- # Test case 6 and test case 7 both use the same input files, but they
- # order the input files differently. In one case, a certain file is
- # used as the older file, but in the other test case, that same file
- # is used as the file which has changes. I could have put echo
- # commands here, but since the echo lines would be the same as those
- # in the previous function, I decided to save space and avoid repeating
- # several lines of code. Instead, I merely swap the files:
- mv testcase07 tmp
- mv testcase06 testcase07
- mv tmp testcase06
-
- # Make the date newer so that cvs thinks that the files are changed:
- touch testcase06 testcase07
-
- cat >testcase08 <<\EOF
-no
-changes
-here
-
-First change has now added this in.
-
- no
- changes
- here
-
-Second change will change it here.
-
- no
- changes
- here
-
-Both changes move this line to the end of the file.
-EOF
-
- cat >testcase09 <<\EOF
-
-m
-a
-{
-}
-b
-{
-}
-c
-{
-}
-EOF
-
- cat >testcase10 <<\EOF
-
- fV ( BzQkV_URYYfYg ) (*jfle_Uecopdk)[0].jfle_Uecopd_KRLIep = ZpfgfYal_jUK;
-
- petRpY ( MtatRk );
- fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
-
- fV ( jfle_Uecopd_KRLIep < 16 )
- {
- MtatRk = Uead_Ktz_qjT_jfle_Uecopd ( jfle_Uecopd_KRLIep, (uofd*)nRVVep );
- }
- elke
- {
- MtatRk = ZreY_GttpfIRte_MtpeaL ( qjT_jfle_Uecopdk, qjT_jfle_Uecopd_BoRYt, HGTG_TvFD, KXbb, KXbb, &acI );
- fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
-
- MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
- OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
-
- Bloke_GttpfIRte_MtpeaL ( &acI );
-MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
-{
-MTGTXM MtatRk = Zy;
-
- fV ( Y < 16 )
- {
- petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
- Y * jfle_Uecopd_MfJe_fY_Mectopk,
- jfle_Uecopd_MfJe_fY_Mectopk,
- nRVVep ) );
- }
- elke
- {
- petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
- ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
- jfle_Uecopd_MfJe_fY_Mectopk,
- nRVVep ) );
- }
-
- petRpY ( MtatRk );
-
-}
-
-
-/****************************************************************************
-* *
-* Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY ) *
-* *
-****************************************************************************/
-
-MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
-{
-MTGTXM MtatRk = Zy;
-
- MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
-
- petRpY ( MtatRk );
-
-}
- HfkQipfte ( waYdle, /* waYdle */
- waYdleFok, /* ZVVket VpoL ktapt oV dfkQ */
- (coYkt RfYt8*) nRVVep, /* nRVVep */
- 0, /* MRrepVlRoRk KfxoYfkL */
- beYgtz /* nEtek to Apfte */
- );
-
- petRpY ( Zy );
-}
-
-EOF
-}
-
-# Create "my" revisions for diffmerge1
-diffmerge_create_my_files() {
- # My working copy still has the Button() method, but I
- # comment out some code at the top of the class.
- cat >testcase01 <<\EOF
-// Button.java
-
-package random.application;
-
-import random.util.*;
-
-public class Button
-{
- /* Instantiates a Button with origin (0, 0) and zero width and height.
- * You must call an initializer method to properly initialize the Button.
- */
- public Button ()
- {
- super ();
-
- // _titleColor = Color.black;
- // _disabledTitleColor = Color.gray;
- // _titleFont = Font.defaultFont ();
- }
-
- /* Convenience constructor for instantiating a Button with
- * bounds x, y, width, and height. Equivalent to
- * foo = new Button ();
- * foo.init (x, y, width, height);
- */
- public Button (int x, int y, int width, int height)
- {
- this ();
- init (x, y, width, height);
- }
-}
-EOF
-
- cat >testcase02 <<\EOF
-a
-a
-a
-a
-m
-EOF
-
- cat >testcase03 <<\EOF
-x
-s
-c
-s
-b
-s
-y
-EOF
-
- cat >testcase04 <<\EOF
-v
-s
-x
-m
-m
-x
-s
-v
-s
-x
-m
-m
-x
-s
-v
-EOF
-
- # Note that in test case 5, there are no changes in the "mine"
- # section, which explains why there is no command here which writes to
- # file testcase05.
-
- # no changes for testcase06
-
- # The two branches make the same changes:
- cp ../yours/testcase07 .
-
- cat >testcase08 <<\EOF
-no
-changes
-here
-
-First change will delete this line.
-
-First change will also delete this line.
-
- no
- changes
- here
-
-Second change has now changed it here.
-
- no
- changes
- here
-
-Both changes move this line to the end of the file.
-EOF
-
- cat >testcase09 <<\EOF
-m
-a
-{
-}
-b
-{
-}
-c
-{
-}
-EOF
-
- cat >testcase10 <<\EOF
-
- petRpY ( MtatRk );
- fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
-
- MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
- OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
-
- Bloke_GttpfIRte_MtpeaL ( &acI );
-MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
-{
- fV ( Y < 16 )
- {
- petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
- Y * jfle_Uecopd_MfJe_fY_Mectopk,
- jfle_Uecopd_MfJe_fY_Mectopk,
- nRVVep ) );
- }
- elke
- {
- petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
- ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
- jfle_Uecopd_MfJe_fY_Mectopk,
- nRVVep ) );
- }
-
-}
-
-
-/****************************************************************************
-* *
-* Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY ) *
-* *
-****************************************************************************/
-
-MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
-{
-MTGTXM MtatRk = Zy;
-
- MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
-
- petRpY ( MtatRk );
-
-}
- HfkQipfte ( waYdle, /* waYdle */
- waYdleFok, /* ZVVket VpoL ktapt oV dfkQ */
- (coYkt RfYt8*) nRVVep, /* nRVVep */
- beYgtz /* nEtek to Apfte */
- );
-
- petRpY ( Zy );
-}
-
-EOF
-}
-
-# Create expected results of merge for diffmerge1
-diffmerge_create_expected_files() {
- cat >testcase01 <<\EOF
-// Button.java
-
-package random.application;
-
-import random.util.*;
-
-public class Button
-{
- /* Instantiates a Button with origin (0, 0) and zero width and height.
- * You must call an initializer method to properly initialize the Button.
- */
- public Button ()
- {
- super ();
-
- // _titleColor = Color.black;
- // _disabledTitleColor = Color.gray;
- // _titleFont = Font.defaultFont ();
- }
-}
-EOF
-
- cat >testcase02 <<\EOF
-y
-a
-a
-a
-m
-EOF
-
- cat >testcase03 <<\EOF
-x
-s
-c
-s
-b
-s
-b
-s
-y
-EOF
-
- cat >testcase04 <<\EOF
-v
-s
-m
-s
-v
-s
-m
-s
-v
-EOF
-
- # Since there are no changes in the "mine" section, just take exactly
- # the version in the "yours" section:
- cp ../yours/testcase05 .
-
- cp ../yours/testcase06 .
-
- # Since the two branches make the same changes, the result should be
- # the same as both branches. Here, I happen to pick yours to copy from,
- # but I could have also picked mine, since the source of the copy is
- # the same in either case. However, the mine has already been
- # altered by the update command, so don't use it. Instead, use the
- # yours section which has not had an update on it and so is unchanged:
- cp ../yours/testcase07 .
-
- cat >testcase08 <<\EOF
-no
-changes
-here
-
-First change has now added this in.
-
- no
- changes
- here
-
-Second change has now changed it here.
-
- no
- changes
- here
-
-Both changes move this line to the end of the file.
-EOF
-
- cat >testcase09 <<\EOF
-
-m
-a
-{
-}
-b
-{
-}
-c
-{
-}
-EOF
-
- cat >testcase10 <<\EOF
-
- fV ( BzQkV_URYYfYg ) (*jfle_Uecopdk)[0].jfle_Uecopd_KRLIep = ZpfgfYal_jUK;
-
- petRpY ( MtatRk );
- fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
-
- fV ( jfle_Uecopd_KRLIep < 16 )
- {
- MtatRk = Uead_Ktz_qjT_jfle_Uecopd ( jfle_Uecopd_KRLIep, (uofd*)nRVVep );
- }
- elke
- {
- MtatRk = ZreY_GttpfIRte_MtpeaL ( qjT_jfle_Uecopdk, qjT_jfle_Uecopd_BoRYt, HGTG_TvFD, KXbb, KXbb, &acI );
- fV ( MtatRk != Zy ) UDTXUK_DUUZU ( BGKT_ZFDK_qjT_HGTG );
-
- MtatRk = MQfr_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_KRLIep * jfle_Uecopd_MfJe_fY_nEtek );
- OjZy MtatRk = Uead_GttpfIRte_MtpeaL ( &acI, jfle_Uecopd_MfJe_fY_nEtek, nRVVep );
-
- Bloke_GttpfIRte_MtpeaL ( &acI );
-MTGTXM Uead_Ktz_qjT_jfle_Uecopd ( fYt Y, uofd *nRVVep )
-{
-MTGTXM MtatRk = Zy;
-
- fV ( Y < 16 )
- {
- petRpY ( Uead_Mectopk ( noot_Uecopd.qVtHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
- Y * jfle_Uecopd_MfJe_fY_Mectopk,
- jfle_Uecopd_MfJe_fY_Mectopk,
- nRVVep ) );
- }
- elke
- {
- petRpY ( Uead_Mectopk ( noot_Uecopd.qVtqfppHatabcY0 * noot_Uecopd.MectopkFepBlRktep +
- ( Y - 16 ) * jfle_Uecopd_MfJe_fY_Mectopk,
- jfle_Uecopd_MfJe_fY_Mectopk,
- nRVVep ) );
- }
-
- petRpY ( MtatRk );
-
-}
-
-
-/****************************************************************************
-* *
-* Uead Mectopk ( Uelatfue to tze cRppeYt raptftfoY ) *
-* *
-****************************************************************************/
-
-MTGTXM Uead_Mectopk ( RfYt64 Mtapt_Mectop, RfYt64 KRL_Mectopk, uofd *nRVVep )
-{
-MTGTXM MtatRk = Zy;
-
- MtatRk = Uead_HfkQ ( FaptftfoY_TaIle.Uelatfue_Mectop + Mtapt_Mectop, KRL_Mectopk, nRVVep );
-
- petRpY ( MtatRk );
-
-}
- HfkQipfte ( waYdle, /* waYdle */
- waYdleFok, /* ZVVket VpoL ktapt oV dfkQ */
- (coYkt RfYt8*) nRVVep, /* nRVVep */
- beYgtz /* nEtek to Apfte */
- );
-
- petRpY ( Zy );
-}
-
-EOF
-}
-
-
-
-# Echo a new CVSROOT based on $1, $remote, and $remotehost
-newroot() {
- if $remote; then
- if test -n "$remotehost"; then
- echo :ext:$remotehost$1
- else
- echo :fork:$1
- fi
- else
- echo $1
- fi
-}
-
-
-
-# Set up CVSROOT (the crerepos tests will test operating without CVSROOT set).
-#
-# Currently we test :fork: and :ext: (see crerepos test). There is a
-# known difference between the two in modes-15 (see comments there).
-#
-# :ext: can be tested against a remote machine if:
-#
-# 1. $remotehost is set using the `-h' option to this script.
-# 2. ${CVS_RSH=rsh} $remotehost works.
-# 3. The path to $TESTDIR is the same on both machines (symlinks are okay)
-# 4. The path to $testcvs is the same on both machines (symlinks are okay)
-# or $CVS_SERVER is overridden in this script's environment to point to
-# a working CVS exectuable on the remote machine.
-#
-# Testing :pserver: would be hard (inetd issues). (How about using tcpserver
-# and some high port number? DRP)
-
-# Allow CVS_SERVER to be overridden. This facilitates constructs like
-# testing a local case-insensitive client against a remote case
-# sensitive server and visa versa.
-: ${CVS_SERVER=$testcvs}; export CVS_SERVER
-
-# Use a name which will be different than CVSROOT on case insensitive
-# filesystems (e.g., HFS+)
-CVSROOTDIR=cvsrootdir
-if $linkroot; then
- mkdir ${TESTDIR}/realcvsroot
- ln -s realcvsroot ${TESTDIR}/${CVSROOTDIR}
-fi
-CVSROOT_DIRNAME=${TESTDIR}/${CVSROOTDIR}
-CVSROOT=`newroot $CVSROOT_DIRNAME`; export CVSROOT
-
-
-
-###
-### Init the repository.
-###
-dotest init-1 "$testcvs -d$CVSROOT_DIRNAME init"
-
-# Copy the admin files for restore_adm.
-cp -Rp $CVSROOT_DIRNAME/CVSROOT $TESTDIR/CVSROOT.save
-
-
-
-###
-### The tests
-###
-if $remote; then
- localonly init-2
- localonly init-3
-else
- dotest init-2 "$testcvs init"
- dotest_fail init-3 "$testcvs -d $CVSROOT/sdir init" \
-"$PROG \[init aborted\]: Cannot initialize repository under existing CVSROOT: \`$CVSROOT_DIRNAME'"
-fi
-
-
-
-### The big loop
-for what in $tests; do
- if test -n "$fromtest" ; then
- if test $fromtest = $what ; then
- unset fromtest
- else
- continue
- fi
- fi
-
- if $verbose; then
- echo "$what:"
- fi
-
- case $what in
-
- version)
- # We've had cases where the version command started dumping core,
- # so we might as well test it
- dotest version-1 "${testcvs} --version" \
-'
-Concurrent Versions System (CVS) [0-9.]*.*
-
-Copyright (C) [0-9]* Free Software Foundation, Inc.
-
-Senior active maintainers include Larry Jones, Derek R. Price,
-and Mark D. Baushke. Please see the AUTHORS and README files from the CVS
-distribution kit for a complete list of contributors and copyrights.
-
-CVS may be copied only under the terms of the GNU General Public License,
-a copy of which can be found with the CVS distribution kit.
-
-Specify the --help option for further information about CVS'
-
- if $remote; then
- dotest version-2r "${testcvs} version" \
-'Client: Concurrent Versions System (CVS) [0-9p.]* (client/server)
-Server: Concurrent Versions System (CVS) [0-9p.]* (client/server)'
- else
- dotest version-2 "${testcvs} version" \
-'Concurrent Versions System (CVS) [0-9.]*.*'
- fi
- ;;
-
- basica)
- # Similar in spirit to some of the basic1, and basic2
- # tests, but hopefully a lot faster. Also tests operating on
- # files two directories down *without* operating on the parent dirs.
-
- # Tests basica-0a and basica-0b provide the equivalent of the:
- # mkdir ${CVSROOT_DIRNAME}/first-dir
- # used by many of the tests. It is "more official" in the sense
- # that is does everything through CVS; the reason most of the
- # tests don't use it is mostly historical.
- mkdir 1; cd 1
- dotest basica-0a "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest basica-0b "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd ..
- rm -r 1
-
- dotest basica-1 "${testcvs} -q co first-dir" ''
- cd first-dir
-
- # Test a few operations, to ensure they gracefully do
- # nothing in an empty directory.
- dotest basica-1a0 "${testcvs} -q update" ''
- dotest basica-1a1 "${testcvs} -q diff -c" ''
- dotest basica-1a2 "${testcvs} -q status" ''
- dotest basica-1a3 "${testcvs} -q update ." ''
- dotest basica-1a4 "${testcvs} -q update ./" ''
-
- mkdir sdir
- # Remote CVS gives the "cannot open CVS/Entries" error, which is
- # clearly a bug, but not a simple one to fix.
- dotest basica-1a10 "${testcvs} -n add sdir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/sdir added to the repository" \
-"${PROG} add: cannot open CVS/Entries for reading: No such file or directory
-Directory ${CVSROOT_DIRNAME}/first-dir/sdir added to the repository"
- dotest_fail basica-1a11 \
- "test -d ${CVSROOT_DIRNAME}/first-dir/sdir" ''
- dotest basica-2 "${testcvs} add sdir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/sdir added to the repository"
- cd sdir
- mkdir ssdir
- dotest basica-3 "${testcvs} add ssdir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir added to the repository"
- cd ssdir
- echo ssfile >ssfile
-
- # Trying to commit it without a "cvs add" should be an error.
- # The "use `cvs add' to create an entry" message is the one
- # that I consider to be more correct, but local cvs prints the
- # "nothing known" message and noone has gotten around to fixing it.
- dotest_fail basica-notadded "${testcvs} -q ci ssfile" \
-"${PROG} [a-z]*: use .${PROG} add. to create an entry for ssfile
-${PROG}"' \[[a-z]* aborted\]: correct above errors first!' \
-"${PROG}"' [a-z]*: nothing known about `ssfile'\''
-'"${PROG}"' \[[a-z]* aborted\]: correct above errors first!'
-
- dotest basica-4 "${testcvs} add ssfile" \
-"${PROG}"' add: scheduling file `ssfile'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest_fail basica-4a "${testcvs} tag tag0 ssfile" \
-"${PROG} tag: nothing known about ssfile
-${PROG} "'\[tag aborted\]: correct the above errors first!'
- cd ../..
- dotest basica-5 "${testcvs} -q ci -m add-it" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
-done
-Checking in sdir/ssdir/ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-initial revision: 1\.1
-done"
- dotest_fail basica-5a \
- "${testcvs} -q tag BASE sdir/ssdir/ssfile" \
-"${PROG} tag: Attempt to add reserved tag name BASE
-${PROG} \[tag aborted\]: failed to set tag BASE to revision 1\.1 in ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v"
- dotest basica-5b "${testcvs} -q tag NOT_RESERVED" \
-'T sdir/ssdir/ssfile'
-
- dotest basica-6 "${testcvs} -q update" ''
- echo "ssfile line 2" >>sdir/ssdir/ssfile
- dotest_fail basica-6.2 "${testcvs} -q diff -c" \
-"Index: sdir/ssdir/ssfile
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
-retrieving revision 1\.1
-diff -c -r1\.1 ssfile
-\*\*\* sdir/ssdir/ssfile ${RFCDATE} 1\.1
---- sdir/ssdir/ssfile ${RFCDATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
---- 1,2 ----
- ssfile
-${PLUS} ssfile line 2"
- dotest_fail basica-6.3 "${testcvs} -q diff -c -rBASE" \
-"Index: sdir/ssdir/ssfile
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
-retrieving revision 1\.1
-diff -c -r1\.1 ssfile
-\*\*\* sdir/ssdir/ssfile ${RFCDATE} 1\.1
---- sdir/ssdir/ssfile ${RFCDATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
---- 1,2 ----
- ssfile
-${PLUS} ssfile line 2"
- dotest_fail basica-6.4 "${testcvs} -q diff -c -rBASE -C3isacrowd" \
-"Index: sdir/ssdir/ssfile
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
-retrieving revision 1\.1
-diff -c -C 3isacrowd -r1\.1 ssfile
-${PROG} diff: invalid context length argument"
- dotest basica-7 "${testcvs} -q ci -m modify-it" \
-"Checking in sdir/ssdir/ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-new revision: 1\.2; previous revision: 1\.1
-done"
- dotest_fail basica-nonexist "${testcvs} -q ci nonexist" \
-"${PROG}"' [a-z]*: nothing known about `nonexist'\''
-'"${PROG}"' \[[a-z]* aborted\]: correct above errors first!'
- dotest basica-8 "${testcvs} -q update ." ''
-
- # Test the -f option to ci
- cd sdir/ssdir
- dotest basica-8a0 "${testcvs} -q ci -m not-modified ssfile" ''
- dotest basica-8a "${testcvs} -q ci -f -m force-it" \
-"Checking in ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-new revision: 1\.3; previous revision: 1\.2
-done"
- dotest basica-8a1 "${testcvs} -q ci -m bump-it -r 2.0" \
-"Checking in ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-new revision: 2\.0; previous revision: 1\.3
-done"
- dotest basica-8a1a "${testcvs} -q ci -m bump-it -r 2.9" \
-"Checking in ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-new revision: 2\.9; previous revision: 2\.0
-done"
- # Test string-based revion number increment rollover
- dotest basica-8a1b "${testcvs} -q ci -m bump-it -f -r 2" \
-"Checking in ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-new revision: 2\.10; previous revision: 2\.9
-done"
- dotest basica-8a1c "${testcvs} -q ci -m bump-it -r 2.99" \
-"Checking in ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-new revision: 2\.99; previous revision: 2\.10
-done"
- # Test string-based revion number increment rollover
- dotest basica-8a1d "${testcvs} -q ci -m bump-it -f -r 2" \
-"Checking in ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-new revision: 2\.100; previous revision: 2\.99
-done"
- dotest basica-8a1e "${testcvs} -q ci -m bump-it -r 2.1099" \
-"Checking in ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-new revision: 2\.1099; previous revision: 2\.100
-done"
- # Test string-based revion number increment rollover
- dotest basica-8a1f "${testcvs} -q ci -m bump-it -f -r 2" \
-"Checking in ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-new revision: 2\.1100; previous revision: 2\.1099
-done"
- # -f should not be necessary, but it should be harmless.
- # Also test the "-r 3" (rather than "-r 3.0") usage.
- dotest basica-8a2 "${testcvs} -q ci -m bump-it -f -r 3" \
-"Checking in ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-new revision: 3\.1; previous revision: 2\.1100
-done"
-
- # Test using -r to create a branch
- dotest_fail basica-8a3 "${testcvs} -q ci -m bogus -r 3.0.0" \
-"Checking in ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-${PROG} commit: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v: can't find branch point 3\.0
-${PROG} commit: could not check in ssfile"
- dotest basica-8a4 "${testcvs} -q ci -m valid -r 3.1.2" \
-"Checking in ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-new revision: 3\.1\.2\.1; previous revision: 3\.1
-done"
-
- # Verify that this file remains unchanged since up -A should not
- # change the contents here.
- cp ssfile $TESTDIR/ssfile.sav
- # now get rid of the sticky tag and go back to the trunk
- dotest basica-8a5 "$testcvs -q up -A ./" '[UP] ssfile'
- dotest basica-8a6 "cmp ssfile $TESTDIR/ssfile.sav"
- rm $TESTDIR/ssfile.sav
-
- cd ../..
- dotest basica-8b "${testcvs} -q diff -r1.2 -r1.3"
- dotest basica-8b1 "${testcvs} -q diff -r1.2 -r1.3 -C 3isacrowd"
-
- # The .* here will normally be "No such file or directory",
- # but if memory serves some systems (AIX?) have a different message.
-: dotest_fail basica-9 \
- "${testcvs} -q -d ${TESTDIR}/nonexist update" \
-"${PROG}: cannot access cvs root ${TESTDIR}/nonexist: .*"
- dotest_fail basica-9 \
- "${testcvs} -q -d ${TESTDIR}/nonexist update" \
-"${PROG} \[[a-z]* aborted\]: ${TESTDIR}/nonexist/CVSROOT: .*"
-
- dotest basica-10 "${testcvs} annotate" \
-'
-Annotations for sdir/ssdir/ssfile
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-1\.1 .'"$username8"' *[0-9a-zA-Z-]*.: ssfile
-1\.2 .'"$username8"' *[0-9a-zA-Z-]*.: ssfile line 2'
-
- # Test resurrecting with strange revision numbers
- cd sdir/ssdir
- dotest basica-r1 "${testcvs} rm -f ssfile" \
-"${PROG} remove: scheduling .ssfile. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest basica-r2 "${testcvs} -q ci -m remove" \
-"Removing ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-new revision: delete; previous revision: 3\.1
-done"
- dotest basica-r3 "${testcvs} -q up -p -r 3.1 ./ssfile >ssfile" ""
- dotest basica-r4 "${testcvs} add ssfile" \
-"${PROG} add: Re-adding file .ssfile. (in place of dead revision 3\.2)\.
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest basica-r5 "${testcvs} -q ci -m resurrect" \
-"Checking in ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v <-- ssfile
-new revision: 3\.3; previous revision: 3\.2
-done"
- cd ../..
-
- # As long as we have a file with a few revisions, test
- # a few "cvs admin -o" invocations.
- cd sdir/ssdir
- dotest_fail basica-o1 "${testcvs} admin -o 1.2::1.2" \
-"${PROG} [a-z]*: while processing more than one file:
-${PROG} \[[a-z]* aborted\]: attempt to specify a numeric revision"
- dotest basica-o2 "${testcvs} admin -o 1.2::1.2 ssfile" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
-done"
- dotest basica-o2a "${testcvs} admin -o 1.1::NOT_RESERVED ssfile" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
-done"
- dotest_fail basica-o2b "${testcvs} admin -o 1.1::NOT_EXIST ssfile" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
-${PROG} admin: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v: Revision NOT_EXIST doesn't exist.
-${PROG} admin: RCS file for .ssfile. not modified\."
- dotest basica-o3 "${testcvs} admin -o 1.2::1.3 ssfile" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
-done"
- dotest basica-o4 "${testcvs} admin -o 3.1:: ssfile" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
-deleting revision 3\.3
-deleting revision 3\.2
-done"
- dotest basica-o5 "${testcvs} admin -o ::1.1 ssfile" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
-done"
- dotest basica-o5a "${testcvs} -n admin -o 1.2::3.1 ssfile" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
-deleting revision 2\.1100
-deleting revision 2\.1099
-deleting revision 2\.100
-deleting revision 2\.99
-deleting revision 2\.10
-deleting revision 2\.9
-deleting revision 2\.0
-deleting revision 1\.3
-done"
- dotest basica-o6 "${testcvs} admin -o 1.2::3.1 ssfile" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
-deleting revision 2\.1100
-deleting revision 2\.1099
-deleting revision 2\.100
-deleting revision 2\.99
-deleting revision 2\.10
-deleting revision 2\.9
-deleting revision 2\.0
-deleting revision 1\.3
-done"
- dotest basica-o6a "${testcvs} admin -o 3.1.2: ssfile" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
-deleting revision 3\.1\.2\.1
-done"
- dotest basica-o7 "${testcvs} log -N ssfile" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/ssdir/ssfile,v
-Working file: ssfile
-head: 3\.1
-branch:
-locks: strict
-access list:
-keyword substitution: kv
-total revisions: 3; selected revisions: 3
-description:
-----------------------------
-revision 3\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}0 -0
-bump-it
-----------------------------
-revision 1\.2
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-modify-it
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-add-it
-============================================================================="
- dotest basica-o8 "${testcvs} -q update -p -r 1.1 ./ssfile" "ssfile"
- cd ../..
-
- cd ..
-
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- rm -r first-dir
- ;;
-
- basicb)
- # More basic tests, including non-branch tags and co -d.
- mkdir 1; cd 1
- dotest basicb-0a "${testcvs} -q co -l ." ''
- touch topfile
- dotest basicb-0b "${testcvs} add topfile" \
-"${PROG} add: scheduling file .topfile. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest basicb-0c "${testcvs} -q ci -m add-it topfile" \
-"RCS file: ${CVSROOT_DIRNAME}/topfile,v
-done
-Checking in topfile;
-${CVSROOT_DIRNAME}/topfile,v <-- topfile
-initial revision: 1\.1
-done"
- cd ..
- rm -r 1
- mkdir 2; cd 2
- dotest basicb-0d "${testcvs} -q co -l ." "U topfile"
- # Now test the ability to run checkout on an existing working
- # directory without having it lose its mind. I don't know
- # whether this is tested elsewhere in sanity.sh. A more elaborate
- # test might also have modified files, make sure it works if
- # the modules file was modified to add new directories to the
- # module, and such.
- dotest basicb-0d0 "${testcvs} -q co -l ." ""
- mkdir first-dir
- dotest basicb-0e "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd ..
- rm -r 2
-
- dotest basicb-1 "${testcvs} -q co first-dir" ''
-
- # The top-level CVS directory is not created by default.
- # I'm leaving basicb-1a and basicb-1b untouched, mostly, in
- # case we decide that the default should be reversed...
-
- dotest_fail basicb-1a "test -d CVS" ''
-
- dotest basicb-1c "cat first-dir/CVS/Repository" "first-dir"
-
- cd first-dir
- # Note that the name Emptydir is chosen to test that CVS just
- # treats it like any other directory name. It should be
- # special only when it is directly in $CVSROOT/CVSROOT.
- mkdir Emptydir sdir2
- dotest basicb-2 "${testcvs} add Emptydir sdir2" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/Emptydir added to the repository
-Directory ${CVSROOT_DIRNAME}/first-dir/sdir2 added to the repository"
- cd Emptydir
- echo sfile1 starts >sfile1
- dotest basicb-2a10 "${testcvs} -n add sfile1" \
-"${PROG} add: scheduling file .sfile1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest basicb-2a11 "${testcvs} status sfile1" \
-"${PROG} status: use .${PROG} add. to create an entry for sfile1
-===================================================================
-File: sfile1 Status: Unknown
-
- Working revision: No entry for sfile1
- Repository revision: No revision control file"
- dotest basicb-3 "${testcvs} add sfile1" \
-"${PROG} add: scheduling file .sfile1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest basicb-3a1 "${testcvs} status sfile1" \
-"===================================================================
-File: sfile1 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
-
- cd ../sdir2
- echo sfile2 starts >sfile2
- dotest basicb-4 "${testcvs} add sfile2" \
-"${PROG} add: scheduling file .sfile2. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest basicb-4a "${testcvs} -q ci CVS" \
-"${PROG} [a-z]*: warning: directory CVS specified in argument
-${PROG} [a-z]*: but CVS uses CVS for its own purposes; skipping CVS directory"
- cd ..
- dotest basicb-5 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Emptydir/sfile1,v
-done
-Checking in Emptydir/sfile1;
-${CVSROOT_DIRNAME}/first-dir/Emptydir/sfile1,v <-- sfile1
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir2/sfile2,v
-done
-Checking in sdir2/sfile2;
-${CVSROOT_DIRNAME}/first-dir/sdir2/sfile2,v <-- sfile2
-initial revision: 1\.1
-done"
- echo sfile1 develops >Emptydir/sfile1
- dotest basicb-6 "${testcvs} -q ci -m modify" \
-"Checking in Emptydir/sfile1;
-${CVSROOT_DIRNAME}/first-dir/Emptydir/sfile1,v <-- sfile1
-new revision: 1\.2; previous revision: 1\.1
-done"
- dotest basicb-7 "${testcvs} -q tag release-1" 'T Emptydir/sfile1
-T sdir2/sfile2'
- echo not in time for release-1 >sdir2/sfile2
- dotest basicb-8 "${testcvs} -q ci -m modify-2" \
-"Checking in sdir2/sfile2;
-${CVSROOT_DIRNAME}/first-dir/sdir2/sfile2,v <-- sfile2
-new revision: 1\.2; previous revision: 1\.1
-done"
- # See if CVS can correctly notice when an invalid numeric
- # revision is specified.
- # Commented out until we get around to fixing CVS
-: dotest basicb-8a0 "${testcvs} diff -r 1.5 -r 1.7 sfile2" 'error msg'
- cd ..
-
- # Test that we recurse into the correct directory when checking
- # for existing files, even if co -d is in use.
- touch first-dir/extra
- dotest basicb-cod-1 "${testcvs} -q co -d first-dir1 first-dir" \
-'U first-dir1/Emptydir/sfile1
-U first-dir1/sdir2/sfile2'
- rm -r first-dir1
-
- rm -r first-dir
-
- # FIXME? basicb-9 used to check things out like this:
- # U newdir/Emptydir/sfile1
- # U newdir/sdir2/sfile2
- # but that's difficult to do. The whole "shorten" thing
- # is pretty bogus, because it will break on things
- # like "cvs co foo/bar baz/quux". Unless there's some
- # pretty detailed expansion and analysis of the command-line
- # arguments, we shouldn't do "shorten" stuff at all.
-
- dotest basicb-9 \
-"${testcvs} -q co -d newdir -r release-1 first-dir/Emptydir first-dir/sdir2" \
-'U newdir/first-dir/Emptydir/sfile1
-U newdir/first-dir/sdir2/sfile2'
-
- # basicb-9a and basicb-9b: see note about basicb-1a
-
- dotest_fail basicb-9a "test -d CVS" ''
-
- dotest basicb-9c "cat newdir/CVS/Repository" "\."
- dotest basicb-9d "cat newdir/first-dir/CVS/Repository" \
-"${CVSROOT_DIRNAME}/first-dir" \
-"first-dir"
- dotest basicb-9e "cat newdir/first-dir/Emptydir/CVS/Repository" \
-"${CVSROOT_DIRNAME}/first-dir/Emptydir" \
-"first-dir/Emptydir"
- dotest basicb-9f "cat newdir/first-dir/sdir2/CVS/Repository" \
-"${CVSROOT_DIRNAME}/first-dir/sdir2" \
-"first-dir/sdir2"
-
- dotest basicb-10 "cat newdir/first-dir/Emptydir/sfile1 newdir/first-dir/sdir2/sfile2" \
-"sfile1 develops
-sfile2 starts"
-
- rm -r newdir
-
- # Hmm, this might be a case for CVSNULLREPOS, but CVS doesn't
- # seem to deal with it...
- if false; then
- dotest basicb-11 "${testcvs} -q co -d sub1/sub2 first-dir" \
-"U sub1/sub2/Emptydir/sfile1
-U sub1/sub2/sdir2/sfile2"
- cd sub1
- dotest basicb-12 "${testcvs} -q update ./." ''
- touch xx
- dotest basicb-13 "${testcvs} add xx" fixme
- cd ..
- rm -r sub1
- # to test: sub1/sub2/sub3
- fi # end of tests commented out.
-
- # Create a second directory.
- mkdir 1
- cd 1
- dotest basicb-14 "${testcvs} -q co -l ." 'U topfile'
- mkdir second-dir
- dotest basicb-15 "${testcvs} add second-dir" \
-"Directory ${CVSROOT_DIRNAME}/second-dir added to the repository"
- cd second-dir
- touch aa
- dotest basicb-16 "${testcvs} add aa" \
-"${PROG} add: scheduling file .aa. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest basicb-17 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/second-dir/aa,v
-done
-Checking in aa;
-${CVSROOT_DIRNAME}/second-dir/aa,v <-- aa
-initial revision: 1\.1
-done"
- cd ..
-
- # Try to remove all revisions in a file.
- dotest_fail basicb-o1 "${testcvs} admin -o1.1 topfile" \
-"RCS file: ${CVSROOT_DIRNAME}/topfile,v
-deleting revision 1\.1
-${PROG} \[admin aborted\]: attempt to delete all revisions"
- dotest basicb-o2 "${testcvs} -q update -d first-dir" \
-"U first-dir/Emptydir/sfile1
-U first-dir/sdir2/sfile2"
- dotest_fail basicb-o3 \
-"${testcvs} admin -o1.1:1.2 first-dir/sdir2/sfile2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir2/sfile2,v
-deleting revision 1\.2
-deleting revision 1\.1
-${PROG} \[admin aborted\]: attempt to delete all revisions"
- cd ..
- rm -r 1
-
- mkdir 1; cd 1
- # Note that -H is an illegal option.
- # I suspect that the choice between "illegal" and "invalid"
- # depends on the user's environment variables, the phase
- # of the moon (weirdness with optind), and who knows what else.
- # I've been seeing "illegal"...
- dotest_fail basicb-21 "${testcvs} -q admin -H" \
-"admin: illegal option -- H
-${PROG} \[admin aborted\]: specify ${PROG} -H admin for usage information" \
-"admin: invalid option -- H
-${PROG} \[admin aborted\]: specify ${PROG} -H admin for usage information"
- cd ..
- rmdir 1
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- rm -rf ${CVSROOT_DIRNAME}/second-dir
- rm -f ${CVSROOT_DIRNAME}/topfile,v
- ;;
-
- basicc)
- # More tests of basic/miscellaneous functionality.
- mkdir 1; cd 1
- dotest_fail basicc-1 "${testcvs} diff" \
-"${PROG} [a-z]*: in directory \.:
-${PROG} \[[a-z]* aborted\]: there is no version here; run .${PROG} checkout. first"
- dotest basicc-2 "${testcvs} -q co -l ." ''
- mkdir first-dir second-dir
- dotest basicc-3 "${testcvs} add first-dir second-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository
-Directory ${CVSROOT_DIRNAME}/second-dir added to the repository"
- # Old versions of CVS often didn't create this top-level CVS
- # directory in the first place. I think that maybe the only
- # way to get it to work currently is to let CVS create it,
- # and then blow it away (don't complain if it does not
- # exist). But that is perfectly 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" \
-"${PROG} update: Updating first-dir
-${PROG} update: Updating second-dir" \
-"${PROG} update: Updating \.
-${PROG} update: Updating first-dir
-${PROG} update: Updating second-dir"
-
- cd first-dir
- dotest basicc-6 "${testcvs} release -d" ""
- dotest basicc-7 "test -d ../first-dir" ""
- # The Linux 2.2 kernel lets you delete ".". That's OK either way,
- # the point is that CVS must not mess with anything *outside* "."
- # the way that CVS 1.10 and older tried to.
- dotest basicc-8 "${testcvs} -Q release -d ." \
-"" "${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
- # Apparently `cd ..' doesn't work with Linux 2.2 & Bash 2.05b.
- cd $TESTDIR/1
- mkdir ./first-dir
- cd ./first-dir
- fi
- dotest basicc-11 "${testcvs} -Q release -d ./." \
-"" "${PROG} release: deletion of directory \./\. failed: .*"
- dotest basicc-11a "test -d ../second-dir" ""
-
- cd ../..
-
- mkdir 2; cd 2
- dotest basicc-12 "${testcvs} -Q co ." ""
- # actual entries can be in either Entries or Entries.log, do
- # an update to get them consolidated into Entries
- dotest basicc-12a "${testcvs} -Q up" ""
- dotest basicc-12b "cat CVS/Entries" \
-"D/CVSROOT////
-D/first-dir////
-D/second-dir////"
- dotest basicc-13 "echo *" "CVS CVSROOT first-dir second-dir"
- dotest basicc-14 "${testcvs} -Q release first-dir second-dir" ""
- # a normal release shouldn't affect the Entries file
- dotest basicc-14b "cat CVS/Entries" \
-"D/CVSROOT////
-D/first-dir////
-D/second-dir////"
- # FIXCVS: but release -d probably should
- dotest basicc-15 "${testcvs} -Q release -d first-dir second-dir" ""
- dotest basicc-16 "echo *" "CVS CVSROOT"
- dotest basicc-17 "cat CVS/Entries" \
-"D/CVSROOT////
-D/first-dir////
-D/second-dir////"
- # FIXCVS: if not, update should notice the missing directories
- # and update Entries accordingly
- dotest basicc-18 "${testcvs} -Q up" ""
- dotest basicc-19 "cat CVS/Entries" \
-"D/CVSROOT////
-D/first-dir////
-D/second-dir////"
-
- cd ..
- rm -r 1 2
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- basic1)
- # first dive - add a files, first singly, then in a group.
- mkdir ${CVSROOT_DIRNAME}/first-dir
- mkdir basic1; cd basic1
- # check out an empty directory
- dotest basic1-1 "${testcvs} -q co first-dir" ''
-
- cd first-dir
- echo file2 >file2
- echo file3 >file3
- echo file4 >file4
- echo file5 >file5
-
- dotest basic1-14-add-add "${testcvs} add file2 file3 file4 file5" \
-"${PROG} add: scheduling file \`file2' for addition
-${PROG} add: scheduling file \`file3' for addition
-${PROG} add: scheduling file \`file4' for addition
-${PROG} add: scheduling file \`file5' for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest basic1-15-add-add \
-"${testcvs} -q update file2 file3 file4 file5" \
-"A file2
-A file3
-A file4
-A file5"
- dotest basic1-16-add-add "${testcvs} -q update" \
-"A file2
-A file3
-A file4
-A file5"
- dotest basic1-17-add-add "${testcvs} -q status" \
-"===================================================================
-File: file2 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file3 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file4 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file5 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest basic1-18-add-add "${testcvs} -q log" \
-"${PROG} log: file2 has been added, but not committed
-${PROG} log: file3 has been added, but not committed
-${PROG} log: file4 has been added, but not committed
-${PROG} log: file5 has been added, but not committed"
- cd ..
- dotest basic1-21-add-add "${testcvs} -q update" \
-"A first-dir/file2
-A first-dir/file3
-A first-dir/file4
-A first-dir/file5"
- # FIXCVS? Shouldn't this read first-dir/file2 instead of file2?
- dotest basic1-22-add-add "${testcvs} log first-dir" \
-"${PROG} log: Logging first-dir
-${PROG} log: file2 has been added, but not committed
-${PROG} log: file3 has been added, but not committed
-${PROG} log: file4 has been added, but not committed
-${PROG} log: file5 has been added, but not committed"
- dotest basic1-23-add-add "${testcvs} status first-dir" \
-"${PROG} status: Examining first-dir
-===================================================================
-File: file2 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file3 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file4 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file5 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest basic1-24-add-add "${testcvs} update first-dir" \
-"${PROG} update: Updating first-dir
-A first-dir/file2
-A first-dir/file3
-A first-dir/file4
-A first-dir/file5"
- dotest basic1-27-add-add "${testcvs} co first-dir" \
-"${PROG} checkout: Updating first-dir
-A first-dir/file2
-A first-dir/file3
-A first-dir/file4
-A first-dir/file5"
- cd first-dir
- dotest basic1-14-add-ci \
-"${testcvs} commit -m test file2 file3 file4 file5" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file3,v
-done
-Checking in file3;
-${CVSROOT_DIRNAME}/first-dir/file3,v <-- file3
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file4,v
-done
-Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file5,v
-done
-Checking in file5;
-${CVSROOT_DIRNAME}/first-dir/file5,v <-- file5
-initial revision: 1\.1
-done"
- dotest basic1-15-add-ci \
-"${testcvs} -q update file2 file3 file4 file5" ''
- dotest basic1-16-add-ci "${testcvs} -q update" ''
- dotest basic1-17-add-ci "${testcvs} -q status" \
-"===================================================================
-File: file2 Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file2,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file3 Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file3,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file4 Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file4,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file5 Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file5,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- # The "log" tests and friends probably already test the output
- # from log quite adequately.
- # Note: using dotest fails here. It seems to be related
- # to the output being sufficiently large (Red Hat 4.1).
- # dotest basic1-18-add-ci "${testcvs} log" "${DOTSTAR}"
- if ${testcvs} -q log >>${LOGFILE}; then
- pass basic1-18-add-ci
- else
- pass basic1-18-add-ci
- fi
- cd ..
- dotest basic1-21-add-ci "${testcvs} -q update" ''
- # See test basic1-18-add-ci for explanation of non-use of dotest.
- if ${testcvs} -q log first-dir >>${LOGFILE}; then
- pass basic1-22-add-ci
- else
- pass basic1-22-add-ci
- fi
- # At least for the moment I am going to consider 17-add-ci
- # an adequate test of the output here.
- # See test basic1-18-add-ci for explanation of non-use of dotest.
- if ${testcvs} -q status first-dir >>${LOGFILE}; then
- pass basic1-23-add-ci
- else
- pass basic1-23-add-ci
- fi
- dotest basic1-24-add-ci "${testcvs} -q update first-dir" ''
- dotest basic1-27-add-ci "${testcvs} -q co first-dir" ''
-
- cd first-dir
- rm file2 file3 file4 file5
- dotest basic1-14-rm-rm "${testcvs} rm file2 file3 file4 file5" \
-"${PROG} remove: scheduling .file2. for removal
-${PROG} remove: scheduling .file3. for removal
-${PROG} remove: scheduling .file4. for removal
-${PROG} remove: scheduling .file5. for removal
-${PROG} remove: use .${PROG} commit. to remove these files permanently"
- # 15-rm-rm was commented out. Why?
- dotest basic1-15-rm-rm \
-"${testcvs} -q update file2 file3 file4 file5" \
-"R file2
-R file3
-R file4
-R file5"
- dotest basic1-16-rm-rm "${testcvs} -q update" \
-"R file2
-R file3
-R file4
-R file5"
- dotest basic1-17-rm-rm "${testcvs} -q status" \
-"===================================================================
-File: no file file2 Status: Locally Removed
-
- Working revision: -1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file2,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: no file file3 Status: Locally Removed
-
- Working revision: -1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file3,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: no file file4 Status: Locally Removed
-
- Working revision: -1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file4,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: no file file5 Status: Locally Removed
-
- Working revision: -1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file5,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- # Would be nice to test that real logs appear (with dead state
- # and all), either here or someplace like log2 tests.
- if ${testcvs} -q log >>${LOGFILE}; then
- pass basic1-18-rm-rm
- else
- fail basic1-18-rm-rm
- fi
- cd ..
- dotest basic1-21-rm-rm "${testcvs} -q update" \
-"R first-dir/file2
-R first-dir/file3
-R first-dir/file4
-R first-dir/file5"
- if ${testcvs} -q log first-dir >>${LOGFILE}; then
- pass basic1-22-rm-rm
- else
- fail basic1-22-rm-rm
- fi
- if ${testcvs} -q status first-dir >>${LOGFILE}; then
- pass basic1-23-rm-rm
- else
- fail basic1-23-rm-rm
- fi
- dotest basic1-24-rm-rm "${testcvs} -q update first-dir" \
-"R first-dir/file2
-R first-dir/file3
-R first-dir/file4
-R first-dir/file5"
- dotest basic1-27-rm-rm "${testcvs} -q co first-dir" \
-"R first-dir/file2
-R first-dir/file3
-R first-dir/file4
-R first-dir/file5"
- cd first-dir
- dotest basic1-14-rm-ci "${testcvs} -q commit -m test" \
-"Removing file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: delete; previous revision: 1\.1
-done
-Removing file3;
-${CVSROOT_DIRNAME}/first-dir/file3,v <-- file3
-new revision: delete; previous revision: 1\.1
-done
-Removing file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: delete; previous revision: 1\.1
-done
-Removing file5;
-${CVSROOT_DIRNAME}/first-dir/file5,v <-- file5
-new revision: delete; previous revision: 1\.1
-done"
- dotest basic1-15-rm-ci \
-"${testcvs} -q update file2 file3 file4 file5" ''
- dotest basic1-16-rm-ci "${testcvs} -q update" ''
- dotest basic1-17-rm-ci "${testcvs} -q status" ''
- # Would be nice to test that real logs appear (with dead state
- # and all), either here or someplace like log2 tests.
- if ${testcvs} -q log >>${LOGFILE}; then
- pass basic1-18-rm-ci
- else
- fail basic1-18-rm-ci
- fi
- cd ..
- dotest basic1-21-rm-ci "${testcvs} -q update" ''
- if ${testcvs} -q log first-dir >>${LOGFILE}; then
- pass basic1-22-rm-ci
- else
- fail basic1-22-rm-ci
- fi
- if ${testcvs} -q status first-dir >>${LOGFILE}; then
- pass basic1-23-rm-ci
- else
- fail basic1-23-rm-ci
- fi
- dotest basic1-24-rm-ci "${testcvs} -q update first-dir" ''
- dotest basic1-27-rm-ci "${testcvs} -q co first-dir" ''
- cd first-dir
- # All the files are removed, so nothing gets tagged.
- dotest basic1-28 "${testcvs} -q tag first-dive" ''
- cd ..
- cd ..
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- rm -r basic1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- deep)
- # Test the ability to operate on directories nested rather deeply.
- mkdir ${CVSROOT_DIRNAME}/first-dir
- dotest deep-1 "${testcvs} -q co first-dir" ''
- cd first-dir
- for i in dir1 dir2 dir3 dir4 dir5 dir6 dir7 dir8; do
- mkdir $i
- dotest deep-2-$i "${testcvs} add $i" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/dir1[/dir0-9]* added to the repository"
- cd $i
- echo file1 >file1
- dotest deep-3-$i "${testcvs} add file1" \
-"${PROG}"' add: scheduling file `file1'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- done
- cd ../../../../../../../../..
- dotest_lit deep-4 "${testcvs} -q ci -m add-them first-dir" <<HERE
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/file1,v
-done
-Checking in first-dir/dir1/file1;
-${CVSROOT_DIRNAME}/first-dir/dir1/file1,v <-- file1
-initial revision: 1.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file1,v
-done
-Checking in first-dir/dir1/dir2/file1;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file1,v <-- file1
-initial revision: 1.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/file1,v
-done
-Checking in first-dir/dir1/dir2/dir3/file1;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/file1,v <-- file1
-initial revision: 1.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/dir4/file1,v
-done
-Checking in first-dir/dir1/dir2/dir3/dir4/file1;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/dir4/file1,v <-- file1
-initial revision: 1.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/dir4/dir5/file1,v
-done
-Checking in first-dir/dir1/dir2/dir3/dir4/dir5/file1;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/dir4/dir5/file1,v <-- file1
-initial revision: 1.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/file1,v
-done
-Checking in first-dir/dir1/dir2/dir3/dir4/dir5/dir6/file1;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/file1,v <-- file1
-initial revision: 1.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/file1,v
-done
-Checking in first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/file1;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/file1,v <-- file1
-initial revision: 1.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/file1,v
-done
-Checking in first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/file1;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/file1,v <-- file1
-initial revision: 1.1
-done
-HERE
-
- cd first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8
- rm file1
- dotest deep-4a0 "${testcvs} rm file1" \
-"${PROG} remove: scheduling .file1. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest deep-4a1 "${testcvs} -q ci -m rm-it" "Removing file1;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/file1,v <-- file1
-new revision: delete; previous revision: 1\.1
-done"
- cd ../../..
- dotest deep-4a2 "${testcvs} -q update -P dir6/dir7" ''
- # Should be using "test -e" if that is portable enough.
- dotest_fail deep-4a3 "test -d dir6/dir7/dir8" ''
-
- # Test that if we remove the working directory, CVS does not
- # recreate it. (I realize that this behavior is what the
- # users expect, but in the longer run we might want to
- # re-think it. The corresponding behavior for a file is that
- # CVS *will* recreate it, and we might want to make it so
- # that "cvs release -d" is the way to delete the directory
- # and have it stay gone -kingdon, Oct1996).
- rm -r dir6
- dotest deep-4b0a "${testcvs} -q diff" ''
- dotest deep-4b0b "${testcvs} -q ci" ''
- dotest deep-4b1 "${testcvs} -q update" ''
- dotest deep-4b2 "${testcvs} -q update -d -P" \
-'U dir6/file1
-U dir6/dir7/file1'
-
- # Test what happens if one uses -P when there are files removed
- # but not committed.
- cd dir6/dir7
- dotest deep-rm1 "${testcvs} rm -f file1" \
-"${PROG} remove: scheduling .file1. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- cd ..
- dotest deep-rm2 "${testcvs} -q update -d -P" 'R dir7/file1'
- dotest deep-rm3 "test -d dir7" ''
- dotest deep-rm4 "${testcvs} -q ci -m rm-it" "Removing dir7/file1;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/dir7/file1,v <-- file1
-new revision: delete; previous revision: 1\.1
-done"
- dotest deep-rm5 "${testcvs} -q update -d -P" ''
- dotest_fail deep-rm6 "test -d dir7" ''
-
- # Test rm -f -R.
- cd ../..
- dotest deep-rm7 "${testcvs} rm -f -R dir5" \
-"${PROG} remove: Removing dir5
-${PROG} remove: scheduling .dir5/file1. for removal
-${PROG} remove: Removing dir5/dir6
-${PROG} remove: scheduling .dir5/dir6/file1. for removal
-${PROG} remove: use .${PROG} commit. to remove these files permanently"
- dotest deep-rm8 "${testcvs} -q ci -m rm-it" \
-"Removing dir5/file1;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/dir4/dir5/file1,v <-- file1
-new revision: delete; previous revision: 1\.1
-done
-Removing dir5/dir6/file1;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/dir3/dir4/dir5/dir6/file1,v <-- file1
-new revision: delete; previous revision: 1\.1
-done"
- dotest deep-rm9 "${testcvs} -q update -d -P" ''
- dotest_fail deep-rm10 "test -d dir5"
-
- cd ../../../../..
-
- if echo "yes" | ${testcvs} release -d first-dir >>${LOGFILE}; then
- pass deep-5
- else
- fail deep-5
- fi
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- basic2)
- # Test rtag, import, history, various miscellaneous operations
-
- # NOTE: this section has reached the size and
- # complexity where it is getting to be a good idea to
- # add new tests to a new section rather than
- # continuing to piggyback them onto the tests here.
-
- # First empty the history file
- rm ${CVSROOT_DIRNAME}/CVSROOT/history
- touch ${CVSROOT_DIRNAME}/CVSROOT/history
-
-### XXX maybe should use 'cvs imprt -b1 -m new-module first-dir F F1' in an
-### empty directory to do this instead of hacking directly into $CVSROOT
- mkdir ${CVSROOT_DIRNAME}/first-dir
- dotest basic2-1 "${testcvs} -q co first-dir" ''
- for i in first-dir dir1 dir2 ; do
- if test ! -d $i ; then
- mkdir $i
- dotest basic2-2-$i "${testcvs} add $i" \
-"Directory ${CVSROOT_DIRNAME}/.*/$i added to the repository"
- fi
-
- cd $i
-
- for j in file6 file7; do
- echo $j > $j
- done
-
- dotest basic2-3-$i "${testcvs} add file6 file7" \
-"${PROG} add: scheduling file .file6. for addition
-${PROG} add: scheduling file .file7. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
-
- done
- cd ../../..
- dotest basic2-4 "${testcvs} update first-dir" \
-"${PROG} update: Updating first-dir
-A first-dir/file6
-A first-dir/file7
-${PROG} update: Updating first-dir/dir1
-A first-dir/dir1/file6
-A first-dir/dir1/file7
-${PROG} update: Updating first-dir/dir1/dir2
-A first-dir/dir1/dir2/file6
-A first-dir/dir1/dir2/file7"
-
- # fixme: doesn't work right for added files.
- dotest basic2-5 "${testcvs} log first-dir" \
-"${PROG} log: Logging first-dir
-${PROG} log: file6 has been added, but not committed
-${PROG} log: file7 has been added, but not committed
-${PROG} log: Logging first-dir/dir1
-${PROG} log: file6 has been added, but not committed
-${PROG} log: file7 has been added, but not committed
-${PROG} log: Logging first-dir/dir1/dir2
-${PROG} log: file6 has been added, but not committed
-${PROG} log: file7 has been added, but not committed"
-
- dotest basic2-6 "${testcvs} status first-dir" \
-"${PROG} status: Examining first-dir
-===================================================================
-File: file6 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file7 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-${PROG} status: Examining first-dir/dir1
-===================================================================
-File: file6 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file7 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-${PROG} status: Examining first-dir/dir1/dir2
-===================================================================
-File: file6 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file7 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
-
-# XXX why is this commented out???
-# if ${CVS} diff -u first-dir >> ${LOGFILE} || test $? = 1 ; then
-# pass 34
-# else
-# fail 34
-# fi
-
- dotest basic2-8 "${testcvs} -q ci -m 'second dive' first-dir" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file6,v
-done
-Checking in first-dir/file6;
-${CVSROOT_DIRNAME}/first-dir/file6,v <-- file6
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file7,v
-done
-Checking in first-dir/file7;
-${CVSROOT_DIRNAME}/first-dir/file7,v <-- file7
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/file6,v
-done
-Checking in first-dir/dir1/file6;
-${CVSROOT_DIRNAME}/first-dir/dir1/file6,v <-- file6
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/file7,v
-done
-Checking in first-dir/dir1/file7;
-${CVSROOT_DIRNAME}/first-dir/dir1/file7,v <-- file7
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file6,v
-done
-Checking in first-dir/dir1/dir2/file6;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file6,v <-- file6
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file7,v
-done
-Checking in first-dir/dir1/dir2/file7;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file7,v <-- file7
-initial revision: 1\.1
-done"
-
- dotest basic2-9 "${testcvs} tag second-dive first-dir" \
-"${PROG} tag: Tagging first-dir
-T first-dir/file6
-T first-dir/file7
-${PROG} tag: Tagging first-dir/dir1
-T first-dir/dir1/file6
-T first-dir/dir1/file7
-${PROG} tag: Tagging first-dir/dir1/dir2
-T first-dir/dir1/dir2/file6
-T first-dir/dir1/dir2/file7"
-
- # third dive - in bunch o' directories, add bunch o' files,
- # delete some, change some.
-
- for i in first-dir dir1 dir2 ; do
- cd $i
-
- # modify a file
- echo file6 >>file6
-
- # delete a file
- rm file7
-
- dotest basic2-10-$i "${testcvs} rm file7" \
-"${PROG} remove: scheduling .file7. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
-
- # and add a new file
- echo file14 >file14
-
- dotest basic2-11-$i "${testcvs} add file14" \
-"${PROG} add: scheduling file .file14. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- done
-
- cd ../../..
- dotest basic2-12 "${testcvs} update first-dir" \
-"${PROG} update: Updating first-dir
-A first-dir/file14
-M first-dir/file6
-R first-dir/file7
-${PROG} update: Updating first-dir/dir1
-A first-dir/dir1/file14
-M first-dir/dir1/file6
-R first-dir/dir1/file7
-${PROG} update: Updating first-dir/dir1/dir2
-A first-dir/dir1/dir2/file14
-M first-dir/dir1/dir2/file6
-R first-dir/dir1/dir2/file7"
-
- # FIXME: doesn't work right for added files
- dotest basic2-13 "${testcvs} log first-dir" \
-"${PROG} log: Logging first-dir
-${PROG} log: file14 has been added, but not committed
-
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file6,v
-Working file: first-dir/file6
-head: 1\.1
-branch:
-locks: strict
-access list:
-symbolic names:
- second-dive: 1\.1
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-second dive
-=============================================================================
-
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file7,v
-Working file: first-dir/file7
-head: 1\.1
-branch:
-locks: strict
-access list:
-symbolic names:
- second-dive: 1\.1
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-second dive
-=============================================================================
-${PROG} log: Logging first-dir/dir1
-${PROG} log: file14 has been added, but not committed
-
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/file6,v
-Working file: first-dir/dir1/file6
-head: 1\.1
-branch:
-locks: strict
-access list:
-symbolic names:
- second-dive: 1\.1
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-second dive
-=============================================================================
-
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/file7,v
-Working file: first-dir/dir1/file7
-head: 1\.1
-branch:
-locks: strict
-access list:
-symbolic names:
- second-dive: 1\.1
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-second dive
-=============================================================================
-${PROG} log: Logging first-dir/dir1/dir2
-${PROG} log: file14 has been added, but not committed
-
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file6,v
-Working file: first-dir/dir1/dir2/file6
-head: 1\.1
-branch:
-locks: strict
-access list:
-symbolic names:
- second-dive: 1\.1
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-second dive
-=============================================================================
-
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file7,v
-Working file: first-dir/dir1/dir2/file7
-head: 1\.1
-branch:
-locks: strict
-access list:
-symbolic names:
- second-dive: 1\.1
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-second dive
-============================================================================="
-
- dotest basic2-14 "${testcvs} status first-dir" \
-"${PROG} status: Examining first-dir
-===================================================================
-File: file14 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file6 Status: Locally Modified
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file6,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: no file file7 Status: Locally Removed
-
- Working revision: -1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file7,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-${PROG} status: Examining first-dir/dir1
-===================================================================
-File: file14 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file6 Status: Locally Modified
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/dir1/file6,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: no file file7 Status: Locally Removed
-
- Working revision: -1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/dir1/file7,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-${PROG} status: Examining first-dir/dir1/dir2
-===================================================================
-File: file14 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file6 Status: Locally Modified
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file6,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: no file file7 Status: Locally Removed
-
- Working revision: -1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file7,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
-
-# XXX why is this commented out?
-# if ${CVS} diff -u first-dir >> ${LOGFILE} || test $? = 1 ; then
-# pass 42
-# else
-# fail 42
-# fi
-
- dotest basic2-16 "${testcvs} ci -m 'third dive' first-dir" \
-"${PROG} [a-z]*: Examining first-dir
-${PROG} [a-z]*: Examining first-dir/dir1
-${PROG} [a-z]*: Examining first-dir/dir1/dir2
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file14,v
-done
-Checking in first-dir/file14;
-${CVSROOT_DIRNAME}/first-dir/file14,v <-- file14
-initial revision: 1\.1
-done
-Checking in first-dir/file6;
-${CVSROOT_DIRNAME}/first-dir/file6,v <-- file6
-new revision: 1\.2; previous revision: 1\.1
-done
-Removing first-dir/file7;
-${CVSROOT_DIRNAME}/first-dir/file7,v <-- file7
-new revision: delete; previous revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/file14,v
-done
-Checking in first-dir/dir1/file14;
-${CVSROOT_DIRNAME}/first-dir/dir1/file14,v <-- file14
-initial revision: 1\.1
-done
-Checking in first-dir/dir1/file6;
-${CVSROOT_DIRNAME}/first-dir/dir1/file6,v <-- file6
-new revision: 1\.2; previous revision: 1\.1
-done
-Removing first-dir/dir1/file7;
-${CVSROOT_DIRNAME}/first-dir/dir1/file7,v <-- file7
-new revision: delete; previous revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file14,v
-done
-Checking in first-dir/dir1/dir2/file14;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file14,v <-- file14
-initial revision: 1\.1
-done
-Checking in first-dir/dir1/dir2/file6;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file6,v <-- file6
-new revision: 1\.2; previous revision: 1\.1
-done
-Removing first-dir/dir1/dir2/file7;
-${CVSROOT_DIRNAME}/first-dir/dir1/dir2/file7,v <-- file7
-new revision: delete; previous revision: 1\.1
-done"
- dotest basic2-17 "${testcvs} -q update first-dir" ''
-
- dotest basic2-18 "${testcvs} tag third-dive first-dir" \
-"${PROG} tag: Tagging first-dir
-T first-dir/file14
-T first-dir/file6
-${PROG} tag: Tagging first-dir/dir1
-T first-dir/dir1/file14
-T first-dir/dir1/file6
-${PROG} tag: Tagging first-dir/dir1/dir2
-T first-dir/dir1/dir2/file14
-T first-dir/dir1/dir2/file6"
-
- dotest basic2-19 "echo yes | ${testcvs} release -d first-dir" \
-"You have \[0\] altered files in this repository\.
-Are you sure you want to release (and delete) directory .first-dir.: "
-
- # end of third dive
- dotest_fail basic2-20 "test -d first-dir" ""
-
- # now try some rtags
-
- # rtag HEADS
- dotest basic2-21 "${testcvs} rtag rtagged-by-head first-dir" \
-"${PROG} rtag: Tagging first-dir
-${PROG} rtag: Tagging first-dir/dir1
-${PROG} rtag: Tagging first-dir/dir1/dir2"
- # The next test used to cause an assert failure
- # something like:
- # cvs: ./recurse.c:667: do_recursion: Assertion `repository != ((void *)0)' failed.
- dotest basic2-21b "${testcvs} co -p -r rtagged-by-head first-dir/file6" \
-"===================================================================
-Checking out first-dir/file6
-RCS: $CVSROOT_DIRNAME/first-dir/file6,v
-VERS: 1\.2
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-file6
-file6"
- # tag by tag
- dotest basic2-22 "${testcvs} rtag -r rtagged-by-head rtagged-by-tag first-dir" \
-"${PROG} rtag: Tagging first-dir
-${PROG} rtag: Tagging first-dir/dir1
-${PROG} rtag: Tagging first-dir/dir1/dir2"
-
- # tag by revision
- dotest basic2-23 "${testcvs} rtag -r1.1 rtagged-by-revision first-dir" \
-"${PROG} rtag: Tagging first-dir
-${PROG} rtag: Tagging first-dir/dir1
-${PROG} rtag: Tagging first-dir/dir1/dir2"
-
- # rdiff by revision
- dotest basic2-24 "${testcvs} rdiff -r1.1 -rrtagged-by-head first-dir" \
-"${PROG} rdiff: Diffing first-dir
-Index: first-dir/file6
-diff -c first-dir/file6:1\.1 first-dir/file6:1\.2
-\*\*\* first-dir/file6:1\.1 ${DATE}
---- first-dir/file6 ${DATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
---- 1,2 ----
- file6
-${PLUS} file6
-Index: first-dir/file7
-diff -c first-dir/file7:1\.1 first-dir/file7:removed
-\*\*\* first-dir/file7:1.1 ${DATE}
---- first-dir/file7 ${DATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-- file7
---- 0 ----
-${PROG} rdiff: Diffing first-dir/dir1
-Index: first-dir/dir1/file6
-diff -c first-dir/dir1/file6:1\.1 first-dir/dir1/file6:1\.2
-\*\*\* first-dir/dir1/file6:1\.1 ${DATE}
---- first-dir/dir1/file6 ${DATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
---- 1,2 ----
- file6
-${PLUS} file6
-Index: first-dir/dir1/file7
-diff -c first-dir/dir1/file7:1\.1 first-dir/dir1/file7:removed
-\*\*\* first-dir/dir1/file7:1\.1 ${DATE}
---- first-dir/dir1/file7 ${DATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-- file7
---- 0 ----
-${PROG} rdiff: Diffing first-dir/dir1/dir2
-Index: first-dir/dir1/dir2/file6
-diff -c first-dir/dir1/dir2/file6:1\.1 first-dir/dir1/dir2/file6:1\.2
-\*\*\* first-dir/dir1/dir2/file6:1\.1 ${DATE}
---- first-dir/dir1/dir2/file6 ${DATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
---- 1,2 ----
- file6
-${PLUS} file6
-Index: first-dir/dir1/dir2/file7
-diff -c first-dir/dir1/dir2/file7:1\.1 first-dir/dir1/dir2/file7:removed
-\*\*\* first-dir/dir1/dir2/file7:1\.1 ${DATE}
---- first-dir/dir1/dir2/file7 ${DATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-- file7
---- 0 ----"
- dotest basic2-24a "${testcvs} rdiff -l -r1.1 -rrtagged-by-head first-dir" \
-"${PROG} rdiff: Diffing first-dir
-Index: first-dir/file6
-diff -c first-dir/file6:1\.1 first-dir/file6:1\.2
-\*\*\* first-dir/file6:1\.1 ${DATE}
---- first-dir/file6 ${DATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
---- 1,2 ----
- file6
-${PLUS} file6
-Index: first-dir/file7
-diff -c first-dir/file7:1\.1 first-dir/file7:removed
-\*\*\* first-dir/file7:1.1 ${DATE}
---- first-dir/file7 ${DATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-- file7
---- 0 ----"
- # now export by rtagged-by-head and rtagged-by-tag and compare.
- dotest basic2-25 "${testcvs} export -r rtagged-by-head -d 1dir first-dir" \
-"${PROG} export: Updating 1dir
-U 1dir/file14
-U 1dir/file6
-${PROG} export: Updating 1dir/dir1
-U 1dir/dir1/file14
-U 1dir/dir1/file6
-${PROG} export: Updating 1dir/dir1/dir2
-U 1dir/dir1/dir2/file14
-U 1dir/dir1/dir2/file6"
- dotest_fail basic2-25a "test -d 1dir/CVS"
- dotest_fail basic2-25b "test -d 1dir/dir1/CVS"
- dotest_fail basic2-25c "test -d 1dir/dir1/dir2/CVS"
-
- dotest basic2-26 "${testcvs} export -r rtagged-by-tag first-dir" \
-"${PROG} export: Updating first-dir
-U first-dir/file14
-U first-dir/file6
-${PROG} export: Updating first-dir/dir1
-U first-dir/dir1/file14
-U first-dir/dir1/file6
-${PROG} export: Updating first-dir/dir1/dir2
-U first-dir/dir1/dir2/file14
-U first-dir/dir1/dir2/file6"
- dotest_fail basic2-26a "test -d first-dir/CVS"
- dotest_fail basic2-26b "test -d first-dir/dir1/CVS"
- dotest_fail basic2-26c "test -d first-dir/dir1/dir2/CVS"
-
- dotest basic2-27 "directory_cmp 1dir first-dir"
- rm -r 1dir first-dir
-
- # checkout by revision vs export by rtagged-by-revision and compare.
- mkdir export-dir
- dotest basic2-28 "${testcvs} export -rrtagged-by-revision -d export-dir first-dir" \
-"${PROG} export: Updating export-dir
-U export-dir/file14
-U export-dir/file6
-U export-dir/file7
-${PROG} export: Updating export-dir/dir1
-U export-dir/dir1/file14
-U export-dir/dir1/file6
-U export-dir/dir1/file7
-${PROG} export: Updating export-dir/dir1/dir2
-U export-dir/dir1/dir2/file14
-U export-dir/dir1/dir2/file6
-U export-dir/dir1/dir2/file7"
- dotest_fail basic2-28a "test -d export-dir/CVS"
- dotest_fail basic2-28b "test -d export-dir/dir1/CVS"
- dotest_fail basic2-28c "test -d export-dir/dir1/dir2/CVS"
-
- dotest basic2-29 "${testcvs} co -r1.1 first-dir" \
-"${PROG} checkout: Updating first-dir
-U first-dir/file14
-U first-dir/file6
-U first-dir/file7
-${PROG} checkout: Updating first-dir/dir1
-U first-dir/dir1/file14
-U first-dir/dir1/file6
-U first-dir/dir1/file7
-${PROG} checkout: Updating first-dir/dir1/dir2
-U first-dir/dir1/dir2/file14
-U first-dir/dir1/dir2/file6
-U first-dir/dir1/dir2/file7"
-
- # directory copies are done in an oblique way in order to avoid a bug in sun's tmp filesystem.
- mkdir first-dir.cpy ; (cd first-dir ; tar cf - . | (cd ../first-dir.cpy ; tar xf -))
-
- dotest basic2-30 "directory_cmp first-dir export-dir"
-
- # interrupt, while we've got a clean 1.1 here, let's import it
- # into a couple of other modules.
- cd export-dir
- dotest_sort basic2-31 "${testcvs} import -m first-import second-dir first-immigration immigration1 immigration1_0" \
-"
-
-N second-dir/dir1/dir2/file14
-N second-dir/dir1/dir2/file6
-N second-dir/dir1/dir2/file7
-N second-dir/dir1/file14
-N second-dir/dir1/file6
-N second-dir/dir1/file7
-N second-dir/file14
-N second-dir/file6
-N second-dir/file7
-No conflicts created by this import
-${PROG} import: Importing ${CVSROOT_DIRNAME}/second-dir/dir1
-${PROG} import: Importing ${CVSROOT_DIRNAME}/second-dir/dir1/dir2"
- cd ..
-
- dotest basic2-32 "${testcvs} export -r HEAD second-dir" \
-"${PROG} export: Updating second-dir
-U second-dir/file14
-U second-dir/file6
-U second-dir/file7
-${PROG} export: Updating second-dir/dir1
-U second-dir/dir1/file14
-U second-dir/dir1/file6
-U second-dir/dir1/file7
-${PROG} export: Updating second-dir/dir1/dir2
-U second-dir/dir1/dir2/file14
-U second-dir/dir1/dir2/file6
-U second-dir/dir1/dir2/file7"
-
- dotest basic2-33 "directory_cmp first-dir second-dir"
-
- rm -r second-dir
-
- rm -r export-dir first-dir
- mkdir first-dir
- (cd first-dir.cpy ; tar cf - . | (cd ../first-dir ; tar xf -))
-
- # update the top, cancelling sticky tags, retag, update other copy, compare.
- cd first-dir
- dotest basic2-34 "${testcvs} update -A -l *file*" \
-"[UP] file6
-${PROG} update: file7 is no longer in the repository"
-
- # If we don't delete the tag first, cvs won't retag it.
- # This would appear to be a feature.
- dotest basic2-35 "${testcvs} tag -l -d rtagged-by-revision" \
-"${PROG} tag: Untagging \.
-D file14
-D file6"
- dotest basic2-36 "${testcvs} tag -l rtagged-by-revision" \
-"${PROG} tag: Tagging \.
-T file14
-T file6"
-
- cd ..
- mv first-dir 1dir
- mv first-dir.cpy first-dir
- cd first-dir
-
- dotest basic2-37 "${testcvs} -q diff -u" ''
-
- dotest basic2-38 "${testcvs} update" \
-"${PROG} update: Updating .
-${PROG} update: Updating dir1
-${PROG} update: Updating dir1/dir2"
-
- cd ..
-
- #### FIXME: is this expected to work??? Need to investigate
- #### and fix or remove the test.
-# dotest basic2-39 "directory_cmp 1dir first-dir"
-
- rm -r 1dir first-dir
-
- # Test the cvs history command.
-
- # The reason that there are two patterns rather than using
- # \(${TESTDIR}\|<remote>\) is that we are trying to
- # make this portable. Perhaps at some point we should
- # ditch that notion and require GNU expr (or dejagnu or....)
- # since it seems to be so painful.
-
- # why are there two lines at the end of the local output
- # which don't exist in the remote output? would seem to be
- # a CVS bug.
- dotest basic2-64 "${testcvs} his -x TOFWUPCGMAR -a" \
-"O [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir =first-dir= ${TESTDIR}/\*
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6 first-dir == ${TESTDIR}
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7 first-dir == ${TESTDIR}
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6 first-dir/dir1 == ${TESTDIR}
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7 first-dir/dir1 == ${TESTDIR}
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6 first-dir/dir1/dir2 == ${TESTDIR}
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7 first-dir/dir1/dir2 == ${TESTDIR}
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14 first-dir == ${TESTDIR}
-M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir == ${TESTDIR}
-R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7 first-dir == ${TESTDIR}
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14 first-dir/dir1 == ${TESTDIR}
-M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir/dir1 == ${TESTDIR}
-R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7 first-dir/dir1 == ${TESTDIR}
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14 first-dir/dir1/dir2 == ${TESTDIR}
-M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir/dir1/dir2 == ${TESTDIR}
-R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7 first-dir/dir1/dir2 == ${TESTDIR}
-F [0-9-]* [0-9:]* ${PLUS}0000 ${username} =first-dir= ${TESTDIR}/\*
-T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-head:A\]
-T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-tag:rtagged-by-head\]
-T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-revision:1\.1\]
-O [0-9-]* [0-9:]* ${PLUS}0000 ${username} \[1\.1\] first-dir =first-dir= ${TESTDIR}/\*
-U [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir == ${TESTDIR}/first-dir
-W [0-9-]* [0-9:]* ${PLUS}0000 ${username} file7 first-dir == ${TESTDIR}/first-dir" \
-"O [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir =first-dir= <remote>/\*
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6 first-dir == <remote>
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7 first-dir == <remote>
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6 first-dir/dir1 == <remote>
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7 first-dir/dir1 == <remote>
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file6 first-dir/dir1/dir2 == <remote>
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file7 first-dir/dir1/dir2 == <remote>
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14 first-dir == <remote>
-M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir == <remote>
-R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7 first-dir == <remote>
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14 first-dir/dir1 == <remote>
-M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir/dir1 == <remote>
-R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7 first-dir/dir1 == <remote>
-A [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.1 file14 first-dir/dir1/dir2 == <remote>
-M [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir/dir1/dir2 == <remote>
-R [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file7 first-dir/dir1/dir2 == <remote>
-F [0-9-]* [0-9:]* ${PLUS}0000 ${username} =first-dir= <remote>/\*
-T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-head:A\]
-T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-tag:rtagged-by-head\]
-T [0-9-]* [0-9:]* ${PLUS}0000 ${username} first-dir \[rtagged-by-revision:1\.1\]
-O [0-9-]* [0-9:]* ${PLUS}0000 ${username} \[1\.1\] first-dir =first-dir= <remote>/\*
-P [0-9-]* [0-9:]* ${PLUS}0000 ${username} 1\.2 file6 first-dir == <remote>
-W [0-9-]* [0-9:]* ${PLUS}0000 ${username} file7 first-dir == <remote>"
-
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- rm -rf ${CVSROOT_DIRNAME}/second-dir
- ;;
-
- parseroot)
- mkdir 1; cd 1
- # Test odd cases involving CVSROOT. At the moment, that means we
- # are testing roots with '/'s on the end, which CVS should parse off.
- CVSROOT_save=${CVSROOT}
- CVSROOT="${CVSROOT}/////"
- dotest parseroot-1 "${testcvs} -q co CVSROOT/modules" \
-"U CVSROOT/modules"
- dotest parseroot-2 "${testcvs} -q ci -fmnull-change CVSROOT/modules" \
-"Checking in CVSROOT/modules;
-${CVSROOT_DIRNAME}/CVSROOT/modules,v <-- modules
-new revision: 1\.2; previous revision: 1\.1
-done
-${PROG} commit: Rebuilding administrative file database"
-
- if $remote; then
- # I only test these when testing remote in case CVS was compiled
- # without client support.
-
- # logout does not try to contact the server.
- CVSROOT=":pserver;proxy=localhost;proxyport=8080:localhost/dev/null"
- dotest parseroot-3r "$testcvs -d'$CVSROOT' logout" \
-"$PROG logout: WARNING: Ignoring method options found in CVSROOT: \`proxy=localhost;proxyport=8080'\.
-$PROG logout: Use CVS version 1\.12\.7 or later to handle method options\.
-Logging out of :pserver:$username@localhost:2401/dev/null
-$PROG logout: warning: failed to open $HOME/\.cvspass for reading: No such file or directory
-$PROG logout: Entry not found\."
- fi
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- CVSROOT=$CVSROOT_save
- cd ..
- rm -r 1
- ;;
-
-
-
- files)
- # Test of how we specify files on the command line
- # (recurse.c and that sort of thing). Vaguely similar to
- # tests like basic* and deep. See modules and such tests
- # for what happens when we throw in modules and co -d, &c.
-
- # This particular test is fairly carefully crafted, to spot
- # one particular issue with remote.
- mkdir 1; cd 1
- dotest files-1 "${testcvs} -q co -l ." ""
- mkdir first-dir
- dotest files-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- touch tfile
- dotest files-3 "${testcvs} add tfile" \
-"${PROG} add: scheduling file .tfile. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest files-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/tfile,v
-done
-Checking in tfile;
-${CVSROOT_DIRNAME}/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" "U tfile"
- mkdir dir
- dotest files-7 "${testcvs} add dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/dir added to the repository
---> Using per-directory sticky tag .C'"
- cd dir
- touch .file
- dotest files-6 "${testcvs} add .file" \
-"${PROG} add: scheduling file .\.file' for addition on branch .C.
-${PROG} add: use .${PROG} commit. to add this file permanently"
- mkdir sdir
- dotest files-7 "${testcvs} add sdir" \
-"Directory ${CVSROOT_DIRNAME}/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 ${CVSROOT_DIRNAME}/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} add: scheduling file .\.file' for addition on branch .C.
-${PROG} add: use .${PROG} commit. to add this file permanently"
- cd ../..
- dotest files-10 "${testcvs} -q ci -m test" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/dir/Attic/\.file,v
-done
-Checking in \.file;
-${CVSROOT_DIRNAME}/first-dir/dir/Attic/\.file,v <-- \.file
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir/sdir/ssdir/Attic/\.file,v
-done
-Checking in sdir/ssdir/\.file;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/first-dir/dir/sdir/ssdir/Attic/\.file,v <-- \.file
-new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
-done"
- if $remote; then
- # FIXCVS:
- # This is a bug, looks like that toplevel_repos cruft in
- # client.c is coming back to haunt us.
- # May want to think about the whole issue, toplevel_repos
- # has always been crufty and trying to patch it up again
- # might be a mistake.
- dotest files-12 \
-"${testcvs} commit -f -m test ./sdir/ssdir/.file ./.file" \
-"Checking in \./sdir/ssdir/\.file;
-${CVSROOT_DIRNAME}/first-dir/dir/sdir/ssdir/Attic/\.file,v <-- \.file
-new revision: 1\.1\.2\.3; previous revision: 1\.1\.2\.2
-done"
-
- # 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 .file" \
-"Checking in \.file;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/first-dir/dir/sdir/ssdir/Attic/\.file,v <-- \.file
-new revision: 1\.1\.2\.4; previous revision: 1\.1\.2\.3
-done"
- if $remote; then
- dotest files-14 \
-"${testcvs} commit -fmtest ../../first-dir/dir/.file" \
-"Checking in \.\./\.\./first-dir/dir/\.file;
-${CVSROOT_DIRNAME}/first-dir/dir/Attic/\.file,v <-- .file
-new revision: 1\.1\.2\.4; previous revision: 1\.1\.2\.3
-done"
- else
- dotest files-14 \
-"${testcvs} commit -fmtest ../../first-dir/dir/.file" \
-"Checking in \.\./\.\./first-dir/dir/\.file;
-${CVSROOT_DIRNAME}/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.
- # (it might be better to just change a few of the names in
- # basica or some other test instead, always good to keep the
- # testsuite concise).
-
- mkdir 1; cd 1
- dotest spacefiles-1 "${testcvs} -q co -l ." ""
- touch ./-c
- dotest spacefiles-2 "${testcvs} add -- -c" \
-"${PROG} add: scheduling file .-c. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest spacefiles-3 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/-c,v
-done
-Checking in -c;
-${CVSROOT_DIRNAME}/-c,v <-- -c
-initial revision: 1\.1
-done"
- mkdir 'first dir'
- dotest spacefiles-4 "${testcvs} add 'first dir'" \
-"Directory ${CVSROOT_DIRNAME}/first dir added to the repository"
- mkdir ./-b
- dotest spacefiles-5 "${testcvs} add -- -b" \
-"Directory ${CVSROOT_DIRNAME}/-b added to the repository"
- cd 'first dir'
- touch 'a file'
- dotest spacefiles-6 "${testcvs} add 'a file'" \
-"${PROG} add: scheduling file .a file. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest spacefiles-7 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first dir/a file,v
-done
-Checking in a file;
-${CVSROOT_DIRNAME}/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
- dotest spacefiles-10 "${testcvs} co -- -b" \
-"${PROG} checkout: Updating -b"
- dotest spacefiles-11 "${testcvs} -q co -- -c" "U \./-c"
- rm ./-c
- dotest spacefiles-13 "${testcvs} -q co 'first dir'" \
-"U first dir/a file"
- cd ..
-
- mkdir 3; cd 3
- dotest spacefiles-14 "${testcvs} -q co 'first dir/a file'" \
-"U first dir/a file"
- cd ..
-
- rm -r 1 2 3
- rm -rf "${CVSROOT_DIRNAME}/first dir"
- rm -r ${CVSROOT_DIRNAME}/-b
- rm -f ${CVSROOT_DIRNAME}/-c,v
- ;;
-
- commit-readonly)
- mkdir 1; cd 1
- module=x
-
- : > junk
- dotest commit-readonly-1 "$testcvs -Q import -m . $module X Y" ''
- dotest commit-readonly-2 "$testcvs -Q co $module" ''
- cd $module
-
- file=m
-
- # Include an rcs keyword to be expanded.
- echo '$Id''$' > $file
-
- dotest commit-readonly-3 "$testcvs add $file" \
-"${PROG} add: scheduling file .$file. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest commit-readonly-4 "$testcvs -Q ci -m . $file" \
-"RCS file: ${CVSROOT_DIRNAME}/$module/$file,v
-done
-Checking in $file;
-${CVSROOT_DIRNAME}/$module/$file,v <-- $file
-initial revision: 1\.1
-done"
-
- echo line2 >> $file
- # Make the file read-only.
- chmod a-w $file
-
- dotest commit-readonly-5 "$testcvs -Q ci -m . $file" \
-"Checking in $file;
-${CVSROOT_DIRNAME}/$module/$file,v <-- $file
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- cd ../..
- rm -rf 1
- rm -rf ${CVSROOT_DIRNAME}/$module
- ;;
-
- status)
- # This tests for a bug in the status command which failed to
- # notice resolved conflicts.
- mkdir status; cd status
- dotest status-init-1 "${testcvs} -q co -l ." ""
- mkdir first-dir
- dotest status-init-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- echo a line >tfile
- dotest status-init-3 "${testcvs} add tfile" \
-"${PROG} add: scheduling file .tfile. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest status-init-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/tfile,v
-done
-Checking in tfile;
-${CVSROOT_DIRNAME}/first-dir/tfile,v <-- tfile
-initial revision: 1\.1
-done"
- cd ..
- dotest status-init-5 "${testcvs} -q co -dsecond-dir first-dir" \
-"U second-dir/tfile"
- cd second-dir
- echo some junk >>tfile
- dotest status-init-6 "${testcvs} -q ci -maline" \
-"Checking in tfile;
-${CVSROOT_DIRNAME}/first-dir/tfile,v <-- tfile
-new revision: 1\.2; previous revision: 1\.1
-done"
- cd ../first-dir
- echo force a conflict >>tfile
- dotest status-init-7 "${testcvs} -q up" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/tfile,v
-retrieving revision 1\.1
-retrieving revision 1\.2
-Merging differences between 1\.1 and 1\.2 into tfile
-rcsmerge: warning: conflicts during merge
-${PROG} update: conflicts found in tfile
-C tfile"
-
- # Now note our status
- dotest status-1 "${testcvs} status tfile" \
-"===================================================================
-File: tfile Status: Unresolved Conflict
-
- Working revision: 1\.2.*
- Repository revision: 1\.2 ${CVSROOT_DIRNAME}/first-dir/tfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
-
- # touch the file, leaving conflict markers in place
- # and note our status
- touch tfile
- dotest status-2 "${testcvs} status tfile" \
-"===================================================================
-File: tfile Status: File had conflicts on merge
-
- Working revision: 1\.2.*
- Repository revision: 1\.2 ${CVSROOT_DIRNAME}/first-dir/tfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
-
- # resolve the conflict
- echo resolution >tfile
- dotest status-3 "${testcvs} status tfile" \
-"===================================================================
-File: tfile Status: Locally Modified
-
- Working revision: 1\.2.*
- Repository revision: 1\.2 ${CVSROOT_DIRNAME}/first-dir/tfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
-
- # Check that there are no problems just using CVS/Root too.
- save_CVSROOT=$CVSROOT
- unset CVSROOT
- dotest status-3a "${testcvs} status tfile" \
-"===================================================================
-File: tfile Status: Locally Modified
-
- Working revision: 1\.2.*
- Repository revision: 1\.2 ${CVSROOT_DIRNAME}/first-dir/tfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- CVSROOT=$save_CVSROOT
- export CVSROOT
-
- # FIXCVS:
- # Update is supposed to re-Register() the file when it
- # finds resolved conflicts:
- dotest status-4 "grep 'Result of merge' CVS/Entries" \
-"/tfile/1\.2/Result of merge${PLUS}[a-zA-Z0-9 :]*//"
-
- cd ..
- mkdir fourth-dir
- dotest status-init-8 "$testcvs add fourth-dir" \
-"Directory $CVSROOT_DIRNAME/fourth-dir added to the repository"
- cd fourth-dir
- echo yet another line >t3file
- dotest status-init-9 "$testcvs add t3file" \
-"$PROG add: scheduling file .t3file. for addition
-$PROG add: use .$PROG commit. to add this file permanently"
- dotest status-init-10 "$testcvs -q ci -m add" \
-"RCS file: $CVSROOT_DIRNAME/fourth-dir/t3file,v
-done
-Checking in t3file;
-$CVSROOT_DIRNAME/fourth-dir/t3file,v <-- t3file
-initial revision: 1\.1
-done"
- cd ../first-dir
- mkdir third-dir
- dotest status-init-11 "$testcvs add third-dir" \
-"Directory $CVSROOT_DIRNAME/first-dir/third-dir added to the repository"
- cd third-dir
- echo another line >t2file
- dotest status-init-12 "$testcvs add t2file" \
-"$PROG add: scheduling file .t2file. for addition
-$PROG add: use .$PROG commit. to add this file permanently"
- dotest status-init-13 "$testcvs -q ci -m add" \
-"RCS file: $CVSROOT_DIRNAME/first-dir/third-dir/t2file,v
-done
-Checking in t2file;
-$CVSROOT_DIRNAME/first-dir/third-dir/t2file,v <-- t2file
-initial revision: 1\.1
-done"
- dotest status-5 "$testcvs status ../tfile" \
-"===================================================================
-File: tfile Status: Locally Modified
-
- Working revision: 1\.2.*
- Repository revision: 1\.2 $CVSROOT_DIRNAME/first-dir/tfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest status-6 "$testcvs status ../../fourth-dir/t3file" \
-"===================================================================
-File: t3file Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 $CVSROOT_DIRNAME/fourth-dir/t3file,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- cd ../../..
- rm -rf status
- rm -rf $CVSROOT_DIRNAME/first-dir $CVSROOT_DIRNAME/fourth-dir
- ;;
-
- rdiff)
- # Test rdiff
- # XXX for now this is just the most essential test...
- cd ${TESTDIR}
-
- mkdir testimport
- cd testimport
- echo '$''Id$' > foo
- echo '$''Name$' >> foo
- echo '$''Id$' > bar
- echo '$''Name$' >> bar
- dotest_sort rdiff-1 \
- "${testcvs} import -I ! -m test-import-with-keyword trdiff TRDIFF T1" \
-'
-
-N trdiff/bar
-N trdiff/foo
-No conflicts created by this import'
- dotest rdiff-2 \
- "${testcvs} co -ko trdiff" \
-"${PROG} checkout: Updating trdiff
-U trdiff/bar
-U trdiff/foo"
- cd trdiff
- echo something >> foo
- dotest rdiff-3 \
- "${testcvs} ci -m added-something foo" \
-"Checking in foo;
-${CVSROOT_DIRNAME}/trdiff/foo,v <-- foo
-new revision: 1\.2; previous revision: 1\.1
-done"
- echo '#ident "@(#)trdiff:$''Name$:$''Id$"' > new
- echo "new file" >> new
- dotest rdiff-4 \
- "${testcvs} add -m new-file-description new" \
-"${PROG} add: scheduling file \`new' for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest rdiff-5 \
- "${testcvs} commit -m added-new-file new" \
-"RCS file: ${CVSROOT_DIRNAME}/trdiff/new,v
-done
-Checking in new;
-${CVSROOT_DIRNAME}/trdiff/new,v <-- new
-initial revision: 1\.1
-done"
- dotest rdiff-6 \
- "${testcvs} tag local-v0" \
-"${PROG} tag: Tagging .
-T bar
-T foo
-T new"
- dotest rdiff-7 \
- "${testcvs} status -v foo" \
-"===================================================================
-File: foo Status: Up-to-date
-
- Working revision: 1\.2.*
- Repository revision: 1\.2 ${CVSROOT_DIRNAME}/trdiff/foo,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: -ko
-
- Existing Tags:
- local-v0 (revision: 1\.2)
- T1 (revision: 1\.1\.1\.1)
- TRDIFF (branch: 1\.1\.1)"
-
- cd ..
- rm -r trdiff
-
- dotest rdiff-8 \
- "${testcvs} rdiff -r T1 -r local-v0 trdiff" \
-"${PROG}"' rdiff: Diffing trdiff
-Index: trdiff/foo
-diff -c trdiff/foo:1\.1\.1\.1 trdiff/foo:1\.2
-\*\*\* trdiff/foo:1\.1\.1\.1 '"${DATE}"'
---- trdiff/foo '"${DATE}"'
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1,2 \*\*\*\*
-! \$''Id: foo,v 1\.1\.1\.1 [0-9/]* [0-9:]* '"${username}"' Exp \$
-! \$''Name: T1 \$
---- 1,3 ----
-! \$''Id: foo,v 1\.2 [0-9/]* [0-9:]* '"${username}"' Exp \$
-! \$''Name: local-v0 \$
-! something
-Index: trdiff/new
-diff -c /dev/null trdiff/new:1\.1
-\*\*\* /dev/null '"${DATE}"'
---- trdiff/new '"${DATE}"'
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 0 \*\*\*\*
---- 1,2 ----
-'"${PLUS}"' #ident "@(#)trdiff:\$''Name: local-v0 \$:\$''Id: new,v 1\.1 [0-9/]* [0-9:]* '"${username}"' Exp \$"
-'"${PLUS}"' new file'
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- cd ..
- rm -r testimport
- rm -rf ${CVSROOT_DIRNAME}/trdiff
- ;;
-
- rdiff-short)
- # Test that the short patch behaves as expected
- # 1) Added file.
- # 2) Removed file.
- # 3) Different revision number with no difference.
- # 4) Different revision number with changes.
- # 5) Against trunk.
- # 6) Same revision number (no difference).
- mkdir rdiff-short; cd rdiff-short
- mkdir abc
- dotest rdiff-short-init-1 \
-"${testcvs} -q import -I ! -m initial-import abc vendor initial" \
-'
-No conflicts created by this import'
-
- dotest rdiff-short-init-2 "${testcvs} -q get abc" ''
- cd abc
- echo "abc" >file1.txt
- dotest rdiff-short-init-3 "${testcvs} add file1.txt" \
-"${PROG} add: scheduling file .file1\.txt' for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest rdiff-short-init-4 \
-"${testcvs} commit -madd-file1 file1.txt" \
-"RCS file: ${CVSROOT_DIRNAME}/abc/file1\.txt,v
-done
-Checking in file1\.txt;
-${CVSROOT_DIRNAME}/abc/file1\.txt,v <-- file1\.txt
-initial revision: 1\.1
-done"
- echo def >>file1.txt
- dotest rdiff-short-init-5 \
-"${testcvs} commit -mchange-file1 file1.txt" \
-"Checking in file1\.txt;
-${CVSROOT_DIRNAME}/abc/file1\.txt,v <-- file1\.txt
-new revision: 1\.2; previous revision: 1\.1
-done"
- echo "abc" >file1.txt
- dotest rdiff-short-init-6 \
-"${testcvs} commit -mrestore-file1-rev1 file1.txt" \
-"Checking in file1\.txt;
-${CVSROOT_DIRNAME}/abc/file1\.txt,v <-- file1\.txt
-new revision: 1\.3; previous revision: 1\.2
-done"
- dotest rdiff-short-init-7 \
-"${testcvs} tag -r 1.1 tag1 file1.txt" \
-"T file1\.txt"
- dotest rdiff-short-init-8 \
-"${testcvs} tag -r 1.2 tag2 file1.txt" \
-"T file1\.txt"
- dotest rdiff-short-init-9 \
-"${testcvs} tag -r 1.3 tag3 file1.txt" \
-"T file1\.txt"
- echo "abc" >file2.txt
- dotest rdiff-short-init-10 \
-"${testcvs} add file2.txt" \
-"${PROG} add: scheduling file .file2\.txt' for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest rdiff-add-remove-nodiff-init-11 \
-"${testcvs} commit -madd-file2 file2.txt" \
-"RCS file: ${CVSROOT_DIRNAME}/abc/file2\.txt,v
-done
-Checking in file2\.txt;
-${CVSROOT_DIRNAME}/abc/file2\.txt,v <-- file2\.txt
-initial revision: 1\.1
-done"
- dotest rdiff-short-init-12 \
-"${testcvs} tag -r 1.1 tag4 file2.txt" \
-"T file2\.txt"
- dotest rdiff-short-init-13 \
-"${testcvs} tag -r 1.1 tag5 file2.txt" \
-"T file2\.txt"
- cd ../..
- rm -fr rdiff-short
-
- # 3) Different revision number with no difference.
- dotest rdiff-short-no-real-change \
-"${testcvs} -q rdiff -s -r tag1 -r tag3 abc"
-
- # 4) Different revision number with changes.
- dotest rdiff-short-real-change \
-"${testcvs} -q rdiff -s -r tag1 -r tag2 abc" \
-'File abc/file1.txt changed from revision 1\.1 to 1\.2'
-
- # 1) Added file.
- # 2) Removed file.
- dotest_sort rdiff-short-remove-add \
-"${testcvs} -q rdiff -s -r tag2 -r tag4 abc" \
-'File abc/file1\.txt is removed; tag2 revision 1\.2
-File abc/file2\.txt is new; tag4 revision 1\.1'
-
- # 6) Same revision number (no difference).
- dotest rdiff-short-no-change \
-"${testcvs} -q rdiff -s -r tag4 -r tag5 abc"
-
- # 5) Against trunk.
- # Check that the messages change when we diff against the trunk
- # rather than a tag or date.
- dotest rdiff-short-against-trunk-1 \
-"${testcvs} -q rdiff -s -rtag4 abc" \
-"File abc/file1\.txt is new; current revision 1\.3"
-
- dotest rdiff-short-against-trunk-2 \
-"${testcvs} -q rdiff -s -rtag2 abc" \
-"File abc/file1\.txt changed from revision 1\.2 to 1\.3
-File abc/file2\.txt is new; current revision 1\.1"
-
- rm -rf ${CVSROOT_DIRNAME}/abc
- ;;
-
- rdiff2)
- # Test for the segv problem reported by James Cribb
- # Somewhere to work
- mkdir rdiff2; cd rdiff2
- # Create a module "m" with files "foo" and "d/bar"
- mkdir m; cd m
- echo foo >foo
- mkdir d
- echo bar >d/bar
- dotest_sort rdiff2-1 \
-"${testcvs} -q import -I ! -m initial-import m vendor initial" \
-'
-
-N m/d/bar
-N m/foo
-No conflicts created by this import'
-
- cd ..
- rm -r m
-
- # Remove "foo"
- dotest rdiff2-2 "${testcvs} get m" \
-"${PROG} checkout: Updating m
-U m/foo
-${PROG} checkout: Updating m/d
-U m/d/bar"
- cd m
- dotest rdiff2-3 "${testcvs} rm -f foo" \
-"${PROG} remove: scheduling .foo. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
-
- dotest rdiff2-4 "${testcvs} commit -m Removed foo" \
-"Removing foo;
-${CVSROOT_DIRNAME}/m/foo,v <-- foo
-new revision: delete; previous revision: 1\.1\.1\.1
-done"
-
- # Modify "d/bar"
- echo foo >d/bar
- dotest rdiff2-5 "${testcvs} commit -m Changed d/bar" \
-"Checking in d/bar;
-${CVSROOT_DIRNAME}/m/d/bar,v <-- bar
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # Crash before showing d/bar diffs
- dotest_fail rdiff2-6 "${testcvs} rdiff -t m" \
-"${PROG} rdiff: Diffing m
-${PROG} rdiff: Diffing m/d
-Index: m/d/bar
-diff -c m/d/bar:1\.1\.1\.1 m/d/bar:1\.2
-\*\*\* m/d/bar:1\.1\.1\.1 ${DATE}
---- m/d/bar ${DATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-! bar
---- 1 ----
-! foo"
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
- cd ../..
- rm -rf rdiff2
- rm -rf ${CVSROOT_DIRNAME}/m
- ;;
-
- diff)
- # Various tests specific to the "cvs diff" command.
- # Related tests:
- # death2: -N
- # rcslib: cvs diff and $Name.
- # rdiff: cvs rdiff.
- # diffmerge*: nuts and bolts (stuff within diff library)
- mkdir 1; cd 1
- dotest diff-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest diff-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir 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} diff: I know nothing about xyzpdq"
- touch abc
- dotest diff-4 "${testcvs} add abc" \
-"${PROG} add: scheduling file .abc. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest diff-5 "${testcvs} -q ci -mtest" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
-done
-Checking in abc;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/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: ${CVSROOT_DIRNAME}/first-dir/abc,v
-retrieving revision 1\.2
-diff --ifdef HAVE_WINSOCK_H -r1\.2 abc
-#ifndef HAVE_WINSOCK_H
-extern int gethostname ();
-#else /\* HAVE_WINSOCK_H \*/
-#include <winsock\.h>
-#endif /\* HAVE_WINSOCK_H \*/"
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- cd ../..
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- rm -r 1
- ;;
-
- diffnl)
- # Test handling of 'cvs diff' of files without newlines
- mkdir 1; cd 1
- dotest diffnl-000 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest diffnl-001 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
-
- ${AWK} 'BEGIN {printf("one\ntwo\nthree\nfour\nfive\nsix")}' </dev/null >abc
- dotest diffnl-002 "${testcvs} add abc" \
-"${PROG} add: scheduling file .abc. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest diffnl-003 "${testcvs} -q ci -mtest" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
-done
-Checking in abc;
-${CVSROOT_DIRNAME}/first-dir/abc,v <-- abc
-initial revision: 1\.1
-done"
-
- # change to line near EOF
- ${AWK} 'BEGIN {printf("one\ntwo\nthree\nfour\nsix")}' </dev/null >abc
- dotest_fail diffnl-100 "${testcvs} diff abc" \
-"Index: abc
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
-retrieving revision 1\.1
-diff -r1\.1 abc
-5d4
-< five"
- dotest_fail diffnl-101 "${testcvs} diff -u abc" \
-"Index: abc
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
-retrieving revision 1\.1
-diff -u -r1\.1 abc
---- abc ${RFCDATE} 1\.1
-+++ abc ${RFCDATE}
-@@ -2,5 +2,4 @@
- two
- three
- four
--five
- six
-\\\\ No newline at end of file"
- dotest diffnl-102 "${testcvs} -q ci -mtest abc" \
-"Checking in abc;
-${CVSROOT_DIRNAME}/first-dir/abc,v <-- abc
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # Change to last line
- ${AWK} 'BEGIN {printf("one\ntwo\nthree\nfour\nseven")}' </dev/null >abc
- dotest_fail diffnl-200 "${testcvs} diff abc" \
-"Index: abc
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
-retrieving revision 1\.2
-diff -r1\.2 abc
-5c5
-< six
-\\\\ No newline at end of file
----
-> seven
-\\\\ No newline at end of file"
- dotest_fail diffnl-201 "${testcvs} diff -u abc" \
-"Index: abc
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
-retrieving revision 1\.2
-diff -u -r1\.2 abc
---- abc ${RFCDATE} 1\.2
-+++ abc ${RFCDATE}
-@@ -2,4 +2,4 @@
- two
- three
- four
--six
-\\\\ No newline at end of file
-+seven
-\\\\ No newline at end of file"
- dotest diffnl-202 "${testcvs} ci -mtest abc" \
-"Checking in abc;
-${CVSROOT_DIRNAME}/first-dir/abc,v <-- abc
-new revision: 1\.3; previous revision: 1\.2
-done"
-
- # Addition of newline
- echo "one
-two
-three
-four
-seven" > abc
- dotest_fail diffnl-300 "${testcvs} diff abc" \
-"Index: abc
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
-retrieving revision 1\.3
-diff -r1\.3 abc
-5c5
-< seven
-\\\\ No newline at end of file
----
-> seven"
- dotest_fail diffnl-301 "${testcvs} diff -u abc" \
-"Index: abc
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
-retrieving revision 1\.3
-diff -u -r1\.3 abc
---- abc ${RFCDATE} 1\.3
-+++ abc ${RFCDATE}
-@@ -2,4 +2,4 @@
- two
- three
- four
--seven
-\\\\ No newline at end of file
-+seven"
- dotest diffnl-302 "${testcvs} ci -mtest abc" \
-"Checking in abc;
-${CVSROOT_DIRNAME}/first-dir/abc,v <-- abc
-new revision: 1\.4; previous revision: 1\.3
-done"
-
- # Removal of newline
- ${AWK} 'BEGIN {printf("one\ntwo\nthree\nfour\nseven")}' </dev/null >abc
- dotest_fail diffnl-400 "${testcvs} diff abc" \
-"Index: abc
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
-retrieving revision 1\.4
-diff -r1\.4 abc
-5c5
-< seven
----
-> seven
-\\\\ No newline at end of file"
- dotest_fail diffnl-401 "${testcvs} diff -u abc" \
-"Index: abc
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
-retrieving revision 1\.4
-diff -u -r1\.4 abc
---- abc ${RFCDATE} 1\.4
-+++ abc ${RFCDATE}
-@@ -2,4 +2,4 @@
- two
- three
- four
--seven
-+seven
-\\\\ No newline at end of file"
-
- cd ../..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- death)
- # next dive. test death support.
-
- # NOTE: this section has reached the size and
- # complexity where it is getting to be a good idea to
- # add new death support tests to a new section rather
- # than continuing to piggyback them onto the tests here.
-
- mkdir ${CVSROOT_DIRNAME}/first-dir
- if ${CVS} co first-dir ; then
- pass 65
- else
- fail 65
- fi
-
- cd first-dir
-
- # Create a directory with only dead files, to make sure CVS
- # doesn't get confused by it.
- mkdir subdir
- dotest 65a0 "${testcvs} add subdir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/subdir added to the repository"
- cd subdir
- echo file in subdir >sfile
- dotest 65a1 "${testcvs} add sfile" \
-"${PROG}"' add: scheduling file `sfile'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest 65a2 "${testcvs} -q ci -m add-it" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/subdir/sfile,v
-done
-Checking in sfile;
-${CVSROOT_DIRNAME}/first-dir/subdir/sfile,v <-- sfile
-initial revision: 1\.1
-done"
- rm sfile
- dotest 65a3 "${testcvs} rm sfile" \
-"${PROG}"' remove: scheduling `sfile'\'' for removal
-'"${PROG}"' remove: use .'"${PROG}"' commit. to remove this file permanently'
- dotest 65a4 "${testcvs} -q ci -m remove-it" \
-"Removing sfile;
-${CVSROOT_DIRNAME}/first-dir/subdir/sfile,v <-- sfile
-new revision: delete; previous revision: 1\.1
-done"
- cd ..
- dotest 65a5 "${testcvs} -q update -P" ''
- dotest_fail 65a6 "test -d subdir" ''
-
- # add a file.
- touch file1
- if ${CVS} add file1 2>> ${LOGFILE}; then
- pass 66
- else
- fail 66
- fi
-
- # commit
- if ${CVS} ci -m test >> ${LOGFILE} 2>&1; then
- pass 67
- else
- fail 67
- fi
-
- # remove
- rm file1
- if ${CVS} rm file1 2>> ${LOGFILE}; then
- pass 68
- else
- fail 68
- fi
-
- # commit
- if ${CVS} ci -m test >>${LOGFILE} ; then
- pass 69
- else
- fail 69
- fi
-
- dotest_fail 69a0 "test -f file1" ''
- # get the old contents of file1 back
- if ${testcvs} update -p -r 1.1 file1 >file1 2>>${LOGFILE}; then
- pass 69a1
- else
- fail 69a1
- fi
- dotest 69a2 "cat file1" ''
-
- # create second file
- touch file2
- if ${CVS} add file1 file2 2>> ${LOGFILE}; then
- pass 70
- else
- fail 70
- fi
-
- # commit
- if ${CVS} ci -m test >> ${LOGFILE} 2>&1; then
- pass 71
- else
- fail 71
- fi
-
- # log
- if ${CVS} log file1 >> ${LOGFILE}; then
- pass 72
- else
- fail 72
- fi
-
- # file4 will be dead at the time of branching and stay dead.
- echo file4 > file4
- dotest death-file4-add "${testcvs} add file4" \
-"${PROG}"' add: scheduling file `file4'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest death-file4-ciadd "${testcvs} -q ci -m add file4" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file4,v
-done
-Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-initial revision: 1\.1
-done"
- rm file4
- dotest death-file4-rm "${testcvs} remove file4" \
-"${PROG}"' remove: scheduling `file4'\'' for removal
-'"${PROG}"' remove: use .'"${PROG}"' commit. to remove this file permanently'
- dotest death-file4-cirm "${testcvs} -q ci -m remove file4" \
-"Removing file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: delete; previous revision: 1\.1
-done"
-
- # Tag the branchpoint.
- dotest death-72a "${testcvs} -q tag bp_branch1" 'T file1
-T file2'
-
- # branch1
- if ${CVS} tag -b branch1 ; then
- pass 73
- else
- fail 73
- fi
-
- # and move to the branch.
- if ${CVS} update -r branch1 ; then
- pass 74
- else
- fail 74
- fi
-
- dotest_fail death-file4-3 "test -f file4" ''
-
- # add a file in the branch
- echo line1 from branch1 >> file3
- if ${CVS} add file3 2>> ${LOGFILE}; then
- pass 75
- else
- fail 75
- fi
-
- # commit
- if ${CVS} ci -m test >> ${LOGFILE} 2>&1; then
- pass 76
- else
- fail 76
- fi
-
- dotest death-76a0 \
-"${testcvs} -q rdiff -r bp_branch1 -r branch1 first-dir" \
-"Index: first-dir/file3
-diff -c /dev/null first-dir/file3:1\.1\.2\.1
-\*\*\* /dev/null ${DATE}
---- first-dir/file3 ${DATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 0 \*\*\*\*
---- 1 ----
-${PLUS} line1 from branch1"
- dotest death-76a1 \
-"${testcvs} -q rdiff -r branch1 -r bp_branch1 first-dir" \
-"Index: first-dir/file3
-diff -c first-dir/file3:1\.1\.2\.1 first-dir/file3:removed
-\*\*\* first-dir/file3:1\.1\.2\.1 ${DATE}
---- first-dir/file3 ${DATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-- line1 from branch1
---- 0 ----"
-
- # remove
- rm file3
- if ${CVS} rm file3 2>> ${LOGFILE}; then
- pass 77
- else
- fail 77
- fi
-
- # commit
- if ${CVS} ci -m test >>${LOGFILE} ; then
- pass 78
- else
- fail 78
- fi
-
- # add again
- echo line1 from branch1 >> file3
- if ${CVS} add file3 2>> ${LOGFILE}; then
- pass 79
- else
- fail 79
- fi
-
- # commit
- if ${CVS} ci -m test >> ${LOGFILE} 2>&1; then
- pass 80
- else
- fail 80
- fi
-
- # change the first file
- echo line2 from branch1 >> file1
-
- # commit
- if ${CVS} ci -m test >> ${LOGFILE} 2>&1; then
- pass 81
- else
- fail 81
- fi
-
- # remove the second
- rm file2
- if ${CVS} rm file2 2>> ${LOGFILE}; then
- pass 82
- else
- fail 82
- fi
-
- # commit
- if ${CVS} ci -m test >>${LOGFILE}; then
- pass 83
- else
- fail 83
- fi
-
- # back to the trunk.
- if ${CVS} update -A 2>> ${LOGFILE}; then
- pass 84
- else
- fail 84
- fi
-
- dotest_fail death-file4-4 "test -f file4" ''
-
- if test -f file3 ; then
- fail 85
- else
- pass 85
- fi
-
- # join
- dotest 86 "${testcvs} -q update -j branch1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-retrieving revision 1\.3
-retrieving revision 1\.3\.2\.1
-Merging differences between 1\.3 and 1\.3\.2\.1 into file1
-${PROG} update: scheduling file2 for removal
-U file3"
-
- dotest_fail death-file4-5 "test -f file4" ''
-
- if test -f file3 ; then
- pass 87
- else
- fail 87
- fi
-
- # Make sure that we joined the correct change to file1
- if echo line2 from branch1 | cmp - file1 >/dev/null; then
- pass 87a
- else
- fail 87a
- fi
-
- # update
- if ${CVS} update ; then
- pass 88
- else
- fail 88
- fi
-
- # commit
- dotest 89 "${testcvs} -q ci -m test" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.4; previous revision: 1\.3
-done
-Removing file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: delete; previous revision: 1\.1
-done
-Checking in file3;
-${CVSROOT_DIRNAME}/first-dir/file3,v <-- file3
-new revision: 1\.2; previous revision: 1\.1
-done"
- cd ..
- mkdir 2
- cd 2
- dotest 89a "${testcvs} -q co first-dir" 'U first-dir/file1
-U first-dir/file3'
- cd ..
- rm -r 2
- cd first-dir
-
- # remove first file.
- rm file1
- if ${CVS} rm file1 2>> ${LOGFILE}; then
- pass 90
- else
- fail 90
- fi
-
- # commit
- if ${CVS} ci -m test >>${LOGFILE}; then
- pass 91
- else
- fail 91
- fi
-
- if test -f file1 ; then
- fail 92
- else
- pass 92
- fi
-
- # typo; try to get to the branch and fail
- dotest_fail 92.1a "${testcvs} update -r brnach1" \
- "${PROG}"' \[update aborted\]: no such tag brnach1'
- # Make sure we are still on the trunk
- if test -f file1 ; then
- fail 92.1b
- else
- pass 92.1b
- fi
- if test -f file3 ; then
- pass 92.1c
- else
- fail 92.1c
- fi
-
- # back to branch1
- if ${CVS} update -r branch1 2>> ${LOGFILE}; then
- pass 93
- else
- fail 93
- fi
-
- dotest_fail death-file4-6 "test -f file4" ''
-
- if test -f file1 ; then
- pass 94
- else
- fail 94
- fi
-
- # and join
- dotest 95 "$testcvs -q update -j HEAD" \
-"$PROG update: file file1 has been removed in revision HEAD, but the destination is incompatibly modified
-C file1
-$PROG update: file file3 exists, but has been added in revision HEAD"
-
- dotest_fail death-file4-7 "test -f file4" ''
-
- # file2 should not have been recreated. It was
- # deleted on the branch, and has not been modified on
- # the trunk. That means that there have been no
- # changes between the greatest common ancestor (the
- # trunk version) and HEAD.
- dotest_fail death-file2-1 "test -f file2" ''
-
- cd .. ; rm -rf first-dir ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- death2)
- # More tests of death support.
- mkdir ${CVSROOT_DIRNAME}/first-dir
- dotest death2-1 "${testcvs} -q co first-dir" ''
-
- cd first-dir
-
- # Add two files on the trunk.
- echo "first revision" > file1
- echo "file4 first revision" > file4
- dotest death2-2 "${testcvs} add file1 file4" \
-"${PROG}"' add: scheduling file `file1'\'' for addition
-'"${PROG}"' add: scheduling file `file4'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add these files permanently'
-
- dotest death2-3 "${testcvs} -q commit -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file4,v
-done
-Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-initial revision: 1\.1
-done"
-
- # Make a branch and a non-branch tag.
- dotest death2-4 "${testcvs} -q tag -b branch" \
-'T file1
-T file4'
- dotest death2-5 "${testcvs} -q tag tag" \
-'T file1
-T file4'
-
- # Switch over to the branch.
- dotest death2-6 "$testcvs -q update -r branch" \
-'[UP] file1
-[UP] file4'
-
- # Delete the file on the branch.
- rm file1
- dotest death2-7 "${testcvs} rm file1" \
-"${PROG} remove: scheduling .file1. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
-
- # Test diff of the removed file before it is committed.
- dotest_fail death2-diff-1 "${testcvs} -q diff file1" \
-"${PROG} diff: file1 was removed, no comparison available"
-
- dotest_fail death2-diff-2 "${testcvs} -q diff -N -c file1" \
-"Index: file1
-===================================================================
-RCS file: file1
-diff -N file1
-\*\*\* file1 ${RFCDATE} [0-9.]*
---- /dev/null ${RFCDATE_EPOCH}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-- first revision
---- 0 ----"
-
- dotest death2-8 "${testcvs} -q ci -m removed" \
-"Removing file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: delete; previous revision: 1\.1
-done"
-
- # Test diff of a dead file.
- dotest_fail death2-diff-3 \
-"${testcvs} -q diff -r1.1 -rbranch -c file1" \
-"${PROG} diff: Tag branch refers to a dead (removed) revision in file .file1.\.
-${PROG} diff: No comparison available\. Pass .-N. to .${PROG} diff.${QUESTION}"
- # and in reverse
- dotest_fail death2-diff-3a \
-"${testcvs} -q diff -rbranch -r1.1 -c file1" \
-"${PROG} diff: Tag branch refers to a dead (removed) revision in file .file1.\.
-${PROG} diff: No comparison available\. Pass .-N. to .${PROG} diff.${QUESTION}"
-
- dotest_fail death2-diff-4 \
-"${testcvs} -q diff -r1.1 -rbranch -N -c file1" \
-"Index: file1
-===================================================================
-RCS file: file1
-diff -N file1
-\*\*\* file1 ${RFCDATE} [0-9.]*
---- /dev/null ${RFCDATE_EPOCH}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-- first revision
---- 0 ----"
- # and in reverse
- dotest_fail death2-diff-4a \
-"${testcvs} -q diff -rbranch -r1.1 -N -c file1" \
-"Index: file1
-===================================================================
-RCS file: file1
-diff -N file1
-\*\*\* /dev/null ${RFCDATE_EPOCH}
---- file1 ${RFCDATE} [0-9.]*
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 0 \*\*\*\*
---- 1 ----
-+ first revision"
-
-
- dotest_fail death2-diff-5 "${testcvs} -q diff -rtag -c ." \
-"${PROG} diff: file1 no longer exists, no comparison available"
-
- dotest_fail death2-diff-6 "${testcvs} -q diff -rtag -N -c ." \
-"Index: file1
-===================================================================
-RCS file: file1
-diff -N file1
-\*\*\* file1 [-a-zA-Z0-9: ]* [0-9.]*
---- /dev/null ${RFCDATE_EPOCH}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-- first revision
---- 0 ----"
-
- # Test rdiff of a dead file.
- dotest death2-rdiff-1 \
-"${testcvs} -q rtag -rbranch rdiff-tag first-dir" ''
-
- dotest death2-rdiff-2 "${testcvs} -q rdiff -rtag -rbranch first-dir" \
-"Index: first-dir/file1
-diff -c first-dir/file1:1\.1 first-dir/file1:removed
-\*\*\* first-dir/file1:1\.1 [a-zA-Z0-9: ]*
---- first-dir/file1 [a-zA-Z0-9: ]*
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-- first revision
---- 0 ----"
-
- # Readd the file to the branch.
- echo "second revision" > file1
- dotest death2-9 "${testcvs} add file1" \
-"${PROG}"' add: file `file1'\'' will be added on branch `branch'\'' from version 1\.1\.2\.1
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
-
- # Test diff of the added file before it is committed.
- dotest_fail death2-diff-7 "${testcvs} -q diff file1" \
-"${PROG} diff: file1 is a new entry, no comparison available"
-
- dotest_fail death2-diff-8 "${testcvs} -q diff -N -c file1" \
-"Index: file1
-===================================================================
-RCS file: file1
-diff -N file1
-\*\*\* /dev/null ${RFCDATE_EPOCH}
---- file1 ${RFCDATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 0 \*\*\*\*
---- 1 ----
-${PLUS} second revision"
-
- dotest death2-10 "${testcvs} -q commit -m add" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
-done"
-
- # Delete file4 from the branch
- dotest death2-10a "${testcvs} rm -f file4" \
-"${PROG} remove: scheduling .file4. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest death2-10b "${testcvs} -q ci -m removed" \
-"Removing file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: delete; previous revision: 1\.1
-done"
-
- # Back to the trunk.
- dotest death2-11 "${testcvs} -q update -A" \
-"[UP] file1
-U file4"
-
- # Add another file on the trunk.
- echo "first revision" > file2
- dotest death2-12 "${testcvs} add file2" \
-"${PROG}"' add: scheduling file `file2'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest death2-13 "${testcvs} -q commit -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1\.1
-done"
-
- # Modify file4 on the trunk.
- echo "new file4 revision" > file4
- dotest death2-13a "${testcvs} -q commit -m mod" \
-"Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # Back to the branch.
- # The ``no longer in the repository'' message doesn't really
- # look right to me, but that's what CVS currently prints for
- # this case.
- dotest death2-14 "${testcvs} -q update -r branch" \
-"[UP] file1
-${PROG} update: file2 is no longer in the repository
-${PROG} update: file4 is no longer in the repository"
-
- # Add a file on the branch with the same name.
- echo "branch revision" > file2
- dotest death2-15 "${testcvs} add file2" \
-"${PROG}"' add: scheduling file `file2'\'' for addition on branch `branch'\''
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest death2-16 "${testcvs} -q commit -m add" \
-"Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
-done"
-
- # Add a new file on the branch.
- echo "first revision" > file3
- dotest death2-17 "${testcvs} add file3" \
-"${PROG}"' add: scheduling file `file3'\'' for addition on branch `branch'\''
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest death2-18 "${testcvs} -q commit -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file3,v
-done
-Checking in file3;
-${CVSROOT_DIRNAME}/first-dir/Attic/file3,v <-- file3
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
-
- # Test diff of a nonexistent tag
- dotest_fail death2-diff-9 "${testcvs} -q diff -rtag -c file3" \
-"${PROG} diff: tag tag is not in file file3"
-
- dotest_fail death2-diff-10 "${testcvs} -q diff -rtag -N -c file3" \
-"Index: file3
-===================================================================
-RCS file: file3
-diff -N file3
-\*\*\* /dev/null ${RFCDATE_EPOCH}
---- file3 ${RFCDATE} [0-9.]*
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 0 \*\*\*\*
---- 1 ----
-${PLUS} first revision"
-
- dotest_fail death2-diff-11 "${testcvs} -q diff -rtag -c ." \
-"Index: file1
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-retrieving revision 1\.1
-retrieving revision 1\.1\.2\.2
-diff -c -r1\.1 -r1\.1\.2\.2
-\*\*\* file1 ${RFCDATE} [0-9.]*
---- file1 ${RFCDATE} [0-9.]*
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-! first revision
---- 1 ----
-! second revision
-${PROG} diff: tag tag is not in file file2
-${PROG} diff: tag tag is not in file file3
-${PROG} diff: file4 no longer exists, no comparison available"
-
- dotest_fail death2-diff-12 "${testcvs} -q diff -rtag -c -N ." \
-"Index: file1
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-retrieving revision 1\.1
-retrieving revision 1\.1\.2\.2
-diff -c -r1\.1 -r1\.1\.2\.2
-\*\*\* file1 ${RFCDATE} [0-9.]*
---- file1 ${RFCDATE} [0-9.]*
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-! first revision
---- 1 ----
-! second revision
-Index: file2
-===================================================================
-RCS file: file2
-diff -N file2
-\*\*\* /dev/null ${RFCDATE_EPOCH}
---- file2 ${RFCDATE} [0-9.]*
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 0 \*\*\*\*
---- 1 ----
-${PLUS} branch revision
-Index: file3
-===================================================================
-RCS file: file3
-diff -N file3
-\*\*\* /dev/null ${RFCDATE_EPOCH}
---- file3 ${RFCDATE} [0-9.]*
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 0 \*\*\*\*
---- 1 ----
-${PLUS} first revision
-Index: file4
-===================================================================
-RCS file: file4
-diff -N file4
-\*\*\* file4 ${RFCDATE} [0-9.]*
---- /dev/null ${RFCDATE_EPOCH}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-- file4 first revision
---- 0 ----"
-
- # Switch to the nonbranch tag.
- dotest death2-19 "${testcvs} -q update -r tag" \
-"[UP] file1
-${PROG} update: file2 is no longer in the repository
-${PROG} update: file3 is no longer in the repository
-U file4"
-
- dotest_fail death2-20 "test -f file2"
-
- # Make sure diff only reports appropriate files.
- dotest_fail death2-diff-13 "${testcvs} -q diff -r rdiff-tag" \
-"${PROG} diff: Tag rdiff-tag refers to a dead (removed) revision in file .file1.\.
-${PROG} diff: No comparison available\. Pass .-N. to .${PROG} diff.${QUESTION}"
-
- dotest_fail death2-diff-14 "${testcvs} -q diff -r rdiff-tag -c -N" \
-"Index: file1
-===================================================================
-RCS file: file1
-diff -N file1
-\*\*\* /dev/null ${RFCDATE_EPOCH}
---- file1 ${RFCDATE} [0-9.]*
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 0 \*\*\*\*
---- 1 ----
-${PLUS} first revision"
-
- # now back to the trunk
- dotest death2-21 "$testcvs -q update -A" \
-'[UP] file1
-U file2
-U file4'
-
- # test merging with a dead file
- dotest death2-22 "${testcvs} -q co first-dir" \
-"U first-dir/file1
-U first-dir/file2
-U first-dir/file4"
-
- cd first-dir
- dotest death2-23 "${testcvs} rm -f file4" \
-"${PROG} remove: scheduling .file4. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest death2-24 "${testcvs} -q ci -m removed file4" \
-"Removing file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: delete; previous revision: 1\.2
-done"
- cd ..
- echo "new stuff" >file4
- dotest_fail death2-25 "${testcvs} up file4" \
-"${PROG} update: conflict: file4 is modified but no longer in the repository
-C file4"
-
- cd .. ; rm -rf first-dir ${CVSROOT_DIRNAME}/first-dir
- ;;
-
-
-
- death-rtag)
- # This documents a bug in CVS that prevents rtag from tagging files
- # in the Attic.
- mkdir $CVSROOT_DIRNAME/death-rtag
- dotest death-rtag-init-1 "$testcvs -Q co death-rtag"
- cd death-rtag
- echo "This is the file foo" > foo
- echo "This is the file bar" > bar
- dotest death-rtag-init-2 "$testcvs -Q add foo bar"
- dotest death-rtag-init-3 "$testcvs -Q ci -m 'Add foo and bar.'" \
-"RCS file: $CVSROOT_DIRNAME/death-rtag/bar,v
-done
-Checking in bar;
-$CVSROOT_DIRNAME/death-rtag/bar,v <-- bar
-initial revision: 1\.[0-9]*
-done
-RCS file: $CVSROOT_DIRNAME/death-rtag/foo,v
-done
-Checking in foo;
-$CVSROOT_DIRNAME/death-rtag/foo,v <-- foo
-initial revision: 1\.[0-9]*
-done"
- dotest death-rtag-init-5 "$testcvs -Q tag -b mybranch"
-
- dotest death-rtag-1 "$testcvs -q rtag -rmybranch willtag death-rtag"
- dotest death-rtag-2 "$testcvs -Q rm -f foo"
- dotest death-rtag-3 "$testcvs -Q ci -m 'Remove foo.'" \
-"Removing foo;
-$CVSROOT_DIRNAME/death-rtag/foo,v <-- foo
-new revision: delete; previous revision: 1\.[0-9]*
-done"
- # commit something on the branch so that the moving tag is visible.
- dotest death-rtag-3.2 "$testcvs -Q up -rmybranch"
- echo some branch content >>foo
- echo some branch content >>bar
- dotest death-rtag-3.3 "$testcvs -Q ci -m 'Change foo.'" \
-"Checking in bar;
-$CVSROOT_DIRNAME/death-rtag/bar,v <-- bar
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in foo;
-$CVSROOT_DIRNAME/death-rtag/Attic/foo,v <-- foo
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
- dotest death-rtag-3.4 \
-"$testcvs -q rtag -rmybranch wontmove death-rtag"
- dotest death-rtag-3.5 "$testcvs -q rtag -F wontmove death-rtag"
-
- cd ..
- # Removing -f below avoids this bug.
- dotest death-rtag-4 "$testcvs -q rtag -frmybranch wonttag death-rtag"
-
- # When the bug existed, `wonttag' would not have been present in
- # foo,v.
- #
- # A second bug prevented `wontmove' from moving from the branch to
- # the dead revision on the trunk (death-rtag-3.4 & death-rtag-3.5).
- dotest death-rtag-5 "$testcvs -q rlog death-rtag" \
-"
-RCS file: $CVSROOT_DIRNAME/death-rtag/bar,v
-head: 1.[0-9]*
-branch:
-locks: strict
-access list:
-symbolic names:
- wonttag: 1\.1\.2\.1
- wontmove: 1\.1
- willtag: 1\.1
- mybranch: 1\.1.0\.2
-keyword substitution: kv
-$DOTSTAR
-RCS file: $CVSROOT_DIRNAME/death-rtag/Attic/foo,v
-head: 1.[0-9]*
-branch:
-locks: strict
-access list:
-symbolic names:
- wonttag: 1\.1\.2\.1
- wontmove: 1\.2
- willtag: 1\.1
- mybranch: 1\.1.0\.2
-keyword substitution: kv
-$DOTSTAR"
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- rm -r death-rtag
- rm -rf $CVSROOT_DIRNAME/death-rtag
- ;;
-
-
-
- rm-update-message)
- # FIXME
- # local CVS prints a warning message when update notices a missing
- # file and client/server CVS doesn't. These should be identical.
- mkdir rm-update-message; cd rm-update-message
- mkdir $CVSROOT_DIRNAME/rm-update-message
- dotest rm-update-message-setup-1 "$testcvs -q co rm-update-message" ''
- cd rm-update-message
- file=x
- echo >$file
- dotest rm-update-message-setup-2 "$testcvs -q add $file" \
-"${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest rm-update-message-setup-3 "$testcvs -q ci -mcreate $file" \
-"RCS file: $CVSROOT_DIRNAME/rm-update-message/$file,v
-done
-Checking in $file;
-$CVSROOT_DIRNAME/rm-update-message/$file,v <-- $file
-initial revision: 1\.1
-done"
-
- rm $file
- dotest rm-update-message-1 "$testcvs up $file" \
-"${PROG} update: warning: $file was lost
-U $file"
-
- cd ../..
- if $keep; then :; else
- rm -rf rm-update-message
- rm -rf $CVSROOT_DIRNAME/rm-update-message
- fi
- ;;
-
- rmadd)
- # More tests of adding and removing files.
- # In particular ci -r.
- # Other ci -r tests:
- # * editor-9: checking in a modified file,
- # where "ci -r" means a branch.
- # * basica-8a1: checking in a modified file with numeric revision.
- # * basica-8a2: likewise.
- # * keywordlog-4: adding a new file with numeric revision.
- mkdir 1; cd 1
- dotest rmadd-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest rmadd-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- echo first file1 >file1
- dotest rmadd-3 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
-
- dotest_fail rmadd-4 "${testcvs} -q ci -r 1.2.2.4 -m add" \
-"${PROG} commit: cannot add file .file1' with revision .1\.2\.2\.4'; must be on trunk
-${PROG} \[commit aborted\]: correct above errors first!"
- dotest_fail rmadd-5 "${testcvs} -q ci -r 1.2.2 -m add" \
-"${PROG} commit: cannot add file .file1' with revision .1\.2\.2'; must be on trunk
-${PROG} \[commit aborted\]: correct above errors first!"
- dotest_fail rmadd-6 "${testcvs} -q ci -r mybranch -m add" \
-"${PROG} \[commit aborted\]: no such tag mybranch"
-
- # The thing with the trailing periods strikes me as a very
- # bizarre behavior, but it would seem to be intentional
- # (see commit.c). It probably could go away....
- dotest rmadd-7 "${testcvs} -q ci -r 7.... -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 7\.1
-done"
- if $remote; then
- # I guess remote doesn't set a sticky tag in this case.
- # Kind of odd, in the sense that rmadd-24a does set one
- # both local and remote.
- dotest_fail rmadd-7a "test -f CVS/Tag"
- echo T7 >CVS/Tag
- else
- dotest rmadd-7a "cat CVS/Tag" "T7"
- fi
-
- dotest rmadd-8 "${testcvs} -q tag -b mybranch" "T file1"
- dotest rmadd-9 "${testcvs} -q tag mynonbranch" "T file1"
-
- touch file2
- # The previous "cvs ci -r" set a sticky tag of '7'. Seems a
- # bit odd, and I guess commit.c (findmaxrev) makes '7' sticky
- # tags unnecessary (?). I kind of suspect that it should be
- # saying "sticky tag is not a branch" like keywordlog-4b.
- # Or something.
- dotest rmadd-10 "${testcvs} add file2" \
-"${PROG} add: scheduling file .file2. for addition on branch .7'
-${PROG} add: 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: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/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} add: scheduling file .file3. for addition
-${PROG} add: 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} commit: Up-to-date check failed for .file2'
-${PROG} \[commit aborted\]: correct above errors first!"
- # Whatever, let's not let file2 distract us....
- dotest rmadd-15 "${testcvs} -q ci -r mybranch -m add file3" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file3,v
-done
-Checking in file3;
-${CVSROOT_DIRNAME}/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} add: scheduling file .file4. for addition
-${PROG} add: 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} \[commit 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} \[commit aborted\]: no such tag mynonbranch"
- # Now make CVS write val-tags for real.
- dotest rmadd-20 "$testcvs -q update -r mynonbranch file1" '[UP] 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: ${CVSROOT_DIRNAME}/first-dir/Attic/file4,v
-done
-Checking in file4;
-${CVSROOT_DIRNAME}/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} add: scheduling file .file5. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- if $remote; then
- # Interesting bug (or missing feature) here. findmaxrev
- # gets the major revision from the Entries. Well, remote
- # doesn't send the entries for files which are not involved.
- dotest rmadd-23r "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file5,v
-done
-Checking in file5;
-${CVSROOT_DIRNAME}/first-dir/file5,v <-- file5
-initial revision: 1\.1
-done"
- dotest rmadd-23-workaroundr \
-"${testcvs} -q ci -r 7 -m bump-it file5" \
-"Checking in file5;
-${CVSROOT_DIRNAME}/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: ${CVSROOT_DIRNAME}/first-dir/file5,v
-done
-Checking in file5;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/first-dir/file5,v <-- file5
-${PROG} commit: ${CVSROOT_DIRNAME}/first-dir/file5,v: revision 4\.8 too low; must be higher than 7\.1
-${PROG} commit: could not check in file5"
- dotest rmadd-24a "${testcvs} -q ci -r 8.4 -m change file5" \
-"Checking in file5;
-${CVSROOT_DIRNAME}/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 ${CVSROOT_DIRNAME}/first-dir/file5,v
- Sticky Tag: 8\.4
- Sticky Date: (none)
- Sticky Options: (none)"
-
- # now try forced revision with recursion
- mkdir sub
- dotest rmadd-26 "${testcvs} -q add sub" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/sub added to the repository"
- echo hello >sub/subfile
- dotest rmadd-27 "${testcvs} -q add sub/subfile" \
-"${PROG} add: use .${PROG} commit. to add this file permanently"
-
- dotest rmadd-28 "${testcvs} -q ci -m. sub" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/sub/subfile,v
-done
-Checking in sub/subfile;
-${CVSROOT_DIRNAME}/first-dir/sub/subfile,v <-- subfile
-initial revision: 1\.1
-done"
-
- # lose the branch
- dotest rmadd-29 "$testcvs -q up -A" \
-"[UP] file1
-$PROG update: file3 is no longer in the repository
-$PROG update: file4 is no longer in the repository"
-
- # -f disables recursion
- dotest rmadd-30 "${testcvs} -q ci -f -r9 -m." \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 9\.1; previous revision: 7\.1
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 9\.1; previous revision: 7\.1
-done
-Checking in file5;
-${CVSROOT_DIRNAME}/first-dir/file5,v <-- file5
-new revision: 9\.1; previous revision: 8\.4
-done"
-
- # add -R to force recursion
- dotest rmadd-31 "${testcvs} -q ci -f -r9 -R -m." \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 9\.2; previous revision: 9\.1
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 9\.2; previous revision: 9\.1
-done
-Checking in file5;
-${CVSROOT_DIRNAME}/first-dir/file5,v <-- file5
-new revision: 9\.2; previous revision: 9\.1
-done
-Checking in sub/subfile;
-${CVSROOT_DIRNAME}/first-dir/sub/subfile,v <-- subfile
-new revision: 9\.1; previous revision: 1\.1
-done"
-
- if $remote; then
- # as noted above, remote doesn't set a sticky tag
- :
- else
- dotest rmadd-32 "cat CVS/Tag" "T9"
- dotest rmadd-33 "cat sub/CVS/Tag" "T9"
- fi
-
- 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 ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- echo 'initial contents' >file1
- dotest rmadd2-3 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest rmadd2-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/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} remove: scheduling .file1. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest rmadd2-6 "${testcvs} -q ci -m remove" \
-"Removing file1;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/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: ${CVSROOT_DIRNAME}/first-dir/file1,v
-retrieving revision 1\.4
-retrieving revision 1\.3
-Merging differences between 1\.4 and 1\.3 into file1"
- dotest rmadd2-11 "${testcvs} -q ci -m undo" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/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} update: scheduling file1 for removal"
-
- # Check that -p can get arbitrary revisions of a removed file
- dotest rmadd2-14a "${testcvs} -q update -p" "initial contents"
- dotest rmadd2-14b "${testcvs} -q update -p -r 1.5" "initial contents"
- dotest rmadd2-14c "${testcvs} -q update -p -r 1.3" "initial contents"
-
- dotest rmadd2-15 "${testcvs} -q ci -m re-remove" \
-"Removing file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: delete; previous revision: 1\.5
-done"
- dotest rmadd2-16 "${testcvs} log -h file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
-Working file: file1
-head: 1\.6
-branch:
-locks: strict
-access list:
-symbolic names:
- tagone: 1\.1
-keyword substitution: kv
-total revisions: 6
-============================================================================="
- dotest rmadd2-17 "${testcvs} status -v file1" \
-"===================================================================
-File: no file file1 Status: Up-to-date
-
- Working revision: No entry for file1
- Repository revision: 1\.6 ${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
-
- Existing Tags:
- tagone (revision: 1.1)"
-
- cd ../..
-
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- rmadd3)
- # This test demonstrates that CVS notices that file1 exists rather
- # that deleting or writing over it after:
- #
- # cvs remove -f file1; touch file1; cvs add file1.
- #
- # According to the manual, this should work for:
- #
- # rm file1; cvs remove file1; cvs add file1
- #
- # but in past version of CVS, new content in file1 would be
- # erroneously deleted when file1 reappeared between the remove and
- # the add.
- #
- # Later versions of CVS would refuse to perform the add, but still
- # allow a subsequent local commit to erase the file from the
- # workspace, possibly losing data.
- mkdir 1; cd 1
- dotest rmadd3-init1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest rmadd3-init2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
-
- echo initial content for file1 >file1
- dotest rmadd3-init3 "${testcvs} add file1" \
-"${PROG} add: scheduling file \`file1' for addition
-${PROG} add: use '${PROG} commit' to add this file permanently"
- dotest rmadd3-init4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
-
- # Here begins the guts of this test, as detailed above.
- dotest rmadd3-1 "${testcvs} rm -f file1" \
-"${PROG} remove: scheduling \`file1' for removal
-${PROG} remove: use '${PROG} commit' to remove this file permanently"
-
- # Now recreate the file:
- echo desired future contents for file1 >file1
-
- # And attempt to resurrect it at the same time:
- dotest_fail rmadd3-2 "${testcvs} add file1" \
-"${PROG} add: file1 should be removed and is still there (or is back again)"
-
- # Now prove that commit knows that it shouldn't erase files.
- dotest_fail rmadd3-3 "${testcvs} -q ci -m." \
-"$PROG commit: \`file1' should be removed and is still there (or is back again)
-$PROG \[commit aborted\]: correct above errors first!"
-
- # Then these should pass too:
- dotest rmadd3-4 "test -f file1"
- dotest rmadd3-5 "cat file1" "desired future contents for file1"
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- cd ../..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- resurrection)
- # This test tests a few file resurrection scenarios.
- mkdir 1; cd 1
- dotest resurrection-init1 "$testcvs -q co -l ." ''
- mkdir first-dir
- dotest resurrection-init2 "$testcvs add first-dir" \
-"Directory $CVSROOT_DIRNAME/first-dir added to the repository"
- cd first-dir
-
- echo initial content for file1 >file1
- dotest resurrection-init3 "$testcvs add file1" \
-"$PROG add: scheduling file \`file1' for addition
-$PROG add: use '$PROG commit' to add this file permanently"
- dotest resurrection-init4 "$testcvs -q ci -m add" \
-"RCS file: $CVSROOT_DIRNAME/first-dir/file1,v
-done
-Checking in file1;
-$CVSROOT_DIRNAME/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
-
- dotest resurrection-init5 "$testcvs -Q rm -f file1"
-
- # The first test is that `cvs add' will resurrect a file before its
- # removal has been committed.
- dotest_sort resurrection-1 "$testcvs add file1" \
-"U file1
-$PROG add: file1, version 1\.1, resurrected"
- dotest resurrection-2 "$testcvs -Q diff file1" ""
-
- dotest resurrection-init6 "$testcvs -Q tag -b resurrection"
- dotest resurrection-init7 "$testcvs -Q rm -f file1"
- dotest resurrection-init8 "$testcvs -Q ci -mrm" \
-"Removing file1;
-$CVSROOT_DIRNAME/first-dir/file1,v <-- file1
-new revision: delete; previous revision: 1\.1
-done"
-
- # The next test is that CVS will resurrect a committed removal.
- dotest_sort resurrection-3 "$testcvs add file1" \
-"U file1
-$PROG add: Re-adding file \`file1' (in place of dead revision 1\.2)\.
-$PROG add: Resurrecting file \`file1' from revision 1\.1\.
-$PROG add: use 'cvs commit' to add this file permanently"
- dotest resurrection-4 "$testcvs -q diff -r1.1 file1" ""
- dotest resurrection-5 "$testcvs -q ci -mreadd" \
-"Checking in file1;
-$CVSROOT_DIRNAME/first-dir/file1,v <-- file1
-new revision: 1\.3; previous revision: 1\.2
-done"
-
- dotest resurrection-init9 "$testcvs -Q up -rresurrection"
- dotest resurrection-init10 "$testcvs -Q rm -f file1"
- dotest resurrection-init11 "$testcvs -Q ci -mrm-on-resurrection" \
-"Removing file1;
-$CVSROOT_DIRNAME/first-dir/file1,v <-- file1
-new revision: delete; previous revision: 1\.1
-done"
-
- # The next test is that CVS will resurrect a committed removal to a
- # branch.
- dotest_sort resurrection-6 "$testcvs add file1" \
-"U file1
-$PROG add: Resurrecting file \`file1' from revision 1\.1\.
-$PROG add: file \`file1' will be added on branch \`resurrection' from version 1\.1\.2\.1
-$PROG add: use 'cvs commit' to add this file permanently"
- dotest resurrection-7 "$testcvs -Q diff -r1.1 file1" ""
- dotest resurrection-8 "$testcvs -q ci -mreadd" \
-"Checking in file1;
-$CVSROOT_DIRNAME/first-dir/file1,v <-- file1
-new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
-done"
-
- # The next few tests verify that an attempted resurrection of a file
- # with no previous revision on the trunk fails.
- touch file2
- dotest resurrection-9 "$testcvs -Q add file2"
- dotest resurrection-10 "$testcvs -Q ci -mnew-file2" \
-"RCS file: $CVSROOT_DIRNAME/first-dir/Attic/file2,v
-done
-Checking in file2;
-$CVSROOT_DIRNAME/first-dir/Attic/file2,v <-- file2
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
- dotest resurrection-11 "$testcvs -Q up -A"
-
- # This command once caused an assertion failure.
- dotest resurrection-12 "$testcvs add file2" \
-"$PROG add: File \`file2' has no previous revision to resurrect\."
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- cd ../..
- rm -r 1
- rm -rf $CVSROOT_DIRNAME/first-dir
- ;;
-
- dirs)
- # Tests related to removing and adding directories.
- # See also:
- # conflicts (especially dir1 in conflicts-130): What happens if
- # directory exists in repository and a non-CVS-controlled
- # directory in the working directory?
- # conflicts3-15. More cases, especially where CVS directory
- # exists but without CVS/Repository and friends.
- # conflicts3-22. Similar to conflicts-130 but there is a file
- # in the directory.
- # dirs2. Sort of similar to conflicts3-22 but somewhat different.
- mkdir imp-dir; cd imp-dir
- echo file1 >file1
- mkdir sdir
- echo sfile >sdir/sfile
- dotest_sort dirs-1 \
-"${testcvs} import -m import-it dir1 vend rel" "
-
-N dir1/file1
-N dir1/sdir/sfile
-No conflicts created by this import
-${PROG} import: Importing ${CVSROOT_DIRNAME}/dir1/sdir"
- cd ..
-
- mkdir 1; cd 1
- dotest dirs-2 "${testcvs} -Q co dir1" ""
-
- # Various CVS administrators are in the habit of removing
- # the repository directory for things they don't want any
- # more. I've even been known to do it myself (on rare
- # occasions). Not the usual recommended practice, but we want
- # to try to come up with some kind of reasonable/documented/sensible
- # behavior.
- rm -rf ${CVSROOT_DIRNAME}/dir1/sdir
-
- dotest dirs-3 "${testcvs} update" \
-"${PROG} update: Updating dir1
-${PROG} update: Updating dir1/sdir
-${PROG} update: cannot open directory ${CVSROOT_DIRNAME}/dir1/sdir: No such file or directory
-${PROG} update: skipping directory dir1/sdir"
- dotest dirs-3a "${testcvs} update -d" \
-"${PROG} update*: Updating dir1
-${PROG} update: Updating dir1/sdir
-${PROG} update: cannot open directory ${CVSROOT_DIRNAME}/dir1/sdir: No such file or directory
-${PROG} update: skipping directory dir1/sdir"
-
- # If we say "yes", then CVS gives errors about not being able to
- # create lock files.
- # The fact that it says "skipping directory " rather than
- # "skipping directory dir1/sdir" is some kind of bug.
- dotest dirs-4 "echo no | ${testcvs} release -d dir1/sdir" \
-"${PROG} update: cannot open directory ${CVSROOT_DIRNAME}/dir1/sdir: No such file or directory
-${PROG} update: skipping directory
-You have \[0\] altered files in this repository\.
-Are you sure you want to release (and delete) directory .dir1/sdir': .. .release' aborted by user choice."
-
- # OK, if "cvs release" won't help, we'll try it the other way...
- rm -r dir1/sdir
-
- dotest dirs-5 "cat dir1/CVS/Entries" \
-"/file1/1.1.1.1/[a-zA-Z0-9 :]*//
-D/sdir////"
- dotest dirs-6 "${testcvs} update" "${PROG} update: Updating dir1"
- dotest dirs-7 "cat dir1/CVS/Entries" \
-"/file1/1.1.1.1/[a-zA-Z0-9 :]*//
-D/sdir////"
- dotest dirs-8 "${testcvs} update -d dir1" \
-"${PROG} update: Updating dir1"
-
- cd ..
-
- rm -r imp-dir 1
-
- # 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 ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- mkdir sdir
- dotest dirs2-3 "${testcvs} add sdir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/sdir added to the repository"
- touch sdir/file1
- dotest dirs2-4 "${testcvs} add sdir/file1" \
-"${PROG} add: scheduling file .sdir/file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest dirs2-5 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/file1,v
-done
-Checking in sdir/file1;
-${CVSROOT_DIRNAME}/first-dir/sdir/file1,v <-- file1
-initial revision: 1\.1
-done"
- rm -r sdir/CVS
- if $remote; then
- # This is just like conflicts3-23
- dotest_fail dirs2-6 "${testcvs} update -d" \
-"${QUESTION} sdir
-${PROG} update: Updating \.
-${PROG} update: Updating sdir
-${PROG} update: move away sdir/file1; it is in the way
-C sdir/file1"
- rm sdir/file1
- rm -r sdir/CVS
-
- # This is where things are not just like conflicts3-23
- dotest dirs2-7 "${testcvs} update -d" \
-"${QUESTION} sdir
-${PROG} update: Updating \.
-${PROG} update: Updating sdir
-U sdir/file1"
- 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 $remote; 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} \[update aborted\]: no such tag br"
- dotest dirs2-10ar \
-"${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} update: Updating \.
-${PROG} update: Updating sdir
-${PROG} update: move away sdir/file1; it is in the way
-C sdir/file1"
- 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} remove: scheduling .sdir/file1. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest dirs2-13 "${testcvs} -q ci -m remove" \
-"Removing sdir/file1;
-${CVSROOT_DIRNAME}/first-dir/sdir/file1,v <-- file1
-new revision: delete; previous revision: 1\.1
-done"
- cd ../../2/first-dir
- if $remote; then
- dotest dirs2-14 "${testcvs} update -d -r br" \
-"${QUESTION} sdir/file1
-${PROG} update: Updating \.
-${PROG} update: Updating sdir"
- else
- dotest dirs2-14 "${testcvs} update -d -r br" \
-"${PROG} update: Updating \.
-${QUESTION} sdir"
- fi
- cd ../..
-
- rm -r 1 2 3
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- branches)
- # More branch tests, including branches off of branches
- mkdir ${CVSROOT_DIRNAME}/first-dir
- dotest branches-1 "${testcvs} -q co first-dir" ''
- cd first-dir
- echo 1:ancest >file1
- echo 2:ancest >file2
- echo 3:ancest >file3
- echo 4:trunk-1 >file4
- dotest branches-2 "${testcvs} add file1 file2 file3 file4" \
-"${PROG}"' add: scheduling file `file1'\'' for addition
-'"${PROG}"' add: scheduling file `file2'\'' for addition
-'"${PROG}"' add: scheduling file `file3'\'' for addition
-'"${PROG}"' add: scheduling file `file4'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add these files permanently'
- dotest branches-2a "${testcvs} -n -q ci -m dont-commit" ""
- dotest_lit branches-3 "${testcvs} -q ci -m add-it" <<HERE
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file3,v
-done
-Checking in file3;
-${CVSROOT_DIRNAME}/first-dir/file3,v <-- file3
-initial revision: 1.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file4,v
-done
-Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-initial revision: 1.1
-done
-HERE
- echo 4:trunk-2 >file4
- dotest branches-3.2 "${testcvs} -q ci -m trunk-before-branch" \
-"Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: 1\.2; previous revision: 1\.1
-done"
- # The "cvs log file4" in test branches-14.3 will test that we
- # didn't really add the tag.
- dotest branches-3.3 "${testcvs} -qn tag dont-tag" \
-"T file1
-T file2
-T file3
-T file4"
- # Modify this file before branching, to deal with the case where
- # someone is hacking along, says "oops, I should be doing this on
- # a branch", and only then creates the branch.
- echo 1:br1 >file1
- dotest branches-4 "${testcvs} tag -b br1" "${PROG}"' tag: Tagging \.
-T file1
-T file2
-T file3
-T file4'
- dotest branches-5 "$testcvs update -r br1" \
-"$PROG update: Updating \.
-M file1
-[UP] file2
-[UP] file3
-[UP] file4"
- echo 2:br1 >file2
- echo 4:br1 >file4
- dotest branches-6 "${testcvs} -q ci -m modify" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: 1\.2\.2\.1; previous revision: 1\.2
-done"
- dotest branches-7 "${testcvs} -q tag -b brbr" 'T file1
-T file2
-T file3
-T file4'
- dotest branches-8 "$testcvs -q update -r brbr" \
-'[UP] file1
-[UP] file2
-[UP] file3
-[UP] file4'
- echo 1:brbr >file1
- echo 4:brbr >file4
- dotest branches-9 "${testcvs} -q ci -m modify" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.2\.1\.2\.1; previous revision: 1\.1\.2\.1
-done
-Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: 1\.2\.2\.1\.2\.1; previous revision: 1\.2\.2\.1
-done"
- dotest branches-10 "cat file1 file2 file3 file4" '1:brbr
-2:br1
-3:ancest
-4:brbr'
- dotest branches-11 "$testcvs -q update -r br1" \
-'U file1
-[UP] file2
-[UP] file3
-U file4'
- dotest branches-12 "cat file1 file2 file3 file4" '1:br1
-2:br1
-3:ancest
-4:br1'
- echo 4:br1-2 >file4
- dotest branches-12.2 "${testcvs} -q ci -m change-on-br1" \
-"Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: 1\.2\.2\.2; previous revision: 1\.2\.2\.1
-done"
- dotest branches-13 "${testcvs} -q update -A" \
-'U file1
-U file2
-[UP] file3
-U file4'
- dotest branches-14 "cat file1 file2 file3 file4" '1:ancest
-2:ancest
-3:ancest
-4:trunk-2'
- echo 4:trunk-3 >file4
- dotest branches-14.2 \
- "${testcvs} -q ci -m trunk-change-after-branch" \
-"Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: 1\.3; previous revision: 1\.2
-done"
- dotest branches-14.3 "${testcvs} log file4" \
-"
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file4,v
-Working file: file4
-head: 1\.3
-branch:
-locks: strict
-access list:
-symbolic names:
- brbr: 1\.2\.2\.1\.0\.2
- br1: 1\.2\.0\.2
-keyword substitution: kv
-total revisions: 6; selected revisions: 6
-description:
-----------------------------
-revision 1\.3
-date: [0-9/: ]*; author: ${username}; state: Exp; lines: ${PLUS}1 -1
-trunk-change-after-branch
-----------------------------
-revision 1\.2
-date: [0-9/: ]*; author: ${username}; state: Exp; lines: ${PLUS}1 -1
-branches: 1\.2\.2;
-trunk-before-branch
-----------------------------
-revision 1\.1
-date: [0-9/: ]*; author: ${username}; state: Exp;
-add-it
-----------------------------
-revision 1\.2\.2\.2
-date: [0-9/: ]*; author: ${username}; state: Exp; lines: ${PLUS}1 -1
-change-on-br1
-----------------------------
-revision 1\.2\.2\.1
-date: [0-9/: ]*; author: ${username}; state: Exp; lines: ${PLUS}1 -1
-branches: 1\.2\.2\.1\.2;
-modify
-----------------------------
-revision 1\.2\.2\.1\.2\.1
-date: [0-9/: ]*; author: ${username}; state: Exp; lines: ${PLUS}1 -1
-modify
-============================================================================="
- dotest_fail branches-14.4 \
- "${testcvs} diff -c -r 1.1 -r 1.3 file4" \
-"Index: file4
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file4,v
-retrieving revision 1\.1
-retrieving revision 1\.3
-diff -c -r1\.1 -r1\.3
-\*\*\* file4 ${RFCDATE} 1\.1
---- file4 ${RFCDATE} 1\.3
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-! 4:trunk-1
---- 1 ----
-! 4:trunk-3"
- dotest_fail branches-14.5 \
- "${testcvs} diff -c -r 1.1 -r 1.2.2.1 file4" \
-"Index: file4
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file4,v
-retrieving revision 1\.1
-retrieving revision 1\.2\.2\.1
-diff -c -r1\.1 -r1\.2\.2\.1
-\*\*\* file4 ${RFCDATE} 1\.1
---- file4 ${RFCDATE} 1\.2\.2\.1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1 \*\*\*\*
-! 4:trunk-1
---- 1 ----
-! 4:br1"
- dotest branches-15 \
- "${testcvs} update -j 1.1.2.1 -j 1.1.2.1.2.1 file1" \
- "RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-retrieving revision 1\.1\.2\.1
-retrieving revision 1\.1\.2\.1\.2\.1
-Merging differences between 1\.1\.2\.1 and 1\.1\.2\.1\.2\.1 into file1
-rcsmerge: warning: conflicts during merge"
- dotest branches-16 "cat file1" '<<<<<<< file1
-1:ancest
-[=]======
-1:brbr
-[>]>>>>>> 1\.1\.2\.1\.2\.1'
-
- dotest branches-o1 "${testcvs} -q admin -o ::brbr" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file3,v
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file4,v
-done"
- cd ..
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- rm -r first-dir
- ;;
-
- branches2)
- # More branch tests.
- # Test that when updating a new subdirectory in a directory
- # which was checked out on a branch, the new subdirectory is
- # created on the appropriate branch. Test this when joining
- # as well.
-
- mkdir ${CVSROOT_DIRNAME}/first-dir
- mkdir trunk; cd trunk
-
- # Create a file.
- dotest branches2-1 "${testcvs} -q co first-dir"
- cd first-dir
- echo "file1 first revision" > file1
- dotest branches2-2 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest branches2-3 "${testcvs} commit -m add file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
-
- # Tag the file.
- dotest branches2-4 "${testcvs} -q tag tag1" 'T file1'
-
- # Make two branches.
- dotest branches2-5 "${testcvs} -q rtag -b -r tag1 b1 first-dir" ''
- dotest branches2-6 "${testcvs} -q rtag -b -r tag1 b2 first-dir" ''
-
- # Create some files and a subdirectory on branch b1.
- cd ../..
- mkdir b1; cd b1
- dotest branches2-7 "${testcvs} -q co -r b1 first-dir" \
-"U first-dir/file1"
- cd first-dir
- echo "file2 first revision" > file2
- dotest branches2-8 "${testcvs} add file2" \
-"${PROG}"' add: scheduling file `file2'\'' for addition on branch `b1'\''
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- mkdir dir1
- dotest branches2-9 "${testcvs} add dir1" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/dir1 added to the repository
---> Using per-directory sticky tag "'`'"b1'"
- echo "file3 first revision" > dir1/file3
- dotest branches2-10 "${testcvs} add dir1/file3" \
-"${PROG}"' add: scheduling file `dir1/file3'\'' for addition on branch `b1'\''
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest branches2-11 "${testcvs} -q ci -madd ." \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/Attic/file2,v <-- file2
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir1/Attic/file3,v
-done
-Checking in dir1/file3;
-${CVSROOT_DIRNAME}/first-dir/dir1/Attic/file3,v <-- file3
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
-
- # Check out the second branch, and update the working
- # directory to the first branch, to make sure the right
- # happens with dir1.
- cd ../..
- mkdir b2; cd b2
- dotest branches2-12 "${testcvs} -q co -r b2 first-dir" \
-'U first-dir/file1'
- cd first-dir
- dotest branches2-13 "${testcvs} update -d -r b1 dir1" \
-"${PROG} update: Updating dir1
-U dir1/file3"
- dotest branches2-14 "${testcvs} -q status" \
-"===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: b2 (branch: 1\.1\.4)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file3 Status: Up-to-date
-
- Working revision: 1\.1\.2\.1.*
- Repository revision: 1\.1\.2\.1 ${CVSROOT_DIRNAME}/first-dir/dir1/Attic/file3,v
- Sticky Tag: b1 (branch: 1\.1\.2)
- Sticky Date: (none)
- Sticky Options: (none)"
-
- # FIXME: Just clobbering the directory like this is a bit
- # tacky, although people generally expect it to work. Maybe
- # we should release it instead. We do it a few other places
- # below as well.
- rm -r dir1
- dotest branches2-15 "${testcvs} update -d -j b1 dir1" \
-"${PROG} update: Updating dir1
-U dir1/file3"
- # FIXCVS: The `No revision control file' stuff seems to be
- # CVS's way of telling us that we're adding the file on a
- # branch, and the file is not on that branch yet. This
- # should be nicer.
- dotest branches2-16 "${testcvs} -q status" \
-"===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: b2 (branch: 1\.1\.4)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file3 Status: Locally Added
-
- Working revision: New file!
- Repository revision: No revision control file
- Sticky Tag: b2 - MISSING from RCS file!
- Sticky Date: (none)
- Sticky Options: (none)"
-
- cd ../../trunk/first-dir
- dotest branches2-17 "${testcvs} update -d -P dir1" \
-"${PROG} update: Updating dir1"
- dotest_fail branches2-18 "test -d dir1"
- dotest branches2-19 "${testcvs} update -d -P -r b1 dir1" \
-"${PROG} update: Updating dir1
-U dir1/file3"
- dotest branches2-20 "${testcvs} -q status" \
-"===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file3 Status: Up-to-date
-
- Working revision: 1\.1\.2\.1.*
- Repository revision: 1\.1\.2\.1 ${CVSROOT_DIRNAME}/first-dir/dir1/Attic/file3,v
- Sticky Tag: b1 (branch: 1\.1\.2)
- Sticky Date: (none)
- Sticky Options: (none)"
-
- rm -r dir1
- dotest branches2-21 "${testcvs} update -d -P -j b1 dir1" \
-"${PROG} update: Updating dir1
-U dir1/file3"
- dotest branches2-22 "${testcvs} -q status" \
-"===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file3 Status: Locally Added
-
- Working revision: New file!
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/dir1/Attic/file3,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
-
- cd ../..
- rm -r b1 b2
-
- # Check out branch b1 twice. Crate a new directory in one
- # working directory, then do a cvs update in the other
- # working directory and see if the tags are right.
- mkdir b1a
- mkdir b1b
- cd b1b
- dotest branches2-23 "${testcvs} -q co -r b1 first-dir" \
-'U first-dir/file1
-U first-dir/file2
-U first-dir/dir1/file3'
- cd ../b1a
- dotest branches2-24 "${testcvs} -q co -r b1 first-dir" \
-'U first-dir/file1
-U first-dir/file2
-U first-dir/dir1/file3'
- cd first-dir
- mkdir dir2
- dotest branches2-25 "${testcvs} add dir2" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/dir2 added to the repository
---> Using per-directory sticky tag "'`'"b1'"
- echo "file4 first revision" > dir2/file4
- dotest branches2-26 "${testcvs} add dir2/file4" \
-"${PROG}"' add: scheduling file `dir2/file4'\'' for addition on branch `b1'\''
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest branches2-27 "${testcvs} -q commit -madd" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/dir2/Attic/file4,v
-done
-Checking in dir2/file4;
-${CVSROOT_DIRNAME}/first-dir/dir2/Attic/file4,v <-- file4
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
-
- cd ../../b1b/first-dir
- dotest branches2-28 "${testcvs} update -d dir2" \
-"${PROG} update: Updating dir2
-U dir2/file4"
- cd dir2
- dotest branches2-29 "${testcvs} -q status" \
-"===================================================================
-File: file4 Status: Up-to-date
-
- Working revision: 1\.1\.2\.1.*
- Repository revision: 1\.1\.2\.1 ${CVSROOT_DIRNAME}/first-dir/dir2/Attic/file4,v
- Sticky Tag: b1 (branch: 1\.1\.2)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest branches2-30 "cat CVS/Tag" 'Tb1'
-
- # Test update -A on a subdirectory
- cd ..
- rm -r dir2
- dotest branches2-31 "${testcvs} update -A -d dir2" \
-"${PROG} update: Updating dir2"
- cd dir2
- dotest branches2-32 "${testcvs} -q status" ''
- dotest_fail branches2-33 "test -f CVS/Tag"
-
- # Add a file on the trunk.
- echo "file5 first revision" > file5
- dotest branches2-34 "${testcvs} add file5" \
-"${PROG}"' add: scheduling file `file5'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest branches2-35 "${testcvs} -q commit -madd" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/dir2/file5,v
-done
-Checking in file5;
-${CVSROOT_DIRNAME}/first-dir/dir2/file5,v <-- file5
-initial revision: 1\.1
-done"
-
- cd ../../../trunk/first-dir
- dotest branches2-36 "${testcvs} -q update -d dir2" 'U dir2/file5'
- cd dir2
- dotest branches2-37 "${testcvs} -q status" \
-"===================================================================
-File: file5 Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/dir2/file5,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest_fail branches2-38 "test -f CVS/status"
-
- cd ../../..
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- 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 ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- touch file1 file2
- dotest tagc-3 "${testcvs} add file1 file2" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest tagc-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1\.1
-done"
- dotest tagc-5 "${testcvs} -q tag -c tag1" \
-"T file1
-T file2"
- touch file1 file2
- dotest tagc-6 "${testcvs} -q tag -c tag2" \
-"T file1
-T file2"
- # Avoid timestamp granularity bugs (FIXME: CVS should be
- # doing the sleep, right?).
- sleep 1
- echo myedit >>file1
- dotest tagc-6a "${testcvs} rm -f file2" \
-"${PROG} remove: scheduling .file2. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- touch file3
- dotest tagc-6b "${testcvs} add file3" \
-"${PROG} add: scheduling file .file3. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest_fail tagc-7 "${testcvs} -q tag -c tag3" \
-"${PROG} tag: file1 is locally modified
-${PROG} tag: file2 is locally modified
-${PROG} tag: file3 is locally modified
-${PROG} \[tag aborted\]: correct the above errors first!"
- cd ../..
- mkdir 2
- cd 2
- dotest tagc-8 "${testcvs} -q co first-dir" \
-"U first-dir/file1
-U first-dir/file2"
- cd ../1/first-dir
- dotest tagc-9 "${testcvs} -q ci -m modify" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done
-Removing file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: delete; previous revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file3,v
-done
-Checking in file3;
-${CVSROOT_DIRNAME}/first-dir/file3,v <-- file3
-initial revision: 1\.1
-done"
- cd ../../2/first-dir
- dotest tagc-10 "${testcvs} -q tag -c tag4" \
-"${PROG} tag: file2 is no longer in the repository
-T file1
-T file2"
- cd ../..
-
- rm -r 1 2
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- update-p)
- # Make sure `cvs update -p -rT FILE' works from a branch when
- # FILE is already on the trunk and is being added to that branch.
-
- mkdir 1; cd 1
- module=x
-
- echo > unused-file
-
- # Create the module.
- dotest update-p-1 \
- "$testcvs -Q import -m. $module X Y" ''
-
- file=F
- # Check it out and tag it.
- dotest update-p-2 "$testcvs -Q co $module" ''
- cd $module
- dotest update-p-3 "$testcvs -Q tag -b B" ''
- echo v1 > $file
- dotest update-p-4 "$testcvs -Q add $file" ''
- dotest update-p-5 "$testcvs -Q ci -m. $file" \
-"RCS file: ${CVSROOT_DIRNAME}/$module/$file,v
-done
-Checking in $file;
-${CVSROOT_DIRNAME}/$module/$file,v <-- $file
-initial revision: 1\.1
-done"
- dotest update-p-6 "$testcvs -Q tag T $file" ''
- dotest update-p-7 "$testcvs -Q update -rB" ''
-
- # This merge effectively adds file F on branch B.
- dotest update-p-8 "$testcvs -Q update -jT" ''
-
- # Before the fix that prompted the addition of this test,
- # the following command would fail with this diagnostic:
- # cvs update: conflict: F created independently by second party
- dotest update-p-9 "$testcvs update -p -rT $file" \
-"===================================================================
-Checking out $file
-RCS: ${CVSROOT_DIRNAME}/$module/$file,v
-VERS: 1\.1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-v1"
-
- # Repeat the above, but with $file removed.
- # This exercises a slightly different code path.
- rm $file
- # Before the fix that prompted the addition of this test,
- # the following command would fail with this diagnostic:
- # cvs update: warning: new-born F has disappeared
- dotest update-p-10 "$testcvs update -p -rT $file" \
-"===================================================================
-Checking out $file
-RCS: ${CVSROOT_DIRNAME}/$module/$file,v
-VERS: 1\.1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-v1"
-
- # Exercise yet another code path:
- # the one that involves reviving a `dead' file.
- # And a little more, for good measure...
- touch new
- dotest update-p-a1 "$testcvs -Q add new" ''
- dotest update-p-a2 "$testcvs -Q update -p new" ''
- dotest update-p-a3 "$testcvs -Q rm -f new" ''
-
- # Both an update -A, *and* the following update are required
- # to return to the state of being on the trunk with a $file
- # that we can then remove.
- dotest update-p-undead-0 "$testcvs update -A" \
-"$PROG update: Updating \.
-$PROG update: warning: new-born $file has disappeared
-[UP] unused-file"
- dotest update-p-undead-1 "$testcvs update" \
-"${PROG} update: Updating \.
-U $file"
- dotest update-p-undead-2 "$testcvs -Q update -p -rT $file" v1
- dotest update-p-undead-3 "$testcvs -Q rm -f $file" ''
- dotest update-p-undead-4 "$testcvs -Q update -p -rT $file" v1
- dotest update-p-undead-5 "$testcvs -Q ci -m. $file" \
-"Removing $file;
-${CVSROOT_DIRNAME}/$module/$file,v <-- $file
-new revision: delete; previous revision: 1\.1
-done"
- dotest update-p-undead-6 "$testcvs -Q update -p -rT $file" v1
- echo v2 > $file
- dotest update-p-undead-7 "$testcvs -Q update -p -rT $file" v1
- dotest update-p-undead-8 "$testcvs add $file" \
-"${PROG} add: Re-adding file .$file. (in place of dead revision 1\.2)\.
-${PROG} add: use .${PROG} commit. to add this file permanently"
-
- dotest update-p-undead-9 "$testcvs -Q update -p -rT $file" v1
-
- cd ../..
- rm -rf 1
- rm -rf ${CVSROOT_DIRNAME}/$module
- ;;
-
- tagf)
- # More tagging tests, including using tag -F -B to convert a
- # branch tag to a regular tag and recovering thereof.
-
- # Setup; check in first-dir/file1
- mkdir 1; cd 1
- dotest tagf-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest tagf-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- touch file1 file2
- dotest tagf-3 "${testcvs} add file1 file2" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest tagf-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/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" \
-'U file1
-U file2'
- echo brmod >> file1
- echo brmod >> file2
- dotest tagf-7 "${testcvs} -q ci -m modify" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
- # Here we try to make it a non-branch tag, but will
- # succeed in getting only warnings, even with -F
- # because converting a branch tag to non-branch
- # is potentially catastrophic.
- dotest tagf-8a "${testcvs} -q tag -F br" \
-"${PROG} tag: file1: Not moving branch tag .br. from 1\.1\.2\.1 to 1\.1\\.2\.1\.
-${PROG} tag: file2: Not moving branch tag .br. from 1\.1\.2\.1 to 1\.1\.2\.1\."
- # however, if we *really* are sure we want to move a branch tag,
- # "-F -B" will do the trick
- dotest tagf-8 "${testcvs} -q tag -F -B br" "T file1
-T file2"
- echo moremod >> file1
- echo moremod >> file2
- dotest tagf-9 "${testcvs} -q status -v file1" \
-"===================================================================
-File: file1 Status: Locally Modified
-
- Working revision: 1\.1\.2\.1.*
- Repository revision: 1\.1\.2\.1 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: br (revision: 1\.1\.2\.1)
- Sticky Date: (none)
- Sticky Options: (none)
-
- Existing Tags:
- br (revision: 1\.1\.2\.1)"
-
- # Now, how do we recover?
- dotest tagf-10 "${testcvs} -q tag -d br" "D file1
-D file2"
- # This creates a new branch, 1.1.4. See the code in RCS_magicrev
- # which will notice that there is a (non-magic) 1.1.2 and thus
- # skip that number.
- dotest tagf-11 "${testcvs} -q tag -r 1.1 -b br file1" "T file1"
- # Fix it with admin -n (cf admin-18, admin-26-4).
- dotest tagf-12 "${testcvs} -q admin -nbr:1.1.2 file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done"
- # Another variation on the file2 test would be to use two working
- # directories so that the update -r br would need to
- # a merge to get from 1.1.2.1 to the head of the 1.1.2 branch.
- dotest tagf-13 "${testcvs} -q update -r br" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-retrieving revision 1\.1\.2\.1
-retrieving revision 1\.1
-Merging differences between 1\.1\.2\.1 and 1\.1 into file1
-rcsmerge: warning: conflicts during merge
-${PROG} update: conflicts found in file1
-C file1
-M file2"
- # CVS is giving a conflict because we are trying to get back to
- # 1.1.4. I'm not sure why it is a conflict rather than just
- # "M file1".
- dotest tagf-14 "cat file1" \
-"<<<<<<< file1
-brmod
-moremod
-[=]======
-[>]>>>>>> 1\.1"
- echo resolve >file1
- dotest tagf-15 "${testcvs} -q ci -m recovered" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.4\.1; previous revision: 1\.1
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
-done"
- # try accidentally deleting branch tag, "tag -d"
- dotest_fail tagf-16 "${testcvs} tag -d br" \
-"${PROG} tag: Untagging \.
-${PROG} tag: Not removing branch tag .br. from .${CVSROOT_DIRNAME}/first-dir/file1,v.\.
-${PROG} tag: Not removing branch tag .br. from .${CVSROOT_DIRNAME}/first-dir/file2,v.\."
- # try accidentally deleting branch tag, "rtag -d"
- dotest_fail tagf-17 "${testcvs} rtag -d br first-dir" \
-"${PROG} rtag: Untagging first-dir
-${PROG} rtag: Not removing branch tag .br. from .${CVSROOT_DIRNAME}/first-dir/file1,v.\.
-${PROG} rtag: Not removing branch tag .br. from .${CVSROOT_DIRNAME}/first-dir/file2,v.\."
- # try accidentally converting branch tag to non-branch tag "tag -F"
- dotest tagf-18 "${testcvs} tag -r1.1 -F br file1" \
-"${PROG} tag: file1: Not moving branch tag .br. from 1\.1\.4\.1 to 1\.1\."
- # try accidentally converting branch tag to non-branch tag "rtag -F"
- dotest tagf-19 "${testcvs} rtag -r1.1 -F br first-dir" \
-"${PROG} rtag: Tagging first-dir
-${PROG} rtag: first-dir/file1: Not moving branch tag .br. from 1\.1\.4\.1 to 1\.1\.
-${PROG} rtag: first-dir/file2: Not moving branch tag .br. from 1\.1\.2\.2 to 1\.1\."
- # create a non-branch tag
- dotest tagf-20 "${testcvs} rtag regulartag first-dir" \
-"${PROG} rtag: Tagging first-dir"
- # try accidentally converting non-branch tag to branch tag (tag -F -B -b)
- dotest tagf-21 "${testcvs} tag -F -B -b regulartag file1" \
-"${PROG} tag: file1: Not moving non-branch tag .regulartag. from 1\.1 to 1\.1\.4\.1\.0\.2 due to .-B. option\."
- # try accidentally converting non-branch tag to branch rtag (rtag -F -B -b)
- dotest tagf-22 "${testcvs} rtag -F -B -b regulartag first-dir" \
-"${PROG} rtag: Tagging first-dir
-${PROG} rtag: first-dir/file1: Not moving non-branch tag .regulartag. from 1\.1 to 1\.1\.0\.6 due to .-B. option\.
-${PROG} rtag: first-dir/file2: Not moving non-branch tag .regulartag. from 1\.1 to 1\.1\.0\.4 due to .-B. option\."
- # Try accidentally deleting non-branch: (tag -d -B)
- dotest_fail tagf-23 "${testcvs} tag -d -B regulartag file1" \
-"${PROG} tag: Not removing non-branch tag .regulartag. from .${CVSROOT_DIRNAME}/first-dir/file1,v. due to .-B. option\."
- # Try accidentally deleting non-branch: (rtag -d -B)
- dotest_fail tagf-24 \
- "${testcvs} rtag -d -B regulartag first-dir" \
-"${PROG} rtag: Untagging first-dir
-${PROG} rtag: Not removing non-branch tag .regulartag. from .${CVSROOT_DIRNAME}/first-dir/file1,v. due to .-B. option\.
-${PROG} rtag: Not removing non-branch tag .regulartag. from .${CVSROOT_DIRNAME}/first-dir/file2,v. due to .-B. option\."
-
- # the following tests (throught the next commit) keep moving the same
- # tag back and forth between 1.1.6 & 1.1.8 in file1 and between
- # 1.1.4 and 1.1.6 in file2 since nothing was checked in on some of
- # these branches and CVS only tracks branches via tags unless they contain data.
-
- # try intentionally converting non-branch tag to branch tag (tag -F -b)
- dotest tagf-25a "${testcvs} tag -F -b regulartag file1" "T file1"
- # try intentionally moving a branch tag to a newly created branch (tag -F -b -B)
- dotest tagf-25b "${testcvs} tag -F -B -b -r1.1 regulartag file1" \
-"T file1"
- # try intentionally converting mixed tags to branch tags (rtag -F -b)
- dotest tagf-26a "${testcvs} rtag -F -b regulartag first-dir" \
-"${PROG} rtag: Tagging first-dir
-${PROG} rtag: first-dir/file1: Not moving branch tag .regulartag. from 1\.1 to 1\.1\.0\.8\."
- # try intentionally converting a branch to a new branch tag (rtag -F -b -B)
- dotest tagf-26b "${testcvs} rtag -F -B -b -r1.1 regulartag first-dir" \
-"${PROG} rtag: Tagging first-dir"
- # update to our new branch
- dotest tagf-27 "${testcvs} update -r regulartag" \
-"${PROG} update: Updating \.
-U file1
-U file2"
- # commit some changes and see that all rev numbers look right
- echo changes >> file1
- echo changes >> file2
- dotest tagf-28 "${testcvs} ci -m changes" \
-"${PROG} [a-z]*: Examining \.
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.8\.1; previous revision: 1\.1
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.1\.6\.1; previous revision: 1\.1
-done"
- # try intentional branch to non-branch (tag -F -B)
- dotest tagf-29 "${testcvs} tag -F -B -r1.1 regulartag file1" \
-"T file1"
- # try non-branch to non-branch (tag -F -B)
- dotest tagf-29a "${testcvs} tag -F -B -r br regulartag file1" \
-"${PROG} tag: file1: Not moving non-branch tag .regulartag. from 1\.1 to 1\.1\.4\.1 due to .-B. option\."
- # try mixed-branch to non-branch (rtag -F -B )
- dotest tagf-29b "${testcvs} rtag -F -B -r br regulartag first-dir" \
-"${PROG} rtag: Tagging first-dir
-${PROG} rtag: first-dir/file1: Not moving non-branch tag .regulartag. from 1\.1 to 1\.1\.4\.1 due to .-B. option\."
- # at this point, regulartag is a regular tag within
- # file1 and file2
-
- # try intentional branch to non-branch (rtag -F -B)
- dotest tagf-30 "${testcvs} rtag -F -B -r1.1 br first-dir" \
-"${PROG} rtag: Tagging first-dir"
- # create a branch tag so we can try to delete it.
- dotest tagf-31 "${testcvs} rtag -b brtag first-dir" \
-"${PROG} rtag: Tagging first-dir"
-
- # try intentinal deletion of branch tag (tag -d -B)
- dotest tagf-32 "${testcvs} tag -d -B brtag file1" "D file1"
- # try intentinal deletion of branch tag (rtag -d -B)
- dotest tagf-33 "${testcvs} rtag -d -B brtag first-dir" \
-"${PROG} rtag: Untagging first-dir"
-
- cd ../..
-
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- tag-log)
- # Test log output for tags
- mkdir 1; cd 1
- dotest tag-log-init-1 "$testcvs -q co -l ."
- mkdir first-dir
- dotest tag-log-init-2 "$testcvs add first-dir" \
-"Directory $CVSROOT_DIRNAME/first-dir added to the repository"
- cd first-dir
- touch file1
- dotest tag-log-init-3 "$testcvs add file1" \
-"${PROG}"' add: scheduling file `file1'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest tag-log-init-4 "$testcvs -Q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
-
- dotest tag-log-1 "$testcvs -Q tag mytag file1" ''
- dotest tag-log-2 "$testcvs log -N file1" \
-"
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-add
-============================================================================="
- dotest tag-log-3 "$testcvs log -N -n file1" \
-"
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
-symbolic names:
- mytag: 1\.1
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-add
-============================================================================="
- dotest tag-log-4 "$testcvs log file1" \
-"
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
-symbolic names:
- mytag: 1\.1
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-add
-============================================================================="
- dotest tag-log-5 "$testcvs log -n file1" \
-"
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
-symbolic names:
- mytag: 1\.1
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-add
-============================================================================="
-
- cd ../..
- rm -fr 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- tag-space)
- # Test tags with spaces in the names.
- #
- # Prior to releases 1.11.18 & 1.12.10, some commands used with
- # tags with spaces in the names could hang CVS.
-
- # Setup; check in first-dir/file1
- mkdir 1; cd 1
- dotest tag-space-init-1 "$testcvs -q co -l ."
- mkdir first-dir
- dotest tag-space-init-2 "$testcvs add first-dir" \
-"Directory $CVSROOT_DIRNAME/first-dir added to the repository"
- cd first-dir
- touch file1
- dotest tag-space-init-3 "$testcvs add file1" \
-"$PROG add: scheduling file \`file1' for addition
-$PROG add: use '$PROG commit' to add this file permanently"
- dotest tag-space-init-4 "$testcvs -Q ci -m add" \
-"RCS file: $CVSROOT_DIRNAME/first-dir/file1,v
-done
-Checking in file1;
-$CVSROOT_DIRNAME/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
-
- # Reportedly, the following two tags make it past WinCVS.
- dotest_fail tag-space-1 "$testcvs tag ' spacetag '" \
-"$PROG \[tag aborted\]: tag \` spacetag ' must start with a letter"
- dotest_fail tag-space-2 "$testcvs tag 'spacetag '" \
-"$PROG \[tag aborted\]: tag \`spacetag ' has non-visible graphic characters"
-
- if $remote; then
- # Verify that this isn't a client check.
- dotest tag-space-3 "$testcvs server" \
-"E $PROG \[tag aborted\]: tag \` spacetag ' must start with a letter
-error " <<EOF
-Root $CVSROOT_DIRNAME
-UseUnchanged
-Argument --
-Argument spacetag
-Directory .
-$CVSROOT_DIRNAME/first-dir
-Entry /file1/1.1///
-Unchanged file1
-tag
-EOF
-
- dotest tag-space-4 "$testcvs server" \
-"E $PROG \[tag aborted\]: tag \`spacetag ' has non-visible graphic characters
-error " <<EOF
-Root $CVSROOT_DIRNAME
-UseUnchanged
-Argument --
-Argument spacetag
-Directory .
-$CVSROOT_DIRNAME/first-dir
-Entry /file1/1.1///
-Unchanged file1
-tag
-EOF
- fi # $remote
-
- # Any number of normal tags and branches were handled correctly.
- dotest tag-space-5 "$testcvs -Q tag t1"
- dotest tag-space-5b "$testcvs -Q tag t2"
- dotest tag-space-5c "$testcvs -Q tag -b b1"
-
- cd ../..
- mkdir 2; cd 2
-
- # But once a vendor branch exists, it's all over.
- mkdir project; cd project
- touch file1
- dotest tag-space-init-4 \
-"$testcvs -Q import -mimport second-dir VENDOR RELEASE"
-
- cd ..
-
- dotest_fail tag-space-6 "$testcvs -Q co -r ' spacetag ' first-dir" \
-"$PROG \[checkout aborted\]: tag \` spacetag ' must start with a letter"
-
- # But when any files were imported, this test hung prior to CVS
- # versions 1.11.18 & 1.12.10.
- dotest_fail tag-space-7 "$testcvs -Q co -r ' spacetag ' second-dir" \
-"$PROG \[checkout aborted\]: tag \` spacetag ' must start with a letter"
-
- if $remote; then
- # I based the client input in the next two tests on actual input
- # from WinCVS 1.2.
- dotest tag-space-8 "$testcvs server" \
-"E $PROG \[checkout aborted\]: tag \` spacetag ' must start with a letter
-error " <<EOF
-Root $CVSROOT_DIRNAME
-Argument -P
-Argument -r
-Argument spacetag
-Argument first-dir
-Directory .
-$CVSROOT_DIRNAME
-co
-EOF
-
- # Verify the test is not on the client side.
- dotest tag-space-9 "$testcvs server" \
-"E $PROG \[checkout aborted\]: tag \` spacetag ' must start with a letter
-error " <<EOF
-Root $CVSROOT_DIRNAME
-Argument -P
-Argument -r
-Argument spacetag
-Argument second-dir
-Directory .
-$CVSROOT_DIRNAME
-co
-EOF
- fi # $remote
-
- dotest tag-space-10 "$testcvs -Q co second-dir"
- cd second-dir
-
- # This test would also hang.
- dotest_fail tag-space-11 "$testcvs -Q up -r ' spacetag '" \
-"$PROG \[update aborted\]: tag \` spacetag ' must start with a letter"
-
- if $remote; then
- dotest tag-space-12 "$testcvs server" \
-"E $PROG \[update aborted\]: tag \` spacetag ' must start with a letter
-error " <<EOF
-Root $CVSROOT_DIRNAME
-Argument -r
-Argument spacetag
-Argument -u
-Argument --
-Directory .
-$CVSROOT_DIRNAME
-Unchanged file1
-update
-EOF
- fi # $remote
-
- # I'm skipping tests for other commands that may have had the same
- # problem. Hopefully, if a new issue arises, one of the above tests
- # will catch the problem.
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- cd ../..
- rm -r 1 2
- rm -rf $CVSROOT_DIRNAME/first-dir $CVSROOT_DIRNAME/second-dir
- ;;
-
- rcslib)
- # Test librarification of RCS.
- # First: test whether `cvs diff' handles $Name expansion
- # correctly. We diff two revisions with their symbolic tags;
- # neither tag should be expanded in the output. Also diff
- # one revision with the working copy.
-
- mkdir ${CVSROOT_DIRNAME}/first-dir
- dotest rcsdiff-1 "${testcvs} -q co first-dir" ''
- cd first-dir
- echo "I am the first foo, and my name is $""Name$." > foo.c
- dotest rcsdiff-2 "${testcvs} add -m new-file foo.c" \
-"${PROG} add: scheduling file .foo\.c. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest rcsdiff-3 "${testcvs} commit -m rev1 foo.c" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/foo\.c,v
-done
-Checking in foo\.c;
-${CVSROOT_DIRNAME}/first-dir/foo.c,v <-- foo\.c
-initial revision: 1\.1
-done"
- dotest rcsdiff-4 "${testcvs} tag first foo.c" "T foo\.c"
- dotest rcsdiff-5 "${testcvs} update -p -r first foo.c" \
-"===================================================================
-Checking out foo\.c
-RCS: ${CVSROOT_DIRNAME}/first-dir/foo\.c,v
-VERS: 1\.1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-I am the first foo, and my name is \$""Name: first \$\."
-
- echo "I am the second foo, and my name is $""Name$." > foo.c
- dotest rcsdiff-6 "${testcvs} commit -m rev2 foo.c" \
-"Checking in foo\.c;
-${CVSROOT_DIRNAME}/first-dir/foo\.c,v <-- foo\.c
-new revision: 1\.2; previous revision: 1\.1
-done"
- dotest rcsdiff-7 "${testcvs} tag second foo.c" "T foo\.c"
- dotest rcsdiff-8 "${testcvs} update -p -r second foo.c" \
-"===================================================================
-Checking out foo\.c
-RCS: ${CVSROOT_DIRNAME}/first-dir/foo\.c,v
-VERS: 1\.2
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-I am the second foo, and my name is \$""Name: second \$\."
-
- dotest_fail rcsdiff-9 "${testcvs} diff -r first -r second" \
-"${PROG} diff: Diffing \.
-Index: foo\.c
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/foo\.c,v
-retrieving revision 1\.1
-retrieving revision 1\.2
-diff -r1\.1 -r1\.2
-1c1
-< I am the first foo, and my name is \$""Name: \$\.
----
-> I am the second foo, and my name is \$""Name: \$\."
-
- echo "I am the once and future foo, and my name is $""Name$." > foo.c
- dotest_fail rcsdiff-10 "${testcvs} diff -r first" \
-"${PROG} diff: Diffing \.
-Index: foo\.c
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/foo\.c,v
-retrieving revision 1\.1
-diff -r1\.1 foo\.c
-1c1
-< I am the first foo, and my name is \$""Name: \$\.
----
-> I am the once and future foo, and my name is \$""Name\$\."
-
- # Test handling of libdiff options. diff gets quite enough
- # of a workout elsewhere in sanity.sh, so we assume that it's
- # mostly working properly if it passes all the other tests.
- # The main one we want to try is regex handling, since we are
- # using CVS's regex matcher and not diff's.
-
- cat >rgx.c <<EOF
-test_regex (whiz, bang)
-{
-foo;
-bar;
-baz;
-grumble;
-}
-EOF
-
- dotest rcslib-diffrgx-1 "${testcvs} -q add -m '' rgx.c" \
-"${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest rcslib-diffrgx-2 "${testcvs} -q ci -m '' rgx.c" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/rgx\.c,v
-done
-Checking in rgx\.c;
-${CVSROOT_DIRNAME}/first-dir/rgx\.c,v <-- rgx\.c
-initial revision: 1\.1
-done"
- cat >rgx.c <<EOF
-test_regex (whiz, bang)
-{
-foo;
-bar;
-baz;
-mumble;
-}
-EOF
- # Use dotest_fail because exit status from `cvs diff' must be 1.
- dotest_fail rcslib-diffrgx-3 "${testcvs} diff -c -F'.* (' rgx.c" \
-"Index: rgx\.c
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/rgx\.c,v
-retrieving revision 1\.1
-diff -c -F \.\* ( -r1\.1 rgx\.c
-\*\*\* rgx\.c ${RFCDATE} 1\.1
---- rgx\.c ${RFCDATE}
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* test_regex (whiz, bang)
-\*\*\* 3,7 \*\*\*\*
- foo;
- bar;
- baz;
-! grumble;
- }
---- 3,7 ----
- foo;
- bar;
- baz;
-! mumble;
- }"
-
- # Tests of rcsmerge/diff3. Merge operations get a good general
- # workout elsewhere; we want to make sure that options are still
- # handled properly. Try merging two branches with -kv, to test
- # both -j and -k switches.
-
- cd ..
-
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- rm -r first-dir
-
- mkdir 1; cd 1
- dotest rcslib-merge-1 "${testcvs} -q co -l ." ""
- mkdir first-dir
- dotest rcslib-merge-2 "${testcvs} -q add first-dir" \
-"Directory ${CVSROOT_DIRNAME}.*/first-dir added to the repository"
- cd ..; rm -r 1
-
- dotest rcslib-merge-3 "${testcvs} -q co first-dir" ""
- cd first-dir
-
- echo '$''Revision$' > file1
- echo '2' >> file1
- echo '3' >> file1
- dotest rcslib-merge-4 "${testcvs} -q add file1" \
-"${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest rcslib-merge-5 "${testcvs} -q commit -m '' file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- sed -e 's/2/two/' file1 > f; mv f file1
- dotest rcslib-merge-6 "${testcvs} -q commit -m '' file1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
- dotest rcslib-merge-7 "${testcvs} -q tag -b -r 1.1 patch1" "T file1"
- dotest rcslib-merge-8 "${testcvs} -q update -r patch1" "[UP] file1"
- dotest rcslib-merge-9 "${testcvs} -q status" \
-"===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: patch1 (branch: 1\.1\.2)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest rcslib-merge-10 "cat file1" \
-'$''Revision: 1\.1 $
-2
-3'
- sed -e 's/3/three/' file1 > f; mv f file1
- dotest rcslib-merge-11 "${testcvs} -q commit -m '' file1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
- dotest rcslib-merge-12 "${testcvs} -q update -kv -j1.2" \
-"U file1
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-retrieving revision 1\.1
-retrieving revision 1\.2
-Merging differences between 1\.1 and 1\.2 into file1
-rcsmerge: warning: conflicts during merge"
- dotest rcslib-merge-13 "cat file1" \
-"<<<<<<< file1
-1\.1\.2\.1
-2
-three
-[=]======
-1\.2
-two
-3
-[>]>>>>>> 1\.2"
-
- # Test behavior of symlinks in the repository.
- if test -n "$remotehost"; then
- # Create the link on the remote system. This is because Cygwin's
- # Windows support creates *.lnk files for Windows. When creating
- # these in an SMB share from UNIX, these links won't work from the
- # UNIX side.
- dotest rcslib-symlink-1remotehost "${CVS_RSH} $remotehost 'ln -s file1,v ${CVSROOT_DIRNAME}/first-dir/file2,v'"
- else
- dotest rcslib-symlink-1 "ln -s file1,v ${CVSROOT_DIRNAME}/first-dir/file2,v"
- fi
- dotest rcslib-symlink-2 "${testcvs} update file2" "U file2"
- echo "This is a change" >> file2
- dotest rcslib-symlink-3 "${testcvs} ci -m because file2" \
-"Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file2
-new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
-done"
-
- # Switch as for rcslib-symlink-1
- if test -n "$remotehost"; then
- dotest rcslib-symlink-4 "$CVS_RSH $remotehost 'ls -l $CVSROOT_DIRNAME/first-dir/file2,v'" \
-".*$CVSROOT_DIRNAME/first-dir/file2,v -> file1,v"
- else
- dotest rcslib-symlink-4 "ls -l $CVSROOT_DIRNAME/first-dir/file2,v" \
-".*$CVSROOT_DIRNAME/first-dir/file2,v -> file1,v"
- fi
-
- # CVS was failing to check both the symlink and the file
- # for timestamp changes for a while. Test that.
- rm file1
- dotest rcslib-symlink-3a "${testcvs} -q up file1" \
-"${PROG} update: warning: file1 was lost
-U file1"
- echo "This is a change" >> file1
- dotest rcslib-symlink-3b "${testcvs} ci -m because file1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.2\.[0-9]*; previous revision: 1\.1\.2\.[0-9]*
-done"
- dotest rcslib-symlink-3c "${testcvs} update file2" "[UP] file2"
-
- echo some new text >file3
- dotest rcslib-symlink-3d "${testcvs} -Q add file3" ''
- dotest rcslib-symlink-3e "${testcvs} -Q ci -mtest file3" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file3,v
-done
-Checking in file3;
-${CVSROOT_DIRNAME}/first-dir/Attic/file3,v <-- file3
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
-
- rm -f ${CVSROOT_DIRNAME}/first-dir/file2,v
- # As for rcslib-symlink-1
- if test -n "$remotehost"; then
- dotest rcslib-symlink-3f "$CVS_RSH $remotehost 'ln -s Attic/file3,v ${CVSROOT_DIRNAME}/first-dir/file2,v'"
- else
- dotest rcslib-symlink-3f "ln -s Attic/file3,v ${CVSROOT_DIRNAME}/first-dir/file2,v"
- fi
-
- dotest rcslib-symlink-3g "${testcvs} update file2" "U file2"
-
- # restore the link to file1 for the following tests
- dotest rcslib-symlink-3i "${testcvs} -Q rm -f file3" ''
- dotest rcslib-symlink-3j "${testcvs} -Q ci -mwhatever file3" \
-"Removing file3;
-${CVSROOT_DIRNAME}/first-dir/Attic/file3,v <-- file3
-new revision: delete; previous revision: 1\.1\.2\.1
-done"
- rm -f ${CVSROOT_DIRNAME}/first-dir/file2,v
- rm -f ${CVSROOT_DIRNAME}/first-dir/Attic/file3,v
- # As for rcslib-symlink-1
- if test -n "$remotehost"; then
- dotest rcslib-symlink-3h "$CVS_RSH $remotehost 'ln -s file1,v ${CVSROOT_DIRNAME}/first-dir/file2,v'"
- else
- dotest rcslib-symlink-3h "ln -s file1,v ${CVSROOT_DIRNAME}/first-dir/file2,v"
- fi
-
- # Test 5 reveals a problem with having symlinks in the
- # repository. CVS will try to tag both of the files
- # separately. After processing one, it will do the same
- # operation to the other, which is actually the same file,
- # so the tag will already be there. FIXME: do we bother
- # changing operations to notice cases like this? This
- # strikes me as a difficult problem. -Noel
- dotest rcslib-symlink-5 "${testcvs} tag the_tag" \
-"${PROG} tag: Tagging .
-T file1
-W file2 : the_tag already exists on version 1.1.2.3 : NOT MOVING tag to version 1.1.2.1"
- # As for rcslib-symlink-1
- if test -n "$remotehost"; then
- dotest rcslib-symlink-6 "$CVS_RSH $remotehost 'ls -l $CVSROOT_DIRNAME/first-dir/file2,v'" \
-".*$CVSROOT_DIRNAME/first-dir/file2,v -> file1,v"
- else
- dotest rcslib-symlink-6 "ls -l $CVSROOT_DIRNAME/first-dir/file2,v" \
-".*$CVSROOT_DIRNAME/first-dir/file2,v -> file1,v"
- fi
-
- # Symlinks tend to interact poorly with the Attic.
- cd ..
- mkdir 2; cd 2
- dotest rcslib-symlink-7 "${testcvs} -q co first-dir" \
-"U first-dir/file1
-U first-dir/file2"
- cd first-dir
- dotest rcslib-symlink-8 "${testcvs} rm -f file2" \
-"${PROG} remove: scheduling .file2. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest rcslib-symlink-9 "${testcvs} -q ci -m rm-it" \
-"Removing file2;
-${CVSROOT_DIRNAME}/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} rtag: could not read RCS file for file2
-${PROG} rtag: could not read RCS file for first-dir/file2
-${PROG} rtag: could not read RCS file for first-dir/file2"
-
- # Restore file1 for the next test.
- dotest rcslib-long-symlink-init-1 "$testcvs -Q up -A"
- dotest rcslib-long-symlink-init-2 "$testcvs -Q add file1"
- dotest rcslib-long-symlink-init-3 "$testcvs -Q ci -mback" \
-"Checking in file1;
-$CVSROOT_DIRNAME/first-dir/file1,v <-- file1
-new revision: 1\.4; previous revision: 1\.3
-done"
-
- cd ../.. # $TESTDIR
-
- # CVS has a hard-coded default link path size of 127 characters.
- # Make sure it knows how to exceed that.
- longpath=$CVSROOT_DIRNAME
- count=0
- while test $count -lt 10; do
- count=`expr $count + 1`
- longpath=$longpath/123456789012345678901234567890
- mkdir $longpath
- done
- cp $CVSROOT_DIRNAME/first-dir/file1,v $longpath
- mkdir $CVSROOT_DIRNAME/second-dir
-
- # Switch as for rcslib-symlink-1
- if test -n "$remotehost"; then
- dotest rcslib-long-symlink-1rh \
-"$CVS_RSH $remotehost 'ln -s $longpath/file1,v $CVSROOT_DIRNAME/second-dir/fileX,v'"
- else
- dotest rcslib-long-symlink-1 \
-"ln -s $longpath/file1,v $CVSROOT_DIRNAME/second-dir/fileX,v"
- fi
-
- dotest rcslib-long-symlink-2 "$testcvs co second-dir" \
-"$PROG checkout: Updating second-dir
-U second-dir/fileX"
-
- cd second-dir
- echo change-it >>fileX
-
- # Writes actually cause symlinks to be resolved.
- dotest rcslib-long-symlink-3 "$testcvs -q ci -mwrite-it" \
-"Checking in fileX;
-$CVSROOT_DIRNAME/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/123456789012345678901234567890/file1,v <-- fileX
-new revision: 1\.5; previous revision: 1\.4
-done"
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- cd ..
- # Must remove the symlink first. Samba doesn't appear to show
- # broken symlink across the SMB share, and rm -rf by itself
- # will remove file1,v first and leave file2,v a broken link and the
- # rm -rf will fail since it doesn't find file2,v and it still gets
- # directory not empty errors removing cvsroot/first-dir.
- #
- # I'm not sure why I need to do this on $remotehost. The rm above
- # rcslib-symlink-3j works fine, but the next one doesn't unless run
- # remotely under Cygwin and using a TESTDIR on a Samba share.
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost \
-"rm -f $CVSROOT_DIRNAME/first-dir/file2,v $CVSROOT_DIRNAME/second-dir/fileX,v"
- fi
- rm -rf $CVSROOT_DIRNAME/first-dir $CVSROOT_DIRNAME/second-dir \
- $CVSROOT_DIRNAME/123456789012345678901234567890
- rm -r first-dir second-dir 2
- ;;
-
- multibranch)
- # Test the ability to have several branchpoints coming off the
- # same revision.
- mkdir ${CVSROOT_DIRNAME}/first-dir
- dotest multibranch-1 "${testcvs} -q co first-dir" ''
- cd first-dir
- echo 1:trunk-1 >file1
- dotest multibranch-2 "${testcvs} add file1" \
-"${PROG}"' add: scheduling file `file1'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest_lit multibranch-3 "${testcvs} -q ci -m add-it" <<HERE
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1.1
-done
-HERE
- dotest multibranch-4 "${testcvs} tag -b br1" \
-"${PROG} tag: Tagging \.
-T file1"
- dotest multibranch-5 "${testcvs} tag -b br2" \
-"${PROG} tag: Tagging \.
-T file1"
- dotest multibranch-6 "$testcvs -q update -r br1" '[UP] file1'
- echo on-br1 >file1
- dotest multibranch-7 "${testcvs} -q ci -m modify-on-br1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
- dotest multibranch-8 "${testcvs} -q update -r br2" '[UP] file1'
- echo br2 adds a line >>file1
- dotest multibranch-9 "${testcvs} -q ci -m modify-on-br2" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.4\.1; previous revision: 1\.1
-done"
- dotest multibranch-10 "${testcvs} -q update -r br1" '[UP] file1'
- dotest multibranch-11 "cat file1" 'on-br1'
- dotest multibranch-12 "${testcvs} -q update -r br2" '[UP] file1'
- dotest multibranch-13 "cat file1" '1:trunk-1
-br2 adds a line'
-
- dotest multibranch-14 "${testcvs} log file1" \
-"
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
-symbolic names:
- br2: 1\.1\.0\.4
- br1: 1\.1\.0\.2
-keyword substitution: kv
-total revisions: 3; selected revisions: 3
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-branches: 1\.1\.2; 1\.1\.4;
-add-it
-----------------------------
-revision 1\.1\.4\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-modify-on-br2
-----------------------------
-revision 1\.1\.2\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -1
-modify-on-br1
-============================================================================="
- cd ..
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- rm -r first-dir
- ;;
-
- import) # test death after import
- # Tests of "cvs import":
- # basic2
- # rdiff -- imports with keywords
- # import -- more tests of imports with keywords
- # importb -- -b option.
- # importc -- bunch o' files in bunch o' directories
- # modules3
- # mflag -- various -m messages
- # ignore -- import and cvsignore
- # binwrap -- import and -k wrappers
- # info -- imports which are rejected by verifymsg
- # head -- intended to test vendor branches and HEAD,
- # although it doesn't really do it yet.
- # import-CVS -- refuse to import directories named "CVS".
- # import-quirks -- short tests of import quirks.
-
- # import
- mkdir import-dir ; cd import-dir
-
- for i in 1 2 3 4 ; do
- echo imported file"$i" > imported-f"$i"
- done
-
- # This directory should be on the default ignore list,
- # so it shouldn't get imported.
- mkdir RCS
- echo ignore.me >RCS/ignore.me
-
- echo 'import should not expand $''Id$' >>imported-f2
- cp imported-f2 ../imported-f2-orig.tmp
-
- dotest_sort import-96 \
-"${testcvs} import -m first-import first-dir vendor-branch junk-1_0" \
-"
-
-I first-dir/RCS
-N first-dir/imported-f1
-N first-dir/imported-f2
-N first-dir/imported-f3
-N first-dir/imported-f4
-No conflicts created by this import"
-
- dotest import-96.5 "cmp ../imported-f2-orig.tmp imported-f2" ''
-
- cd ..
-
- # co
- dotest import-97 "${testcvs} -q co first-dir" \
-"U first-dir/imported-f1
-U first-dir/imported-f2
-U first-dir/imported-f3
-U first-dir/imported-f4"
-
- cd first-dir
-
- for i in 1 2 3 4 ; do
- dotest import-98-$i "test -f imported-f$i" ''
- done
- dotest_fail import-98.5 "test -d RCS" ''
-
- # remove
- rm imported-f1
- dotest import-99 "${testcvs} rm imported-f1" \
-"${PROG}"' remove: scheduling `imported-f1'\'' for removal
-'"${PROG}"' remove: use .'"${PROG}"' commit. to remove this file permanently'
-
- # change
- echo local-change >> imported-f2
-
- # commit
- dotest import-100 "${testcvs} ci -m local-changes" \
-"${PROG} [a-z]*: Examining .
-Removing imported-f1;
-${CVSROOT_DIRNAME}/first-dir/imported-f1,v <-- imported-f1
-new revision: delete; previous revision: 1\.1\.1\.1
-done
-Checking in imported-f2;
-${CVSROOT_DIRNAME}/first-dir/imported-f2,v <-- imported-f2
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # log
- dotest import-101 "${testcvs} log imported-f1" \
-"
-RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/imported-f1,v
-Working file: imported-f1
-head: 1\.2
-branch:
-locks: strict
-access list:
-symbolic names:
- junk-1_0: 1\.1\.1\.1
- vendor-branch: 1\.1\.1
-keyword substitution: kv
-total revisions: 3; selected revisions: 3
-description:
-----------------------------
-revision 1\.2
-date: [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.
- dotest import-102 "$testcvs update -rvendor-branch" \
-"$PROG update: Updating .
-U imported-f1
-[UP] imported-f2
-[UP] imported-f3
-[UP] imported-f4"
-
- # remove file4 on the vendor branch
- rm imported-f4
- dotest import-103 "${testcvs} rm imported-f4" \
-"${PROG}"' remove: scheduling `imported-f4'\'' for removal
-'"${PROG}"' remove: use .'"${PROG}"' commit. to remove this file permanently'
-
- # commit
- dotest import-104 \
-"${testcvs} ci -m vendor-removed imported-f4" \
-"Removing imported-f4;
-${CVSROOT_DIRNAME}/first-dir/imported-f4,v <-- imported-f4
-new revision: delete; previous revision: 1\.1\.1\.1
-done"
-
- # update to main line
- dotest import-105 "$testcvs -q update -A" \
-"$PROG update: imported-f1 is no longer in the repository
-[UP] imported-f2
-[UP] imported-f3"
-
- # second import - file4 deliberately unchanged
- cd ../import-dir
- for i in 1 2 3 ; do
- echo rev 2 of file $i >> imported-f"$i"
- done
- cp imported-f2 ../imported-f2-orig.tmp
-
- dotest_sort import-106 \
-"${testcvs} import -m second-import first-dir vendor-branch junk-2_0" \
-"
-
-
- ${PROG} checkout -j<prev_rel_tag> -jjunk-2_0 first-dir
-2 conflicts created by this import.
-C first-dir/imported-f1
-C first-dir/imported-f2
-I first-dir/RCS
-U first-dir/imported-f3
-U first-dir/imported-f4
-Use the following command to help the merge:"
-
- dotest import-106.5 "cmp ../imported-f2-orig.tmp imported-f2" \
-''
-
- cd ..
-
- rm imported-f2-orig.tmp
-
- # co
- dotest import-107 "${testcvs} co first-dir" \
-"${PROG} checkout: Updating first-dir
-[UP] first-dir/imported-f3
-[UP] first-dir/imported-f4"
-
- cd first-dir
-
- dotest_fail import-108 "test -f imported-f1" ''
-
- for i in 2 3 ; do
- dotest import-109-$i "test -f imported-f$i" ''
- done
-
- # check vendor branch for file4
- dotest import-110 "$testcvs -q update -rvendor-branch" \
-'U imported-f1
-[UP] imported-f2
-[UP] imported-f3
-[UP] imported-f4'
-
- dotest import-111 "test -f imported-f4" ''
-
- # update to main line
- dotest import-112 "$testcvs -q update -A" \
-"$PROG update: imported-f1 is no longer in the repository
-[UP] imported-f2
-[UP] imported-f3
-[UP] imported-f4"
-
- cd ..
-
- dotest import-113 \
-"${testcvs} -q co -jjunk-1_0 -jjunk-2_0 first-dir" \
-"${PROG} checkout: file first-dir/imported-f1 does not exist, but is present in revision junk-2_0
-RCS file: ${CVSROOT_DIRNAME}/first-dir/imported-f2,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.1\.1\.2
-Merging differences between 1\.1\.1\.1 and 1\.1\.1\.2 into imported-f2
-rcsmerge: warning: conflicts during merge
-first-dir/imported-f3 already contains the differences between 1\.1\.1\.1 and 1\.1\.1\.2
-first-dir/imported-f4 already contains the differences between 1\.1\.1\.1 and 1\.1\.1\.3"
-
- cd first-dir
-
- dotest_fail import-114 "test -f imported-f1" ''
-
- for i in 2 3 ; do
- dotest import-115-$i "test -f imported-f$i" ''
- done
-
- dotest import-116 'cat imported-f2' \
-'imported file2
-[<]<<<<<< imported-f2
-import should not expand \$''Id: imported-f2,v 1\.2 [0-9/]* [0-9:]* '"${username}"' Exp \$
-local-change
-[=]======
-import should not expand \$''Id: imported-f2,v 1\.1\.1\.2 [0-9/]* [0-9:]* '"${username}"' Exp \$
-rev 2 of file 2
-[>]>>>>>> 1\.1\.1\.2'
-
- cd ..
- rm -r first-dir
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- rm -r import-dir
- ;;
-
- importb)
- # More cvs import tests, especially -b option.
-
- # OK, first we get some sources from the NetMunger project, and
- # import them into the 1.1.1 vendor branch.
- mkdir imp-dir
- cd imp-dir
- echo 'OpenMunger sources' >file1
- echo 'OpenMunger sources' >file2
- dotest_sort importb-1 \
-"${testcvs} import -m add first-dir openmunger openmunger-1_0" \
-"
-
-N first-dir/file1
-N first-dir/file2
-No conflicts created by this import"
- cd ..
- rm -r imp-dir
-
- # Now we put the sources we get from FreeMunger into 1.1.3
- mkdir imp-dir
- cd imp-dir
- echo 'FreeMunger sources' >file1
- echo 'FreeMunger sources' >file2
- # Not completely sure how the conflict detection is supposed to
- # be working here (haven't really thought about it).
- # We use an explicit -d option to test that it is reflected
- # in the suggested checkout.
- dotest_sort importb-2 \
-"${testcvs} -d ${CVSROOT} import -m add -b 1.1.3 first-dir freemunger freemunger-1_0" \
-"
-
-
- ${PROG} -d ${CVSROOT} checkout -j<prev_rel_tag> -jfreemunger-1_0 first-dir
-2 conflicts created by this import.
-C first-dir/file1
-C first-dir/file2
-Use the following command to help the merge:"
- cd ..
- rm -r imp-dir
-
- # Now a test of main branch import (into second-dir, not first-dir).
- mkdir imp-dir
- cd imp-dir
- echo 'my own stuff' >mine1.c
- echo 'my own stuff' >mine2.c
- dotest_fail importb-3 \
-"${testcvs} import -m add -b 1 second-dir dummy really_dumb_y" \
-"$PROG \[import aborted\]: Only numeric branch specifications with two dots are
-supported by import, not \`1'\. For example: \`1\.1\.1'\."
- : when we implement main-branch import, should be \
-"N second-dir/mine1\.c
-N second-dir/mine2\.c
-
-No conflicts created by this import"
- cd ..
- rm -r imp-dir
-
- mkdir 1
- cd 1
- # when we implement main branch import, will want to
- # add "second-dir" here.
- dotest importb-4 "${testcvs} -q co first-dir" \
-"U first-dir/file1
-U first-dir/file2"
- cd first-dir
- dotest importb-5 "${testcvs} -q log file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch: 1\.1\.1
-locks: strict
-access list:
-symbolic names:
- freemunger-1_0: 1\.1\.3\.1
- freemunger: 1\.1\.3
- openmunger-1_0: 1\.1\.1\.1
- openmunger: 1\.1\.1
-keyword substitution: kv
-total revisions: 3; selected revisions: 3
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-branches: 1\.1\.1; 1\.1\.3;
-Initial revision
-----------------------------
-revision 1\.1\.3\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -1
-add
-----------------------------
-revision 1\.1\.1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}0 -0
-add
-============================================================================="
-
- cd ../..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir ${CVSROOT_DIRNAME}/second-dir
- ;;
-
- importc)
- # Test importing a bunch o' files in a bunch o' directories.
- # Also the -d option.
- mkdir 1; cd 1
- mkdir adir bdir cdir
- mkdir adir/sub1 adir/sub2
- mkdir adir/sub1/ssdir
- mkdir bdir/subdir
- touch adir/sub1/file1 adir/sub2/file2 adir/sub1/ssdir/ssfile
- touch -t 197107040343 bdir/subdir/file1
- touch -t 203412251801 cdir/cfile
- dotest_sort importc-1 \
-"${testcvs} import -d -m import-it first-dir vendor release" \
-"
-
-N first-dir/adir/sub1/file1
-N first-dir/adir/sub1/ssdir/ssfile
-N first-dir/adir/sub2/file2
-N first-dir/bdir/subdir/file1
-N first-dir/cdir/cfile
-No conflicts created by this import
-${PROG} import: Importing ${CVSROOT_DIRNAME}/first-dir/adir
-${PROG} import: Importing ${CVSROOT_DIRNAME}/first-dir/adir/sub1
-${PROG} import: Importing ${CVSROOT_DIRNAME}/first-dir/adir/sub1/ssdir
-${PROG} import: Importing ${CVSROOT_DIRNAME}/first-dir/adir/sub2
-${PROG} import: Importing ${CVSROOT_DIRNAME}/first-dir/bdir
-${PROG} import: Importing ${CVSROOT_DIRNAME}/first-dir/bdir/subdir
-${PROG} import: Importing ${CVSROOT_DIRNAME}/first-dir/cdir"
- cd ..
- mkdir 2; cd 2
- dotest importc-2 "${testcvs} -q co first-dir" \
-"U first-dir/adir/sub1/file1
-U first-dir/adir/sub1/ssdir/ssfile
-U first-dir/adir/sub2/file2
-U first-dir/bdir/subdir/file1
-U first-dir/cdir/cfile"
- cd first-dir
- dotest importc-3 "${testcvs} update adir/sub1" \
-"${PROG} update: Updating adir/sub1
-${PROG} update: Updating adir/sub1/ssdir"
- dotest importc-4 "${testcvs} update adir/sub1 bdir/subdir" \
-"${PROG} update: Updating adir/sub1
-${PROG} update: Updating adir/sub1/ssdir
-${PROG} update: Updating bdir/subdir"
-
- echo modify >>cdir/cfile
- dotest importc-5 \
-"${testcvs} -q rtag -b -r release wip_test first-dir" ""
- dotest importc-6 "$testcvs -q update -r wip_test" \
-'U adir/sub1/file1
-U adir/sub1/ssdir/ssfile
-U adir/sub2/file2
-U bdir/subdir/file1
-M cdir/cfile'
-
- # This used to fail in local mode
- dotest importc-7 "${testcvs} -q ci -m modify -r wip_test" \
-"Checking in cdir/cfile;
-${CVSROOT_DIRNAME}/first-dir/cdir/cfile,v <-- cfile
-new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1
-done"
-
- # TODO: should also be testing "import -d" when we update
- # an existing file.
- dotest importc-8 "${testcvs} -q log cdir/cfile" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/cdir/cfile,v
-Working file: cdir/cfile
-head: 1\.1
-branch: 1\.1\.1
-locks: strict
-access list:
-symbolic names:
- wip_test: 1\.1\.1\.1\.0\.2
- release: 1\.1\.1\.1
- vendor: 1\.1\.1
-keyword substitution: kv
-total revisions: 3; selected revisions: 3
-description:
-----------------------------
-revision 1\.1
-date: 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: ${CVSROOT_DIRNAME}/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-CVS)
- mkdir import-CVS
- cd import-CVS
- touch file1 file2 file3
- dotest_fail import-CVS-1 "$testcvs import -mimport CVS vtag rtag" \
-"$PROG import: The word \`CVS' is reserved by CVS and may not be used
-$PROG \[import aborted\]: as a directory in a path or as a file name\."
- dotest_fail import-CVS-1b \
-"$testcvs import -mimport CVS-/CVS vtag rtag" \
-"$PROG import: The word \`CVS' is reserved by CVS and may not be used
-$PROG \[import aborted\]: as a directory in a path or as a file name\."
- mkdir sdir
- mkdir sdir/CVS
- touch CVS sdir/CVS/file4 sdir/CVS/file5 sdir/file6 sdir/file7
- # Calling the imported directory import-CVS is dual purpose in the
- # following test. It makes sure the path test which matched above
- # wasn't too strict.
- dotest_sort import-CVS-2 \
-"$testcvs import -I! -mimport import-CVS vtag rtag" \
-"
-
-I import-CVS/CVS
-I import-CVS/sdir/CVS
-N import-CVS/file1
-N import-CVS/file2
-N import-CVS/file3
-N import-CVS/sdir/file6
-N import-CVS/sdir/file7
-No conflicts created by this import
-$PROG import: Importing $CVSROOT_DIRNAME/import-CVS/sdir"
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- cd ..
- rm -r import-CVS
- rm -rf $CVSROOT_DIRNAME/import-CVS
- ;;
-
-
-
- import-quirks)
- # Short tests of quirky import behavior.
- #
- # For a list of other import tests with short descriptions, see the
- # comment header of the "import" test.
- mkdir import-quirks
- cd import-quirks
- touch file1 file2 file3
-
- # CVS prior to 1.11.18 and 1.12.10 used to happily import to
- # "branch 1.1", creating RCS archives with revisions like,
- # "1.1..1". That double-dot is *not* a typo.
- dotest_fail import-quirks-1 \
-"$testcvs import -b1.1. -mbad-bad-bad import-quirks VB RT" \
-"$PROG \[import aborted\]: Only numeric branch specifications with two dots are
-supported by import, not \`1\.1\.'\. For example: \`1\.1\.1'\."
-
- dotest_fail import-quirks-2 \
-"$testcvs import -b1.1.1.. -mbad-bad-bad import-quirks VB RT" \
-"$PROG \[import aborted\]: Only numeric branch specifications with two dots are
-supported by import, not \`1\.1\.1\.\.'\. For example: \`1\.1\.1'\."
-
- # Try a few odd numbers. This is hardly comprehensive.
- dotest_sort import-quirks-2 \
-"$testcvs import -b10.10.101 -mthis-ones-ok import-quirks-2 VB RT" \
-"
-
-N import-quirks-2/file1
-N import-quirks-2/file2
-N import-quirks-2/file3
-No conflicts created by this import"
-
- dotest_sort import-quirks-3 \
-"$testcvs import -b2345678901.2345678901.2345678901 -mthis-ones-ok import-quirks-3 VB RT" \
-"
-
-N import-quirks-3/file1
-N import-quirks-3/file2
-N import-quirks-3/file3
-No conflicts created by this import"
-
- dotest_sort import-quirks-4 \
-"$testcvs import -b1.1.2 -mthis-ones-ok import-quirks-4 VB RT" \
-"
-
-N import-quirks-4/file1
-N import-quirks-4/file2
-N import-quirks-4/file3
-No conflicts created by this import"
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- cd ..
- rm -r import-quirks
- rm -rf $CVSROOT_DIRNAME/import-quirks-2 \
- $CVSROOT_DIRNAME/import-quirks-3 \
- $CVSROOT_DIRNAME/import-quirks-4
- ;;
-
-
-
- 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" ""
- dotest import-after-initial-4 "${testcvs} -Q ci -m. $file" \
-"RCS file: ${CVSROOT_DIRNAME}/$module/$file,v
-done
-Checking in $file;
-${CVSROOT_DIRNAME}/$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
- ;;
-
- branch-after-import)
- # Test branching after an import via both cvs tag -b and
- # cvs add to verify that the HEAD remains at 1.1.1.1
- # This was a FreeBSD bug documented at the URL:
- # http://www.freebsd.org/cgi/query-pr.cgi?pr=4033
-
- mkdir branch-after-import
- cd branch-after-import
-
- # OK, first we get some sources from the NetMunger project,
- # and import them into the 1.1.1 vendor branch.
- mkdir imp-dir
- cd imp-dir
- echo 'OpenMunger sources' >file1
- echo 'OpenMunger sources' >file2
- dotest_sort branch-after-import-1 \
-"${testcvs} import -m add first-dir openmunger openmunger-1_0" \
-'
-
-N first-dir/file1
-N first-dir/file2
-No conflicts created by this import'
- cd ..
-
- # Next checkout the new module
- dotest branch-after-import-2 \
-"${testcvs} -q co first-dir" \
-'U first-dir/file1
-U first-dir/file2'
- cd first-dir
- # Branch tag the file1 and cvs add file2,
- # the branch should remain the same in both cases
- # such that a new import will not require a conflict
- # resolution.
- dotest branch-after-import-3 \
-"${testcvs} tag -b TESTTOTRON file1" \
-'T file1'
- dotest branch-after-import-4 \
-"$testcvs -q update -r TESTTOTRON" \
-"[UP] file1
-$PROG update: file2 is no longer in the repository"
-
- cp ../imp-dir/file2 .
- dotest branch-after-import-5 \
-"${testcvs} add file2" \
-"${PROG} add: scheduling file .file2. for addition on branch .TESTTOTRON.
-${PROG} add: use .${PROG} commit. to add this file permanently"
-
- dotest branch-after-import-6 \
-"${testcvs} commit -m cvs-add file2" \
-"Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.1\.1\.1\.2\.2; previous revision: 1\.1\.1\.1\.2\.1
-done"
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- cd ../..
- rm -r branch-after-import
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- join)
- # Test doing joins which involve adding and removing files.
- # Variety of scenarios (see list below), in the context of:
- # * merge changes from T1 to T2 into the main line
- # * merge changes from branch 'branch' into the main line
- # * merge changes from branch 'branch' into branch 'br2'.
- # 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:
- #
- # --->bp---->trunk too many to mention
- # \----->branch
- #
- # /----->branch1
- # --->bp---->trunk multibranch, multibranch2
- # \----->branch2
- #
- # --->bp1----->bp2---->trunk join3
- # \->br1 \->br2
- #
- # --->bp1----->trunk
- # \----bp2---->branch branches
- # \------>branch-of-branch
-
- # We check merging changes from T1 to T2 into the main line.
- # Here are the interesting cases I can think of:
- # 1) File added between T1 and T2, not on main line.
- # File should be marked for addition.
- # 2) File added between T1 and T2, also added on main line.
- # Conflict.
- # 3) File removed between T1 and T2, unchanged on main line.
- # File should be marked for removal.
- # 4) File removed between T1 and T2, modified on main line.
- # If mod checked in, file should be marked for removal.
- # If mod still in working directory, conflict.
- # 5) File removed between T1 and T2, was never on main line.
- # Nothing should happen.
- # 6) File removed between T1 and T2, also removed on main line.
- # Nothing should happen.
- # 7) File not added between T1 and T2, added on main line.
- # Nothing should happen.
- # 8) File not modified between T1 and T2, removed on main line.
- # Nothing should happen.
- # 9) File modified between T1 and T2, removed on main line.
- # Conflict.
- # 10) File was never on branch, removed on main line.
- # Nothing should happen.
-
- # We also check merging changes from a branch into the main
- # line. Here are the interesting cases:
- # 1) File added on branch, not on main line.
- # File should be marked for addition.
- # 2) File added on branch, also added on main line.
- # Conflict.
- # 3) File removed on branch, unchanged on main line.
- # File should be marked for removal.
- # 4) File removed on branch, modified on main line.
- # Conflict.
- # 5) File removed on branch, was never on main line.
- # Nothing should happen.
- # 6) File removed on branch, also removed on main line.
- # Nothing should happen.
- # 7) File added on main line, not added on branch.
- # Nothing should happen.
- # 8) File removed on main line, not modified on branch.
- # Nothing should happen.
- # 9) File modified on branch, removed on main line.
- # Conflict.
- # 10) File was never on branch, removed on main line.
- # Nothing should happen.
-
- # In the tests below, fileN represents case N in the above
- # lists.
-
- mkdir ${CVSROOT_DIRNAME}/first-dir
- mkdir 1
- cd 1
- dotest join-1 "${testcvs} -q co first-dir" ''
-
- cd first-dir
-
- # Add two files.
- echo 'first revision of file3' > file3
- echo 'first revision of file4' > file4
- echo 'first revision of file6' > file6
- echo 'first revision of file8' > file8
- echo 'first revision of file9' > file9
- dotest join-2 "${testcvs} add file3 file4 file6 file8 file9" \
-"${PROG}"' add: scheduling file `file3'\'' for addition
-'"${PROG}"' add: scheduling file `file4'\'' for addition
-'"${PROG}"' add: scheduling file `file6'\'' for addition
-'"${PROG}"' add: scheduling file `file8'\'' for addition
-'"${PROG}"' add: scheduling file `file9'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add these files permanently'
-
- dotest join-3 "${testcvs} -q commit -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file3,v
-done
-Checking in file3;
-${CVSROOT_DIRNAME}/first-dir/file3,v <-- file3
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file4,v
-done
-Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file6,v
-done
-Checking in file6;
-${CVSROOT_DIRNAME}/first-dir/file6,v <-- file6
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file8,v
-done
-Checking in file8;
-${CVSROOT_DIRNAME}/first-dir/file8,v <-- file8
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file9,v
-done
-Checking in file9;
-${CVSROOT_DIRNAME}/first-dir/file9,v <-- file9
-initial revision: 1\.1
-done"
-
- # Make a branch.
- dotest join-4 "${testcvs} -q tag -b branch ." \
-'T file3
-T file4
-T file6
-T file8
-T file9'
-
- # Add file2, file7, and file10, modify file4, and remove
- # file6, file8, and file9.
- echo 'first revision of file2' > file2
- echo 'second revision of file4' > file4
- echo 'first revision of file7' > file7
- rm file6 file8 file9
- echo 'first revision of file10' > file10
- dotest join-5 "${testcvs} add file2 file7 file10" \
-"${PROG}"' add: scheduling file `file2'\'' for addition
-'"${PROG}"' add: scheduling file `file7'\'' for addition
-'"${PROG}"' add: scheduling file `file10'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add these files permanently'
- dotest join-6 "${testcvs} rm file6 file8 file9" \
-"${PROG}"' remove: scheduling `file6'\'' for removal
-'"${PROG}"' remove: scheduling `file8'\'' for removal
-'"${PROG}"' remove: scheduling `file9'\'' for removal
-'"${PROG}"' remove: use .'"${PROG}"' commit. to remove these files permanently'
- dotest join-7 "${testcvs} -q ci -mx ." \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file10,v
-done
-Checking in file10;
-${CVSROOT_DIRNAME}/first-dir/file10,v <-- file10
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1\.1
-done
-Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: 1\.2; previous revision: 1\.1
-done
-Removing file6;
-${CVSROOT_DIRNAME}/first-dir/file6,v <-- file6
-new revision: delete; previous revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file7,v
-done
-Checking in file7;
-${CVSROOT_DIRNAME}/first-dir/file7,v <-- file7
-initial revision: 1\.1
-done
-Removing file8;
-${CVSROOT_DIRNAME}/first-dir/file8,v <-- file8
-new revision: delete; previous revision: 1\.1
-done
-Removing file9;
-${CVSROOT_DIRNAME}/first-dir/file9,v <-- file9
-new revision: delete; previous revision: 1\.1
-done"
-
- # Remove file10
- dotest join-7a "${testcvs} rm -f file10" \
-"${PROG}"' remove: scheduling `file10'\'' for removal
-'"${PROG}"' remove: use .'"${PROG}"' commit. to remove this file permanently'
- dotest join-7b "${testcvs} -q ci -mx ." \
-"Removing file10;
-${CVSROOT_DIRNAME}/first-dir/file10,v <-- file10
-new revision: delete; previous revision: 1\.1
-done"
-
- # Check out the branch.
- cd ../..
- mkdir 2
- cd 2
- dotest join-8 "${testcvs} -q co -r branch first-dir" \
-'U first-dir/file3
-U first-dir/file4
-U first-dir/file6
-U first-dir/file8
-U first-dir/file9'
-
- cd first-dir
-
- # Modify the files on the branch, so that T1 is not an
- # ancestor of the main line, and add file5
- echo 'first branch revision of file3' > file3
- echo 'first branch revision of file4' > file4
- echo 'first branch revision of file5' > file5
- echo 'first branch revision of file6' > file6
- echo 'first branch revision of file9' > file9
- dotest join-9 "${testcvs} add file5" \
-"${PROG}"' add: scheduling file `file5'\'' for addition on branch `branch'\''
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest join-10 "${testcvs} -q ci -mx ." \
-"Checking in file3;
-${CVSROOT_DIRNAME}/first-dir/file3,v <-- file3
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file5,v
-done
-Checking in file5;
-${CVSROOT_DIRNAME}/first-dir/Attic/file5,v <-- file5
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in file6;
-${CVSROOT_DIRNAME}/first-dir/Attic/file6,v <-- file6
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in file9;
-${CVSROOT_DIRNAME}/first-dir/Attic/file9,v <-- file9
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
-
- # Tag the current revisions on the branch.
- dotest join-11 "${testcvs} -q tag T1 ." \
-'T file3
-T file4
-T file5
-T file6
-T file8
-T file9'
-
- # Add file1 and file2, modify file9, and remove the other files.
- echo 'first branch revision of file1' > file1
- echo 'first branch revision of file2' > file2
- echo 'second branch revision of file9' > file9
- rm file3 file4 file5 file6
- dotest join-12 "${testcvs} add file1 file2" \
-"${PROG}"' add: scheduling file `file1'\'' for addition on branch `branch'\''
-'"${PROG}"' add: scheduling file `file2'\'' for addition on branch `branch'\''
-'"${PROG}"' add: use .'"${PROG}"' commit. to add these files permanently'
- dotest join-13 "${testcvs} rm file3 file4 file5 file6" \
-"${PROG}"' remove: scheduling `file3'\'' for removal
-'"${PROG}"' remove: scheduling `file4'\'' for removal
-'"${PROG}"' remove: scheduling `file5'\'' for removal
-'"${PROG}"' remove: scheduling `file6'\'' for removal
-'"${PROG}"' remove: use .'"${PROG}"' commit. to remove these files permanently'
- dotest join-14 "${testcvs} -q ci -mx ." \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/Attic/file1,v <-- file1
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
-done
-Removing file3;
-${CVSROOT_DIRNAME}/first-dir/file3,v <-- file3
-new revision: delete; previous revision: 1\.1\.2\.1
-done
-Removing file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: delete; previous revision: 1\.1\.2\.1
-done
-Removing file5;
-${CVSROOT_DIRNAME}/first-dir/Attic/file5,v <-- file5
-new revision: delete; previous revision: 1\.1\.2\.1
-done
-Removing file6;
-${CVSROOT_DIRNAME}/first-dir/Attic/file6,v <-- file6
-new revision: delete; previous revision: 1\.1\.2\.1
-done
-Checking in file9;
-${CVSROOT_DIRNAME}/first-dir/Attic/file9,v <-- file9
-new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
-done"
-
- # Tag the current revisions on the branch.
- dotest join-15 "${testcvs} -q tag T2 ." \
-'T file1
-T file2
-T file8
-T file9'
-
- # Do a checkout with a merge.
- cd ../..
- mkdir 3
- cd 3
- dotest join-16 "$testcvs -q co -jT1 -jT2 first-dir" \
-"U first-dir/file1
-U first-dir/file2
-$PROG checkout: file first-dir/file2 exists, but has been added in revision T2
-U first-dir/file3
-$PROG checkout: scheduling first-dir/file3 for removal
-U first-dir/file4
-$PROG checkout: file first-dir/file4 has been removed in revision T2, but the destination is incompatibly modified
-C first-dir/file4
-U first-dir/file7
-$PROG checkout: file first-dir/file9 does not exist, but is present in revision T2"
-
- # Verify that the right changes have been scheduled.
- cd first-dir
- dotest_fail join-17 "$testcvs -q update" \
-'A file1
-R file3
-C file4'
-
- # Modify file4 locally, and do an update with a merge.
- cd ../../1/first-dir
- echo 'third revision of file4' > file4
- dotest join-18 "$testcvs -q update -jT1 -jT2 ." \
-"U file1
-$PROG update: file file2 exists, but has been added in revision T2
-$PROG update: scheduling file3 for removal
-M file4
-$PROG update: file file4 has been removed in revision T2, but the destination is incompatibly modified
-C file4
-$PROG update: file file9 does not exist, but is present in revision T2"
-
- # Verify that the right changes have been scheduled.
- dotest_fail join-19 "$testcvs -q update" \
-'A file1
-R file3
-C file4'
-
- # Do a checkout with a merge from a single revision.
-
- # FIXME: CVS currently gets this wrong. file2 has been
- # added on both the branch and the main line, and so should
- # be regarded as a conflict. However, given the way that
- # CVS sets up the RCS file, there is no way to distinguish
- # this case from the case of file2 having existed before the
- # branch was made. This could be fixed by reserving
- # a revision somewhere, perhaps 1.1, as an always dead
- # revision which can be used as the source for files added
- # on branches.
- cd ../../3
- rm -r first-dir
- dotest join-20 "$testcvs -q co -jbranch first-dir" \
-"U first-dir/file1
-U first-dir/file2
-RCS file: $CVSROOT_DIRNAME/first-dir/file2,v
-retrieving revision 1\.1
-retrieving revision 1\.1\.2\.2
-Merging differences between 1\.1 and 1\.1\.2\.2 into file2
-U first-dir/file3
-$PROG checkout: scheduling first-dir/file3 for removal
-U first-dir/file4
-$PROG checkout: file first-dir/file4 has been removed in revision branch, but the destination is incompatibly modified
-C first-dir/file4
-U first-dir/file7
-$PROG checkout: file first-dir/file9 does not exist, but is present in revision branch"
-
- # Verify that the right changes have been scheduled.
- # The M file2 line is a bug; see above join-20.
- cd first-dir
- dotest_fail join-21 "$testcvs -q update" \
-'A file1
-M file2
-R file3
-C file4'
-
- # Checkout the main line again.
- cd ../../1
- rm -r first-dir
- dotest join-22 "${testcvs} -q co first-dir" \
-'U first-dir/file2
-U first-dir/file3
-U first-dir/file4
-U first-dir/file7'
-
- # Modify file4 locally, and do an update with a merge from a
- # single revision.
- # The file2 handling is a bug; see above join-20.
- cd first-dir
- echo 'third revision of file4' > file4
- dotest join-23 "$testcvs -q update -jbranch ." \
-"U file1
-RCS file: $CVSROOT_DIRNAME/first-dir/file2,v
-retrieving revision 1\.1
-retrieving revision 1\.1\.2\.2
-Merging differences between 1\.1 and 1\.1\.2\.2 into file2
-$PROG update: scheduling file3 for removal
-M file4
-$PROG update: file file4 has been removed in revision branch, but the destination is incompatibly modified
-C file4
-$PROG update: file file9 does not exist, but is present in revision branch"
-
- # Verify that the right changes have been scheduled.
- # The M file2 line is a bug; see above join-20
- dotest_fail join-24 "$testcvs -q update" \
-'A file1
-M file2
-R file3
-C file4'
-
- cd ..
-
- # Checkout the main line again and make a new branch which we
- # merge to.
- rm -r first-dir
- dotest join-25 "${testcvs} -q co first-dir" \
-'U first-dir/file2
-U first-dir/file3
-U first-dir/file4
-U first-dir/file7'
- cd first-dir
- dotest join-26 "${testcvs} -q tag -b br2" \
-"T file2
-T file3
-T file4
-T file7"
- dotest join-27 "$testcvs -q update -r br2" \
-'[UP] file2
-[UP] file3
-[UP] file4
-[UP] file7'
- # The handling of file8 and file9 here look fishy to me. I don't
- # see why it should be different from the case where we merge to
- # the trunk (e.g. join-23).
- dotest join-28 "$testcvs -q update -j branch" \
-"U file1
-RCS file: $CVSROOT_DIRNAME/first-dir/file2,v
-retrieving revision 1\.1
-retrieving revision 1\.1\.2\.2
-Merging differences between 1\.1 and 1\.1\.2\.2 into file2
-$PROG update: scheduling file3 for removal
-$PROG update: file file4 has been removed in revision branch, but the destination is incompatibly modified
-C file4
-U file8
-U file9"
- # Verify that the right changes have been scheduled.
- dotest_fail join-29 "$testcvs -q update" \
-"A file1
-M file2
-R file3
-C file4
-A file8
-A file9"
-
- # Checkout the mainline again to try updating and merging between two
- # branches in the same step
- # this seems a likely scenario - the user finishes up on branch and
- # updates to br2 and merges in the same step - and there was a bug
- # once that if the file was removed in the update then it wouldn't be
- # readded in the merge
- cd ..
- rm -rf first-dir
- dotest join-twobranch-1 "${testcvs} -q co -rbranch first-dir" \
-'U first-dir/file1
-U first-dir/file2
-U first-dir/file8
-U first-dir/file9'
- cd first-dir
- dotest join-twobranch-2 "$testcvs -q update -rbr2 -jbranch" \
-"$PROG update: file1 is no longer in the repository
-U file1
-U file2
-RCS file: $CVSROOT_DIRNAME/first-dir/file2,v
-retrieving revision 1\.1
-retrieving revision 1\.1\.2\.2
-Merging differences between 1\.1 and 1\.1\.2\.2 into file2
-U file3
-$PROG update: scheduling file3 for removal
-U file4
-$PROG update: file file4 has been removed in revision branch, but the destination is incompatibly modified
-C file4
-U file7
-$PROG update: file8 is no longer in the repository
-U file8
-$PROG update: file9 is no longer in the repository
-U file9"
- # Verify that the right changes have been scheduled.
- dotest_fail join-twobranch-3 "$testcvs -q update" \
-"A file1
-M file2
-R file3
-C file4
-A file8
-A file9"
-
- # Checkout the mainline again to try merging from the trunk
- # to a branch.
- cd ..
- rm -r first-dir
- dotest join-30 "${testcvs} -q co first-dir" \
-'U first-dir/file2
-U first-dir/file3
-U first-dir/file4
-U first-dir/file7'
- cd first-dir
-
- # Tag the current revisions on the trunk.
- dotest join-31 "${testcvs} -q tag T3 ." \
-'T file2
-T file3
-T file4
-T file7'
-
- # Modify file7.
- echo 'second revision of file7' > file7
- dotest join-32 "${testcvs} -q ci -mx ." \
-"Checking in file7;
-${CVSROOT_DIRNAME}/first-dir/file7,v <-- file7
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # And Tag again.
- dotest join-33 "${testcvs} -q tag T4 ." \
-'T file2
-T file3
-T file4
-T file7'
-
- # Now update branch to T3.
- cd ../../2/first-dir
- dotest join-34 "${testcvs} -q up -jT3" \
-"${PROG} update: file file4 does not exist, but is present in revision T3
-U file7"
-
- # Verify that the right changes have been scheduled.
- dotest join-35 "${testcvs} -q update" \
-'A file7'
-
- # Now update to T4.
- # This is probably a bug, although in this particular case it just
- # happens to do the right thing; see above join-20.
- dotest join-36 "${testcvs} -q up -j T3 -j T4" \
-"A file7
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file7,v
-retrieving revision 1\.1
-retrieving revision 1\.2
-Merging differences between 1\.1 and 1\.2 into file7"
-
- # Verify that the right changes have been scheduled.
- dotest join-37 "${testcvs} -q update" \
-'A file7'
-
- cd ../..
-
- rm -r 1 2 3
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- join2)
- # More joining tests.
-
- # First the usual setup; create a directory first-dir, a file
- # first-dir/file1, and a branch br1.
- mkdir 1; cd 1
- dotest join2-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest join2-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- echo 'initial contents of file1' >file1
- dotest join2-3 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest join2-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- dotest join2-5 "${testcvs} -q tag -b br1" "T file1"
- dotest join2-6 "$testcvs -q update -r br1" '[UP] file1'
- echo 'modify on branch' >>file1
- touch bradd
- dotest join2-6a "${testcvs} add bradd" \
-"${PROG} add: scheduling file .bradd. for addition on branch .br1.
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest join2-7 "${testcvs} -q ci -m modify" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/bradd,v
-done
-Checking in bradd;
-${CVSROOT_DIRNAME}/first-dir/Attic/bradd,v <-- bradd
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
-
- # Here is the unusual/pathological part. We switch back to
- # the trunk *for file1 only*, not for the whole directory.
- dotest join2-8 "${testcvs} -q update -A file1" '[UP] file1'
- dotest join2-9 "${testcvs} -q status file1" \
-"===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest join2-10 "cat CVS/Tag" "Tbr1"
-
- dotest join2-11 "${testcvs} -q update -j br1 file1" \
-"RCS file: ${CVSROOT_DIRNAME}/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"
- dotest join2-12 "cat file1" "initial contents of file1
-modify on branch"
- # We should have no sticky tag on file1
- dotest join2-13 "${testcvs} -q status file1" \
-"===================================================================
-File: file1 Status: Locally Modified
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest join2-14 "cat CVS/Tag" "Tbr1"
- # And the checkin should go to the trunk
- dotest join2-15 "${testcvs} -q ci -m modify file1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # OK, the above is all well and good and has worked for some
- # time. Now try the case where the file had been added on
- # the branch.
- dotest join2-16 "${testcvs} -q update -r br1" "[UP] file1"
- # The workaround is to update the whole directory.
- # The non-circumvented version won't work. The reason is that
- # update removes the entry from CVS/Entries, so of course we get
- # the tag from CVS/Tag and not Entries. I suppose maybe
- # we could invent some new format in Entries which would handle
- # this, but doing so, and handling it properly throughout
- # CVS, would be a lot of work and I'm not sure this case justifies
- # it.
- dotest join2-17-circumvent "${testcvs} -q update -A" \
-"${PROG} update: bradd is no longer in the repository
-[UP] file1"
-: dotest join2-17 "${testcvs} -q update -A bradd" \
-"${PROG} update: warning: bradd is not (any longer) pertinent"
- dotest join2-18 "${testcvs} -q update -j br1 bradd" "U bradd"
- dotest join2-19 "${testcvs} -q status bradd" \
-"===================================================================
-File: bradd Status: Locally Added
-
- Working revision: New file!
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/Attic/bradd,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest join2-20 "${testcvs} -q ci -m modify bradd" \
-"Checking in bradd;
-${CVSROOT_DIRNAME}/first-dir/bradd,v <-- bradd
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- cd ../..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- join3)
- # See "join" for a list of other joining/branching tests.
- # First the usual setup; create a directory first-dir, a file
- # first-dir/file1, and a branch br1.
- mkdir 1; cd 1
- dotest join3-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest join3-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- echo 'initial contents of file1' >file1
- dotest join3-3 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest join3-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- dotest join3-5 "${testcvs} -q tag -b br1" "T file1"
- dotest join3-6 "$testcvs -q update -r br1" '[UP] file1'
- echo 'br1:line1' >>file1
- dotest join3-7 "${testcvs} -q ci -m modify" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
-
- # Now back to the trunk for:
- # another revision and another branch for file1.
- # add file2, which will exist on trunk and br2 but not br1.
- dotest join3-8 "${testcvs} -q update -A" "[UP] file1"
- echo 'trunk:line1' > file2
- dotest join3-8a "${testcvs} add file2" \
-"${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- echo 'trunk:line1' >>file1
- dotest join3-9 "${testcvs} -q ci -m modify" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1\.1
-done"
- dotest join3-10 "${testcvs} -q tag -b br2" "T file1
-T file2"
-
- # Before we actually have any revision on br2, let's try a join
- dotest join3-11 "${testcvs} -q update -r br1" "[UP] file1
-${PROG} update: file2 is no longer in the repository"
- dotest join3-12 "${testcvs} -q update -j br2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-retrieving revision 1\.1
-retrieving revision 1\.2
-Merging differences between 1\.1 and 1\.2 into file1
-rcsmerge: warning: conflicts during merge
-U file2"
- dotest join3-13 "cat file1" \
-"initial contents of file1
-[<]<<<<<< file1
-br1:line1
-[=]======
-trunk:line1
-[>]>>>>>> 1\.2"
- rm file1
-
- # OK, we'll try the same thing with a revision on br2.
- dotest join3-14 "${testcvs} -q update -r br2 file1" \
-"${PROG} update: warning: file1 was lost
-U file1" "U file1"
- echo 'br2:line1' >>file1
- dotest join3-15 "${testcvs} -q ci -m modify file1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2\.2\.1; previous revision: 1\.2
-done"
-
- # OK, now we can join br2 to br1
- dotest join3-16 "${testcvs} -q update -r br1 file1" "[UP] file1"
- # It may seem odd, to merge a higher branch into a lower
- # branch, but in fact CVS defines the ancestor as 1.1
- # and so it merges both the 1.1->1.2 and 1.2->1.2.2.1 changes.
- # This seems like a reasonably plausible behavior.
- dotest join3-17 "${testcvs} -q update -j br2 file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-retrieving revision 1\.1
-retrieving revision 1\.2\.2\.1
-Merging differences between 1\.1 and 1\.2\.2\.1 into file1
-rcsmerge: warning: conflicts during merge"
- dotest join3-18 "cat file1" \
-"initial contents of file1
-[<]<<<<<< file1
-br1:line1
-[=]======
-trunk:line1
-br2:line1
-[>]>>>>>> 1\.2\.2\.1"
-
- cd ../..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- join4)
- # Like join, but with local (uncommitted) modifications.
-
- mkdir ${CVSROOT_DIRNAME}/first-dir
- mkdir 1
- cd 1
- dotest join4-1 "${testcvs} -q co first-dir" ''
-
- cd first-dir
-
- # Add two files.
- echo 'first revision of file3' > file3
- echo 'first revision of file4' > file4
- echo 'first revision of file6' > file6
- echo 'first revision of file8' > file8
- echo 'first revision of file9' > file9
- dotest join4-2 "${testcvs} add file3 file4 file6 file8 file9" \
-"${PROG}"' add: scheduling file `file3'\'' for addition
-'"${PROG}"' add: scheduling file `file4'\'' for addition
-'"${PROG}"' add: scheduling file `file6'\'' for addition
-'"${PROG}"' add: scheduling file `file8'\'' for addition
-'"${PROG}"' add: scheduling file `file9'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add these files permanently'
-
- dotest join4-3 "${testcvs} -q commit -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file3,v
-done
-Checking in file3;
-${CVSROOT_DIRNAME}/first-dir/file3,v <-- file3
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file4,v
-done
-Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file6,v
-done
-Checking in file6;
-${CVSROOT_DIRNAME}/first-dir/file6,v <-- file6
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file8,v
-done
-Checking in file8;
-${CVSROOT_DIRNAME}/first-dir/file8,v <-- file8
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file9,v
-done
-Checking in file9;
-${CVSROOT_DIRNAME}/first-dir/file9,v <-- file9
-initial revision: 1\.1
-done"
-
- # Make a branch.
- dotest join4-4 "${testcvs} -q tag -b branch ." \
-'T file3
-T file4
-T file6
-T file8
-T file9'
-
- # Add file10
- echo 'first revision of file10' > file10
- dotest join4-7a "${testcvs} add file10" \
-"${PROG}"' add: scheduling file `file10'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest join4-7b "${testcvs} -q ci -mx ." \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file10,v
-done
-Checking in file10;
-${CVSROOT_DIRNAME}/first-dir/file10,v <-- file10
-initial revision: 1\.1
-done"
-
- # Add file2 and file7, modify file4, and remove
- # file6, file8, file9, and file10.
- echo 'first revision of file2' > file2
- echo 'second revision of file4' > file4
- echo 'first revision of file7' > file7
- rm file6 file8 file9 file10
- dotest join4-5 "${testcvs} add file2 file7" \
-"${PROG}"' add: scheduling file `file2'\'' for addition
-'"${PROG}"' add: scheduling file `file7'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add these files permanently'
- dotest join4-6 "${testcvs} rm file6 file8 file9 file10" \
-"${PROG}"' remove: scheduling `file6'\'' for removal
-'"${PROG}"' remove: scheduling `file8'\'' for removal
-'"${PROG}"' remove: scheduling `file9'\'' for removal
-'"${PROG}"' remove: scheduling `file10'\'' for removal
-'"${PROG}"' remove: use .'"${PROG}"' commit. to remove these files permanently'
-
- # Check out the branch.
- cd ../..
- mkdir 2
- cd 2
- dotest join4-8 "${testcvs} -q co -r branch first-dir" \
-'U first-dir/file3
-U first-dir/file4
-U first-dir/file6
-U first-dir/file8
-U first-dir/file9'
-
- cd first-dir
-
- # Modify the files on the branch, so that T1 is not an
- # ancestor of the main line, and add file5
- echo 'first branch revision of file3' > file3
- echo 'first branch revision of file4' > file4
- echo 'first branch revision of file5' > file5
- echo 'first branch revision of file6' > file6
- echo 'first branch revision of file9' > file9
- dotest join4-9 "${testcvs} add file5" \
-"${PROG}"' add: scheduling file `file5'\'' for addition on branch `branch'\''
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest join4-10 "${testcvs} -q ci -mx ." \
-"Checking in file3;
-${CVSROOT_DIRNAME}/first-dir/file3,v <-- file3
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file5,v
-done
-Checking in file5;
-${CVSROOT_DIRNAME}/first-dir/Attic/file5,v <-- file5
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in file6;
-${CVSROOT_DIRNAME}/first-dir/file6,v <-- file6
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in file9;
-${CVSROOT_DIRNAME}/first-dir/file9,v <-- file9
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
-
- # Tag the current revisions on the branch.
- dotest join4-11 "${testcvs} -q tag T1 ." \
-'T file3
-T file4
-T file5
-T file6
-T file8
-T file9'
-
- # Add file1 and file2, modify file9, and remove the other files.
- echo 'first branch revision of file1' > file1
- echo 'first branch revision of file2' > file2
- echo 'second branch revision of file9' > file9
- rm file3 file4 file5 file6
- dotest join4-12 "${testcvs} add file1 file2" \
-"${PROG}"' add: scheduling file `file1'\'' for addition on branch `branch'\''
-'"${PROG}"' add: scheduling file `file2'\'' for addition on branch `branch'\''
-'"${PROG}"' add: use .'"${PROG}"' commit. to add these files permanently'
- dotest join4-13 "${testcvs} rm file3 file4 file5 file6" \
-"${PROG}"' remove: scheduling `file3'\'' for removal
-'"${PROG}"' remove: scheduling `file4'\'' for removal
-'"${PROG}"' remove: scheduling `file5'\'' for removal
-'"${PROG}"' remove: scheduling `file6'\'' for removal
-'"${PROG}"' remove: use .'"${PROG}"' commit. to remove these files permanently'
- dotest join4-14 "${testcvs} -q ci -mx ." \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/Attic/file1,v <-- file1
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/Attic/file2,v <-- file2
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Removing file3;
-${CVSROOT_DIRNAME}/first-dir/file3,v <-- file3
-new revision: delete; previous revision: 1\.1\.2\.1
-done
-Removing file4;
-${CVSROOT_DIRNAME}/first-dir/file4,v <-- file4
-new revision: delete; previous revision: 1\.1\.2\.1
-done
-Removing file5;
-${CVSROOT_DIRNAME}/first-dir/Attic/file5,v <-- file5
-new revision: delete; previous revision: 1\.1\.2\.1
-done
-Removing file6;
-${CVSROOT_DIRNAME}/first-dir/file6,v <-- file6
-new revision: delete; previous revision: 1\.1\.2\.1
-done
-Checking in file9;
-${CVSROOT_DIRNAME}/first-dir/file9,v <-- file9
-new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
-done"
-
- # Tag the current revisions on the branch.
- dotest join4-15 "${testcvs} -q tag T2 ." \
-'T file1
-T file2
-T file8
-T file9'
-
- # Modify file4 locally, and do an update with a merge.
- cd ../../1/first-dir
- echo 'third revision of file4' > file4
- dotest join4-18 "$testcvs -q update -jT1 -jT2 ." \
-"U file1
-R file10
-A file2
-$PROG update: file file2 exists, but has been added in revision T2
-$PROG update: scheduling file3 for removal
-M file4
-$PROG update: file file4 has been removed in revision T2, but the destination is incompatibly modified
-C file4
-R file6
-A file7
-R file8
-R file9
-$PROG update: file file9 does not exist, but is present in revision T2"
-
- # Verify that the right changes have been scheduled.
- dotest_fail join4-19 "${testcvs} -q update" \
-'A file1
-R file10
-A file2
-R file3
-C file4
-R file6
-A file7
-R file8
-R file9'
-
- cd ../..
-
- rm -r 1 2
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- join5)
- # This test verifies that CVS can handle filenames starting with a
- # dash (`-') properly. What used to happen was that CVS handled it
- # just fine, until it went to pass them as arguments to the diff
- # library, at which point it neglected to pass `--' before the file
- # list, causing the diff library to attempt to interpret the file
- # name as an argument.
- mkdir join5; cd join5
- mkdir 1; cd 1
- dotest join5-init-1 "${testcvs} -Q co -l ."
- mkdir join5
- dotest join5-init-2 "${testcvs} -Q add join5"
- cd join5
- echo "there once was a file from harrisburg" >-file
- echo "who's existance it seems was quiteabsurd" >>-file
- dotest join5-init-3 "${testcvs} -Q add -- -file"
- dotest join5-init-4 "${testcvs} -q ci -minitial" \
-"RCS file: ${CVSROOT_DIRNAME}/join5/-file,v
-done
-Checking in -file;
-${CVSROOT_DIRNAME}/join5/-file,v <-- -file
-initial revision: 1\.1
-done"
- cd ../..
-
- mkdir 2; cd 2
- dotest join5-init-5 "${testcvs} -Q co join5"
- cd join5
- echo "it tested for free" >>-file
- echo "when paid it should be" >>-file
- dotest join5-init-4 "${testcvs} -q ci -msecond" \
-"Checking in -file;
-${CVSROOT_DIRNAME}/join5/-file,v <-- -file
-new revision: 1\.2; previous revision: 1\.1
-done"
- cd ../..
-
- cd 1/join5
- echo "but maybe it could charge bytheword" >>-file
- # This is the test that used to spew complaints from diff3:
- dotest join5 "${testcvs} up" \
-"${PROG} update: Updating \.
-RCS file: ${CVSROOT_DIRNAME}/join5/-file,v
-retrieving revision 1\.1
-retrieving revision 1\.2
-Merging differences between 1\.1 and 1\.2 into -file
-rcsmerge: warning: conflicts during merge
-${PROG} update: conflicts found in -file
-C -file"
- cd ../..
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- cd ..
- rm -r join5
- rm -rf ${CVSROOT_DIRNAME}/join5
- ;;
-
- join6)
- mkdir join6; cd join6
- mkdir 1; cd 1
- dotest join6-init-1 "${testcvs} -Q co -l ."
- mkdir join6
- dotest join6-init-2 "${testcvs} -Q add join6"
- cd join6
- echo aaa >temp.txt
- echo bbb >>temp.txt
- echo ccc >>temp.txt
- dotest join6-1 "${testcvs} -Q add temp.txt"
- dotest join6-2 "${testcvs} -q commit -minitial temp.txt" \
-"RCS file: ${CVSROOT_DIRNAME}/join6/temp\.txt,v
-done
-Checking in temp\.txt;
-${CVSROOT_DIRNAME}/join6/temp.txt,v <-- temp\.txt
-initial revision: 1\.1
-done"
- cp temp.txt temp2.txt
- echo ddd >>temp.txt
- dotest join6-3 "${testcvs} -q commit -madd temp.txt" \
-"Checking in temp\.txt;
-${CVSROOT_DIRNAME}/join6/temp.txt,v <-- temp\.txt
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # The case where the merge target is up-to-date and its base revision
- # matches the second argument to -j: CVS doesn't bother attempting
- # the merge since it already knows that the target contains the
- # change.
- dotest join6-3.3 "${testcvs} update -j1.1 -j1.2 temp.txt" \
-"temp\.txt already contains the differences between 1\.1 and 1\.2"
- dotest join6-3.4 "${testcvs} diff temp.txt" ""
-
- # The case where the merge target is modified but already contains
- # the change.
- echo bbb >temp.txt
- echo ccc >>temp.txt
- echo ddd >>temp.txt
- dotest join6-3.5 "${testcvs} update -j1.1 -j1.2 temp.txt" \
-"M temp\.txt
-RCS file: ${CVSROOT_DIRNAME}/join6/temp\.txt,v
-retrieving revision 1\.1
-retrieving revision 1\.2
-Merging differences between 1\.1 and 1\.2 into temp\.txt
-temp\.txt already contains the differences between 1\.1 and 1\.2"
- dotest_fail join6-3.6 "${testcvs} diff temp.txt" \
-"Index: temp\.txt
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/join6/temp\.txt,v
-retrieving revision 1\.2
-diff -r1\.2 temp.txt
-1d0
-< aaa"
-
- cp temp2.txt temp.txt
- dotest_fail join6-4 "${testcvs} diff temp.txt" \
-"Index: temp.txt
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/join6/temp\.txt,v
-retrieving revision 1\.2
-diff -r1\.2 temp\.txt
-4d3
-< ddd"
-
- dotest join6-5 "${testcvs} update -j1.1 -j1.2 temp.txt" \
-"M temp\.txt
-RCS file: ${CVSROOT_DIRNAME}/join6/temp\.txt,v
-retrieving revision 1\.1
-retrieving revision 1\.2
-Merging differences between 1\.1 and 1\.2 into temp\.txt"
- dotest join6-6 "${testcvs} diff temp.txt" ""
- mv temp.txt temp3.txt
- dotest join6-7 "sed 's/ddd/dddd/' < temp3.txt > temp.txt" ""
- dotest join6-8 "${testcvs} update -j1.1 -j1.2 temp.txt" \
-"M temp\.txt
-RCS file: ${CVSROOT_DIRNAME}/join6/temp\.txt,v
-retrieving revision 1\.1
-retrieving revision 1\.2
-Merging differences between 1\.1 and 1\.2 into temp\.txt
-rcsmerge: warning: conflicts during merge"
- dotest_fail join6-9 "${testcvs} diff temp.txt" \
-"Index: temp\.txt
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/join6/temp.txt,v
-retrieving revision 1\.2
-diff -r1\.2 temp\.txt
-3a4,6
-> <<<<<<< temp\.txt
-> dddd
-> =======
-4a8
-> >>>>>>> 1\.2"
- cp temp2.txt temp.txt
- dotest join6-10 "${testcvs} -q ci -m del temp.txt" \
-"Checking in temp\.txt;
-${CVSROOT_DIRNAME}/join6/temp.txt,v <-- temp\.txt
-new revision: 1\.3; previous revision: 1\.2
-done"
- cp temp3.txt temp.txt
- dotest_fail join6-11 "${testcvs} diff temp.txt" \
-"Index: temp\.txt
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/join6/temp.txt,v
-retrieving revision 1\.3
-diff -r1\.3 temp\.txt
-3a4
-> ddd"
- dotest join6-12 "${testcvs} update -j1.2 -j1.3 temp.txt" \
-"M temp\.txt
-RCS file: ${CVSROOT_DIRNAME}/join6/temp\.txt,v
-retrieving revision 1\.2
-retrieving revision 1\.3
-Merging differences between 1\.2 and 1\.3 into temp\.txt"
- dotest join6-13 "${testcvs} diff temp.txt" ""
-
- # The case where the merge target wasn't created until after the
- # first tag was applied
- rm temp2.txt temp3.txt
- dotest join6-20 "${testcvs} -q tag -r1.1 t1" \
-"T temp.txt"
- echo xxx >temp2.txt
- dotest join6-21 "${testcvs} -Q add temp2.txt"
- dotest join6-22 "${testcvs} -q ci -m." \
-"RCS file: ${CVSROOT_DIRNAME}/join6/temp2.txt,v
-done
-Checking in temp2\.txt;
-${CVSROOT_DIRNAME}/join6/temp2\.txt,v <-- temp2\.txt
-initial revision: 1\.1
-done"
- dotest join6-23 "${testcvs} -q tag t2" \
-"T temp.txt
-T temp2.txt"
- echo xxx >>temp.txt
- dotest join6-24 "${testcvs} -q ci -m." \
-"Checking in temp\.txt;
-${CVSROOT_DIRNAME}/join6/temp.txt,v <-- temp\.txt
-new revision: 1\.4; previous revision: 1\.3
-done"
- dotest join6-25 "${testcvs} -q up -jt1 -jt2" \
-"RCS file: ${CVSROOT_DIRNAME}/join6/temp.txt,v
-retrieving revision 1\.1
-retrieving revision 1\.3
-Merging differences between 1\.1 and 1\.3 into temp.txt
-temp.txt already contains the differences between 1\.1 and 1\.3
-temp2.txt already contains the differences between creation and 1\.1"
-
- # Now for my next trick: delete the file, recreate it, and
- # try to merge
- dotest join6-30 "${testcvs} -q rm -f temp2.txt" \
-"${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest join6-31 "${testcvs} -q ci -m. temp2.txt" \
-"Removing temp2\.txt;
-${CVSROOT_DIRNAME}/join6/temp2\.txt,v <-- temp2\.txt
-new revision: delete; previous revision: 1\.1
-done"
- echo new >temp2.txt
- # FIXCVS: Local and remote really shouldn't be different and there
- # really shouldn't be two different status lines for temp2.txt
- if $remote; then
- dotest_fail join6-32 "${testcvs} -q up -jt1 -jt2" \
-"? temp2\.txt
-RCS file: ${CVSROOT_DIRNAME}/join6/temp.txt,v
-retrieving revision 1\.1
-retrieving revision 1\.3
-Merging differences between 1\.1 and 1\.3 into temp.txt
-temp.txt already contains the differences between 1\.1 and 1\.3
-${PROG} update: move away \./temp2\.txt; it is in the way
-C temp2\.txt"
- else
- dotest join6-32 "${testcvs} -q up -jt1 -jt2" \
-"RCS file: ${CVSROOT_DIRNAME}/join6/temp.txt,v
-retrieving revision 1\.1
-retrieving revision 1\.3
-Merging differences between 1\.1 and 1\.3 into temp.txt
-temp.txt already contains the differences between 1\.1 and 1\.3
-${PROG} update: use .${PROG} add. to create an entry for temp2\.txt
-U temp2\.txt
-? temp2\.txt"
- fi
-
- cd ../../..
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- rm -r join6
- rm -rf ${CVSROOT_DIRNAME}/join6
- ;;
-
- join7)
- # This test deals with joins that happen with the -n switch
- mkdir join7; cd join7
- mkdir impdir; cd impdir
- echo aaa >temp.txt
- echo bbb >>temp.txt
- echo ccc >>temp.txt
- dotest join7-1 \
-"${testcvs} -Q import -minitial join7 vendor vers-1" \
-""
- cd ..
- dotest join7-2 "${testcvs} -Q co join7" ""
- cd join7
- echo ddd >> temp.txt
- dotest join7-3 "${testcvs} -Q ci -madded-line temp.txt" \
-"Checking in temp.txt;
-$CVSROOT_DIRNAME/join7/temp.txt,v <-- temp.txt
-new revision: 1\.2; previous revision: 1\.1
-done"
- cd ../impdir
- echo aaaa >temp.txt
- echo bbbb >>temp.txt
- echo ccc >>temp.txt
- echo eee >>temp.txt
- dotest join7-4 \
-"${testcvs} -Q import -minitial join7 vendor vers-2" \
-""
- cd ../join7
- dotest join7-5 \
-"${testcvs} -n update -jvers-1 -jvers-2 temp.txt" \
-"RCS file: $CVSROOT_DIRNAME/join7/temp.txt,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.1\.1\.2
-Merging differences between 1\.1\.1\.1 and 1\.1\.1\.2 into temp.txt
-rcsmerge: warning: conflicts during merge"
- touch temp.txt
- dotest join7-6 "${testcvs} -n update -jvers-1 -jvers-2 temp.txt" \
-"RCS file: $CVSROOT_DIRNAME/join7/temp.txt,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.1\.1\.2
-Merging differences between 1\.1\.1\.1 and 1\.1\.1\.2 into temp.txt
-rcsmerge: warning: conflicts during merge" \
-"RCS file: $CVSROOT_DIRNAME/join7/temp.txt,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.1\.1\.2
-Merging differences between 1\.1\.1\.1 and 1\.1\.1\.2 into temp.txt
-rcsmerge: warning: conflicts during merge"
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- cd ../..
- rm -r join7
- rm -rf $CVSROOT_DIRNAME/join7
- ;;
-
-
-
- join8)
- # In this test case, we have 2 projects, one called "pvcs" and one
- # called "project". The "pvcs" project has modified the file, while
- # the "project" project has caused a deletion. When "project" is
- # merged into "pvcs", we expect CVS to detect a conflict.
- mkdir join8; cd join8
- mkdir combine
- mkdir base
- mkdir pvcs
- mkdir project
-
- echo "aaa" >base/file.txt
- echo "bbb" >pvcs/file.txt
- echo "ccc" >project/xxx.txt
-
- cd base
- dotest join8-1 \
-"$testcvs import -b 1.1.101 -ko -m 'base import' join8 base base-1" \
-"N join8/file\.txt
-
-No conflicts created by this import"
-
- cd ../pvcs
- dotest join8-2 \
-"$testcvs import -b 1.1.201 -ko -m 'pvcs import' join8 pvcs pvcs-1" \
-"C join8/file\.txt
-
-1 conflicts created by this import.
-Use the following command to help the merge:
-
- $PROG checkout -j<prev_rel_tag> -jpvcs-1 join8"
-
- cd ../project
- dotest join8-3 \
-"$testcvs import -b 1.1.301 -ko -m 'project import' join8 project project-1" \
-"N join8/xxx\.txt
-
-No conflicts created by this import"
-
- cd ..
- dotest join8-4 \
-"$testcvs checkout -r pvcs-1 -j base-1 -j project-1 -d combine join8" \
-"$PROG checkout: Updating combine
-U combine/file\.txt
-$PROG checkout: file combine/file\.txt has been removed in revision project-1, but the destination is incompatibly modified
-C combine/file.txt
-U combine/xxx\.txt"
-
- dotest join8-5 \
-"$testcvs -Q up -pr base-1 combine/file.txt >combine/file.txt"
-
- dotest join8-6 \
-"$testcvs up -j base-1 -j project-1 combine" \
-"$PROG update: Updating combine
-M combine/file\.txt
-$PROG update: scheduling combine/file\.txt for removal
-A combine/xxx\.txt
-$PROG update: file combine/xxx\.txt exists, but has been added in revision project-1"
- cd ..
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- rm -r join8
- rm -rf $CVSROOT_DIRNAME/join8
- ;;
-
-
-
- join9)
- # In this test case, we have 2 projects, one called "pvcs" and one
- # called "project". The "pvcs" project has not modified the file,
- # while the "project" project has caused a deletion. When "project"
- # is merged into "pvcs", we expect CVS to remove the file without
- # fuss, as there is no conflict.
- mkdir join9; cd join9
- mkdir combine
- mkdir base
- mkdir pvcs
- mkdir project
-
- echo "aaa" >base/file.txt
- echo "aaa" >pvcs/file.txt
- echo "ccc" >project/xxx.txt
-
- cd base
- dotest join9-1 \
-"$testcvs import -b 1.1.101 -ko -m 'base import' join9 base base-1" \
-"N join9/file\.txt
-
-No conflicts created by this import"
-
- cd ../pvcs
- dotest join9-2 \
-"$testcvs import -b 1.1.201 -ko -m 'pvcs import' join9 pvcs pvcs-1" \
-"C join9/file\.txt
-
-1 conflicts created by this import.
-Use the following command to help the merge:
-
- $PROG checkout -j<prev_rel_tag> -jpvcs-1 join9"
-
- cd ../project
- dotest join9-3 \
-"$testcvs import -b 1.1.301 -ko -m 'project import' join9 project project-1" \
-"N join9/xxx\.txt
-
-No conflicts created by this import"
-
- cd ..
- dotest join9-4 \
-"$testcvs checkout -r pvcs-1 -j base-1 -j project-1 -d combine join9" \
-"$PROG checkout: Updating combine
-U combine/file\.txt
-$PROG checkout: scheduling combine/file\.txt for removal
-U combine/xxx\.txt"
-
- cd ..
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- rm -r join9
- rm -rf $CVSROOT_DIRNAME/join9
- ;;
-
-
-
- join-readonly-conflict)
- # Previously, only tests 1 & 11 were being tested. I added the
- # intermediate dotest's to try and diagnose a different failure
- #
- # 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 join-readonly-conflict; cd join-readonly-conflict
- dotest join-readonly-conflict-1 "$testcvs -q co -l ." ''
- module=join-readonly-conflict
- mkdir $module
- $testcvs -q add $module >>$LOGFILE 2>&1
- cd $module
-
- file=m
- echo trunk > $file
- dotest join-readonly-conflict-2 "$testcvs -Q add $file" ''
-
- dotest join-readonly-conflict-3 "$testcvs -q ci -m . $file" \
-"RCS file: $CVSROOT_DIRNAME/$module/$file,v
-done
-Checking in $file;
-$CVSROOT_DIRNAME/$module/$file,v <-- $file
-initial revision: 1\.1
-done"
-
- dotest join-readonly-conflict-4 "$testcvs tag -b B $file" "T $file"
- dotest join-readonly-conflict-5 "$testcvs -q update -rB $file" \
-"[UP] $file"
- echo branch B > $file
- dotest join-readonly-conflict-6 "$testcvs -q ci -m . $file" \
-"Checking in $file;
-$CVSROOT_DIRNAME/$module/$file,v <-- $file
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
-
- rm $file
- dotest join-readonly-conflict-7 "$testcvs -Q update -A $file" ''
- # 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
- dotest join-readonly-conflict-8 "$testcvs update -r B $file" \
-"RCS file: $CVSROOT_DIRNAME/$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} update: conflicts found in $file
-C $file"
-
- # restore to the trunk
- rm -f $file
- dotest join-readonly-conflict-9 "$testcvs -Q update -A $file" ''
-
- # This one would fail because cvs couldn't open the existing
- # (and read-only) .# file for writing.
- echo conflict > $file
-
- # verify that the backup file is not writable
- if test -w ".#$file.1.1"; then
- fail "join-readonly-conflict-10 : .#$file.1.1 is writable"
- else
- pass "join-readonly-conflict-10"
- fi
- dotest join-readonly-conflict-11 "$testcvs update -r B $file" \
-"RCS file: $CVSROOT_DIRNAME/$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} update: conflicts found in $file
-C m"
-
- cd ../..
- if $keep; then :; else
- rm -rf join-readonly-conflict
- rm -rf $CVSROOT_DIRNAME/$module
- fi
- ;;
-
- join-admin)
- mkdir 1; cd 1
- dotest join-admin-1 "$testcvs -q co -l ." ''
- module=x
- mkdir $module
- $testcvs -q add $module >>$LOGFILE 2>&1
- cd $module
-
- # Create a file so applying the first tag works.
- echo foo > a
- $testcvs -Q add a > /dev/null 2>&1
- $testcvs -Q ci -m. a > /dev/null 2>&1
-
- $testcvs -Q tag -b B
- $testcvs -Q tag -b M1
- echo '$''Id$' > b
- $testcvs -Q add b > /dev/null 2>&1
- $testcvs -Q ci -m. b > /dev/null 2>&1
- $testcvs -Q tag -b M2
-
- $testcvs -Q update -r B
- $testcvs -Q update -kk -jM1 -jM2
- $testcvs -Q ci -m. b >/dev/null 2>&1
-
- $testcvs -Q update -A
-
- # Verify that the -kk flag from the update did not
- # propagate to the repository.
- dotest join-admin-1 "$testcvs status b" \
-"===================================================================
-File: b Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/x/b,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
-
- cd ../..
- rm -rf 1
- rm -rf ${CVSROOT_DIRNAME}/$module
- ;;
-
- join-admin-2)
- # Show that when a merge (via update -kk -jtag1 -jtag2) first
- # removes a file, then modifies another containing an $Id...$ line,
- # the resulting file contains the unexpanded `$Id.$' string, as
- # -kk requires.
- mkdir 1; cd 1
- dotest join-admin-2-1 "$testcvs -q co -l ." ''
- module=x
- mkdir $module
- dotest join-admin-2-2 "$testcvs -q add $module" \
-"Directory ${CVSROOT_DIRNAME}/x added to the repository"
- cd $module
-
- # Create a file so applying the first tag works.
- echo '$''Id$' > e0
- cp e0 e
- dotest join-admin-2-3 "$testcvs -Q add e" ''
- dotest join-admin-2-4 "$testcvs -Q ci -m. e" \
-"RCS file: ${CVSROOT_DIRNAME}/x/e,v
-done
-Checking in e;
-${CVSROOT_DIRNAME}/x/e,v <-- e
-initial revision: 1\.1
-done"
-
- dotest join-admin-2-5 "$testcvs -Q tag -b T" '' "${QUESTION} e0"
- dotest join-admin-2-6 "$testcvs -Q update -r T" '' "${QUESTION} e0"
- cp e0 e
- dotest join-admin-2-7 "$testcvs -Q ci -m. e" \
-"Checking in e;
-${CVSROOT_DIRNAME}/x/e,v <-- e
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
-
- dotest join-admin-2-8 "$testcvs -Q update -A" '' "${QUESTION} e0"
- dotest join-admin-2-9 "$testcvs -Q tag -b M1" '' "${QUESTION} e0"
-
- echo '$''Id$' > b
- dotest join-admin-2-10 "$testcvs -Q add b" ''
- cp e0 e
- dotest join-admin-2-11 "$testcvs -Q ci -m. b e" \
-"RCS file: ${CVSROOT_DIRNAME}/x/b,v
-done
-Checking in b;
-${CVSROOT_DIRNAME}/x/b,v <-- b
-initial revision: 1\.1
-done
-Checking in e;
-${CVSROOT_DIRNAME}/x/e,v <-- e
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- dotest join-admin-2-12 "$testcvs -Q tag -b M2" '' "${QUESTION} e0"
-
- dotest join-admin-2-13 "$testcvs -Q update -r T" '' "${QUESTION} e0"
- dotest join-admin-2-14 "$testcvs update -kk -jM1 -jM2" \
-"${PROG} update: Updating .
-U b
-U e
-RCS file: ${CVSROOT_DIRNAME}/x/e,v
-retrieving revision 1\.1
-retrieving revision 1\.2
-Merging differences between 1\.1 and 1\.2 into e
-e already contains the differences between 1\.1 and 1\.2
-${QUESTION} e0" \
-"${QUESTION} e0
-${PROG} update: Updating .
-U b
-U e
-RCS file: ${CVSROOT_DIRNAME}/x/e,v
-retrieving revision 1\.1
-retrieving revision 1\.2
-Merging differences between 1\.1 and 1\.2 into e
-e already contains the differences between 1\.1 and 1\.2"
-
- # Verify that the $Id.$ string is not expanded.
- dotest join-admin-2-15 "cat e" '$''Id$'
-
- cd ../..
- rm -rf 1
- rm -rf ${CVSROOT_DIRNAME}/$module
- ;;
-
- join-rm)
- # This first half of this test checks that a single-argument merge
- # from a branch is capable of removing files.
- #
- # The second half verifies that an update to another location with an
- # uncommitted removal will transfer the destination branch of the
- # removal.
-
- module=join-rm
- mkdir $module; cd $module
-
- dotest join-rm-init-1 "$testcvs -q co -l ." ''
- mkdir $module
- dotest join-rm-init-2 "$testcvs -q add $module" \
-"Directory $CVSROOT_DIRNAME/$module added to the repository"
- cd $module
-
- # add some files.
- touch a b c d e f g
- dotest join-rm-init-3 "$testcvs -Q add a b c d e f g"
- dotest join-rm-init-4 "$testcvs -Q ci -m add-em" \
-"RCS file: $CVSROOT_DIRNAME/join-rm/a,v
-done
-Checking in a;
-$CVSROOT_DIRNAME/join-rm/a,v <-- a
-initial revision: 1\.1
-done
-RCS file: $CVSROOT_DIRNAME/join-rm/b,v
-done
-Checking in b;
-$CVSROOT_DIRNAME/join-rm/b,v <-- b
-initial revision: 1\.1
-done
-RCS file: $CVSROOT_DIRNAME/join-rm/c,v
-done
-Checking in c;
-$CVSROOT_DIRNAME/join-rm/c,v <-- c
-initial revision: 1\.1
-done
-RCS file: $CVSROOT_DIRNAME/join-rm/d,v
-done
-Checking in d;
-$CVSROOT_DIRNAME/join-rm/d,v <-- d
-initial revision: 1\.1
-done
-RCS file: $CVSROOT_DIRNAME/join-rm/e,v
-done
-Checking in e;
-$CVSROOT_DIRNAME/join-rm/e,v <-- e
-initial revision: 1\.1
-done
-RCS file: $CVSROOT_DIRNAME/join-rm/f,v
-done
-Checking in f;
-$CVSROOT_DIRNAME/join-rm/f,v <-- f
-initial revision: 1\.1
-done
-RCS file: $CVSROOT_DIRNAME/join-rm/g,v
-done
-Checking in g;
-$CVSROOT_DIRNAME/join-rm/g,v <-- g
-initial revision: 1\.1
-done"
-
- # create the branch and update to it
- dotest join-rm-init-5 "$testcvs -Q tag -b br"
- dotest join-rm-init-6 "$testcvs -Q up -rbr"
-
- # remove a few files from the branch
- dotest join-rm-init-7 "$testcvs -Q rm -f b d g"
- dotest join-rm-init-8 "$testcvs -Q ci -mrm" \
-"Removing b;
-$CVSROOT_DIRNAME/join-rm/b,v <-- b
-new revision: delete; previous revision: 1\.1
-done
-Removing d;
-$CVSROOT_DIRNAME/join-rm/d,v <-- d
-new revision: delete; previous revision: 1\.1
-done
-Removing g;
-$CVSROOT_DIRNAME/join-rm/g,v <-- g
-new revision: delete; previous revision: 1\.1
-done"
-
- # update to the trunk
- dotest join-rm-init-9 "$testcvs -Q up -A"
-
- # now for the test - try and merge the removals.
- dotest join-rm-1 "$testcvs -q up -jbr" \
-"$PROG update: scheduling b for removal
-$PROG update: scheduling d for removal
-$PROG update: scheduling g for removal"
-
- # And make sure the merge took
- dotest join-rm-2 "$testcvs -qn up" \
-"R b
-R d
-R g"
-
- dotest join-rm-3 "$testcvs -q ci -m 'save the merge'" \
-"Removing b;
-$CVSROOT_DIRNAME/join-rm/b,v <-- b
-new revision: delete; previous revision: 1\.1
-done
-Removing d;
-$CVSROOT_DIRNAME/join-rm/d,v <-- d
-new revision: delete; previous revision: 1\.1
-done
-Removing g;
-$CVSROOT_DIRNAME/join-rm/g,v <-- g
-new revision: delete; previous revision: 1\.1
-done"
-
- # and verify that it was the head revision which was removed.
- dotest join-rm-4 "$testcvs -q log b" "
-RCS file: $CVSROOT_DIRNAME/join-rm/Attic/b,v
-Working file: b
-head: 1\.2
-branch:
-locks: strict
-access list:
-symbolic names:
- br: 1\.1\.0\.2
-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
-save the merge
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: $username; state: Exp;
-branches: 1.1.2;
-add-em
-----------------------------
-revision 1\.1\.2\.1
-date: [0-9/]* [0-9:]*; author: $username; state: dead; lines: ${PLUS}0 -0
-rm
-============================================================================="
-
- # go back to the branch to set up for the second set of tests
- dotest join-rm-init-10 "$testcvs -Q up -rbr"
- dotest join-rm-init-11 "$testcvs -Q rm -f a"
- dotest join-rm-init-12 "$testcvs -Q ci -m rma" \
-"Removing a;
-$CVSROOT_DIRNAME/join-rm/a,v <-- a
-new revision: delete; previous revision: 1\.1
-done"
-
- # now the test: update to the trunk
- #
- # FIXCVS: This update should merge the removal to the trunk. It does
- # not.
- dotest join-rm-5 "$testcvs -q up -A" \
-'U a
-U c
-U e
-U f'
-
- # and verify that there is no sticky tag
- dotest join-rm-6 "$testcvs status a" \
-"===================================================================
-File: a Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 $CVSROOT_DIRNAME/join-rm/a,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- cd ../..
- rm -rf $CVSROOT_DIRNAME/$module
- rm -r $module
- ;;
-
- new) # look for stray "no longer pertinent" messages.
- mkdir ${CVSROOT_DIRNAME}/first-dir
-
- if ${CVS} co first-dir ; then
- pass 117
- else
- fail 117
- fi
-
- cd first-dir
- touch a
-
- if ${CVS} add a 2>>${LOGFILE}; then
- pass 118
- else
- fail 118
- fi
-
- if ${CVS} ci -m added >>${LOGFILE} 2>&1; then
- pass 119
- else
- fail 119
- fi
-
- rm a
-
- if ${CVS} rm a 2>>${LOGFILE}; then
- pass 120
- else
- fail 120
- fi
-
- if ${CVS} ci -m removed >>${LOGFILE} ; then
- pass 121
- else
- fail 121
- fi
-
- if ${CVS} update -A 2>&1 | grep longer ; then
- fail 122
- else
- pass 122
- fi
-
- if ${CVS} update -rHEAD 2>&1 | grep longer ; then
- fail 123
- else
- pass 123
- fi
-
- cd ..
- rm -r first-dir
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- newb)
- # Test removing a file on a branch and then checking it out.
-
- # We call this "newb" only because it, like the "new" tests,
- # has something to do with "no longer pertinent" messages.
- # Not necessarily the most brilliant nomenclature.
-
- # Create file 'a'.
- mkdir ${CVSROOT_DIRNAME}/first-dir
- dotest newb-123a "${testcvs} -q co first-dir" ''
- cd first-dir
- touch a
- dotest newb-123b "${testcvs} add a" \
-"${PROG} add: scheduling file .a. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest newb-123c "${testcvs} -q ci -m added" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/a,v
-done
-Checking in a;
-${CVSROOT_DIRNAME}/first-dir/a,v <-- a
-initial revision: 1\.1
-done"
-
- # Make a branch.
- dotest newb-123d "${testcvs} -q tag -b branch" "T a"
-
- # Check out the branch.
- cd ..
- rm -r first-dir
- mkdir 1
- cd 1
- dotest newb-123e "${testcvs} -q co -r branch first-dir" \
-"U first-dir/a"
-
- # Remove 'a' on another copy of the branch.
- cd ..
- mkdir 2
- cd 2
- dotest newb-123f "${testcvs} -q co -r branch first-dir" \
-"U first-dir/a"
- cd first-dir
- rm a
- dotest newb-123g "${testcvs} rm a" \
-"${PROG} remove: scheduling .a. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest newb-123h "${testcvs} -q ci -m removed" \
-"Removing a;
-${CVSROOT_DIRNAME}/first-dir/a,v <-- a
-new revision: delete; previous revision: 1\.1
-done"
-
- # Check out the file on the branch. This should report
- # that the file is not pertinent, but it should not
- # say anything else.
- cd ..
- rm -r first-dir
- dotest newb-123i "${testcvs} -q co -r branch first-dir/a" \
-"${PROG} checkout: warning: first-dir/a is not (any longer) pertinent"
-
- # Update the other copy, and make sure that a is removed.
- cd ../1/first-dir
- # "Entry Invalid" is a rather strange output here. Something like
- # "Removed in Repository" would make more sense.
- dotest newb-123j0 "${testcvs} status a" \
-"${PROG} status: a is no longer in the repository
-===================================================================
-File: a Status: Entry Invalid
-
- Working revision: 1\.1.*
- Repository revision: 1\.1\.2\.1 ${CVSROOT_DIRNAME}/first-dir/a,v
- Sticky Tag: branch (branch: 1\.1\.2)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest newb-123j "${testcvs} -q update" \
-"${PROG} update: a is no longer in the repository"
-
- if test -f a; then
- fail newb-123k
- else
- pass newb-123k
- fi
-
- cd ../..
- rm -r 1 2
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- conflicts)
- mkdir ${CVSROOT_DIRNAME}/first-dir
-
- mkdir 1
- cd 1
-
- dotest conflicts-124 "${testcvs} -q co first-dir" ''
-
- cd first-dir
- touch a
-
- dotest conflicts-125 "${testcvs} add a" \
-"${PROG} add: scheduling file .a. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest conflicts-126 "${testcvs} -q ci -m added" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/a,v
-done
-Checking in a;
-${CVSROOT_DIRNAME}/first-dir/a,v <-- a
-initial revision: 1\.1
-done"
-
- cd ../..
- mkdir 2
- cd 2
-
- dotest conflicts-126.5 "${testcvs} co -p first-dir" \
-"${PROG} checkout: Updating first-dir
-===================================================================
-Checking out first-dir/a
-RCS: ${CVSROOT_DIRNAME}/first-dir/a,v
-VERS: 1\.1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*"
- if ${CVS} co first-dir ; then
- pass 127
- else
- fail 127
- fi
- cd first-dir
- if test -f a; then
- pass 127a
- else
- fail 127a
- fi
-
- cd ../../1/first-dir
- echo add a line >>a
- mkdir dir1
- dotest conflicts-127b "${testcvs} add dir1" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/dir1 added to the repository"
- dotest conflicts-128 "${testcvs} -q ci -m changed" \
-"Checking in a;
-${CVSROOT_DIRNAME}/first-dir/a,v <-- a
-new revision: 1\.2; previous revision: 1\.1
-done"
- cd ../..
-
- # Similar to conflicts-126.5, but now the file has nonempty
- # contents.
- mkdir 3
- cd 3
- dotest conflicts-128.5 "${testcvs} co -p -l first-dir" \
-"${PROG} checkout: Updating first-dir
-===================================================================
-Checking out first-dir/a
-RCS: ${CVSROOT_DIRNAME}/first-dir/a,v
-VERS: 1\.2
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-add a line"
- cd ..
- rmdir 3
-
- # Now go over the to the other working directory and
- # start testing conflicts
- cd 2/first-dir
- echo add a conflicting line >>a
- dotest_fail conflicts-129 "${testcvs} -q ci -m changed" \
-"${PROG}"' commit: Up-to-date check failed for `a'\''
-'"${PROG}"' \[commit aborted\]: correct above errors first!'
- mkdir dir1
- mkdir sdir
- dotest conflicts-status-0 "${testcvs} status a" \
-"===================================================================
-File: a Status: Needs Merge
-
- Working revision: 1\.1.*
- Repository revision: 1\.2 ${CVSROOT_DIRNAME}/first-dir/a,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest conflicts-129a "${testcvs} -nq update a" \
-"RCS file: ${CVSROOT_DIRNAME}/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} update: conflicts found in a
-C a"
- dotest conflicts-130 "${testcvs} -q update" \
-"RCS file: ${CVSROOT_DIRNAME}/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} update: conflicts found in a
-C a
-${QUESTION} dir1
-${QUESTION} sdir" \
-"${QUESTION} dir1
-${QUESTION} sdir
-RCS file: ${CVSROOT_DIRNAME}/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} update: conflicts found in a
-C a"
- rmdir dir1 sdir
-
- dotest conflicts-status-1 "${testcvs} status a" \
-"===================================================================
-File: a Status: Unresolved Conflict
-
- Working revision: 1\.2.*
- Repository revision: 1\.2 ${CVSROOT_DIRNAME}/first-dir/a,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest_fail conflicts-131 "${testcvs} -q ci -m try" \
-"${PROG} commit: file .a. had a conflict and has not been modified
-${PROG} \[commit aborted\]: correct above errors first!"
-
- # Try to check in the file with the conflict markers in it.
- # Make sure we detect any one of the three conflict markers
- mv a aa
- grep '^<<<<<<<' aa >a
- dotest conflicts-status-2 "${testcvs} -nq ci -m try a" \
-"${PROG} commit: warning: file .a. seems to still contain conflict indicators"
-
- grep '^=======' aa >a
- dotest conflicts-status-3 "${testcvs} -nq ci -m try a" \
-"${PROG} commit: warning: file .a. seems to still contain conflict indicators"
-
- grep '^>>>>>>>' aa >a
- dotest conflicts-status-4 "${testcvs} -qn ci -m try a" \
-"${PROG} commit: warning: file .a. seems to still contain conflict indicators"
-
- mv aa a
- echo lame attempt at resolving it >>a
- dotest conflicts-status-5 "${testcvs} status a" \
-"===================================================================
-File: a Status: File had conflicts on merge
-
- Working revision: 1\.2.*
- Repository revision: 1\.2 ${CVSROOT_DIRNAME}/first-dir/a,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest conflicts-132 "${testcvs} -q ci -m try" \
-"${PROG} commit: warning: file .a. seems to still contain conflict indicators
-Checking in a;
-${CVSROOT_DIRNAME}/first-dir/a,v <-- a
-new revision: 1\.3; previous revision: 1\.2
-done"
-
- # OK, the user saw the warning (good user), and now
- # resolves it for real.
- echo resolve conflict >a
- dotest conflicts-status-6 "${testcvs} status a" \
-"===================================================================
-File: a Status: Locally Modified
-
- Working revision: 1\.3.*
- Repository revision: 1\.3 ${CVSROOT_DIRNAME}/first-dir/a,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest conflicts-133 "${testcvs} -q ci -m resolved" \
-"Checking in a;
-${CVSROOT_DIRNAME}/first-dir/a,v <-- a
-new revision: 1\.4; previous revision: 1\.3
-done"
- dotest conflicts-status-7 "${testcvs} status a" \
-"===================================================================
-File: a Status: Up-to-date
-
- Working revision: 1\.4.*
- Repository revision: 1\.4 ${CVSROOT_DIRNAME}/first-dir/a,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
-
- # Now test that we can add a file in one working directory
- # and have an update in another get it.
- cd ../../1/first-dir
- echo abc >abc
- if ${testcvs} add abc >>${LOGFILE} 2>&1; then
- pass 134
- else
- fail 134
- fi
- if ${testcvs} ci -m 'add abc' abc >>${LOGFILE} 2>&1; then
- pass 135
- else
- fail 135
- fi
- cd ../../2
- mkdir first-dir/dir1 first-dir/sdir
- dotest conflicts-136 "${testcvs} -q update first-dir" \
-'[UP] first-dir/abc
-'"${QUESTION}"' first-dir/dir1
-'"${QUESTION}"' first-dir/sdir' \
-''"${QUESTION}"' first-dir/dir1
-'"${QUESTION}"' first-dir/sdir
-[UP] first-dir/abc'
- dotest conflicts-137 'test -f first-dir/abc' ''
- rmdir first-dir/dir1 first-dir/sdir
-
- # Now test something similar, but in which the parent directory
- # (not the directory in question) has the Entries.Static flag
- # set.
- cd ../1/first-dir
- mkdir subdir
- if ${testcvs} add subdir >>${LOGFILE}; then
- pass 138
- else
- fail 138
- fi
- cd ../..
- mkdir 3
- cd 3
- if ${testcvs} -q co first-dir/abc first-dir/subdir \
- >>${LOGFILE}; then
- pass 139
- else
- fail 139
- fi
- cd ../1/first-dir/subdir
- echo sss >sss
- if ${testcvs} add sss >>${LOGFILE} 2>&1; then
- pass 140
- else
- fail 140
- fi
- if ${testcvs} ci -m adding sss >>${LOGFILE} 2>&1; then
- pass 140
- else
- fail 140
- fi
- cd ../../../3/first-dir
- if ${testcvs} -q update >>${LOGFILE}; then
- pass 141
- else
- fail 141
- fi
- if test -f subdir/sss; then
- pass 142
- else
- fail 142
- fi
- cd ../..
- rm -r 1 2 3 ; rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- conflicts2)
- # More conflicts tests; separate from conflicts to keep each
- # test a manageable size.
- mkdir ${CVSROOT_DIRNAME}/first-dir
-
- mkdir 1
- cd 1
-
- dotest conflicts2-142a1 "${testcvs} -q co first-dir" ''
-
- cd first-dir
- touch a abc
-
- dotest conflicts2-142a2 "${testcvs} add a abc" \
-"${PROG} add: scheduling file .a. for addition
-${PROG} add: scheduling file .abc. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest conflicts2-142a3 "${testcvs} -q ci -m added" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/a,v
-done
-Checking in a;
-${CVSROOT_DIRNAME}/first-dir/a,v <-- a
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
-done
-Checking in abc;
-${CVSROOT_DIRNAME}/first-dir/abc,v <-- abc
-initial revision: 1\.1
-done"
-
- cd ../..
- mkdir 2
- cd 2
-
- dotest conflicts2-142a4 "${testcvs} -q co first-dir" 'U first-dir/a
-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
- cd 1/first-dir
- echo modify a >>a
- dotest conflicts2-142b2 "${testcvs} -q ci -m modify-a" \
-"Checking in a;
-${CVSROOT_DIRNAME}/first-dir/a,v <-- a
-new revision: 1\.2; previous revision: 1\.1
-done"
- cd ../../2/first-dir
- rm a
- dotest conflicts2-142b3 "${testcvs} rm a" \
-"${PROG} remove: scheduling .a. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest_fail conflicts2-142b4 "${testcvs} -q update" \
-"${PROG} update: conflict: removed a was modified by second party
-C a"
- # Resolve the conflict by deciding not to remove the file
- # after all.
- dotest_sort conflicts2-142b5 "${testcvs} add a" "U a
-${PROG} add: a, version 1\.1, resurrected"
- dotest conflicts2-142b5b1 "$testcvs status a" \
-"===================================================================
-File: a Status: Needs Patch
-
- Working revision: 1\.1.*
- Repository revision: 1\.2 $CVSROOT_DIRNAME/first-dir/a,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest conflicts2-142b6 "${testcvs} -q update" 'U a'
-
- # Now one level up.
- cd ..
- dotest conflicts2-142b7 "${testcvs} rm -f first-dir/a" \
-"${PROG} remove: scheduling .first-dir/a. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
-
- if $remote; then
- # Haven't investigated this one.
- dotest_fail conflicts2-142b8r "$testcvs add first-dir/a" \
-"${PROG} add: in directory \.:
-${PROG} \[add aborted\]: there is no version here; do '${PROG} checkout' first"
- cd first-dir
- else
- dotest conflicts2-142b8 "${testcvs} add first-dir/a" \
-"U first-dir/a
-${PROG} add: 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} remove: scheduling .a. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- fi
-
- dotest_sort conflicts2-142b10 "${testcvs} add a" "U a
-${PROG} add: 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
- # not a conflict.
- cd 1/first-dir
- rm abc
- dotest conflicts2-142c0 "${testcvs} rm abc" \
-"${PROG} remove: scheduling .abc. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest conflicts2-142c1 "${testcvs} -q ci -m remove-abc" \
-"Removing abc;
-${CVSROOT_DIRNAME}/first-dir/abc,v <-- abc
-new revision: delete; previous revision: 1\.1
-done"
- cd ../../2/first-dir
- rm abc
- dotest conflicts2-142c2 "${testcvs} rm abc" \
-"${PROG} remove: scheduling .abc. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest conflicts2-142c3 "${testcvs} update" \
-"${PROG} update: Updating \."
- cd ../..
-
- # conflicts2-142d*: test that if one party adds a file, and another
- # party has a file of the same name, cvs notices
- cd 1/first-dir
- touch aa.c
- echo 'contents unchanged' >same.c
- dotest conflicts2-142d0 "${testcvs} add aa.c same.c" \
-"${PROG} add: scheduling file .aa\.c. for addition
-${PROG} add: scheduling file .same\.c. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest conflicts2-142d1 "${testcvs} -q ci -m added" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/aa\.c,v
-done
-Checking in aa\.c;
-${CVSROOT_DIRNAME}/first-dir/aa\.c,v <-- aa\.c
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/same\.c,v
-done
-Checking in same\.c;
-${CVSROOT_DIRNAME}/first-dir/same\.c,v <-- same\.c
-initial revision: 1\.1
-done"
- cd ../../2/first-dir
- echo "don't you dare obliterate this text" >aa.c
- echo 'contents unchanged' >same.c
- # Note the discrepancy between local and remote in the handling
- # of same.c. I kind
- # of suspect that the local CVS behavior is the more useful one
- # although I do sort of wonder whether we should make people run
- # cvs add just to get them in that habit (also, trying to implement
- # the local CVS behavior for remote without the cvs add seems
- # pretty difficult).
- if $remote; then
- dotest_fail conflicts2-142d2 "${testcvs} -q update" \
-"${QUESTION} aa\.c
-${QUESTION} same\.c
-${PROG} update: move away \./aa\.c; it is in the way
-C aa\.c
-${PROG} update: move away \./same\.c; it is in the way
-C same\.c"
- else
- dotest_fail conflicts2-142d2 "${testcvs} -q update" \
-"${PROG} [a-z]*: move away aa\.c; it is in the way
-C aa\.c
-U same\.c"
- fi
- dotest conflicts2-142d3 "${testcvs} -q status aa.c" \
-"${PROG} status: move away aa\.c; it is in the way
-===================================================================
-File: aa\.c Status: Unresolved Conflict
-
- Working revision: No entry for aa\.c
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/aa\.c,v"
-
- # Could also be testing the case in which the cvs add happened
- # before the commit by the other user.
- # This message seems somewhat bogus. I mean, parallel development
- # means that we get to work in parallel if we choose, right? And
- # then at commit time it would be a conflict.
- dotest_fail conflicts2-142d4 "${testcvs} -q add aa.c" \
-"${PROG} add: aa.c added independently by second party"
-
- # The user might want to see just what the conflict is.
- # Don't bother, diff seems to kind of lose its mind, with or
- # without -N. This is a CVS bug(s).
- #dotest conflicts2-142d5 "${testcvs} -q diff -r HEAD -N aa.c" fixme
-
- # Now: "how can the user resolve this conflict", I hear you cry.
- # Well, one way is to forget about the file in the working
- # directory.
- # Since it didn't let us do the add in conflicts2-142d4, there
- # is no need to run cvs rm here.
- #dotest conflicts2-142d6 "${testcvs} -q rm -f aa.c" fixme
- dotest conflicts2-142d6 "rm aa.c" ''
- dotest conflicts2-142d7 "${testcvs} -q update aa.c" "U aa\.c"
- dotest conflicts2-142d8 "cat aa.c" ''
-
- # The other way is to use the version from the working directory
- # instead of the version from the repository. Unfortunately,
- # there doesn't seem to be any particularly clear way to do
- # this (?).
-
- cd ../..
-
- rm -r 1 2; rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- conflicts3)
- # More tests of conflicts and/or multiple working directories
- # in general.
-
- mkdir 1; cd 1
- dotest conflicts3-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest conflicts3-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd ..
- mkdir 2; cd 2
- dotest conflicts3-3 "${testcvs} -q co -l first-dir" ''
- cd ../1/first-dir
- touch file1 file2
- dotest conflicts3-4 "${testcvs} add file1 file2" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest conflicts3-5 "${testcvs} -q ci -m add-them" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1\.1
-done"
- cd ../../2/first-dir
- # Check that -n doesn't make CVS lose its mind as it creates
- # (or rather, doesn't) a new file.
- dotest conflicts3-6 "${testcvs} -nq update" \
-"U file1
-U file2"
- dotest_fail conflicts3-7 "test -f file1" ''
- dotest conflicts3-8 "${testcvs} -q update" \
-"U file1
-U file2"
- dotest conflicts3-9 "test -f file2" ''
-
- # OK, now remove two files at once
- dotest conflicts3-10 "${testcvs} rm -f file1 file2" \
-"${PROG} remove: scheduling .file1. for removal
-${PROG} remove: scheduling .file2. for removal
-${PROG} remove: use .${PROG} commit. to remove these files permanently"
- dotest conflicts3-11 "${testcvs} -q ci -m remove-them" \
-"Removing file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: delete; previous revision: 1\.1
-done
-Removing file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: delete; previous revision: 1\.1
-done"
- cd ../../1/first-dir
- dotest conflicts3-12 "${testcvs} -n -q update" \
-"${PROG} update: file1 is no longer in the repository
-${PROG} update: file2 is no longer in the repository"
- dotest conflicts3-13 "${testcvs} -q update" \
-"${PROG} update: file1 is no longer in the repository
-${PROG} update: file2 is no longer in the repository"
-
- # OK, now add a directory to both working directories
- # and see that CVS doesn't lose its mind.
- mkdir sdir
- dotest conflicts3-14 "${testcvs} add sdir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/sdir added to the repository"
- touch sdir/sfile
- dotest conflicts3-14a "${testcvs} add sdir/sfile" \
-"${PROG} add: scheduling file .sdir/sfile. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest conflicts3-14b "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir/sfile,v
-done
-Checking in sdir/sfile;
-${CVSROOT_DIRNAME}/first-dir/sdir/sfile,v <-- sfile
-initial revision: 1\.1
-done"
-
- cd ../../2/first-dir
-
- # Create a CVS directory without the proper administrative
- # files in it. This can happen for example if you hit ^C
- # in the middle of a checkout.
- mkdir sdir
- mkdir sdir/CVS
- # OK, in the local case CVS sees that the directory exists
- # in the repository and recurses into it. In the remote case
- # CVS can't see the repository and has no way of knowing
- # that sdir is even a directory (stat'ing everything would be
- # too slow). The remote behavior makes more sense to me (but
- # would this affect other cases?).
- if $remote; then
- dotest conflicts3-15 "${testcvs} -q update" \
-"${QUESTION} sdir"
- else
- dotest conflicts3-15 "${testcvs} -q update" \
-"${QUESTION} sdir
-${PROG} update: ignoring sdir (CVS/Repository missing)"
- touch sdir/CVS/Repository
- dotest conflicts3-16 "${testcvs} -q update" \
-"${QUESTION} sdir
-${PROG} update: ignoring sdir (CVS/Entries missing)"
- cd ..
- dotest conflicts3-16a "${testcvs} -q update first-dir" \
-"${QUESTION} first-dir/sdir
-${PROG} update: ignoring first-dir/sdir (CVS/Entries missing)"
- cd first-dir
- fi
- rm -r sdir
-
- # OK, now the same thing, but the directory doesn't exist
- # in the repository.
- mkdir newdir
- mkdir newdir/CVS
- dotest conflicts3-17 "${testcvs} -q update" "${QUESTION} newdir"
- echo "D/newdir////" >> CVS/Entries
- dotest conflicts3-18 "${testcvs} -q update" \
-"${PROG} [a-z]*: ignoring newdir (CVS/Repository missing)"
- touch newdir/CVS/Repository
- dotest conflicts3-19 "${testcvs} -q update" \
-"${PROG} [a-z]*: ignoring newdir (CVS/Entries missing)"
- cd ..
- dotest conflicts3-20 "${testcvs} -q update first-dir" \
-"${PROG} [a-z]*: ignoring first-dir/newdir (CVS/Entries missing)"
- cd first-dir
- rm -r newdir
-
- # The previous tests have left CVS/Entries in something of a mess.
- # While we "should" be able to deal with that (maybe), for now
- # we just start over.
- cd ..
- rm -r first-dir
- dotest conflicts3-20a "${testcvs} -q co -l first-dir" ''
- cd first-dir
-
- dotest conflicts3-21 "${testcvs} -q update -d sdir" "U sdir/sfile"
- rm -r sdir/CVS
- dotest conflicts3-22 "${testcvs} -q update" "${QUESTION} sdir"
- if $remote; then
- dotest_fail conflicts3-23 "${testcvs} -q update -PdA" \
-"${QUESTION} sdir
-${PROG} update: move away sdir/sfile; it is in the way
-C sdir/sfile"
- else
- dotest conflicts3-23 "${testcvs} -q update -PdA" \
-"${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} remove: scheduling .sdir/sfile. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest conflicts3-26 "${testcvs} ci -m remove sdir/sfile" \
-"Removing sdir/sfile;
-${CVSROOT_DIRNAME}/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"
- dotest conflicts3-28 "${testcvs} -q update -PdA" \
-"${QUESTION} sdir"
-
- cd ../..
-
- rm -r 1 2
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- conflicts4)
- mkdir conflicts4; cd conflicts4
- mkdir 1; cd 1
- dotest conflicts4-1 "$testcvs -q co -l ."
- mkdir first-dir
- dotest conflicts4-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd ..
- mkdir 2; cd 2
- dotest conflicts4-3 "${testcvs} -q co -l first-dir" ''
- cd ../1/first-dir
- echo baseline >file1
- dotest conflicts4-4 "${testcvs} -q add file1" \
-"$PROG add: use .$PROG commit. to add this file permanently"
- dotest conflicts4-5 "${testcvs} -q ci -m add-it" \
-"RCS file: $CVSROOT_DIRNAME/first-dir/file1,v
-done
-Checking in file1;
-$CVSROOT_DIRNAME/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- cd ../../2/first-dir
- dotest conflicts4-6 "${testcvs} -q update" "U file1"
- # Make a local change
- echo wibble2 >> file1
- dotest conflicts4-7 "${testcvs} -q ci -m update2" \
-"Checking in file1;
-$CVSROOT_DIRNAME/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
- cd ../../1/first-dir
- echo wibble1 >>file1
- dotest conflicts4-8 "${testcvs} -Q update" \
-"RCS file: $CVSROOT_DIRNAME/first-dir/file1,v
-retrieving revision 1\.1
-retrieving revision 1\.2
-Merging differences between 1\.1 and 1\.2 into file1
-rcsmerge: warning: conflicts during merge
-cvs update: conflicts found in file1"
- dotest_fail conflicts4-9 "${testcvs} -q update" \
-"C file1"
-
- if $remote; then
- cat >$TESTDIR/conflicts4/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 Global_option"
-echo "ok"
-echo "MT text C "
-echo "MT fname file1"
-echo "MT newline"
-echo "error "
-cat >$TESTDIR/conflicts4/client.out
-EOF
- # Cygwin. Pthffffffffft!
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost "chmod +x $TESTDIR/conflicts4/serveme"
- else
- chmod +x $TESTDIR/conflicts4/serveme
- fi
- save_CVS_SERVER=$CVS_SERVER
- CVS_SERVER=$TESTDIR/conflicts4/serveme; export CVS_SERVER
- dotest_fail conflicts4-10r "$testcvs -q up" "C file1"
- dotest conflicts4-11r "cat $TESTDIR/conflicts4/client.out" \
-"$DOTSTAR
-Argument --
-Directory .
-$CVSROOT_DIRNAME/first-dir
-Entry /file1/1.2/$PLUS=//
-Modified file1
-u=.*,g=.*,o=.*
-59
-baseline
-""<<<<<<< file1
-wibble1
-""=======
-wibble2
-"">>>>>>> 1.2
-update"
-
- cat >$TESTDIR/conflicts4/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 Global_option Empty-conflicts"
-echo "ok"
-echo "MT text C "
-echo "MT fname file1"
-echo "MT newline"
-echo "error "
-cat >$TESTDIR/conflicts4/client.out
-EOF
-
- dotest_fail conflicts4-12r "$testcvs -q up" "C file1"
- dotest conflicts4-13r "cat $TESTDIR/conflicts4/client.out" \
-"$DOTSTAR
-Argument --
-Directory .
-$CVSROOT_DIRNAME/first-dir
-Entry /file1/1.2/$PLUS=//
-Unchanged file1
-update"
-
- CVS_SERVER=$save_CVS_SERVER; export CVS_SERVER
- fi
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- cd ../../..
- rm -rf conflicts4
- rm -rf $CVSROOT_DIRNAME/first-dir
- ;;
-
- clean)
- # Test update -C (overwrite local mods w/ repository copies)
- mkdir 1; cd 1
- dotest clean-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest clean-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- echo "The usual boring test text." > cleanme.txt
- dotest clean-3 "${testcvs} add cleanme.txt" \
-"${PROG} add: scheduling file .cleanme\.txt. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest clean-4 "${testcvs} -q ci -m clean-3" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/cleanme\.txt,v
-done
-Checking in cleanme\.txt;
-${CVSROOT_DIRNAME}/first-dir/cleanme\.txt,v <-- cleanme\.txt
-initial revision: 1\.1
-done"
- # Okay, preparation is done, now test.
- # Check that updating an unmodified copy works.
- dotest clean-5 "${testcvs} -q update" ''
- # Check that updating -C an unmodified copy works.
- dotest clean-6 "${testcvs} -q update -C" ''
- # Check that updating a modified copy works.
- echo "fish" >> cleanme.txt
- dotest clean-7 "${testcvs} -q update" 'M cleanme\.txt'
- # Check that updating -C a modified copy works.
- dotest clean-8 "${testcvs} -q update -C" \
-"(Locally modified cleanme\.txt moved to \.#cleanme\.txt\.1\.1)
-U cleanme\.txt"
- # And check that the backup copy really was made.
- dotest clean-9 "cat .#cleanme.txt.1.1" \
-"The usual boring test text\.
-fish"
-
- # Do it all again, this time naming the file explicitly.
- rm .#cleanme.txt.1.1
- dotest clean-10 "${testcvs} -q update cleanme.txt" ''
- dotest clean-11 "${testcvs} -q update -C cleanme.txt" ''
- echo "bluegill" >> cleanme.txt
- dotest clean-12 "${testcvs} -q update cleanme.txt" 'M cleanme\.txt'
- dotest clean-13 "${testcvs} -q update -C cleanme.txt" \
-"(Locally modified cleanme\.txt moved to \.#cleanme\.txt\.1\.1)
-U cleanme\.txt"
- # And check that the backup copy really was made.
- dotest clean-14 "cat .#cleanme.txt.1.1" \
-"The usual boring test text\.
-bluegill"
-
- # Now try with conflicts
- cd ..
- dotest clean-15 "${testcvs} -q co -d second-dir first-dir" \
-'U second-dir/cleanme\.txt'
- cd second-dir
- echo "conflict test" >> cleanme.txt
- dotest clean-16 "${testcvs} -q ci -m." \
-"Checking in cleanme\.txt;
-${CVSROOT_DIRNAME}/first-dir/cleanme\.txt,v <-- cleanme\.txt
-new revision: 1\.2; previous revision: 1\.1
-done"
- cd ../first-dir
- echo "fish" >> cleanme.txt
- dotest clean-17 "${testcvs} -nq update" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/cleanme\.txt,v
-retrieving revision 1\.1
-retrieving revision 1\.2
-Merging differences between 1\.1 and 1\.2 into cleanme\.txt
-rcsmerge: warning: conflicts during merge
-${PROG} update: conflicts found in cleanme\.txt
-C cleanme\.txt"
- dotest clean-18 "${testcvs} -q update -C" \
-"(Locally modified cleanme\.txt moved to \.#cleanme\.txt\.1\.1)
-U cleanme\.txt"
- dotest clean-19 "cat .#cleanme.txt.1.1" \
-"The usual boring test text\.
-fish"
-
- # Done. Clean up.
- cd ../..
- rm -rf 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- modules)
- # Tests of various ways to define and use modules.
- # Roadmap to various modules tests:
- # -a:
- # error on incorrect placement: modules
- # error combining with other options: modules2-a*
- # infinite loops: modules148a1.1 - modules148a1.2
- # use to specify a file more than once: modules3
- # use with ! feature: modules4
- # regular modules: modules, modules2, cvsadm
- # ampersand modules: modules2
- # -s: modules.
- # -d: modules, modules3, cvsadm
- # -i, -o, -u, -e, -t: modules5
- # slashes in module names: modules3
- # invalid module definitions: modules6
-
- ############################################################
- # These tests are to make sure that administrative files get
- # rebuilt, regardless of how and where files are checked
- # out.
- ############################################################
- # Check out the whole repository
- mkdir 1; cd 1
- dotest modules-1 "${testcvs} -q co ." 'U CVSROOT/checkoutlist
-U CVSROOT/commitinfo
-U CVSROOT/config
-U CVSROOT/cvswrappers
-U CVSROOT/editinfo
-U CVSROOT/loginfo
-U CVSROOT/modules
-U CVSROOT/notify
-U CVSROOT/rcsinfo
-U CVSROOT/taginfo
-U CVSROOT/verifymsg'
- echo "# made a change" >>CVSROOT/modules
- dotest modules-1d "${testcvs} -q ci -m add-modules" \
-"Checking in CVSROOT/modules;
-${CVSROOT_DIRNAME}/CVSROOT/modules,v <-- modules
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ..
- rm -rf 1
-
- ############################################################
- # Check out CVSROOT
- mkdir 1; cd 1
- dotest modules-2 "${testcvs} -q co CVSROOT" 'U CVSROOT/checkoutlist
-U CVSROOT/commitinfo
-U CVSROOT/config
-U CVSROOT/cvswrappers
-U CVSROOT/editinfo
-U CVSROOT/loginfo
-U CVSROOT/modules
-U CVSROOT/notify
-U CVSROOT/rcsinfo
-U CVSROOT/taginfo
-U CVSROOT/verifymsg'
- echo "# made a change" >>CVSROOT/modules
- dotest modules-2d "${testcvs} -q ci -m add-modules" \
-"Checking in CVSROOT/modules;
-${CVSROOT_DIRNAME}/CVSROOT/modules,v <-- modules
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ..
- rm -rf 1
-
- ############################################################
- # Check out CVSROOT in some other directory
- mkdir ${CVSROOT_DIRNAME}/somedir
- mkdir 1; cd 1
- dotest modules-3 "${testcvs} -q co somedir" ''
- cd somedir
- dotest modules-3d "${testcvs} -q co CVSROOT" 'U CVSROOT/checkoutlist
-U CVSROOT/commitinfo
-U CVSROOT/config
-U CVSROOT/cvswrappers
-U CVSROOT/editinfo
-U CVSROOT/loginfo
-U CVSROOT/modules
-U CVSROOT/notify
-U CVSROOT/rcsinfo
-U CVSROOT/taginfo
-U CVSROOT/verifymsg'
- echo "# made a change" >>CVSROOT/modules
- dotest modules-3g "${testcvs} -q ci -m add-modules" \
-"Checking in CVSROOT/modules;
-${CVSROOT_DIRNAME}/CVSROOT/modules,v <-- modules
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ../..
- rm -rf 1
- rm -rf ${CVSROOT_DIRNAME}/somedir
- ############################################################
- # end rebuild tests
- ############################################################
-
-
- mkdir ${CVSROOT_DIRNAME}/first-dir
-
- mkdir 1
- cd 1
-
- dotest modules-143 "${testcvs} -q co first-dir" ""
-
- cd first-dir
- mkdir subdir
- dotest modules-143a "${testcvs} add subdir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/subdir added to the repository"
-
- cd subdir
- mkdir ssdir
- dotest modules-143b "${testcvs} add ssdir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/subdir/ssdir added to the repository"
-
- touch a b
-
- dotest modules-144 "${testcvs} add a b" \
-"${PROG} add: scheduling file .a. for addition
-${PROG} add: scheduling file .b. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
-
- dotest modules-145 "${testcvs} ci -m added" \
-"${PROG} [a-z]*: Examining .
-${PROG} [a-z]*: Examining ssdir
-RCS file: ${CVSROOT_DIRNAME}/first-dir/subdir/a,v
-done
-Checking in a;
-${CVSROOT_DIRNAME}/first-dir/subdir/a,v <-- a
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/subdir/b,v
-done
-Checking in b;
-${CVSROOT_DIRNAME}/first-dir/subdir/b,v <-- b
-initial revision: 1\.1
-done"
-
- cd ..
- dotest modules-146 "${testcvs} -q co CVSROOT" \
-"U CVSROOT/checkoutlist
-U CVSROOT/commitinfo
-U CVSROOT/config
-U CVSROOT/cvswrappers
-U CVSROOT/editinfo
-U CVSROOT/loginfo
-U CVSROOT/modules
-U CVSROOT/notify
-U CVSROOT/rcsinfo
-U CVSROOT/taginfo
-U CVSROOT/verifymsg"
-
- # Here we test that CVS can deal with CVSROOT (whose repository
- # is at top level) in the same directory as subdir (whose repository
- # is a subdirectory of first-dir). TODO: Might want to check that
- # files can actually get updated in this state.
- dotest modules-147 "${testcvs} -q update" ""
-
- cat >CVSROOT/modules <<EOF
-realmodule first-dir/subdir a
-dirmodule first-dir/subdir
-namedmodule -d nameddir first-dir/subdir
-aliasmodule -a first-dir/subdir/a
-aliasnested -a first-dir/subdir/ssdir
-topfiles -a first-dir/file1 first-dir/file2
-world -a .
-statusmod -s Mungeable
-# Check for ability to block infinite loops.
-infinitealias -a infinitealias
-# Prior to 1.11.12 & 1.12.6, the infinite alias loop check didn't strip
-# slashes or work if a module called a module which then called itself
-# (A -> A was blocked, but not A -> B -> A or deeper).
-infinitealias2 -a infinitealias2/
-infinitealias3 -a infinitealias4/
-infinitealias4 -a aliasmodule infinitealias5
-infinitealias5 -a infinitealias3/
-# Options must come before arguments. It is possible this should
-# be relaxed at some point (though the result would be bizarre for
-# -a); for now test the current behavior.
-bogusalias first-dir/subdir/a -a
-EOF
- dotest modules-148 "${testcvs} ci -m 'add modules' CVSROOT/modules" \
-"Checking in CVSROOT/modules;
-${CVSROOT_DIRNAME}/CVSROOT/modules,v <-- modules
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
-
- cd ..
- # The "statusmod" module contains an error; trying to use it
- # will produce "modules file missing directory" I think.
- # However, that shouldn't affect the ability of "cvs co -c" or
- # "cvs co -s" to do something reasonable with it.
- dotest modules-148a0 "${testcvs} co -c" 'aliasmodule -a first-dir/subdir/a
-aliasnested -a first-dir/subdir/ssdir
-bogusalias first-dir/subdir/a -a
-dirmodule first-dir/subdir
-infinitealias -a infinitealias
-infinitealias2 -a infinitealias2/
-infinitealias3 -a infinitealias4/
-infinitealias4 -a aliasmodule infinitealias5
-infinitealias5 -a infinitealias3/
-namedmodule -d nameddir first-dir/subdir
-realmodule first-dir/subdir a
-statusmod -s Mungeable
-topfiles -a first-dir/file1 first-dir/file2
-world -a \.'
- # There is code in modules.c:save_d which explicitly skips
- # modules defined with -a, which is why aliasmodule is not
- # listed.
- dotest modules-148a1 "${testcvs} co -s" \
-'statusmod Mungeable
-bogusalias NONE first-dir/subdir/a -a
-dirmodule NONE first-dir/subdir
-namedmodule NONE first-dir/subdir
-realmodule NONE first-dir/subdir a'
-
- # Check that infinite loops are avoided
- dotest modules-148a1.1 "${testcvs} co infinitealias" \
-"$PROG checkout: module \`infinitealias' in modules file contains infinite loop" \
-"$PROG server: module \`infinitealias' in modules file contains infinite loop
-$PROG checkout: module \`infinitealias' in modules file contains infinite loop"
- # Prior to 1.11.12 & 1.12.6, the inifinte alias loop check did not
- # strip slashes.
- dotest modules-148a1.2 "${testcvs} co infinitealias2" \
-"$PROG checkout: module \`infinitealias2' in modules file contains infinite loop" \
-"$PROG server: module \`infinitealias2' in modules file contains infinite loop
-$PROG checkout: module \`infinitealias2' in modules file contains infinite loop"
- # Prior to 1.11.12 & 1.12.6, the inifinte alias loop check did not
- # notice when A -> B -> A, it only noticed A -> A.
- dotest modules-148a1.3 "${testcvs} co infinitealias3/" \
-"$PROG checkout: module \`infinitealias3' in modules file contains infinite loop" \
-"$PROG server: module \`infinitealias3' in modules file contains infinite loop
-$PROG checkout: module \`infinitealias3' in modules file contains infinite loop"
-
- # Test that real modules check out to realmodule/a, not subdir/a.
- dotest modules-149a1 "${testcvs} co realmodule" "U realmodule/a"
- dotest modules-149a2 "test -d realmodule && test -f realmodule/a" ""
- dotest_fail modules-149a3 "test -f realmodule/b" ""
- dotest modules-149a4 "${testcvs} -q co realmodule" ""
- dotest modules-149a5 "echo yes | ${testcvs} release -d realmodule" \
-"You have \[0\] altered files in this repository\.
-Are you sure you want to release (and delete) directory .realmodule.: "
-
- dotest_fail modules-149b1 "${testcvs} co realmodule/a" \
-"${PROG}"' checkout: module `realmodule/a'\'' is a request for a file in a module which is not a directory' \
-"${PROG}"' server: module `realmodule/a'\'' is a request for a file in a module which is not a directory
-'"${PROG}"' \[checkout aborted\]: cannot expand modules'
-
- # Now test the ability to check out a single file from a directory
- dotest modules-150c "${testcvs} co dirmodule/a" "U dirmodule/a"
- dotest modules-150d "test -d dirmodule && test -f dirmodule/a" ""
- dotest_fail modules-150e "test -f dirmodule/b" ""
- dotest modules-150f "echo yes | ${testcvs} release -d dirmodule" \
-"You have \[0\] altered files in this repository\.
-Are you sure you want to release (and delete) directory .dirmodule.: "
- # Now test the ability to correctly reject a non-existent filename.
- # For maximum studliness we would check that an error message is
- # being output.
- # We accept a zero exit status because it is what CVS does
- # (Dec 95). Probably the exit status should be nonzero,
- # however.
- dotest modules-150g1 "${testcvs} co dirmodule/nonexist" \
-"${PROG} checkout: warning: new-born dirmodule/nonexist has disappeared"
- # We tolerate the creation of the dirmodule directory, since that
- # is what CVS does, not because we view that as preferable to not
- # creating it.
- dotest_fail modules-150g2 "test -f dirmodule/a || test -f dirmodule/b" ""
- rm -r dirmodule
-
- # Now test that a module using -d checks out to the specified
- # directory.
- dotest modules-150h1 "${testcvs} -q co namedmodule" \
-'U nameddir/a
-U nameddir/b'
- dotest modules-150h2 "test -f nameddir/a && test -f nameddir/b" ""
- echo add line >>nameddir/a
- dotest modules-150h3 "${testcvs} -q co namedmodule" 'M nameddir/a'
- rm nameddir/a
- dotest modules-150h4 "${testcvs} -q co namedmodule" 'U nameddir/a'
- dotest modules-150h99 "echo yes | ${testcvs} release -d nameddir" \
-"You have \[0\] altered files in this repository\.
-Are you sure you want to release (and delete) directory .nameddir.: "
-
- # Now test that alias modules check out to subdir/a, not
- # aliasmodule/a.
- dotest modules-151 "${testcvs} co aliasmodule" ""
- dotest_fail modules-152 "test -d aliasmodule" ""
- echo abc >>first-dir/subdir/a
- dotest modules-153 "${testcvs} -q co aliasmodule" "M first-dir/subdir/a"
-
- cd ..
- rm -r 1
-
- mkdir 2
- cd 2
- dotest modules-155a0 "${testcvs} co aliasnested" \
-"${PROG} checkout: Updating first-dir/subdir/ssdir"
- dotest modules-155a1 "test -d first-dir" ''
- dotest modules-155a2 "test -d first-dir/subdir" ''
- dotest modules-155a3 "test -d first-dir/subdir/ssdir" ''
- # Test that nothing extraneous got created.
- dotest modules-155a4 "ls" "first-dir" \
-"CVS
-first-dir"
- cd ..
- rm -r 2
-
- # Test checking out everything.
- mkdir 1
- cd 1
- dotest modules-155b "${testcvs} -q co world" \
-"U CVSROOT/${DOTSTAR}
-U first-dir/subdir/a
-U first-dir/subdir/b"
- cd ..
- rm -r 1
-
- # Test checking out a module which lists at least two
- # specific files twice. At one time, this failed over
- # remote CVS.
- mkdir 1
- cd 1
- dotest modules-155c1 "${testcvs} -q co first-dir" \
-"U first-dir/subdir/a
-U first-dir/subdir/b"
-
- cd first-dir
- echo 'first revision' > file1
- echo 'first revision' > file2
- dotest modules-155c2 "${testcvs} add file1 file2" \
-"${PROG}"' add: scheduling file `file1'\'' for addition
-'"${PROG}"' add: scheduling file `file2'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add these files permanently'
- dotest modules-155c3 "${testcvs} -q ci -m add-it" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1\.1
-done"
-
- cd ..
- rm -r first-dir
- dotest modules-155c4 "${testcvs} -q co topfiles" \
-"U first-dir/file1
-U first-dir/file2"
- dotest modules-155c5 "${testcvs} -q co topfiles" ""
-
- # Make sure the right thing happens if we remove a file.
- cd first-dir
- dotest modules-155c6 "${testcvs} -q rm -f file1" \
-"${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest modules-155c7 "${testcvs} -q ci -m remove-it" \
-"Removing file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: delete; previous revision: 1\.1
-done"
- cd ..
- rm -r first-dir
- dotest modules-155c8 "${testcvs} -q co topfiles" \
-"${PROG} checkout: warning: first-dir/file1 is not (any longer) pertinent
-U first-dir/file2"
-
- cd ..
- rm -r 1
-
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- modules2)
- # More tests of modules, in particular the & feature.
- mkdir 1; cd 1
- dotest modules2-setup-1 "${testcvs} -q co -l ." ''
- mkdir first-dir second-dir third-dir
- dotest modules2-setup-2 \
-"${testcvs} add first-dir second-dir third-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository
-Directory ${CVSROOT_DIRNAME}/second-dir added to the repository
-Directory ${CVSROOT_DIRNAME}/third-dir added to the repository"
- cd third-dir
- touch file3
- dotest modules2-setup-3 "${testcvs} add file3" \
-"${PROG} add: scheduling file .file3. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest modules2-setup-4 "${testcvs} -q ci -m add file3" \
-"RCS file: ${CVSROOT_DIRNAME}/third-dir/file3,v
-done
-Checking in file3;
-${CVSROOT_DIRNAME}/third-dir/file3,v <-- file3
-initial revision: 1\.1
-done"
- cd ../..
- rm -r 1
-
- mkdir 1
- cd 1
-
- dotest modules2-1 "${testcvs} -q co CVSROOT/modules" \
-'U CVSROOT/modules'
- cd CVSROOT
- cat >> modules << EOF
-ampermodule &first-dir &second-dir
-combmodule third-dir file3 &first-dir
-ampdirmod -d newdir &first-dir &second-dir
-badmod -d newdir
-messymod first-dir &messymodchild
-messymodchild -d sdir/child second-dir
-EOF
- # Depending on whether the user also ran the modules test
- # we will be checking in revision 1.2 or 1.3.
- dotest modules2-2 "${testcvs} -q ci -m add-modules" \
-"Checking in modules;
-${CVSROOT_DIRNAME}/CVSROOT/modules,v <-- modules
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
-
- cd ..
-
- dotest modules2-3 "${testcvs} -q co ampermodule" ''
- dotest modules2-4 "test -d ampermodule/first-dir" ''
- dotest modules2-5 "test -d ampermodule/second-dir" ''
-
- # Test ability of cvs release to handle multiple arguments
- # See comment at "release" for list of other cvs release tests.
- cd ampermodule
- if ${testcvs} release -d first-dir second-dir <<EOF >>${LOGFILE}
-yes
-yes
-EOF
- then
- pass modules2-6
- else
- fail modules2-6
- fi
- dotest_fail modules2-7 "test -d first-dir" ''
- dotest_fail modules2-8 "test -d second-dir" ''
-
- cd ..
-
- # There used to be a nasty-hack that made CVS skip creation of the
- # module dir (in this case ampermodule) when -n was specified
- dotest modules2-ampermod-1 "${testcvs} -q co -n ampermodule" ''
- dotest modules2-ampermod-2 "test -d ampermodule/first-dir" ''
- dotest modules2-ampermod-3 "test -d ampermodule/second-dir" ''
-
- # Test release of a module
- if echo yes |${testcvs} release -d ampermodule >>${LOGFILE}; then
- pass modules2-ampermod-release-1
- else
- fail modules2-ampermod-release-1
- fi
- dotest_fail modules2-ampermod-release-2 "test -d ampermodule" ''
-
- # and the '-n' test again, but in conjunction with '-d'
- dotest modules2-ampermod-4 "${testcvs} -q co -n -d newname ampermodule" ''
- dotest modules2-ampermod-5 "test -d newname/first-dir" ''
- dotest modules2-ampermod-6 "test -d newname/second-dir" ''
- rm -rf newname
-
- # Now we create another directory named first-dir and make
- # sure that CVS doesn't get them mixed up.
- mkdir first-dir
- # Note that this message should say "Updating ampermodule/first-dir"
- # I suspect. This is a long-standing behavior/bug....
- dotest modules2-9 "${testcvs} co ampermodule" \
-"${PROG} checkout: Updating first-dir
-${PROG} checkout: Updating second-dir"
- touch ampermodule/first-dir/amper1
- cd ampermodule
- dotest modules2-10 "${testcvs} add first-dir/amper1" \
-"${PROG} add: scheduling file .first-dir/amper1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- cd ..
-
- # As with the "Updating xxx" message, the "U first-dir/amper1"
- # message (instead of "U ampermodule/first-dir/amper1") is
- # rather fishy.
- dotest modules2-12 "${testcvs} co ampermodule" \
-"${PROG} checkout: Updating first-dir
-A first-dir/amper1
-${PROG} checkout: Updating second-dir"
-
- if $remote; then
- dotest modules2-13 "${testcvs} -q ci -m add-it ampermodule" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/amper1,v
-done
-Checking in ampermodule/first-dir/amper1;
-${CVSROOT_DIRNAME}/first-dir/amper1,v <-- amper1
-initial revision: 1\.1
-done"
- else
- # Trying this as above led to a "protocol error" message.
- # Work around this bug.
- cd ampermodule
- dotest modules2-13 "${testcvs} -q ci -m add-it" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/amper1,v
-done
-Checking in first-dir/amper1;
-${CVSROOT_DIRNAME}/first-dir/amper1,v <-- amper1
-initial revision: 1\.1
-done"
- cd ..
- fi
- cd ..
- rm -r 1
-
- # Now test the "combmodule" module (combining regular modules
- # and ampersand modules in the same module definition).
- mkdir 1; cd 1
- dotest modules2-14 "${testcvs} co combmodule" \
-"U combmodule/file3
-${PROG} checkout: Updating first-dir
-U first-dir/amper1"
- dotest modules2-15 "test -f combmodule/file3" ""
- dotest modules2-16 "test -f combmodule/first-dir/amper1" ""
- cd combmodule
- rm -r first-dir
- # At least for now there is no way to tell CVS that
- # some files/subdirectories come from one repository directory,
- # and others from another.
- # 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} update: Updating \."
-
- cd ..
- dotest modules2-18 "${testcvs} -q co combmodule" \
-"U first-dir/amper1"
- dotest modules2-19 "test -f combmodule/first-dir/amper1" ""
- cd ..
- rm -r 1
-
- # Now test the "ampdirmod" and "badmod" modules to be sure that
- # options work with ampersand modules but don't prevent the
- # "missing directory" error message.
- mkdir 1; cd 1
- dotest modules2-20 "${testcvs} co ampdirmod" \
-"${PROG} checkout: Updating first-dir
-U first-dir/amper1
-${PROG} checkout: Updating second-dir"
- dotest modules2-21 "test -f newdir/first-dir/amper1" ""
- dotest modules2-22 "test -d newdir/second-dir" ""
- dotest_fail modules2-23 "${testcvs} co badmod" \
-"${PROG} checkout: modules file missing directory for module badmod" \
-"${PROG} server: modules file missing directory for module badmod
-${PROG} \[checkout aborted\]: cannot expand modules"
- cd ..
- rm -r 1
-
- # Confirm that a rename with added depth nested in an ampersand
- # module works.
- mkdir 1; cd 1
- dotest modules2-nestedrename-1 "${testcvs} -q co messymod" \
-"U messymod/amper1"
- dotest modules2-nestedrename-2 "test -d messymod/sdir" ''
- dotest modules2-nestedrename-3 "test -d messymod/sdir/CVS" ''
- dotest modules2-nestedrename-4 "test -d messymod/sdir/child" ''
- dotest modules2-nestedrename-5 "test -d messymod/sdir/child/CVS" ''
- cd ..; rm -r 1
-
- # FIXME: client/server has a bug. It should be working like a local
- # repository in this case, but fails to check out the second module
- # in the list when a branch is specified.
- mkdir 1; cd 1
- dotest modules2-ampertag-setup-1 \
-"${testcvs} -Q rtag tag first-dir second-dir third-dir" \
-''
- dotest modules2-ampertag-1 "${testcvs} -q co -rtag ampermodule" \
-"U first-dir/amper1"
- if $remote; then
- dotest_fail modules2-ampertag-2 "test -d ampermodule/second-dir" ''
- dotest_fail modules2-ampertag-3 "test -d ampermodule/second-dir/CVS" ''
- else
- dotest modules2-ampertag-2 "test -d ampermodule/second-dir" ''
- dotest modules2-ampertag-3 "test -d ampermodule/second-dir/CVS" ''
- fi
- cd ..; rm -r 1
-
- # Test for tag files when an ampermod is renamed with more path
- # elements than it started with.
- #
- # FIXME: This is currently broken in the remote case, possibly only
- # because the messymodchild isn't being checked out at all.
- mkdir 1; cd 1
-# dotest modules2-tagfiles-setup-1 \
-#"${testcvs} -Q rtag -b branch first-dir second-dir" \
-#''
- dotest modules2-tagfiles-1 "${testcvs} -q co -rtag messymod" \
-"U messymod/amper1"
- if $remote; then
- dotest_fail modules2-tagfiles-2r "test -d messymod/sdir" ''
- else
- dotest modules2-tagfiles-2 "cat messymod/sdir/CVS/Tag" 'Ttag'
- fi
- cd ..; rm -r 1
-
- # Test that CVS gives an error if one combines -a with
- # other options.
- # Probably would be better to break this out into a separate
- # test. Although it is short, it shares no files/state with
- # the rest of the modules2 tests.
- mkdir 1; cd 1
- dotest modules2-a0.5 "${testcvs} -q co CVSROOT/modules" \
-'U CVSROOT/modules'
- cd CVSROOT
- echo 'aliasopt -a -d onedir first-dir' >modules
- dotest modules2-a0 "${testcvs} -q ci -m add-modules" \
-"Checking in modules;
-${CVSROOT_DIRNAME}/CVSROOT/modules,v <-- modules
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ..
- dotest_fail modules2-a1 "${testcvs} -q co aliasopt" \
-"${PROG} checkout: -a cannot be specified in the modules file along with other options" \
-"${PROG} server: -a cannot be specified in the modules file along with other options
-${PROG} \[checkout aborted\]: cannot expand modules"
- cd ..; rm -r 1
-
- # Clean up.
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- rm -rf ${CVSROOT_DIRNAME}/second-dir
- rm -rf ${CVSROOT_DIRNAME}/third-dir
- ;;
-
- modules3)
- # More tests of modules, in particular what happens if several
- # modules point to the same file.
-
- # First just set up a directory first-dir and a file file1 in it.
- mkdir 1; cd 1
-
- dotest modules3-0 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest modules3-1 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
-
- cd first-dir
- echo file1 >file1
- dotest modules3-2 "${testcvs} add file1" \
-"${PROG} add: scheduling file \`file1' for addition
-${PROG} add: use '${PROG} commit' to add this file permanently"
- dotest modules3-3 "${testcvs} -q ci -m add-it" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- cd ..
-
- dotest modules3-4 "${testcvs} -q update -d CVSROOT" \
-"U CVSROOT${DOTSTAR}"
- cd CVSROOT
- cat >modules <<EOF
-mod1 -a first-dir/file1
-bigmod -a mod1 first-dir/file1
-namednest -d src/sub/dir first-dir
-nestdeeper -d src/sub1/sub2/sub3/dir first-dir
-nestshallow -d src/dir second-dir/suba/subb
-path/in/modules &mod1
-another/path/test -d another/path/test first-dir
-EOF
- dotest modules3-5 "${testcvs} -q ci -m add-modules" \
-"Checking in modules;
-${CVSROOT_DIRNAME}/CVSROOT/modules,v <-- modules
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ..
-
- dotest modules3-6 "${testcvs} -q co bigmod" ''
- rm -r first-dir
- dotest modules3-7 "${testcvs} -q co bigmod" 'U first-dir/file1'
- cd ..
- rm -r 1
-
- mkdir 1; cd 1
- mkdir suba
- mkdir suba/subb
- # This fails to work remote (it doesn't notice the directories,
- # I suppose because they contain no files). Bummer, especially
- # considering this is a documented technique and everything.
- dotest modules3-7a \
-"${testcvs} import -m add-dirs second-dir tag1 tag2" \
-"${PROG} import: Importing ${CVSROOT_DIRNAME}/second-dir/suba
-${PROG} import: Importing ${CVSROOT_DIRNAME}/second-dir/suba/subb
-
-No conflicts created by this import" "
-No conflicts created by this import"
- cd ..; rm -r 1
- mkdir 1; cd 1
- dotest modules3-7b "${testcvs} co second-dir" \
-"${PROG} checkout: Updating second-dir
-${PROG} checkout: Updating second-dir/suba
-${PROG} checkout: Updating second-dir/suba/subb" \
-"${PROG} checkout: Updating second-dir"
-
- if $remote; then
- cd second-dir
- mkdir suba
- dotest modules3-7-workaround1 "${testcvs} add suba" \
-"Directory ${CVSROOT_DIRNAME}/second-dir/suba added to the repository"
- cd suba
- mkdir subb
- dotest modules3-7-workaround2 "${testcvs} add subb" \
-"Directory ${CVSROOT_DIRNAME}/second-dir/suba/subb added to the repository"
- cd ../..
- fi
-
- cd second-dir/suba/subb
- touch fileb
- dotest modules3-7c "${testcvs} add fileb" \
-"${PROG} add: scheduling file .fileb. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest modules3-7d "${testcvs} -q ci -m add-it" \
-"RCS file: ${CVSROOT_DIRNAME}/second-dir/suba/subb/fileb,v
-done
-Checking in fileb;
-${CVSROOT_DIRNAME}/second-dir/suba/subb/fileb,v <-- fileb
-initial revision: 1\.1
-done"
- cd ../../..
- cd ..; rm -r 1
-
- mkdir 1
- cd 1
- dotest modules3-8 "${testcvs} -q co namednest" \
-'U src/sub/dir/file1'
- dotest modules3-9 "test -f src/sub/dir/file1" ''
- cd ..
- rm -r 1
-
- # Try the same thing, but with the directories nested even
- # deeper (deeply enough so they are nested more deeply than
- # the number of directories from / to ${TESTDIR}).
- mkdir 1
- cd 1
- dotest modules3-10 "${testcvs} -q co nestdeeper" \
-'U src/sub1/sub2/sub3/dir/file1'
- dotest modules3-11 "test -f src/sub1/sub2/sub3/dir/file1" ''
-
- # While we are doing things like twisted uses of '/' (e.g.
- # modules3-12), try this one.
- if $remote; then
- dotest_fail modules3-11b \
-"${testcvs} -q update ${TESTDIR}/1/src/sub1/sub2/sub3/dir/file1" \
-"absolute pathname .${TESTDIR}/1/src/sub1/sub2/sub3/dir. illegal for server"
- fi # end of remote-only tests
-
- cd ..
- rm -r 1
-
- # This one is almost too twisted for words. The pathname output
- # in the message from "co" doesn't include the "path/in/modules",
- # but those directories do get created (with no CVSADM except
- # in "modules" which has a CVSNULLREPOS).
- # I'm not sure anyone is relying on this nonsense or whether we
- # need to keep doing it, but it is what CVS currently does...
- # Skip it for remote; the remote code has the good sense to
- # not deal with it (on the minus side it gives
- # "internal error: repository string too short." (CVS 1.9) or
- # "warning: server is not creating directories one at a time" (now)
- # instead of a real error).
- # I'm tempted to just make it a fatal error to have '/' in a
- # module name. But see comments at modules3-16.
- if $remote; then :; else
- mkdir 1; cd 1
- dotest modules3-12 "${testcvs} -q co path/in/modules" \
-"U first-dir/file1"
- dotest modules3-13 "test -f path/in/modules/first-dir/file1" ''
- cd ..; rm -r 1
- fi # end of tests skipped for remote
-
- # Now here is where it used to get seriously bogus.
- mkdir 1; cd 1
- dotest modules3-14 \
-"${testcvs} -q rtag tag1 path/in/modules" ''
- # CVS used to create this even though rtag should *never* affect
- # the directory current when it is called!
- dotest_fail modules3-15 "test -d path/in/modules" ''
- # Just for trivia's sake, rdiff was not similarly vulnerable
- # because it passed 0 for run_module_prog to do_module.
- cd ..; rm -r 1
-
- # Some people seem to want this to work. I still suspect there
- # are dark corners in slashes in module names. This probably wants
- # more thought before we start hacking on CVS (one way or the other)
- # or documenting this.
- mkdir 2; cd 2
- dotest modules3-16 "${testcvs} -q co another/path/test" \
-"U another/path/test/file1"
- dotest modules3-17 "cat another/path/test/file1" 'file1'
- cd ..; rm -r 2
-
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- rm -rf ${CVSROOT_DIRNAME}/second-dir
- ;;
-
- modules4)
- # Some tests using the modules file with aliases that
- # exclude particular directories.
-
- mkdir 1; cd 1
-
- dotest modules4-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest modules4-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
-
- cd first-dir
- mkdir subdir subdir_long
- dotest modules4-3 "${testcvs} add subdir subdir_long" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/subdir added to the repository
-Directory ${CVSROOT_DIRNAME}/first-dir/subdir_long added to the repository"
-
- echo file1 > file1
- dotest modules4-4 "${testcvs} add file1" \
-"${PROG}"' add: scheduling file `file1'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
-
- echo file2 > subdir/file2
- dotest modules4-5 "${testcvs} add subdir/file2" \
-"${PROG}"' add: scheduling file `subdir/file2'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
-
- echo file3 > subdir_long/file3
- dotest modules4-6 "${testcvs} add subdir_long/file3" \
-"${PROG}"' add: scheduling file `subdir_long/file3'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
-
- dotest modules4-7 "${testcvs} -q ci -m add-it" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/subdir/file2,v
-done
-Checking in subdir/file2;
-${CVSROOT_DIRNAME}/first-dir/subdir/file2,v <-- file2
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/subdir_long/file3,v
-done
-Checking in subdir_long/file3;
-${CVSROOT_DIRNAME}/first-dir/subdir_long/file3,v <-- file3
-initial revision: 1\.1
-done"
-
- cd ..
-
- dotest modules4-8 "${testcvs} -q update -d CVSROOT" \
-"U CVSROOT${DOTSTAR}"
- cd CVSROOT
- cat >modules <<EOF
-all -a first-dir
-some -a !first-dir/subdir first-dir
-other -a !first-dir/subdir !first-dir/subdir_long first-dir
-somewhat -a first-dir !first-dir/subdir
-EOF
- dotest modules4-9 "${testcvs} -q ci -m add-modules" \
-"Checking in modules;
-${CVSROOT_DIRNAME}/CVSROOT/modules,v <-- modules
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ..
-
- cd ..
- mkdir 2; cd 2
-
- dotest modules4-10 "${testcvs} -q co all" \
-"U first-dir/file1
-U first-dir/subdir/file2
-U first-dir/subdir_long/file3"
- rm -r first-dir
-
- dotest modules4-11 "${testcvs} -q co some" \
-"U first-dir/file1
-U first-dir/subdir_long/file3"
- dotest_fail modules4-12 "test -d first-dir/subdir" ''
- dotest modules4-13 "test -d first-dir/subdir_long" ''
- rm -r first-dir
-
- if $remote; then
- # But remote seems to do it the other way.
- dotest modules4-14r-1 "${testcvs} -q co somewhat" \
-"U first-dir/file1
-U first-dir/subdir_long/file3"
- dotest_fail modules4-14r-2 "test -d first-dir/subdir" ''
- dotest modules4-14r-3 "test -d first-dir/subdir_long" ''
- else
- # This is strange behavior, in that the order of the
- # "!first-dir/subdir" and "first-dir" matter, and it isn't
- # clear that they should. I suspect it is long-standing
- # strange behavior but I haven't verified that.
- dotest modules4-14-1 "${testcvs} -q co somewhat" \
-"U first-dir/file1
-U first-dir/subdir/file2
-U first-dir/subdir_long/file3"
- dotest modules4-14-2 "test -d first-dir/subdir" ''
- dotest modules4-14-3 "test -d first-dir/subdir_long" ''
- fi
- rm -r first-dir
-
- dotest modules4-15 "${testcvs} -q co other" \
-"U first-dir/file1"
- dotest_fail modules4-16 "test -d first-dir/subdir" ''
- dotest_fail modules4-17 "test -d first-dir/subdir_long" ''
- rm -r first-dir
-
- cd ..
- rm -r 2
-
- dotest modules4-18 "${testcvs} rtag tag some" \
-"${PROG} rtag: Tagging first-dir
-${PROG} rtag: Ignoring first-dir/subdir
-${PROG} rtag: Tagging first-dir/subdir_long"
-
- cd 1/first-dir/subdir
- dotest modules4-19 "${testcvs} log file2" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/subdir/file2,v
-Working file: file2
-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;
-add-it
-============================================================================="
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- cd ../../..
- rm -r 1
-
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- modules5)
- # Test module programs
-
- mkdir ${CVSROOT_DIRNAME}/first-dir
- mkdir 1
- cd 1
- dotest modules5-1 "${testcvs} -q co first-dir" ""
- cd first-dir
- mkdir subdir
- dotest modules5-2 "${testcvs} add subdir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/subdir added to the repository"
- cd subdir
- mkdir ssdir
- dotest modules5-3 "${testcvs} add ssdir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/subdir/ssdir added to the repository"
- touch a b
- dotest modules5-4 "${testcvs} add a b" \
-"${PROG} add: scheduling file .a. for addition
-${PROG} add: scheduling file .b. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
-
- dotest modules5-5 "${testcvs} ci -m added" \
-"${PROG} [a-z]*: Examining .
-${PROG} [a-z]*: Examining ssdir
-RCS file: ${CVSROOT_DIRNAME}/first-dir/subdir/a,v
-done
-Checking in a;
-${CVSROOT_DIRNAME}/first-dir/subdir/a,v <-- a
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/subdir/b,v
-done
-Checking in b;
-${CVSROOT_DIRNAME}/first-dir/subdir/b,v <-- b
-initial revision: 1\.1
-done"
-
- cd ..
- dotest modules5-6 "${testcvs} -q co CVSROOT" \
-"U CVSROOT/checkoutlist
-U CVSROOT/commitinfo
-U CVSROOT/config
-U CVSROOT/cvswrappers
-U CVSROOT/editinfo
-U CVSROOT/loginfo
-U CVSROOT/modules
-U CVSROOT/notify
-U CVSROOT/rcsinfo
-U CVSROOT/taginfo
-U CVSROOT/verifymsg"
-
- # FIXCVS: The sleep in the following script helps avoid out of
- # order messages, but we really need to figure out how to fix
- # cvs to prevent them in the first place.
- for i in checkout export tag; do
- cat >> ${CVSROOT_DIRNAME}/$i.sh <<EOF
-#! /bin/sh
-sleep 1
-echo "$i script invoked in \`pwd\`"
-echo "args: \$@"
-EOF
- # Cygwin doesn't set premissions correctly over the Samba share.
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost "chmod +x ${CVSROOT_DIRNAME}/$i.sh"
- else
- chmod +x ${CVSROOT_DIRNAME}/$i.sh
- fi
- done
-
- OPTS="-o${CVSROOT_DIRNAME}/checkout.sh -e ${CVSROOT_DIRNAME}/export.sh -t${CVSROOT_DIRNAME}/tag.sh"
- cat >CVSROOT/modules <<EOF
-realmodule ${OPTS} first-dir/subdir a
-dirmodule ${OPTS} first-dir/subdir
-namedmodule -d nameddir ${OPTS} first-dir/subdir
-EOF
-
- dotest modules5-7 "${testcvs} ci -m 'add modules' CVSROOT/modules" \
-"" \
-"Checking in CVSROOT/modules;
-${CVSROOT_DIRNAME}/CVSROOT/modules,v <-- modules
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
-
- cd ..
- rm -rf first-dir
-
- # Test that real modules check out to realmodule/a, not subdir/a.
- if $remote; then
- # FIXCVS?
- # Mac OSX 10.3 (Darwin ppc-osx1 5.5) fails here when $TMPDIR
- # contains a symlink (it does not fail the local modules5-8).
- # Since no other platforms are exhibiting the same problem, I
- # suspect an issue with OSX and fork() or the like dereferencing
- # the symlink, but it is possible it is something that could be
- # fixed or worked around in CVS.
- dotest modules5-8r "$testcvs co realmodule" \
-"U realmodule/a
-${PROG} checkout: Executing ..${CVSROOT_DIRNAME}/checkout\.sh. .realmodule..
-checkout script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: realmodule"
- else
- dotest modules5-8 "${testcvs} co realmodule" \
-"U realmodule/a
-${PROG} checkout: Executing ..${CVSROOT_DIRNAME}/checkout\.sh. .realmodule..
-checkout script invoked in ${TESTDIR}/1
-args: realmodule"
- fi
- dotest modules5-9 "test -d realmodule && test -f realmodule/a" ""
- dotest_fail modules5-10 "test -f realmodule/b" ""
- if $remote; then
- dotest modules5-11 "${testcvs} -q co realmodule" \
-"checkout script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: realmodule"
- dotest modules5-12 "${testcvs} -q update" ''
- echo "change" >>realmodule/a
- dotest modules5-13 "${testcvs} -q ci -m." \
-"Checking in realmodule/a;
-${CVSROOT_DIRNAME}/first-dir/subdir/a,v <-- a
-new revision: 1\.2; previous revision: 1\.1
-done"
- else
- dotest modules5-11 "${testcvs} -q co realmodule" \
-"checkout script invoked in ${TESTDIR}/1
-args: realmodule"
- dotest modules5-12 "${testcvs} -q update" ''
- echo "change" >>realmodule/a
- dotest modules5-13 "${testcvs} -q ci -m." \
-"Checking in realmodule/a;
-${CVSROOT_DIRNAME}/first-dir/subdir/a,v <-- a
-new revision: 1\.2; previous revision: 1\.1
-done"
- fi
- dotest modules5-14 "echo yes | ${testcvs} release -d realmodule" \
-"You have \[0\] altered files in this repository\.
-Are you sure you want to release (and delete) directory .realmodule.: "
- dotest modules5-15 "${testcvs} -q rtag -Dnow MYTAG realmodule" \
-"tag script invoked in ${TESTDIR}/1
-args: realmodule MYTAG" \
-"tag script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: realmodule MYTAG"
- if $remote; then
- dotest modules5-16 "${testcvs} -q export -r MYTAG realmodule" \
-"U realmodule/a
-export script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: realmodule"
- else
- dotest modules5-16 "${testcvs} -q export -r MYTAG realmodule" \
-"U realmodule/a
-export script invoked in ${TESTDIR}/1
-args: realmodule"
- fi
- rm -r realmodule
-
- dotest_fail modules5-17 "${testcvs} co realmodule/a" \
-"${PROG}"' checkout: module `realmodule/a'\'' is a request for a file in a module which is not a directory' \
-"${PROG}"' server: module `realmodule/a'\'' is a request for a file in a module which is not a directory
-'"${PROG}"' \[checkout aborted\]: cannot expand modules'
-
- # Now test the ability to check out a single file from a directory
- if $remote; then
- dotest modules5-18 "${testcvs} co dirmodule/a" \
-"U dirmodule/a
-${PROG} checkout: Executing ..${CVSROOT_DIRNAME}/checkout\.sh. .dirmodule..
-checkout script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: dirmodule"
- else
- dotest modules5-18 "${testcvs} co dirmodule/a" \
-"U dirmodule/a
-${PROG} checkout: Executing ..${CVSROOT_DIRNAME}/checkout\.sh. .dirmodule..
-checkout script invoked in ${TESTDIR}/1
-args: dirmodule"
- fi
- dotest modules5-19 "test -d dirmodule && test -f dirmodule/a" ""
- dotest_fail modules5-20 "test -f dirmodule/b" ""
- dotest modules5-21 "echo yes | ${testcvs} release -d dirmodule" \
-"You have \[0\] altered files in this repository\.
-Are you sure you want to release (and delete) directory .dirmodule.: "
-
- # Now test the ability to correctly reject a non-existent filename.
- # For maximum studliness we would check that an error message is
- # being output.
- # We accept a zero exit status because it is what CVS does
- # (Dec 95). Probably the exit status should be nonzero,
- # however.
- if $remote; then
- dotest modules5-22 "${testcvs} co dirmodule/nonexist" \
-"${PROG} checkout: warning: new-born dirmodule/nonexist has disappeared
-${PROG} checkout: Executing ..${CVSROOT_DIRNAME}/checkout\.sh. .dirmodule..
-checkout script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: dirmodule"
- else
- dotest modules5-22 "${testcvs} co dirmodule/nonexist" \
-"${PROG} checkout: warning: new-born dirmodule/nonexist has disappeared
-${PROG} checkout: Executing ..${CVSROOT_DIRNAME}/checkout\.sh. .dirmodule..
-checkout script invoked in ${TESTDIR}/1
-args: dirmodule"
- fi
- # We tolerate the creation of the dirmodule directory, since that
- # is what CVS does, not because we view that as preferable to not
- # creating it.
- dotest_fail modules5-23 "test -f dirmodule/a || test -f dirmodule/b" ""
- rm -r dirmodule
-
- # Now test that a module using -d checks out to the specified
- # directory.
- if $remote; then
- dotest modules5-24 "${testcvs} -q co namedmodule" \
-"U nameddir/a
-U nameddir/b
-checkout script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: nameddir"
- else
- dotest modules5-24 "${testcvs} -q co namedmodule" \
-"U nameddir/a
-U nameddir/b
-checkout script invoked in ${TESTDIR}/1
-args: nameddir"
- fi
- dotest modules5-25 "test -f nameddir/a && test -f nameddir/b" ""
- echo add line >>nameddir/a
- # This seems suspicious: when we checkout an existing directory,
- # the checkout script gets executed in addition to the update
- # script. Is that by design or accident?
- if $remote; then
- dotest modules5-26 "${testcvs} -q co namedmodule" \
-"M nameddir/a
-checkout script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: nameddir"
- else
- dotest modules5-26 "${testcvs} -q co namedmodule" \
-"M nameddir/a
-checkout script invoked in ${TESTDIR}/1
-args: nameddir"
- fi
- rm nameddir/a
-
- if $remote; then
- dotest modules5-27 "${testcvs} -q co namedmodule" \
-"U nameddir/a
-checkout script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: nameddir"
- else
- dotest modules5-27 "${testcvs} -q co namedmodule" \
-"U nameddir/a
-checkout script invoked in ${TESTDIR}/1
-args: nameddir"
- fi
- dotest modules5-28 "echo yes | ${testcvs} release -d nameddir" \
-"You have \[0\] altered files in this repository\.
-Are you sure you want to release (and delete) directory .nameddir.: "
-
- # Now try the same tests with -d on command line
- # FIXCVS? The manual says the modules programs get the module name,
- # but they really get the directory name.
- if $remote; then
- dotest modules5-29 "${testcvs} co -d mydir realmodule" \
-"U mydir/a
-${PROG} checkout: Executing ..${CVSROOT_DIRNAME}/checkout\.sh. .mydir..
-checkout script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: mydir"
- else
- dotest modules5-29 "${testcvs} co -d mydir realmodule" \
-"U mydir/a
-${PROG} checkout: Executing ..${CVSROOT_DIRNAME}/checkout\.sh. .mydir..
-checkout script invoked in ${TESTDIR}/1
-args: mydir"
- fi
- dotest modules5-30 "test -d mydir && test -f mydir/a" ""
- dotest_fail modules5-31 "test -d realmodule || test -f mydir/b" ""
- if $remote; then
- dotest modules5-32 "${testcvs} -q co -d mydir realmodule" \
-"checkout script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: mydir"
- dotest modules5-33 "${testcvs} -q update" ''
- echo "change" >>mydir/a
- dotest modules5-34 "${testcvs} -q ci -m." \
-"Checking in mydir/a;
-${CVSROOT_DIRNAME}/first-dir/subdir/a,v <-- a
-new revision: 1\.3; previous revision: 1\.2
-done"
- else
- dotest modules5-32 "${testcvs} -q co -d mydir realmodule" \
-"checkout script invoked in ${TESTDIR}/1
-args: mydir"
- dotest modules5-33 "${testcvs} -q update" ''
- echo "change" >>mydir/a
- dotest modules5-34 "${testcvs} -q ci -m." \
-"Checking in mydir/a;
-${CVSROOT_DIRNAME}/first-dir/subdir/a,v <-- a
-new revision: 1\.3; previous revision: 1\.2
-done"
- fi
- dotest modules5-35 "echo yes | ${testcvs} release -d mydir" \
-"You have \[0\] altered files in this repository\.
-Are you sure you want to release (and delete) directory .mydir.: "
- if $remote; then
- dotest modules5-36 "${testcvs} -q rtag -Dnow MYTAG2 realmodule" \
-"tag script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: realmodule MYTAG2"
- dotest modules5-37 "${testcvs} -q export -r MYTAG2 -d mydir realmodule" \
-"U mydir/a
-export script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: mydir"
- else
- dotest modules5-36 "${testcvs} -q rtag -Dnow MYTAG2 realmodule" \
-"tag script invoked in ${TESTDIR}/1
-args: realmodule MYTAG2"
- dotest modules5-37 "${testcvs} -q export -r MYTAG2 -d mydir realmodule" \
-"U mydir/a
-export script invoked in ${TESTDIR}/1
-args: mydir"
- fi
- rm -r mydir
-
- # Now test the ability to check out a single file from a directory
- if $remote; then
- dotest modules5-38 "${testcvs} co -d mydir dirmodule/a" \
-"U mydir/a
-${PROG} checkout: Executing ..${CVSROOT_DIRNAME}/checkout\.sh. .mydir..
-checkout script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: mydir"
- else
- dotest modules5-38 "${testcvs} co -d mydir dirmodule/a" \
-"U mydir/a
-${PROG} checkout: Executing ..${CVSROOT_DIRNAME}/checkout\.sh. .mydir..
-checkout script invoked in ${TESTDIR}/1
-args: mydir"
- fi
- dotest modules5-39 "test -d mydir && test -f mydir/a" ""
- dotest_fail modules5-40 "test -d dirmodule || test -f mydir/b" ""
- dotest modules5-41 "echo yes | ${testcvs} release -d mydir" \
-"You have \[0\] altered files in this repository\.
-Are you sure you want to release (and delete) directory .mydir.: "
-
- # Now test the ability to correctly reject a non-existent filename.
- # For maximum studliness we would check that an error message is
- # being output.
- # We accept a zero exit status because it is what CVS does
- # (Dec 95). Probably the exit status should be nonzero,
- # however.
- if $remote; then
- dotest modules5-42 "${testcvs} co -d mydir dirmodule/nonexist" \
-"${PROG} checkout: warning: new-born mydir/nonexist has disappeared
-${PROG} checkout: Executing ..${CVSROOT_DIRNAME}/checkout\.sh. .mydir..
-checkout script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: mydir"
- else
- dotest modules5-42 "${testcvs} co -d mydir dirmodule/nonexist" \
-"${PROG} checkout: warning: new-born mydir/nonexist has disappeared
-${PROG} checkout: Executing ..${CVSROOT_DIRNAME}/checkout\.sh. .mydir..
-checkout script invoked in ${TESTDIR}/1
-args: mydir"
- fi
- # We tolerate the creation of the mydir directory, since that
- # is what CVS does, not because we view that as preferable to not
- # creating it.
- dotest_fail modules5-43 "test -f mydir/a || test -f mydir/b" ""
- rm -r mydir
-
- if $remote; then
- dotest modules5-44 "${testcvs} -q co -d mydir namedmodule" \
-"U mydir/a
-U mydir/b
-checkout script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: mydir"
- else
- dotest modules5-44 "${testcvs} -q co -d mydir namedmodule" \
-"U mydir/a
-U mydir/b
-checkout script invoked in ${TESTDIR}/1
-args: mydir"
- fi
- dotest modules5-45 "test -f mydir/a && test -f mydir/b" ""
- dotest_fail modules5-46 "test -d namedir"
- echo add line >>mydir/a
- # This seems suspicious: when we checkout an existing directory,
- # the checkout script gets executed in addition to the update
- # script. Is that by design or accident?
- if $remote; then
- dotest modules5-47 "${testcvs} -q co -d mydir namedmodule" \
-"M mydir/a
-checkout script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: mydir"
- else
- dotest modules5-47 "${testcvs} -q co -d mydir namedmodule" \
-"M mydir/a
-checkout script invoked in ${TESTDIR}/1
-args: mydir"
- fi
- rm mydir/a
-
- if $remote; then
- dotest modules5-48 "${testcvs} -q co -d mydir namedmodule" \
-"U mydir/a
-checkout script invoked in ${TMPDIR}/cvs-serv[0-9a-z]*
-args: mydir"
- else
- dotest modules5-48 "${testcvs} -q co -d mydir namedmodule" \
-"U mydir/a
-checkout script invoked in ${TESTDIR}/1
-args: mydir"
- fi
- dotest modules5-49 "echo yes | ${testcvs} release -d mydir" \
-"You have \[0\] altered files in this repository\.
-Are you sure you want to release (and delete) directory .mydir.: "
-
- cd ..
- rm -rf 1 ${CVSROOT_DIRNAME}/first-dir ${CVSROOT_DIRNAME}/*.sh
- ;;
-
- modules6)
- #
- # Test invalid module definitions
- #
- # See the header comment for the `modules' test for an index of
- # the complete suite of modules tests.
- #
-
- #
- # There was a bug in CVS through 1.11.1p1 where a bad module name
- # would cause the previous line to be parsed as the module
- # definition. This test proves this doesn't happen anymore.
- #
- mkdir modules6
- cd modules6
- dotest module6-setup-1 "${testcvs} -Q co CVSROOT" ""
- cd CVSROOT
- echo "longmodulename who cares" >modules
- echo "badname" >>modules
- # This test almost isn't setup since it generates the error message
- # we are looking for if `-Q' isn't specified, but I want to test the
- # filename in the message later.
- dotest modules6-setup-2 "${testcvs} -Q ci -mbad-modules" \
-"Checking in modules;
-${CVSROOT_DIRNAME}/CVSROOT/modules,v <-- modules
-new revision: [0-9.]*; previous revision: [0-9.]*
-done
-${PROG} commit: Rebuilding administrative file database"
-
- # Here's where CVS would report not being able to find `lename'
- cd ..
- dotest_fail modules6-1 "${testcvs} -q co badname" \
-"${PROG} checkout: warning: NULL value for key .badname. at line 2 of .${CVSROOT_DIRNAME}/CVSROOT/modules.
-${PROG} checkout: cannot find module .badname. - ignored" \
-"${PROG} server: warning: NULL value for key .badname. at line 2 of .${CVSROOT_DIRNAME}/CVSROOT/modules.
-${PROG} server: cannot find module .badname. - ignored
-${PROG} \[checkout aborted\]: cannot expand modules"
-
- # cleanup
- cd CVSROOT
- echo "# empty modules file" >modules
- dotest modules6-cleanup-1 "${testcvs} -Q ci -mempty-modules" \
-"Checking in modules;
-${CVSROOT_DIRNAME}/CVSROOT/modules,v <-- modules
-new revision: [0-9.]*; previous revision: [0-9.]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ../..
-
- if $keep; then :; else
- rm -r modules6
- fi
- ;;
-
-
-
- modules7)
- #
- # Test tag problems vs an empty CVSROOT/val-tags file
- #
- # See the header comment for the `modules' test for an index of
- # the complete suite of modules tests.
- #
- mkdir modules7
- cd modules7
- dotest modules7-1 "$testcvs -Q co -d top ."
- cd top
- mkdir zero one
- dotest modules7-2 "$testcvs -Q add zero one"
- cd one
- echo 'file1 contents' > file1
- dotest modules7-2 "$testcvs -Q add file1"
- dotest modules7-3 "$testcvs -Q ci -mnew file1" \
-"RCS file: $CVSROOT_DIRNAME/one/file1,v
-done
-Checking in file1;
-$CVSROOT_DIRNAME/one/file1,v <-- file1
-initial revision: 1\.1
-done"
- dotest modules7-4 "$testcvs -Q tag mytag file1"
- cd ../CVSROOT
- echo 'all -a zero one' > modules
- dotest modules7-5 "$testcvs -Q ci -mall-module" \
-"Checking in modules;
-$CVSROOT_DIRNAME/CVSROOT/modules,v <-- modules
-new revision: [0-9.]*; previous revision: [0-9.]*
-done
-$PROG commit: Rebuilding administrative file database"
- cd ../..
- mkdir myexport
- cd myexport
- # FIXCVS: The export should NOT be aborted here
- dotest_fail modules7-6 "$testcvs export -rmytag all" \
-"$PROG \[export aborted\]: no such tag mytag"
- cd ..
- rm -fr myexport
- mkdir myexport
- cd myexport
- # FIXCVS: Workaround is to have mytag listed in val-tags
- echo 'mytag y' > $CVSROOT_DIRNAME/CVSROOT/val-tags
- dotest modules7-7 "$testcvs export -rmytag all" \
-"$PROG export: Updating zero
-$PROG export: Updating one
-U one/file1"
- dotest modules7-8 'cat one/file1' 'file1 contents'
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- # cleanup
- cd ../top/CVSROOT
- echo "# empty modules file" >modules
- dotest modules7-cleanup-1 "$testcvs -Q ci -mempty-modules" \
-"Checking in modules;
-$CVSROOT_DIRNAME/CVSROOT/modules,v <-- modules
-new revision: [0-9.]*; previous revision: [0-9.]*
-done
-$PROG commit: Rebuilding administrative file database"
- cd ../../..
- rm -fr modules7
- rm -rf $CVSROOT_DIRNAME/zero $CVSROOT_DIRNAME/one
- ;;
-
-
- mkmodules)
- # 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 mkmodules-temp-file-removal-1 "${testcvs} -Q co CVSROOT" ''
- cd CVSROOT
- echo no-such-file >> checkoutlist
- dotest mkmodules-temp-file-removal-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} commit: Rebuilding administrative file database"
-
- dotest mkmodules-temp-file-removal-3 "echo $CVSROOT_DIRNAME/CVSROOT/.#[0-9]*" \
- "$CVSROOT_DIRNAME/CVSROOT/\.#\[0-9\]\*"
-
- # Versions 1.11.6 & 1.12.1 and earlier of CVS printed most of the
- # white space included before error messages in checkoutlist.
- echo "no-such-file Failed to update no-such-file." >checkoutlist
- dotest mkmodules-error-message-1 "${testcvs} -Q ci -m. checkoutlist" \
-"Checking in checkoutlist;
-$CVSROOT_DIRNAME/CVSROOT/checkoutlist,v <-- checkoutlist
-new revision: 1\.3; previous revision: 1\.2
-done
-${PROG} commit: Rebuilding administrative file database
-${PROG} commit: Failed to update no-such-file\."
-
- # Versions 1.11.6 & 1.12.1 and earlier of CVS used the error string
- # from the checkoutlist file as the format string passed to error()'s
- # printf. Check that this is no longer the case by verifying that
- # printf format patterns remain unchanged.
- echo "no-such-file Failed to update %s %lx times because %s happened %d times." >checkoutlist
- dotest mkmodules-error-message-2 "${testcvs} -Q ci -m. checkoutlist" \
-"Checking in checkoutlist;
-$CVSROOT_DIRNAME/CVSROOT/checkoutlist,v <-- checkoutlist
-new revision: 1\.4; previous revision: 1\.3
-done
-${PROG} commit: Rebuilding administrative file database
-${PROG} commit: Failed to update %s %lx times because %s happened %d times\."
-
- dotest mkmodules-cleanup-1 "${testcvs} -Q up -pr1.1 checkoutlist >checkoutlist"
- dotest mkmodules-cleanup-2 "${testcvs} -Q ci -m. checkoutlist" \
-"Checking in checkoutlist;
-$CVSROOT_DIRNAME/CVSROOT/checkoutlist,v <-- checkoutlist
-new revision: 1\.5; previous revision: 1\.4
-done
-${PROG} commit: Rebuilding administrative file database"
-
- cd ../..
- rm -rf 1
- ;;
-
- co-d)
- # Some tests of various permutations of co-d when directories exist
- # and checkouts lengthen.
- #
- # Interestingly enough, these same tests pass when the directory
- # lengthening happens via the modules file. Go figure.
- module=co-d
- mkdir $module; cd $module
- mkdir top; cd top
- dotest co-d-init-1 "$testcvs -Q co -l ."
- mkdir $module
- dotest co-d-init-2 "$testcvs -Q add $module"
- cd $module
- echo content >file1
- echo different content >file2
- dotest co-d-init-3 "$testcvs -Q add file1 file2"
- dotest co-d-init-4 "$testcvs -Q ci -madd-em" \
-"RCS file: $CVSROOT_DIRNAME/co-d/file1,v
-done
-Checking in file1;
-$CVSROOT_DIRNAME/co-d/file1,v <-- file1
-initial revision: 1\.1
-done
-RCS file: $CVSROOT_DIRNAME/co-d/file2,v
-done
-Checking in file2;
-$CVSROOT_DIRNAME/co-d/file2,v <-- file2
-initial revision: 1\.1
-done"
- cd ../..
-
- mkdir 2; cd 2
- dotest co-d-1 "$testcvs -q co -d dir $module" \
-"U dir/file1
-U dir/file2"
- dotest co-d-1.2 "cat dir/CVS/Repository" "$module"
-
- # FIXCVS: This should work. Correct expected result:
- #
- #"U dir2/sdir/file1
- #U dir2/sdir/file2"
- dotest_fail co-d-2 "$testcvs -q co -d dir2/sdir $module" \
-"$PROG \[checkout aborted\]: could not change directory to requested checkout directory \`dir2': No such file or directory"
- # FIXCVS:
- # dotest co-d-2.2 "cat dir4/CVS/Repository" "CVSROOT/Emptydir"
- # dotest co-d-2.3 "cat dir5/CVS/Repository" "$module"
-
- mkdir dir3
- dotest co-d-3 "$testcvs -q co -d dir3 $module" \
-"U dir3/file1
-U dir3/file2"
- dotest co-d-3.2 "cat dir3/CVS/Repository" "$module"
-
- if $remote; then
- # FIXCVS: As for co-d-2.
- mkdir dir4
- dotest_fail co-d-4r "$testcvs -q co -d dir4/sdir $module" \
-"$PROG \[checkout aborted\]: could not change directory to requested checkout directory \`dir4': No such file or directory"
-
- # FIXCVS: As for co-d-2.
- mkdir dir5
- mkdir dir5/sdir
- dotest_fail co-d-5r "$testcvs -q co -d dir5/sdir $module" \
-"$PROG \[checkout aborted\]: could not change directory to requested checkout directory \`dir5': No such file or directory"
- else
- mkdir dir4
- dotest co-d-4 "$testcvs -q co -d dir4/sdir $module" \
-"U dir4/sdir/file1
-U dir4/sdir/file2"
- # CVS only creates administration directories for directories it
- # creates, and the last portion of the path passed to -d
- # regardless.
- dotest_fail co-d-4.2 "test -d dir4/CVS"
- dotest co-d-4.3 "cat dir4/sdir/CVS/Repository" "$module"
-
- mkdir dir5
- mkdir dir5/sdir
- dotest co-d-5 "$testcvs -q co -d dir5/sdir $module" \
-"U dir5/sdir/file1
-U dir5/sdir/file2"
- # CVS only creates administration directories for directories it
- # creates, and the last portion of the path passed to -d
- # regardless.
- dotest_fail co-d-5.2 "test -d dir5/CVS"
- dotest co-d-5.3 "cat dir5/sdir/CVS/Repository" "$module"
- fi
-
- # clean up
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- cd ../..
- rm -rf $CVSROOT_DIRNAME/$module
- rm -r $module
- ;;
-
- cvsadm)
- # These test check the content of CVS' administrative
- # files as they are checked out in various configurations.
- # (As a side note, I'm not using the "-q" flag in any of
- # this code, which should provide some extra checking for
- # those messages which don't seem to be checked thoroughly
- # anywhere else.) To do a thorough test, we need to make
- # a bunch of modules in various configurations.
- #
- # <1mod> is a directory at the top level of cvsroot
- # ``foo bar''
- # <2mod> is a directory at the second level of cvsroot
- # ``foo bar/baz''
- # <1d1mod> is a directory at the top level which is
- # checked out into another directory
- # ``foo -d bar baz''
- # <1d2mod> is a directory at the second level which is
- # checked out into another directory
- # ``foo -d bar baz/quux''
- # <2d1mod> is a directory at the top level which is
- # checked out into a directory that is two deep
- # ``foo -d bar/baz quux''
- # <2d2mod> is a directory at the second level which is
- # checked out into a directory that is two deep
- # ``foo -d bar/baz quux''
- #
- # The tests do each of these types separately and in twos.
- # We also repeat each test -d flag for 1-deep and 2-deep
- # directories.
- #
- # Each test should check the output for the Repository
- # file, since that is the one which varies depending on
- # the directory and how it was checked out.
- #
- # Yes, this is verbose, but at least it's very thorough.
-
- # convenience variables
- REP=${CVSROOT}
-
- # First, set TopLevelAdmin=yes so we're sure to get
- # top-level CVS directories.
- mkdir 1; cd 1
- dotest cvsadm-setup-1 "${testcvs} -q co CVSROOT/config" \
-"U CVSROOT/config"
- cd CVSROOT
- echo "TopLevelAdmin=yes" >config
- dotest cvsadm-setup-2 "${testcvs} -q ci -m yes-top-level" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ../..
- rm -r 1
-
- # Second, check out the modules file and edit it.
- mkdir 1; cd 1
- dotest cvsadm-1 "${testcvs} co CVSROOT/modules" \
-"U CVSROOT/modules"
-
- # Test CVS/Root once. Since there is only one part of
- # the code which writes CVS/Root files (Create_Admin),
- # there is no point in testing this every time.
- dotest cvsadm-1a "cat CVS/Root" ${REP}
- dotest cvsadm-1b "cat CVS/Repository" "\."
- dotest cvsadm-1c "cat CVSROOT/CVS/Root" ${REP}
- dotest cvsadm-1d "cat CVSROOT/CVS/Repository" "CVSROOT"
- # All of the defined module names begin with a number.
- # All of the top-level directory names begin with "dir".
- # All of the subdirectory names begin with "sub".
- # All of the top-level modules begin with "mod".
- echo "# Module defs for cvsadm tests" > CVSROOT/modules
- echo "1mod mod1" >> CVSROOT/modules
- echo "1mod-2 mod1-2" >> CVSROOT/modules
- echo "2mod mod2/sub2" >> CVSROOT/modules
- echo "2mod-2 mod2-2/sub2-2" >> CVSROOT/modules
- echo "1d1mod -d dir1d1 mod1" >> CVSROOT/modules
- echo "1d1mod-2 -d dir1d1-2 mod1-2" >> CVSROOT/modules
- echo "1d2mod -d dir1d2 mod2/sub2" >> CVSROOT/modules
- echo "1d2mod-2 -d dir1d2-2 mod2-2/sub2-2" >> CVSROOT/modules
- echo "2d1mod -d dir2d1/sub2d1 mod1" >> CVSROOT/modules
- echo "2d1mod-2 -d dir2d1-2/sub2d1-2 mod1-2" >> CVSROOT/modules
- echo "2d2mod -d dir2d2/sub2d2 mod2/sub2" >> CVSROOT/modules
- echo "2d2mod-2 -d dir2d2-2/sub2d2-2 mod2-2/sub2-2" >> CVSROOT/modules
- dotest cvsadm-1e "${testcvs} ci -m add-modules" \
-"${PROG} [a-z]*: Examining .
-${PROG} [a-z]*: Examining CVSROOT
-Checking in CVSROOT/modules;
-${CVSROOT_DIRNAME}/CVSROOT/modules,v <-- modules
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database" \
-"${PROG} commit: Examining .
-${PROG} commit: Examining CVSROOT"
- rm -rf CVS CVSROOT;
-
- # Create the various modules
- dotest cvsadm-2 "${testcvs} -q co -l ." ''
- mkdir mod1
- mkdir mod1-2
- mkdir mod2
- mkdir mod2/sub2
- mkdir mod2-2
- mkdir mod2-2/sub2-2
- dotest cvsadm-2a "${testcvs} add mod1 mod1-2 mod2 mod2/sub2 mod2-2 mod2-2/sub2-2" \
-"Directory ${CVSROOT_DIRNAME}/mod1 added to the repository
-Directory ${CVSROOT_DIRNAME}/mod1-2 added to the repository
-Directory ${CVSROOT_DIRNAME}/mod2 added to the repository
-Directory ${CVSROOT_DIRNAME}/mod2/sub2 added to the repository
-Directory ${CVSROOT_DIRNAME}/mod2-2 added to the repository
-Directory ${CVSROOT_DIRNAME}/mod2-2/sub2-2 added to the repository"
-
- # Populate the directories for the halibut
- echo "file1" > mod1/file1
- echo "file1-2" > mod1-2/file1-2
- echo "file2" > mod2/sub2/file2
- echo "file2-2" > mod2-2/sub2-2/file2-2
- dotest cvsadm-2aa "${testcvs} add mod1/file1 mod1-2/file1-2 mod2/sub2/file2 mod2-2/sub2-2/file2-2" \
-"${PROG} add: scheduling file .mod1/file1. for addition
-${PROG} add: scheduling file .mod1-2/file1-2. for addition
-${PROG} add: scheduling file .mod2/sub2/file2. for addition
-${PROG} add: scheduling file .mod2-2/sub2-2/file2-2. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
-
- dotest cvsadm-2b "${testcvs} ci -m yup mod1 mod1-2 mod2 mod2-2" \
-"${PROG} [a-z]*: Examining mod1
-${PROG} [a-z]*: Examining mod1-2
-${PROG} [a-z]*: Examining mod2
-${PROG} [a-z]*: Examining mod2/sub2
-${PROG} [a-z]*: Examining mod2-2
-${PROG} [a-z]*: Examining mod2-2/sub2-2
-RCS file: ${CVSROOT_DIRNAME}/mod1/file1,v
-done
-Checking in mod1/file1;
-${CVSROOT_DIRNAME}/mod1/file1,v <-- file1
-initial revision: 1.1
-done
-RCS file: ${CVSROOT_DIRNAME}/mod1-2/file1-2,v
-done
-Checking in mod1-2/file1-2;
-${CVSROOT_DIRNAME}/mod1-2/file1-2,v <-- file1-2
-initial revision: 1.1
-done
-RCS file: ${CVSROOT_DIRNAME}/mod2/sub2/file2,v
-done
-Checking in mod2/sub2/file2;
-${CVSROOT_DIRNAME}/mod2/sub2/file2,v <-- file2
-initial revision: 1.1
-done
-RCS file: ${CVSROOT_DIRNAME}/mod2-2/sub2-2/file2-2,v
-done
-Checking in mod2-2/sub2-2/file2-2;
-${CVSROOT_DIRNAME}/mod2-2/sub2-2/file2-2,v <-- file2-2
-initial revision: 1.1
-done"
- # Finished creating the modules -- clean up.
- rm -rf CVS mod1 mod1-2 mod2 mod2-2
- # Done.
-
- ##################################################
- ## Start the dizzying array of possibilities.
- ## Begin with each module type separately.
- ##################################################
-
- # Pattern -- after each checkout, first check the top-level
- # CVS directory. Then, check the directories in numerical
- # order.
-
- dotest cvsadm-3 "${testcvs} co 1mod" \
-"${PROG} checkout: Updating 1mod
-U 1mod/file1"
- dotest cvsadm-3b "cat CVS/Repository" "\."
- dotest cvsadm-3d "cat 1mod/CVS/Repository" "mod1"
- rm -rf CVS 1mod
-
- dotest cvsadm-4 "${testcvs} co 2mod" \
-"${PROG} checkout: Updating 2mod
-U 2mod/file2"
- dotest cvsadm-4b "cat CVS/Repository" "\."
- dotest cvsadm-4d "cat 2mod/CVS/Repository" "mod2/sub2"
- rm -rf CVS 2mod
-
- dotest cvsadm-5 "${testcvs} co 1d1mod" \
-"${PROG} checkout: Updating dir1d1
-U dir1d1/file1"
- dotest cvsadm-5b "cat CVS/Repository" "\."
- dotest cvsadm-5d "cat dir1d1/CVS/Repository" "mod1"
- rm -rf CVS dir1d1
-
- dotest cvsadm-6 "${testcvs} co 1d2mod" \
-"${PROG} checkout: Updating dir1d2
-U dir1d2/file2"
- dotest cvsadm-6b "cat CVS/Repository" "\."
- dotest cvsadm-6d "cat dir1d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir1d2
-
- dotest cvsadm-7 "${testcvs} co 2d1mod" \
-"${PROG} checkout: Updating dir2d1/sub2d1
-U dir2d1/sub2d1/file1"
- dotest cvsadm-7b "cat CVS/Repository" "\."
- dotest cvsadm-7d "cat dir2d1/CVS/Repository" "\."
- dotest cvsadm-7f "cat dir2d1/sub2d1/CVS/Repository" "mod1"
- rm -rf CVS dir2d1
-
- dotest cvsadm-8 "${testcvs} co 2d2mod" \
-"${PROG} checkout: Updating dir2d2/sub2d2
-U dir2d2/sub2d2/file2"
- dotest cvsadm-8b "cat CVS/Repository" "\."
- dotest cvsadm-8d "cat dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-8f "cat dir2d2/sub2d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir2d2
-
- ##################################################
- ## You are in a shell script of twisted little
- ## module combination statements, all alike.
- ##################################################
-
- ### 1mod
-
- dotest cvsadm-9 "${testcvs} co 1mod 1mod-2" \
-"${PROG} checkout: Updating 1mod
-U 1mod/file1
-${PROG} checkout: Updating 1mod-2
-U 1mod-2/file1-2"
- # the usual for the top level
- dotest cvsadm-9b "cat CVS/Repository" "\."
- # the usual for 1mod
- dotest cvsadm-9d "cat 1mod/CVS/Repository" "mod1"
- # the usual for 1mod copy
- dotest cvsadm-9f "cat 1mod-2/CVS/Repository" "mod1-2"
- rm -rf CVS 1mod 1mod-2
-
- # 1mod 2mod redmod bluemod
- dotest cvsadm-10 "${testcvs} co 1mod 2mod" \
-"${PROG} checkout: Updating 1mod
-U 1mod/file1
-${PROG} checkout: Updating 2mod
-U 2mod/file2"
- # the usual for the top level
- dotest cvsadm-10b "cat CVS/Repository" "\."
- # the usual for 1mod
- dotest cvsadm-10d "cat 1mod/CVS/Repository" "mod1"
- # the usual for 2dmod
- dotest cvsadm-10f "cat 2mod/CVS/Repository" "mod2/sub2"
- rm -rf CVS 1mod 2mod
-
- dotest cvsadm-11 "${testcvs} co 1mod 1d1mod" \
-"${PROG} checkout: Updating 1mod
-U 1mod/file1
-${PROG} checkout: Updating dir1d1
-U dir1d1/file1"
- # the usual for the top level
- dotest cvsadm-11b "cat CVS/Repository" "\."
- # the usual for 1mod
- dotest cvsadm-11d "cat 1mod/CVS/Repository" "mod1"
- # the usual for 1d1mod
- dotest cvsadm-11f "cat dir1d1/CVS/Repository" "mod1"
- rm -rf CVS 1mod dir1d1
-
- dotest cvsadm-12 "${testcvs} co 1mod 1d2mod" \
-"${PROG} checkout: Updating 1mod
-U 1mod/file1
-${PROG} checkout: Updating dir1d2
-U dir1d2/file2"
- # the usual for the top level
- dotest cvsadm-12b "cat CVS/Repository" "\."
- # the usual for 1mod
- dotest cvsadm-12d "cat 1mod/CVS/Repository" "mod1"
- # the usual for 1d2mod
- dotest cvsadm-12f "cat dir1d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS 1mod dir1d2
-
- dotest cvsadm-13 "${testcvs} co 1mod 2d1mod" \
-"${PROG} checkout: Updating 1mod
-U 1mod/file1
-${PROG} checkout: Updating dir2d1/sub2d1
-U dir2d1/sub2d1/file1"
- # the usual for the top level
- dotest cvsadm-13b "cat CVS/Repository" "\."
- # the usual for 1mod
- dotest cvsadm-13d "cat 1mod/CVS/Repository" "mod1"
- # the usual for 2d1mod
- dotest cvsadm-13f "cat dir2d1/CVS/Repository" "\."
- dotest cvsadm-13h "cat dir2d1/sub2d1/CVS/Repository" "mod1"
- rm -rf CVS 1mod dir2d1
-
- dotest cvsadm-14 "${testcvs} co 1mod 2d2mod" \
-"${PROG} checkout: Updating 1mod
-U 1mod/file1
-${PROG} checkout: Updating dir2d2/sub2d2
-U dir2d2/sub2d2/file2"
- # the usual for the top level
- dotest cvsadm-14b "cat CVS/Repository" "\."
- # the usual for 1mod
- dotest cvsadm-14d "cat 1mod/CVS/Repository" "mod1"
- # the usual for 2d2mod
- dotest cvsadm-14f "cat dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-14h "cat dir2d2/sub2d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS 1mod dir2d2
-
-
- ### 2mod
-
- dotest cvsadm-15 "${testcvs} co 2mod 2mod-2" \
-"${PROG} checkout: Updating 2mod
-U 2mod/file2
-${PROG} checkout: Updating 2mod-2
-U 2mod-2/file2-2"
- # the usual for the top level
- dotest cvsadm-15b "cat CVS/Repository" "\."
- # the usual for 2mod
- dotest cvsadm-15d "cat 2mod/CVS/Repository" "mod2/sub2"
- # the usual for 2mod copy
- dotest cvsadm-15f "cat 2mod-2/CVS/Repository" "mod2-2/sub2-2"
- rm -rf CVS 2mod 2mod-2
-
-
- dotest cvsadm-16 "${testcvs} co 2mod 1d1mod" \
-"${PROG} checkout: Updating 2mod
-U 2mod/file2
-${PROG} checkout: Updating dir1d1
-U dir1d1/file1"
- # the usual for the top level
- dotest cvsadm-16b "cat CVS/Repository" "\."
- # the usual for 2mod
- dotest cvsadm-16d "cat 2mod/CVS/Repository" "mod2/sub2"
- # the usual for 1d1mod
- dotest cvsadm-16f "cat dir1d1/CVS/Repository" "mod1"
- rm -rf CVS 2mod dir1d1
-
- dotest cvsadm-17 "${testcvs} co 2mod 1d2mod" \
-"${PROG} checkout: Updating 2mod
-U 2mod/file2
-${PROG} checkout: Updating dir1d2
-U dir1d2/file2"
- # the usual for the top level
- dotest cvsadm-17b "cat CVS/Repository" "\."
- # the usual for 2mod
- dotest cvsadm-17d "cat 2mod/CVS/Repository" "mod2/sub2"
- # the usual for 1d2mod
- dotest cvsadm-17f "cat dir1d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS 2mod dir1d2
-
- dotest cvsadm-18 "${testcvs} co 2mod 2d1mod" \
-"${PROG} checkout: Updating 2mod
-U 2mod/file2
-${PROG} checkout: Updating dir2d1/sub2d1
-U dir2d1/sub2d1/file1"
- # the usual for the top level
- dotest cvsadm-18b "cat CVS/Repository" "\."
- # the usual for 2mod
- dotest cvsadm-18d "cat 2mod/CVS/Repository" "mod2/sub2"
- # the usual for 2d1mod
- dotest cvsadm-18f "cat dir2d1/CVS/Repository" "\."
- dotest cvsadm-18h "cat dir2d1/sub2d1/CVS/Repository" "mod1"
- rm -rf CVS 2mod dir2d1
-
- dotest cvsadm-19 "${testcvs} co 2mod 2d2mod" \
-"${PROG} checkout: Updating 2mod
-U 2mod/file2
-${PROG} checkout: Updating dir2d2/sub2d2
-U dir2d2/sub2d2/file2"
- # the usual for the top level
- dotest cvsadm-19b "cat CVS/Repository" "\."
- # the usual for 2mod
- dotest cvsadm-19d "cat 2mod/CVS/Repository" "mod2/sub2"
- # the usual for 2d2mod
- dotest cvsadm-19f "cat dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-19h "cat dir2d2/sub2d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS 2mod dir2d2
-
-
- ### 1d1mod
-
- dotest cvsadm-20 "${testcvs} co 1d1mod 1d1mod-2" \
-"${PROG} checkout: Updating dir1d1
-U dir1d1/file1
-${PROG} checkout: Updating dir1d1-2
-U dir1d1-2/file1-2"
- # the usual for the top level
- dotest cvsadm-20b "cat CVS/Repository" "\."
- # the usual for 1d1mod
- dotest cvsadm-20d "cat dir1d1/CVS/Repository" "mod1"
- # the usual for 1d1mod copy
- dotest cvsadm-20f "cat dir1d1-2/CVS/Repository" "mod1-2"
- rm -rf CVS dir1d1 dir1d1-2
-
- dotest cvsadm-21 "${testcvs} co 1d1mod 1d2mod" \
-"${PROG} checkout: Updating dir1d1
-U dir1d1/file1
-${PROG} checkout: Updating dir1d2
-U dir1d2/file2"
- # the usual for the top level
- dotest cvsadm-21b "cat CVS/Repository" "\."
- # the usual for 1d1mod
- dotest cvsadm-21d "cat dir1d1/CVS/Repository" "mod1"
- # the usual for 1d2mod
- dotest cvsadm-21f "cat dir1d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir1d1 dir1d2
-
- dotest cvsadm-22 "${testcvs} co 1d1mod 2d1mod" \
-"${PROG} checkout: Updating dir1d1
-U dir1d1/file1
-${PROG} checkout: Updating dir2d1/sub2d1
-U dir2d1/sub2d1/file1"
- # the usual for the top level
- dotest cvsadm-22b "cat CVS/Repository" "\."
- # the usual for 1d1mod
- dotest cvsadm-22d "cat dir1d1/CVS/Repository" "mod1"
- # the usual for 2d1mod
- dotest cvsadm-22f "cat dir2d1/CVS/Repository" "\."
- dotest cvsadm-22h "cat dir2d1/sub2d1/CVS/Repository" "mod1"
- rm -rf CVS dir1d1 dir2d1
-
- dotest cvsadm-23 "${testcvs} co 1d1mod 2d2mod" \
-"${PROG} checkout: Updating dir1d1
-U dir1d1/file1
-${PROG} checkout: Updating dir2d2/sub2d2
-U dir2d2/sub2d2/file2"
- # the usual for the top level
- dotest cvsadm-23b "cat CVS/Repository" "\."
- # the usual for 1d1mod
- dotest cvsadm-23d "cat dir1d1/CVS/Repository" "mod1"
- # the usual for 2d2mod
- dotest cvsadm-23f "cat dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-23h "cat dir2d2/sub2d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir1d1 dir2d2
-
-
- ### 1d2mod
-
- dotest cvsadm-24 "${testcvs} co 1d2mod 1d2mod-2" \
-"${PROG} checkout: Updating dir1d2
-U dir1d2/file2
-${PROG} checkout: Updating dir1d2-2
-U dir1d2-2/file2-2"
- # the usual for the top level
- dotest cvsadm-24b "cat CVS/Repository" "\."
- # the usual for 1d2mod
- dotest cvsadm-24d "cat dir1d2/CVS/Repository" "mod2/sub2"
- # the usual for 1d2mod copy
- dotest cvsadm-24f "cat dir1d2-2/CVS/Repository" "mod2-2/sub2-2"
- rm -rf CVS dir1d2 dir1d2-2
-
- dotest cvsadm-25 "${testcvs} co 1d2mod 2d1mod" \
-"${PROG} checkout: Updating dir1d2
-U dir1d2/file2
-${PROG} checkout: Updating dir2d1/sub2d1
-U dir2d1/sub2d1/file1"
- # the usual for the top level
- dotest cvsadm-25b "cat CVS/Repository" "\."
- # the usual for 1d2mod
- dotest cvsadm-25d "cat dir1d2/CVS/Repository" "mod2/sub2"
- # the usual for 2d1mod
- dotest cvsadm-25f "cat dir2d1/CVS/Repository" "\."
- dotest cvsadm-25h "cat dir2d1/sub2d1/CVS/Repository" "mod1"
- rm -rf CVS dir1d2 dir2d1
-
- dotest cvsadm-26 "${testcvs} co 1d2mod 2d2mod" \
-"${PROG} checkout: Updating dir1d2
-U dir1d2/file2
-${PROG} checkout: Updating dir2d2/sub2d2
-U dir2d2/sub2d2/file2"
- # the usual for the top level
- dotest cvsadm-26b "cat CVS/Repository" "\."
- # the usual for 1d2mod
- dotest cvsadm-26d "cat dir1d2/CVS/Repository" "mod2/sub2"
- # the usual for 2d2mod
- dotest cvsadm-26f "cat dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-26h "cat dir2d2/sub2d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir1d2 dir2d2
-
-
- # 2d1mod
-
- dotest cvsadm-27 "${testcvs} co 2d1mod 2d1mod-2" \
-"${PROG} checkout: Updating dir2d1/sub2d1
-U dir2d1/sub2d1/file1
-${PROG} checkout: Updating dir2d1-2/sub2d1-2
-U dir2d1-2/sub2d1-2/file1-2"
- # the usual for the top level
- dotest cvsadm-27b "cat CVS/Repository" "\."
- # the usual for 2d1mod
- dotest cvsadm-27d "cat dir2d1/CVS/Repository" "\."
- dotest cvsadm-27f "cat dir2d1/sub2d1/CVS/Repository" "mod1"
- # the usual for 2d1mod
- dotest cvsadm-27h "cat dir2d1-2/CVS/Repository" "\."
- dotest cvsadm-27j "cat dir2d1-2/sub2d1-2/CVS/Repository" "mod1-2"
- rm -rf CVS dir2d1 dir2d1-2
-
- dotest cvsadm-28 "${testcvs} co 2d1mod 2d2mod" \
-"${PROG} checkout: Updating dir2d1/sub2d1
-U dir2d1/sub2d1/file1
-${PROG} checkout: Updating dir2d2/sub2d2
-U dir2d2/sub2d2/file2"
- # the usual for the top level
- dotest cvsadm-28b "cat CVS/Repository" "\."
- # the usual for 2d1mod
- dotest cvsadm-28d "cat dir2d1/CVS/Repository" "\."
- dotest cvsadm-28f "cat dir2d1/sub2d1/CVS/Repository" "mod1"
- # the usual for 2d2mod
- dotest cvsadm-28h "cat dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-28j "cat dir2d2/sub2d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir2d1 dir2d2
-
-
- # 2d2mod
-
- dotest cvsadm-29 "${testcvs} co 2d2mod 2d2mod-2" \
-"${PROG} checkout: Updating dir2d2/sub2d2
-U dir2d2/sub2d2/file2
-${PROG} checkout: Updating dir2d2-2/sub2d2-2
-U dir2d2-2/sub2d2-2/file2-2"
- # the usual for the top level
- dotest cvsadm-29b "cat CVS/Repository" "\."
- # the usual for 2d2mod
- dotest cvsadm-29d "cat dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-29f "cat dir2d2/sub2d2/CVS/Repository" "mod2/sub2"
- # the usual for 2d2mod
- dotest cvsadm-29h "cat dir2d2-2/CVS/Repository" "mod2-2"
- dotest cvsadm-29j "cat dir2d2-2/sub2d2-2/CVS/Repository" \
-"mod2-2/sub2-2"
- rm -rf CVS dir2d2 dir2d2-2
-
- ##################################################
- ## And now, all of that again using the "-d" flag
- ## on the command line.
- ##################################################
-
- dotest cvsadm-1d3 "${testcvs} co -d dir 1mod" \
-"${PROG} checkout: Updating dir
-U dir/file1"
- dotest cvsadm-1d3b "cat CVS/Repository" "\."
- dotest cvsadm-1d3d "cat dir/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- dotest cvsadm-1d4 "${testcvs} co -d dir 2mod" \
-"${PROG} checkout: Updating dir
-U dir/file2"
- dotest cvsadm-1d4b "cat CVS/Repository" "\."
- dotest cvsadm-1d4d "cat dir/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
- dotest cvsadm-1d5 "${testcvs} co -d dir 1d1mod" \
-"${PROG} checkout: Updating dir
-U dir/file1"
- dotest cvsadm-1d5b "cat CVS/Repository" "\."
- dotest cvsadm-1d5d "cat dir/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- dotest cvsadm-1d6 "${testcvs} co -d dir 1d2mod" \
-"${PROG} checkout: Updating dir
-U dir/file2"
- dotest cvsadm-1d6b "cat CVS/Repository" "\."
- dotest cvsadm-1d6d "cat dir/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
- dotest cvsadm-1d7 "${testcvs} co -d dir 2d1mod" \
-"${PROG} checkout: Updating dir
-U dir/file1"
- dotest cvsadm-1d7b "cat CVS/Repository" "\."
- dotest cvsadm-1d7d "cat dir/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- dotest cvsadm-1d8 "${testcvs} co -d dir 2d2mod" \
-"${PROG} checkout: Updating dir
-U dir/file2"
- dotest cvsadm-1d8b "cat CVS/Repository" "\."
- dotest cvsadm-1d8d "cat dir/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
- ##################################################
- ## Los Combonaciones
- ##################################################
-
- ### 1mod
-
- dotest cvsadm-1d9 "${testcvs} co -d dir 1mod 1mod-2" \
-"${PROG} checkout: Updating dir/1mod
-U dir/1mod/file1
-${PROG} checkout: Updating dir/1mod-2
-U dir/1mod-2/file1-2"
- # the usual for the top level
- dotest cvsadm-1d9b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d9d "cat dir/CVS/Repository" "\."
- # the usual for 1mod
- dotest cvsadm-1d9f "cat dir/1mod/CVS/Repository" "mod1"
- # the usual for 1mod copy
- dotest cvsadm-1d9h "cat dir/1mod-2/CVS/Repository" "mod1-2"
- rm -rf CVS dir
-
- # 1mod 2mod redmod bluemod
- dotest cvsadm-1d10 "${testcvs} co -d dir 1mod 2mod" \
-"${PROG} checkout: Updating dir/1mod
-U dir/1mod/file1
-${PROG} checkout: Updating dir/2mod
-U dir/2mod/file2"
- dotest cvsadm-1d10b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d10d "cat dir/CVS/Repository" "\."
- # the usual for 1mod
- dotest cvsadm-1d10f "cat dir/1mod/CVS/Repository" "mod1"
- # the usual for 2dmod
- dotest cvsadm-1d10h "cat dir/2mod/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
- dotest cvsadm-1d11 "${testcvs} co -d dir 1mod 1d1mod" \
-"${PROG} checkout: Updating dir/1mod
-U dir/1mod/file1
-${PROG} checkout: Updating dir/dir1d1
-U dir/dir1d1/file1"
- dotest cvsadm-1d11b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d11d "cat dir/CVS/Repository" "\."
- # the usual for 1mod
- dotest cvsadm-1d11f "cat dir/1mod/CVS/Repository" "mod1"
- # the usual for 1d1mod
- dotest cvsadm-1d11h "cat dir/dir1d1/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- dotest cvsadm-1d12 "${testcvs} co -d dir 1mod 1d2mod" \
-"${PROG} checkout: Updating dir/1mod
-U dir/1mod/file1
-${PROG} checkout: Updating dir/dir1d2
-U dir/dir1d2/file2"
- dotest cvsadm-1d12b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d12d "cat dir/CVS/Repository" "\."
- # the usual for 1mod
- dotest cvsadm-1d12f "cat dir/1mod/CVS/Repository" "mod1"
- # the usual for 1d2mod
- dotest cvsadm-1d12h "cat dir/dir1d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
- dotest cvsadm-1d13 "${testcvs} co -d dir 1mod 2d1mod" \
-"${PROG} checkout: Updating dir/1mod
-U dir/1mod/file1
-${PROG} checkout: Updating dir/dir2d1/sub2d1
-U dir/dir2d1/sub2d1/file1"
- dotest cvsadm-1d13b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d13d "cat dir/CVS/Repository" "\."
- # the usual for 1mod
- dotest cvsadm-1d13f "cat dir/1mod/CVS/Repository" "mod1"
- # the usual for 2d1mod
- dotest cvsadm-1d13h "cat dir/dir2d1/CVS/Repository" "\."
- dotest cvsadm-1d13j "cat dir/dir2d1/sub2d1/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- dotest cvsadm-1d14 "${testcvs} co -d dir 1mod 2d2mod" \
-"${PROG} checkout: Updating dir/1mod
-U dir/1mod/file1
-${PROG} checkout: Updating dir/dir2d2/sub2d2
-U dir/dir2d2/sub2d2/file2"
- dotest cvsadm-1d14b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d14d "cat dir/CVS/Repository" "\."
- # the usual for 1mod
- dotest cvsadm-1d14f "cat dir/1mod/CVS/Repository" "mod1"
- # the usual for 2d2mod
- dotest cvsadm-1d14h "cat dir/dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-1d14j "cat dir/dir2d2/sub2d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
-
- ### 2mod
-
- dotest cvsadm-1d15 "${testcvs} co -d dir 2mod 2mod-2" \
-"${PROG} checkout: Updating dir/2mod
-U dir/2mod/file2
-${PROG} checkout: Updating dir/2mod-2
-U dir/2mod-2/file2-2"
- dotest cvsadm-1d15b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d15d "cat dir/CVS/Repository" "mod2"
- # the usual for 2mod
- dotest cvsadm-1d15f "cat dir/2mod/CVS/Repository" "mod2/sub2"
- # the usual for 2mod copy
- dotest cvsadm-1d15h "cat dir/2mod-2/CVS/Repository" "mod2-2/sub2-2"
- rm -rf CVS dir
-
- dotest cvsadm-1d16 "${testcvs} co -d dir 2mod 1d1mod" \
-"${PROG} checkout: Updating dir/2mod
-U dir/2mod/file2
-${PROG} checkout: Updating dir/dir1d1
-U dir/dir1d1/file1"
- dotest cvsadm-1d16b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d16d "cat dir/CVS/Repository" "mod2"
- # the usual for 2mod
- dotest cvsadm-1d16f "cat dir/2mod/CVS/Repository" "mod2/sub2"
- # the usual for 1d1mod
- dotest cvsadm-1d16h "cat dir/dir1d1/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- dotest cvsadm-1d17 "${testcvs} co -d dir 2mod 1d2mod" \
-"${PROG} checkout: Updating dir/2mod
-U dir/2mod/file2
-${PROG} checkout: Updating dir/dir1d2
-U dir/dir1d2/file2"
- dotest cvsadm-1d17b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d17d "cat dir/CVS/Repository" "mod2"
- # the usual for 2mod
- dotest cvsadm-1d17f "cat dir/2mod/CVS/Repository" "mod2/sub2"
- # the usual for 1d2mod
- dotest cvsadm-1d17h "cat dir/dir1d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
- dotest cvsadm-1d18 "${testcvs} co -d dir 2mod 2d1mod" \
-"${PROG} checkout: Updating dir/2mod
-U dir/2mod/file2
-${PROG} checkout: Updating dir/dir2d1/sub2d1
-U dir/dir2d1/sub2d1/file1"
- dotest cvsadm-1d18b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d18d "cat dir/CVS/Repository" "mod2"
- # the usual for 2mod
- dotest cvsadm-1d18f "cat dir/2mod/CVS/Repository" "mod2/sub2"
- # the usual for 2d1mod
- dotest cvsadm-1d18h "cat dir/dir2d1/CVS/Repository" "\."
- dotest cvsadm-1d18j "cat dir/dir2d1/sub2d1/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- dotest cvsadm-1d19 "${testcvs} co -d dir 2mod 2d2mod" \
-"${PROG} checkout: Updating dir/2mod
-U dir/2mod/file2
-${PROG} checkout: Updating dir/dir2d2/sub2d2
-U dir/dir2d2/sub2d2/file2"
- dotest cvsadm-1d19b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d19d "cat dir/CVS/Repository" "mod2"
- # the usual for 2mod
- dotest cvsadm-1d19f "cat dir/2mod/CVS/Repository" "mod2/sub2"
- # the usual for 2d2mod
- dotest cvsadm-1d19h "cat dir/dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-1d19j "cat dir/dir2d2/sub2d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
-
- ### 1d1mod
-
- dotest cvsadm-1d20 "${testcvs} co -d dir 1d1mod 1d1mod-2" \
-"${PROG} checkout: Updating dir/dir1d1
-U dir/dir1d1/file1
-${PROG} checkout: Updating dir/dir1d1-2
-U dir/dir1d1-2/file1-2"
- dotest cvsadm-1d20b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d20d "cat dir/CVS/Repository" "\."
- # the usual for 1d1mod
- dotest cvsadm-1d20f "cat dir/dir1d1/CVS/Repository" "mod1"
- # the usual for 1d1mod copy
- dotest cvsadm-1d20h "cat dir/dir1d1-2/CVS/Repository" "mod1-2"
- rm -rf CVS dir
-
- dotest cvsadm-1d21 "${testcvs} co -d dir 1d1mod 1d2mod" \
-"${PROG} checkout: Updating dir/dir1d1
-U dir/dir1d1/file1
-${PROG} checkout: Updating dir/dir1d2
-U dir/dir1d2/file2"
- dotest cvsadm-1d21b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d21d "cat dir/CVS/Repository" "\."
- # the usual for 1d1mod
- dotest cvsadm-1d21f "cat dir/dir1d1/CVS/Repository" "mod1"
- # the usual for 1d2mod
- dotest cvsadm-1d21h "cat dir/dir1d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
- dotest cvsadm-1d22 "${testcvs} co -d dir 1d1mod 2d1mod" \
-"${PROG} checkout: Updating dir/dir1d1
-U dir/dir1d1/file1
-${PROG} checkout: Updating dir/dir2d1/sub2d1
-U dir/dir2d1/sub2d1/file1"
- dotest cvsadm-1d22b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d22d "cat dir/CVS/Repository" "\."
- # the usual for 1d1mod
- dotest cvsadm-1d22f "cat dir/dir1d1/CVS/Repository" "mod1"
- # the usual for 2d1mod
- dotest cvsadm-1d22h "cat dir/dir2d1/CVS/Repository" "\."
- dotest cvsadm-1d22j "cat dir/dir2d1/sub2d1/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- dotest cvsadm-1d23 "${testcvs} co -d dir 1d1mod 2d2mod" \
-"${PROG} checkout: Updating dir/dir1d1
-U dir/dir1d1/file1
-${PROG} checkout: Updating dir/dir2d2/sub2d2
-U dir/dir2d2/sub2d2/file2"
- dotest cvsadm-1d23b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d23d "cat dir/CVS/Repository" "\."
- # the usual for 1d1mod
- dotest cvsadm-1d23f "cat dir/dir1d1/CVS/Repository" "mod1"
- # the usual for 2d2mod
- dotest cvsadm-1d23h "cat dir/dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-1d23j "cat dir/dir2d2/sub2d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
-
- ### 1d2mod
-
- dotest cvsadm-1d24 "${testcvs} co -d dir 1d2mod 1d2mod-2" \
-"${PROG} checkout: Updating dir/dir1d2
-U dir/dir1d2/file2
-${PROG} checkout: Updating dir/dir1d2-2
-U dir/dir1d2-2/file2-2"
- dotest cvsadm-1d24b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d24d "cat dir/CVS/Repository" "mod2"
- # the usual for 1d2mod
- dotest cvsadm-1d24f "cat dir/dir1d2/CVS/Repository" "mod2/sub2"
- # the usual for 1d2mod copy
- dotest cvsadm-1d24h "cat dir/dir1d2-2/CVS/Repository" "mod2-2/sub2-2"
- rm -rf CVS dir
-
- dotest cvsadm-1d25 "${testcvs} co -d dir 1d2mod 2d1mod" \
-"${PROG} checkout: Updating dir/dir1d2
-U dir/dir1d2/file2
-${PROG} checkout: Updating dir/dir2d1/sub2d1
-U dir/dir2d1/sub2d1/file1"
- dotest cvsadm-1d25b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d25d "cat dir/CVS/Repository" "mod2"
- # the usual for 1d2mod
- dotest cvsadm-1d25f "cat dir/dir1d2/CVS/Repository" "mod2/sub2"
- # the usual for 2d1mod
- dotest cvsadm-1d25h "cat dir/dir2d1/CVS/Repository" "\."
- dotest cvsadm-1d25j "cat dir/dir2d1/sub2d1/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- dotest cvsadm-1d26 "${testcvs} co -d dir 1d2mod 2d2mod" \
-"${PROG} checkout: Updating dir/dir1d2
-U dir/dir1d2/file2
-${PROG} checkout: Updating dir/dir2d2/sub2d2
-U dir/dir2d2/sub2d2/file2"
- dotest cvsadm-1d26b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d26d "cat dir/CVS/Repository" "mod2"
- # the usual for 1d2mod
- dotest cvsadm-1d26f "cat dir/dir1d2/CVS/Repository" "mod2/sub2"
- # the usual for 2d2mod
- dotest cvsadm-1d26h "cat dir/dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-1d26j "cat dir/dir2d2/sub2d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
-
- # 2d1mod
-
- dotest cvsadm-1d27 "${testcvs} co -d dir 2d1mod 2d1mod-2" \
-"${PROG} checkout: Updating dir/dir2d1/sub2d1
-U dir/dir2d1/sub2d1/file1
-${PROG} checkout: Updating dir/dir2d1-2/sub2d1-2
-U dir/dir2d1-2/sub2d1-2/file1-2"
- dotest cvsadm-1d27b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d27d "cat dir/CVS/Repository" "CVSROOT/Emptydir"
- # the usual for 2d1mod
- dotest cvsadm-1d27f "cat dir/dir2d1/CVS/Repository" "\."
- dotest cvsadm-1d27h "cat dir/dir2d1/sub2d1/CVS/Repository" "mod1"
- # the usual for 2d1mod
- dotest cvsadm-1d27j "cat dir/dir2d1-2/CVS/Repository" "\."
- dotest cvsadm-1d27l "cat dir/dir2d1-2/sub2d1-2/CVS/Repository" \
-"mod1-2"
- rm -rf CVS dir
-
- dotest cvsadm-1d28 "${testcvs} co -d dir 2d1mod 2d2mod" \
-"${PROG} checkout: Updating dir/dir2d1/sub2d1
-U dir/dir2d1/sub2d1/file1
-${PROG} checkout: Updating dir/dir2d2/sub2d2
-U dir/dir2d2/sub2d2/file2"
- dotest cvsadm-1d28b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d28d "cat dir/CVS/Repository" "CVSROOT/Emptydir"
- # the usual for 2d1mod
- dotest cvsadm-1d28f "cat dir/dir2d1/CVS/Repository" "\."
- dotest cvsadm-1d28h "cat dir/dir2d1/sub2d1/CVS/Repository" "mod1"
- # the usual for 2d2mod
- dotest cvsadm-1d28j "cat dir/dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-1d28l "cat dir/dir2d2/sub2d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
-
- # 2d2mod
-
- dotest cvsadm-1d29 "${testcvs} co -d dir 2d2mod 2d2mod-2" \
-"${PROG} checkout: Updating dir/dir2d2/sub2d2
-U dir/dir2d2/sub2d2/file2
-${PROG} checkout: Updating dir/dir2d2-2/sub2d2-2
-U dir/dir2d2-2/sub2d2-2/file2-2"
- dotest cvsadm-1d29b "cat CVS/Repository" "\."
- # the usual for the dir level
- dotest cvsadm-1d29d "cat dir/CVS/Repository" "\."
- # the usual for 2d2mod
- dotest cvsadm-1d29f "cat dir/dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-1d29h "cat dir/dir2d2/sub2d2/CVS/Repository" "mod2/sub2"
- # the usual for 2d2mod
- dotest cvsadm-1d29j "cat dir/dir2d2-2/CVS/Repository" "mod2-2"
- dotest cvsadm-1d29l "cat dir/dir2d2-2/sub2d2-2/CVS/Repository" \
-"mod2-2/sub2-2"
- rm -rf CVS dir
-
- ##################################################
- ## And now, some of that again using the "-d" flag
- ## on the command line, but use a longer path.
- ##################################################
-
- dotest_fail cvsadm-2d3-1 "${testcvs} co -d dir/dir2 1mod" \
-"${PROG} \[checkout aborted\]: could not change directory to requested checkout directory .dir.: No such file or directory"
-
- if $remote; then :; else
- # Remote can't handle this, even with the "mkdir dir".
- # This was also true of CVS 1.9.
-
- mkdir dir
- dotest cvsadm-2d3 "${testcvs} co -d dir/dir2 1mod" \
-"${PROG} checkout: Updating dir/dir2
-U dir/dir2/file1"
- dotest cvsadm-2d3b "cat CVS/Repository" "\."
- dotest_fail cvsadm-2d3d "test -f dir/CVS/Repository" ""
- dotest cvsadm-2d3f "cat dir/dir2/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- mkdir dir
- dotest cvsadm-2d4 "${testcvs} co -d dir/dir2 2mod" \
-"${PROG} checkout: Updating dir/dir2
-U dir/dir2/file2"
- dotest cvsadm-2d4b "cat CVS/Repository" "\."
- dotest cvsadm-2d4f "cat dir/dir2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
- mkdir dir
- dotest cvsadm-2d5 "${testcvs} co -d dir/dir2 1d1mod" \
-"${PROG} checkout: Updating dir/dir2
-U dir/dir2/file1"
- dotest cvsadm-2d5b "cat CVS/Repository" "\."
- dotest cvsadm-2d5f "cat dir/dir2/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- mkdir dir
- dotest cvsadm-2d6 "${testcvs} co -d dir/dir2 1d2mod" \
-"${PROG} checkout: Updating dir/dir2
-U dir/dir2/file2"
- dotest cvsadm-2d6b "cat CVS/Repository" "\."
- dotest cvsadm-2d6f "cat dir/dir2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
- mkdir dir
- dotest cvsadm-2d7 "${testcvs} co -d dir/dir2 2d1mod" \
-"${PROG} checkout: Updating dir/dir2
-U dir/dir2/file1"
- dotest cvsadm-2d7b "cat CVS/Repository" "\."
- dotest cvsadm-2d7f "cat dir/dir2/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- mkdir dir
- dotest cvsadm-2d8 "${testcvs} co -d dir/dir2 2d2mod" \
-"${PROG} checkout: Updating dir/dir2
-U dir/dir2/file2"
- dotest cvsadm-2d8b "cat CVS/Repository" "\."
- dotest cvsadm-2d8f "cat dir/dir2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
- ##################################################
- ## And now, a few of those tests revisited to
- ## test the behavior of the -N flag.
- ##################################################
-
- dotest cvsadm-N3 "${testcvs} co -N 1mod" \
-"${PROG} checkout: Updating 1mod
-U 1mod/file1"
- dotest cvsadm-N3b "cat CVS/Repository" "\."
- dotest cvsadm-N3d "cat 1mod/CVS/Repository" "mod1"
- rm -rf CVS 1mod
-
- dotest cvsadm-N4 "${testcvs} co -N 2mod" \
-"${PROG} checkout: Updating 2mod
-U 2mod/file2"
- dotest cvsadm-N4b "cat CVS/Repository" "\."
- dotest cvsadm-N4d "cat 2mod/CVS/Repository" "mod2/sub2"
- rm -rf CVS 2mod
-
- dotest cvsadm-N5 "${testcvs} co -N 1d1mod" \
-"${PROG} checkout: Updating dir1d1
-U dir1d1/file1"
- dotest cvsadm-N5b "cat CVS/Repository" "\."
- dotest cvsadm-N5d "cat dir1d1/CVS/Repository" "mod1"
- rm -rf CVS dir1d1
-
- dotest cvsadm-N6 "${testcvs} co -N 1d2mod" \
-"${PROG} checkout: Updating dir1d2
-U dir1d2/file2"
- dotest cvsadm-N6b "cat CVS/Repository" "\."
- dotest cvsadm-N6d "cat dir1d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir1d2
-
- dotest cvsadm-N7 "${testcvs} co -N 2d1mod" \
-"${PROG} checkout: Updating dir2d1/sub2d1
-U dir2d1/sub2d1/file1"
- dotest cvsadm-N7b "cat CVS/Repository" "\."
- dotest cvsadm-N7d "cat dir2d1/CVS/Repository" "\."
- dotest cvsadm-N7f "cat dir2d1/sub2d1/CVS/Repository" "mod1"
- rm -rf CVS dir2d1
-
- dotest cvsadm-N8 "${testcvs} co -N 2d2mod" \
-"${PROG} checkout: Updating dir2d2/sub2d2
-U dir2d2/sub2d2/file2"
- dotest cvsadm-N8b "cat CVS/Repository" "\."
- dotest cvsadm-N8d "cat dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-N8f "cat dir2d2/sub2d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir2d2
-
- ## the ones in one-deep directories
-
- dotest cvsadm-N1d3 "${testcvs} co -N -d dir 1mod" \
-"${PROG} checkout: Updating dir/1mod
-U dir/1mod/file1"
- dotest cvsadm-N1d3b "cat CVS/Repository" "\."
- dotest cvsadm-N1d3d "cat dir/CVS/Repository" "\."
- dotest cvsadm-N1d3f "cat dir/1mod/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- dotest cvsadm-N1d4 "${testcvs} co -N -d dir 2mod" \
-"${PROG} checkout: Updating dir/2mod
-U dir/2mod/file2"
- dotest cvsadm-N1d4b "cat CVS/Repository" "\."
- dotest cvsadm-N1d4d "cat dir/CVS/Repository" "mod2"
- dotest cvsadm-N1d4f "cat dir/2mod/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
- dotest cvsadm-N1d5 "${testcvs} co -N -d dir 1d1mod" \
-"${PROG} checkout: Updating dir/dir1d1
-U dir/dir1d1/file1"
- dotest cvsadm-N1d5b "cat CVS/Repository" "\."
- dotest cvsadm-N1d5d "cat dir/CVS/Repository" "\."
- dotest cvsadm-N1d5d "cat dir/dir1d1/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- dotest cvsadm-N1d6 "${testcvs} co -N -d dir 1d2mod" \
-"${PROG} checkout: Updating dir/dir1d2
-U dir/dir1d2/file2"
- dotest cvsadm-N1d6b "cat CVS/Repository" "\."
- dotest cvsadm-N1d6d "cat dir/CVS/Repository" "mod2"
- dotest cvsadm-N1d6f "cat dir/dir1d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
- dotest cvsadm-N1d7 "${testcvs} co -N -d dir 2d1mod" \
-"${PROG} checkout: Updating dir/dir2d1/sub2d1
-U dir/dir2d1/sub2d1/file1"
- dotest cvsadm-N1d7b "cat CVS/Repository" "\."
- dotest cvsadm-N1d7d "cat dir/CVS/Repository" "CVSROOT/Emptydir"
- dotest cvsadm-N1d7f "cat dir/dir2d1/CVS/Repository" "\."
- dotest cvsadm-N1d7h "cat dir/dir2d1/sub2d1/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- dotest cvsadm-N1d8 "${testcvs} co -N -d dir 2d2mod" \
-"${PROG} checkout: Updating dir/dir2d2/sub2d2
-U dir/dir2d2/sub2d2/file2"
- dotest cvsadm-N1d8b "cat CVS/Repository" "\."
- dotest cvsadm-N1d8d "cat dir/CVS/Repository" "\."
- dotest cvsadm-N1d8d "cat dir/dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-N1d8d "cat dir/dir2d2/sub2d2/CVS/Repository" \
-"mod2/sub2"
- rm -rf CVS dir
-
- ## the ones in two-deep directories
-
- mkdir dir
- dotest cvsadm-N2d3 "${testcvs} co -N -d dir/dir2 1mod" \
-"${PROG} checkout: Updating dir/dir2/1mod
-U dir/dir2/1mod/file1"
- dotest cvsadm-N2d3b "cat CVS/Repository" "\."
- dotest cvsadm-N2d3f "cat dir/dir2/CVS/Repository" "\."
- dotest cvsadm-N2d3h "cat dir/dir2/1mod/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- mkdir dir
- dotest cvsadm-N2d4 "${testcvs} co -N -d dir/dir2 2mod" \
-"${PROG} checkout: Updating dir/dir2/2mod
-U dir/dir2/2mod/file2"
- dotest cvsadm-N2d4b "cat CVS/Repository" "\."
- dotest cvsadm-N2d4f "cat dir/dir2/CVS/Repository" "mod2"
- dotest cvsadm-N2d4h "cat dir/dir2/2mod/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
- mkdir dir
- dotest cvsadm-N2d5 "${testcvs} co -N -d dir/dir2 1d1mod" \
-"${PROG} checkout: Updating dir/dir2/dir1d1
-U dir/dir2/dir1d1/file1"
- dotest cvsadm-N2d5b "cat CVS/Repository" "\."
- dotest cvsadm-N2d5f "cat dir/dir2/CVS/Repository" "\."
- dotest cvsadm-N2d5h "cat dir/dir2/dir1d1/CVS/Repository" "mod1"
- rm -rf CVS dir
-
- mkdir dir
- dotest cvsadm-N2d6 "${testcvs} co -N -d dir/dir2 1d2mod" \
-"${PROG} checkout: Updating dir/dir2/dir1d2
-U dir/dir2/dir1d2/file2"
- dotest cvsadm-N2d6b "cat CVS/Repository" "\."
- dotest cvsadm-N2d6f "cat dir/dir2/CVS/Repository" "mod2"
- dotest cvsadm-N2d6h "cat dir/dir2/dir1d2/CVS/Repository" "mod2/sub2"
- rm -rf CVS dir
-
- mkdir dir
- dotest cvsadm-N2d7 "${testcvs} co -N -d dir/dir2 2d1mod" \
-"${PROG} checkout: Updating dir/dir2/dir2d1/sub2d1
-U dir/dir2/dir2d1/sub2d1/file1"
- dotest cvsadm-N2d7b "cat CVS/Repository" "\."
- dotest cvsadm-N2d7f "cat dir/dir2/CVS/Repository" "CVSROOT/Emptydir"
- dotest cvsadm-N2d7g "cat dir/dir2/dir2d1/CVS/Repository" "\."
- dotest cvsadm-N2d7h "cat dir/dir2/dir2d1/sub2d1/CVS/Repository" \
-"mod1"
- rm -rf CVS dir
-
- mkdir dir
- dotest cvsadm-N2d8 "${testcvs} co -N -d dir/dir2 2d2mod" \
-"${PROG} checkout: Updating dir/dir2/dir2d2/sub2d2
-U dir/dir2/dir2d2/sub2d2/file2"
- dotest cvsadm-N2d8b "cat CVS/Repository" "\."
- dotest cvsadm-N2d8f "cat dir/dir2/CVS/Repository" "\."
- dotest cvsadm-N2d8h "cat dir/dir2/dir2d2/CVS/Repository" "mod2"
- dotest cvsadm-N2d8j "cat dir/dir2/dir2d2/sub2d2/CVS/Repository" \
-"mod2/sub2"
- rm -rf CVS dir
-
- fi # end of tests to be skipped for remote
-
- ##################################################
- ## That's enough of that, thank you very much.
- ##################################################
-
- dotest cvsadm-cleanup-1 "${testcvs} -q co CVSROOT/config" \
-"U CVSROOT/config"
- cd CVSROOT
- echo "# empty file" >config
- dotest cvsadm-cleanup-2 "${testcvs} -q ci -m cvsadm-cleanup" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ..
- rm -rf CVSROOT CVS
-
- # remove our junk
- cd ..
- rm -rf 1
- rm -rf ${CVSROOT_DIRNAME}/1mod
- rm -rf ${CVSROOT_DIRNAME}/1mod-2
- rm -rf ${CVSROOT_DIRNAME}/2mod
- rm -rf ${CVSROOT_DIRNAME}/2mod-2
- rm -rf ${CVSROOT_DIRNAME}/mod1
- rm -rf ${CVSROOT_DIRNAME}/mod1-2
- rm -rf ${CVSROOT_DIRNAME}/mod2
- rm -rf ${CVSROOT_DIRNAME}/mod2-2
- ;;
-
- emptydir)
- # Various tests of the Emptydir (CVSNULLREPOS) code. See also:
- # cvsadm: tests of Emptydir in various module definitions
- # basicb: Test that "Emptydir" is non-special in ordinary contexts
-
- mkdir 1; cd 1
- dotest emptydir-1 "${testcvs} co CVSROOT/modules" \
-"U CVSROOT/modules"
- echo "# Module defs for emptydir tests" > CVSROOT/modules
- echo "2d1mod -d dir2d1/sub/sub2d1 mod1" >> CVSROOT/modules
- echo "2d1moda -d dir2d1/suba moda/modasub" >> CVSROOT/modules
- echo "2d1modb -d dir2d1/suba mod1" >> CVSROOT/modules
- echo "comb -a 2d1modb 2d1moda" >> CVSROOT/modules
-
- dotest emptydir-2 "${testcvs} ci -m add-modules" \
-"${PROG} [a-z]*: Examining CVSROOT
-Checking in CVSROOT/modules;
-${CVSROOT_DIRNAME}/CVSROOT/modules,v <-- modules
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database" \
-"${PROG} commit: Examining CVSROOT"
- rm -rf CVS CVSROOT
-
- mkdir ${CVSROOT_DIRNAME}/mod1 ${CVSROOT_DIRNAME}/moda
- # Populate. Not sure we really need to do this.
- dotest emptydir-3 "${testcvs} -q co -l ." ""
- dotest emptydir-3a "${testcvs} co mod1 moda" \
-"${PROG} checkout: Updating mod1
-${PROG} checkout: Updating moda"
- echo "file1" > mod1/file1
- mkdir moda/modasub
- dotest emptydir-3b "${testcvs} add moda/modasub" \
-"Directory ${CVSROOT_DIRNAME}/moda/modasub added to the repository"
- echo "filea" > moda/modasub/filea
- dotest emptydir-4 "${testcvs} add mod1/file1 moda/modasub/filea" \
-"${PROG} add: scheduling file .mod1/file1. for addition
-${PROG} add: scheduling file .moda/modasub/filea. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest emptydir-5 "${testcvs} -q ci -m yup" \
-"RCS file: ${CVSROOT_DIRNAME}/mod1/file1,v
-done
-Checking in mod1/file1;
-${CVSROOT_DIRNAME}/mod1/file1,v <-- file1
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/moda/modasub/filea,v
-done
-Checking in moda/modasub/filea;
-${CVSROOT_DIRNAME}/moda/modasub/filea,v <-- filea
-initial revision: 1\.1
-done"
- rm -rf mod1 moda CVS
- # End Populate.
-
- dotest emptydir-6 "${testcvs} co 2d1mod" \
-"${PROG} checkout: Updating dir2d1/sub/sub2d1
-U dir2d1/sub/sub2d1/file1"
- cd dir2d1
- touch emptyfile
- # 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_fail emptydir-7 "${testcvs} add emptyfile" \
-"${PROG} \[add aborted\]: cannot add to ${CVSROOT_DIRNAME}/CVSROOT/Emptydir"
- mkdir emptydir
- dotest_fail emptydir-8 "${testcvs} add emptydir" \
-"${PROG} \[[a-z]* aborted\]: cannot add to ${CVSROOT_DIRNAME}/CVSROOT/Emptydir"
- cd ..
- rm -rf CVS dir2d1
-
- # OK, while we have an Emptydir around, test a few obscure
- # things about it.
- mkdir edir; cd edir
- dotest emptydir-9 "${testcvs} -q co -l CVSROOT" \
-"U CVSROOT${DOTSTAR}"
- cd CVSROOT
- dotest_fail emptydir-10 "test -d Emptydir" ''
- # This tests the code in find_dirs which skips Emptydir.
- dotest emptydir-11 "${testcvs} -q -n update -d -P" ''
- cd ../..
- rm -r edir
- cd ..
-
- # Now start playing with moda.
- mkdir 2; cd 2
- dotest emptydir-12 "${testcvs} -q co 2d1moda" \
-"U dir2d1/suba/filea"
- # OK, this is the crux of the matter. This used to show "Emptydir",
- # but everyone seemed to think it should show "moda". This
- # usually works better, but not always as shown by the following
- # test.
- dotest emptydir-13 "cat dir2d1/CVS/Repository" "moda"
- dotest_fail emptydir-14 "${testcvs} co comb" \
-"${PROG} checkout: existing repository ${CVSROOT_DIRNAME}/moda/modasub does not match ${CVSROOT_DIRNAME}/mod1
-${PROG} checkout: ignoring module 2d1modb
-${PROG} checkout: Updating dir2d1/suba"
- dotest emptydir-15 "cat dir2d1/CVS/Repository" "moda"
- cd ..
-
- # Test the effect of a non-cvs directory already existing with the
- # same name as one in the modules file.
- mkdir 3; cd 3
- mkdir dir2d1
- dotest emptydir-16 "${testcvs} co 2d1mod" \
-"${PROG} checkout: Updating dir2d1/sub/sub2d1
-U dir2d1/sub/sub2d1/file1"
- dotest emptydir-17 "test -d dir2d1/CVS"
-
- # clean up
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- cd ..
- rm -r 1 2 3
- rm -rf ${CVSROOT_DIRNAME}/mod1 ${CVSROOT_DIRNAME}/moda
- # I guess for the moment the convention is going to be
- # that we don't need to remove ${CVSROOT_DIRNAME}/CVSROOT/Emptydir
- ;;
-
- abspath)
-
- # These tests test the thituations thin thwitch thoo theck
- # things thout twith thabsolute thaths. Threally.
-
- #
- # CHECKOUTS
- #
-
- # Create a few modules to use
- mkdir ${CVSROOT_DIRNAME}/mod1 ${CVSROOT_DIRNAME}/mod2
- dotest abspath-1a "${testcvs} co mod1 mod2" \
-"${PROG} checkout: Updating mod1
-${PROG} checkout: Updating mod2"
-
- # Populate the module
- echo "file1" > mod1/file1
- echo "file2" > mod2/file2
- cd mod1
- dotest abspath-1ba "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- cd ..
- cd mod2
- dotest abspath-1bb "${testcvs} add file2" \
-"${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- cd ..
-
- dotest abspath-1c "${testcvs} ci -m yup mod1 mod2" \
-"${PROG} [a-z]*: Examining mod1
-${PROG} [a-z]*: Examining mod2
-RCS file: ${CVSROOT_DIRNAME}/mod1/file1,v
-done
-Checking in mod1/file1;
-${CVSROOT_DIRNAME}/mod1/file1,v <-- file1
-initial revision: 1.1
-done
-RCS file: ${CVSROOT_DIRNAME}/mod2/file2,v
-done
-Checking in mod2/file2;
-${CVSROOT_DIRNAME}/mod2/file2,v <-- file2
-initial revision: 1.1
-done"
- # Finished creating the module -- clean up.
- rm -rf CVS mod1 mod2
- # Done.
-
- # Try checking out the module in a local directory
- if $remote; then
- dotest_fail abspath-2a "${testcvs} co -d ${TESTDIR}/1 mod1" \
-"${PROG} \[checkout aborted\]: absolute pathname .${TESTDIR}/1. illegal for server"
- dotest abspath-2a-try2 "${testcvs} co -d 1 mod1" \
-"${PROG} checkout: Updating 1
-U 1/file1"
- else
- dotest abspath-2a "${testcvs} co -d ${TESTDIR}/1 mod1" \
-"${PROG} checkout: Updating ${TESTDIR}/1
-U ${TESTDIR}/1/file1"
- fi # remote workaround
-
- dotest abspath-2b "cat ${TESTDIR}/1/CVS/Repository" "mod1"
-
- # Done. Clean up.
- rm -rf ${TESTDIR}/1
-
-
- # Now try in a subdirectory. We're not covering any more
- # code here, but we might catch a future error if someone
- # changes the checkout code.
-
- # Note that for the same reason that the shell command
- # "touch 1/2/3" requires directories 1 and 1/2 to already
- # exist, we expect ${TESTDIR}/1 to already exist. I believe
- # this is the behavior of CVS 1.9 and earlier.
- if $remote; then :; else
- dotest_fail abspath-3.1 "${testcvs} co -d ${TESTDIR}/1/2 mod1" \
-"${PROG} \[checkout aborted\]: could not change directory to requested checkout directory .${TESTDIR}/1.: No such file or directory"
- fi
- dotest_fail abspath-3.2 "${testcvs} co -d 1/2 mod1" \
-"${PROG} \[checkout aborted\]: could not change directory to requested checkout directory .1.: No such file or directory"
-
- mkdir 1
-
- if $remote; then
- # The server wants the directory to exist, but that is
- # a bug, it should only need to exist on the client side.
- # See also cvsadm-2d3.
- dotest_fail abspath-3a "${testcvs} co -d 1/2 mod1" \
-"${PROG} \[checkout aborted\]: could not change directory to requested checkout directory .1.: No such file or directory"
- cd 1
- dotest abspath-3a-try2 "${testcvs} co -d 2 mod1" \
-"${PROG} checkout: Updating 2
-U 2/file1"
- cd ..
- rm -rf 1/CVS
- else
- dotest abspath-3a "${testcvs} co -d ${TESTDIR}/1/2 mod1" \
-"${PROG} checkout: Updating ${TESTDIR}/1/2
-U ${TESTDIR}/1/2/file1"
- fi # remote workaround
- dotest abspath-3b "cat ${TESTDIR}/1/2/CVS/Repository" "mod1"
-
- # For all the same reasons that we want "1" to already
- # exist, we don't to mess with it to traverse it, for
- # example by creating a CVS directory.
-
- dotest_fail abspath-3c "test -d ${TESTDIR}/1/CVS" ''
- # Done. Clean up.
- rm -rf ${TESTDIR}/1
-
-
- # Now try someplace where we don't have permission.
- mkdir ${TESTDIR}/barf
- chmod -w ${TESTDIR}/barf
- dotest_fail abspath-4r "${testcvs} co -d ${TESTDIR}/barf/sub mod1" \
-"${PROG} \[checkout aborted\]: absolute pathname .${TESTDIR}/barf/sub. illegal for server" \
-"${PROG} \[checkout aborted\]: cannot make directory sub: Permission denied"
- chmod +w ${TESTDIR}/barf
- rmdir ${TESTDIR}/barf
- # Done. Nothing to clean up.
-
-
- # Try checking out two modules into the same directory.
- if $remote; then
- dotest abspath-5ar "${testcvs} co -d 1 mod1 mod2" \
-"${PROG} checkout: Updating 1/mod1
-U 1/mod1/file1
-${PROG} checkout: Updating 1/mod2
-U 1/mod2/file2"
- else
- dotest abspath-5a "${testcvs} co -d ${TESTDIR}/1 mod1 mod2" \
-"${PROG} checkout: Updating ${TESTDIR}/1/mod1
-U ${TESTDIR}/1/mod1/file1
-${PROG} checkout: Updating ${TESTDIR}/1/mod2
-U ${TESTDIR}/1/mod2/file2"
- fi # end remote workaround
- dotest abspath-5b "cat ${TESTDIR}/1/CVS/Repository" "\."
- dotest abspath-5c "cat ${TESTDIR}/1/mod1/CVS/Repository" "mod1"
- dotest abspath-5d "cat ${TESTDIR}/1/mod2/CVS/Repository" "mod2"
- # Done. Clean up.
- rm -rf ${TESTDIR}/1
-
-
- # Try checking out the top-level module.
- if $remote; then
- dotest abspath-6ar "${testcvs} co -d 1 ." \
-"${PROG} checkout: Updating 1
-${PROG} checkout: Updating 1/CVSROOT
-${DOTSTAR}
-${PROG} checkout: Updating 1/mod1
-U 1/mod1/file1
-${PROG} checkout: Updating 1/mod2
-U 1/mod2/file2"
- else
- dotest abspath-6a "${testcvs} co -d ${TESTDIR}/1 ." \
-"${PROG} checkout: Updating ${TESTDIR}/1
-${PROG} checkout: Updating ${TESTDIR}/1/CVSROOT
-${DOTSTAR}
-${PROG} checkout: Updating ${TESTDIR}/1/mod1
-U ${TESTDIR}/1/mod1/file1
-${PROG} checkout: Updating ${TESTDIR}/1/mod2
-U ${TESTDIR}/1/mod2/file2"
- fi # end of remote workaround
- dotest abspath-6b "cat ${TESTDIR}/1/CVS/Repository" "\."
- dotest abspath-6c "cat ${TESTDIR}/1/CVSROOT/CVS/Repository" "CVSROOT"
- dotest abspath-6c "cat ${TESTDIR}/1/mod1/CVS/Repository" "mod1"
- dotest abspath-6d "cat ${TESTDIR}/1/mod2/CVS/Repository" "mod2"
- # Done. Clean up.
- rm -rf ${TESTDIR}/1
-
- # Test that an absolute pathname to some other directory
- # doesn't mess with the current working directory.
- mkdir 1
- cd 1
- if $remote; then
- dotest_fail abspath-7ar "${testcvs} -q co -d ../2 mod2" \
-"${PROG} checkout: protocol error: .\.\./2. contains more leading \.\.
-${PROG} \[checkout aborted\]: than the 0 which Max-dotdot specified"
- cd ..
- dotest abspath-7a-try2r "${testcvs} -q co -d 2 mod2" \
-"U 2/file2"
- cd 1
- else
- dotest abspath-7a "${testcvs} -q co -d ${TESTDIR}/2 mod2" \
-"U ${TESTDIR}/2/file2"
- fi # remote workaround
- dotest abspath-7b "ls" ""
- dotest abspath-7c "${testcvs} -q co mod1" \
-"U mod1/file1"
- cd mod1
- if $remote; then
- cd ../..
- dotest abspath-7dr "${testcvs} -q co -d 3 mod2" \
-"U 3/file2"
- cd 1/mod1
- else
- dotest abspath-7d "${testcvs} -q co -d ${TESTDIR}/3 mod2" \
-"U ${TESTDIR}/3/file2"
- fi # remote workaround
- dotest abspath-7e "${testcvs} -q update -d" ""
- cd ../..
- rm -r 1 2 3
-
- #
- # FIXME: do other functions here (e.g. update /tmp/foo)
- #
-
- # Finished with all tests. Remove the module.
- rm -rf ${CVSROOT_DIRNAME}/mod1 ${CVSROOT_DIRNAME}/mod2
-
- ;;
-
-
-
- abspath2)
- # More absolute path checks. The following used to attempt to create
- # directories in /:
- #
- # $ cvs -d:fork:/cvsroot co /foo
- # cvs checkout: warning: cannot make directory CVS in /: Permission denied
- # cvs [checkout aborted]: cannot make directory /foo: Permission denied
- # $
- #
- # The -z9 in this test also checks for an old server bug where the
- # server would block indefinitely attempting to read an EOF from the
- # client in the compression buffer shutdown routine.
- dotest_fail abspath2-1 "$testcvs -z9 co /foo" \
-"$PROG \[checkout aborted\]: Absolute module reference invalid: \`/foo'" \
-"$PROG \[server aborted\]: Absolute module reference invalid: \`/foo'
-$PROG \[checkout aborted\]: end of file from server (consult above messages if any)"
- ;;
-
-
-
- toplevel)
- # test the feature that cvs creates a CVS subdir also for
- # the toplevel directory
-
- # First set the TopLevelAdmin setting.
- mkdir 1; cd 1
- dotest toplevel-1a "${testcvs} -q co CVSROOT/config" \
-"U CVSROOT/config"
- cd CVSROOT
- echo "TopLevelAdmin=yes" >config
- dotest toplevel-1b "${testcvs} -q ci -m yes-top-level" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ../..
- rm -r 1
-
- mkdir 1; cd 1
- dotest toplevel-1 "${testcvs} -q co -l ." ''
- mkdir top-dir second-dir
- dotest toplevel-2 "${testcvs} add top-dir second-dir" \
-"Directory ${CVSROOT_DIRNAME}/top-dir added to the repository
-Directory ${CVSROOT_DIRNAME}/second-dir added to the repository"
- cd top-dir
-
- touch file1
- dotest toplevel-3 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest toplevel-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/top-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/top-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- cd ..
-
- cd second-dir
- touch file2
- dotest toplevel-3s "${testcvs} add file2" \
-"${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest toplevel-4s "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/second-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/second-dir/file2,v <-- file2
-initial revision: 1\.1
-done"
-
- cd ../..
- rm -r 1; mkdir 1; cd 1
- dotest toplevel-5 "${testcvs} co top-dir" \
-"${PROG} checkout: Updating top-dir
-U top-dir/file1"
-
- dotest toplevel-6 "${testcvs} update top-dir" \
-"${PROG} update: Updating top-dir"
- dotest toplevel-7 "${testcvs} update" \
-"${PROG} update: Updating \.
-${PROG} update: Updating top-dir"
-
- dotest toplevel-8 "${testcvs} update -d top-dir" \
-"${PROG} update: Updating top-dir"
- # There is some sentiment that
- # "${PROG} update: Updating \.
- # ${PROG} update: Updating top-dir"
- # is correct but it isn't clear why that would be correct instead
- # of the remote CVS behavior (which also updates CVSROOT).
- #
- # The DOTSTAR matches of a bunch of lines like
- # "U CVSROOT/checkoutlist". Trying to match them more precisely
- # seemed to cause trouble. For example CVSROOT/cvsignore will
- # be present or absent depending on whether we ran the "ignore"
- # test or not.
- dotest toplevel-9 "${testcvs} update -d" \
-"${PROG} update: Updating \.
-${PROG} update: Updating CVSROOT
-${DOTSTAR}
-${PROG} update: Updating top-dir"
-
- cd ..
- rm -r 1; mkdir 1; cd 1
- dotest toplevel-10 "${testcvs} co top-dir" \
-"${PROG} checkout: Updating top-dir
-U top-dir/file1"
-
- # This tests more or less the same thing, in a particularly
- # "real life" example.
- dotest toplevel-11 "${testcvs} -q update -d second-dir" \
-"U second-dir/file2"
-
- # Now remove the CVS directory (people may do this manually,
- # especially if they formed their habits with CVS
- # 1.9 and older, which didn't create it. Or perhaps the working
- # directory itself was created with 1.9 or older).
- rm -r CVS
- # Now set the permissions so we can't recreate it.
- if test -n "$remotehost"; then
- # Cygwin again.
- $CVS_RSH $remotehost "chmod -w $TESTDIR/1"
- else
- chmod -w ../1
- fi
- # Now see whether CVS has trouble because it can't create CVS.
- # First string is for local, second is for remote.
- dotest toplevel-12 "${testcvs} co top-dir" \
-"${PROG} checkout: warning: cannot make directory CVS in \.: Permission denied
-${PROG} checkout: Updating top-dir" \
-"${PROG} checkout: warning: cannot make directory CVS in \.: Permission denied
-${PROG} checkout: in directory \.:
-${PROG} checkout: cannot open CVS/Entries for reading: No such file or directory
-${PROG} checkout: Updating top-dir"
-
- chmod +w ../1
-
- dotest toplevel-cleanup-1 "${testcvs} -q co CVSROOT/config" \
-"U CVSROOT/config"
- cd CVSROOT
- echo "# empty file" >config
- dotest toplevel-cleanup-2 "${testcvs} -q ci -m toplevel-cleanup" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
-
- cd ../..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/top-dir ${CVSROOT_DIRNAME}/second-dir
- ;;
-
- toplevel2)
- # Similar to toplevel, but test the case where TopLevelAdmin=no.
-
- # First set the TopLevelAdmin setting.
- mkdir 1; cd 1
- dotest toplevel2-1a "${testcvs} -q co CVSROOT/config" \
-"U CVSROOT/config"
- cd CVSROOT
- echo "TopLevelAdmin=no" >config
- dotest toplevel2-1b "${testcvs} -q ci -m no-top-level" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ../..
- rm -r 1
-
- # Now set up some directories and subdirectories
- mkdir 1; cd 1
- dotest toplevel2-1 "${testcvs} -q co -l ." ''
- mkdir top-dir second-dir
- dotest toplevel2-2 "${testcvs} add top-dir second-dir" \
-"Directory ${CVSROOT_DIRNAME}/top-dir added to the repository
-Directory ${CVSROOT_DIRNAME}/second-dir added to the repository"
- cd top-dir
-
- touch file1
- dotest toplevel2-3 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest toplevel2-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/top-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/top-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- cd ..
-
- cd second-dir
- touch file2
- dotest toplevel2-3s "${testcvs} add file2" \
-"${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest toplevel2-4s "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/second-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/second-dir/file2,v <-- file2
-initial revision: 1\.1
-done"
-
- cd ../..
- rm -r 1; mkdir 1; cd 1
- dotest toplevel2-5 "${testcvs} co top-dir" \
-"${PROG} checkout: Updating top-dir
-U top-dir/file1"
-
- dotest toplevel2-6 "${testcvs} update top-dir" \
-"${PROG} update: Updating top-dir"
- dotest toplevel2-7 "${testcvs} update" \
-"${PROG} update: Updating top-dir"
-
- dotest toplevel2-8 "${testcvs} update -d top-dir" \
-"${PROG} update: Updating top-dir"
- # Contrast this with toplevel-9, which has TopLevelAdmin=yes.
- dotest toplevel2-9 "${testcvs} update -d" \
-"${PROG} update: Updating top-dir"
-
- cd ..
- rm -r 1; mkdir 1; cd 1
- dotest toplevel2-10 "${testcvs} co top-dir" \
-"${PROG} checkout: Updating top-dir
-U top-dir/file1"
- # This tests more or less the same thing, in a particularly
- # "real life" example. With TopLevelAdmin=yes, this command
- # would give us second-dir and CVSROOT directories too.
- dotest toplevel2-11 "${testcvs} -q update -d" ""
-
- dotest toplevel2-cleanup-1 "${testcvs} -q co CVSROOT/config" \
-"U CVSROOT/config"
- cd CVSROOT
- echo "# empty file" >config
- dotest toplevel2-cleanup-2 "${testcvs} -q ci -m toplevel2-cleanup" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ../..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/top-dir ${CVSROOT_DIRNAME}/second-dir
- ;;
-
-
-
- rstar-toplevel)
- # This test used to confirm a bug that existed in the r* commands
- # run against the top-level project prior to CVS 1.11.18 & 1.12.10.
- #
- # The assertion failure was something like:
- # do_recursion: Assertion \`strstr (repository, \"/\./\") == ((void \*)0)' failed\..*"
- dotest rstar-toplevel-1 "$testcvs -q rlog ." \
-"
-RCS file: $CVSROOT_DIRNAME/CVSROOT$DOTSTAR"
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
- ;;
-
-
-
- trailingslashes)
- # Some tests of CVS's reactions to path specifications containing
- # trailing slashes.
- mkdir trailingslashes; cd trailingslashes
- dotest trailingslashes-init-1 "$testcvs -Q co -ldt ."
- dotest trailingslashes-init-2 "$testcvs -Q co -dt2 ."
- cd t
- echo "Ahh'll be baaack." >topfile
- dotest trailingslashes-init-3 "$testcvs -Q add topfile"
- dotest trailingslashes-init-4 "$testcvs -Q ci -mto-top" \
-"RCS file: $CVSROOT_DIRNAME/topfile,v
-done
-Checking in topfile;
-$CVSROOT_DIRNAME/topfile,v <-- topfile
-initial revision: 1\.1
-done"
-
- # First, demonstrate the usual case.
- cd ../t2
- dotest trailingslashes-1 "$testcvs -q up CVSROOT"
- dotest_fail trailingslashes-1a "test -f topfile"
-
- # Now the one that used to fail in remote mode prior to 1.11.24
- # & 1.12.14. Formerly TODO item #205.
- dotest trailingslashes-2 "$testcvs -q up CVSROOT/"
- dotest_fail trailingslashes-2a "test -f topfile"
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- cd ../..
- rm -rf trailingslashes $CVSROOT_DIRNAME/topfile,v
- ;;
-
-
-
- checkout_repository)
- dotest_fail checkout_repository-1 \
-"${testcvs} co -d ${CVSROOT_DIRNAME} CVSROOT" \
-"${PROG} \[checkout aborted\]: Cannot check out files into the repository itself" \
-"${PROG} \[checkout aborted\]: absolute pathname \`${CVSROOT_DIRNAME}' illegal for server"
-
- # The behavior of the client/server test below should be correct.
- # The CVS client currently has no way of knowing that the client and
- # server are the same machine and thus skips the $CVSROOT checks.
- # I think checking for this case in CVS would be bloat since this
- # should be a fairly rare occurance.
- cd ${CVSROOT_DIRNAME}
- dotest_fail checkout_repository-2 "${testcvs} co CVSROOT" \
-"${PROG} \[checkout aborted\]: Cannot check out files into the repository itself" \
-"${PROG} checkout: Updating CVSROOT
-${PROG} checkout: move away CVSROOT/checkoutlist; it is in the way
-C CVSROOT/checkoutlist
-${PROG} checkout: move away CVSROOT/commitinfo; it is in the way
-C CVSROOT/commitinfo
-${PROG} checkout: move away CVSROOT/config; it is in the way
-C CVSROOT/config
-${PROG} checkout: move away CVSROOT/cvswrappers; it is in the way
-C CVSROOT/cvswrappers
-${PROG} checkout: move away CVSROOT/editinfo; it is in the way
-C CVSROOT/editinfo
-${PROG} checkout: move away CVSROOT/loginfo; it is in the way
-C CVSROOT/loginfo
-${PROG} checkout: move away CVSROOT/modules; it is in the way
-C CVSROOT/modules
-${PROG} checkout: move away CVSROOT/notify; it is in the way
-C CVSROOT/notify
-${PROG} checkout: move away CVSROOT/rcsinfo; it is in the way
-C CVSROOT/rcsinfo
-${PROG} checkout: move away CVSROOT/taginfo; it is in the way
-C CVSROOT/taginfo
-${PROG} checkout: move away CVSROOT/verifymsg; it is in the way
-C CVSROOT/verifymsg"
-
- dotest checkout_repository-3 \
-"${testcvs} co -p CVSROOT/modules >/dev/null" \
-"===================================================================
-Checking out CVSROOT/modules
-RCS: ${CVSROOT_DIRNAME}/CVSROOT/modules,v
-VERS: 1\.[0-9]*
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*"
- cd ${TESTDIR}
- ;;
-
- mflag)
- for message in '' ' ' '
- ' ' test' ; do
- # Set up
- mkdir a-dir; cd a-dir
- # Test handling of -m during import
- echo testa >>test
- if ${testcvs} import -m "$message" a-dir A A1 >>${LOGFILE} 2>&1;then
- pass 156
- else
- fail 156
- fi
- # Must import twice since the first time uses inline code that
- # avoids RCS call.
- echo testb >>test
- if ${testcvs} import -m "$message" a-dir A A2 >>${LOGFILE} 2>&1;then
- pass 157
- else
- fail 157
- fi
- # Test handling of -m during ci
- cd ..; rm -r a-dir
- if ${testcvs} co a-dir >>${LOGFILE} 2>&1; then
- pass 158
- else
- fail 158
- fi
- cd a-dir
- echo testc >>test
- if ${testcvs} ci -m "$message" >>${LOGFILE} 2>&1; then
- pass 159
- else
- fail 159
- fi
- # Test handling of -m during rm/ci
- rm test;
- if ${testcvs} rm test >>${LOGFILE} 2>&1; then
- pass 160
- else
- fail 160
- fi
- if ${testcvs} ci -m "$message" >>${LOGFILE} 2>&1; then
- pass 161
- else
- fail 161
- fi
- # Clean up
- cd ..
- rm -r a-dir
- rm -rf ${CVSROOT_DIRNAME}/a-dir
- done
- ;;
-
- editor)
- # More tests of log messages, in this case the ability to
- # run an external editor.
- # TODO:
- # * also test $EDITOR, $CVSEDITOR, &c.
- # * test what happens if up-to-date check fails.
-
- # Our "editor" puts "x" at the start of each line, so we
- # can see the "CVS:" lines.
- cat >${TESTDIR}/editme <<EOF
-#!${TESTSHELL}
-sleep 1
-sed <\$1 -e 's/^/x/' >${TESTDIR}/edit.new
-mv ${TESTDIR}/edit.new \$1
-exit 0
-EOF
- chmod +x ${TESTDIR}/editme
-
- mkdir 1; cd 1
- dotest editor-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest editor-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- touch file1 file2
- dotest editor-3 "${testcvs} add file1 file2" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest editor-4 "${testcvs} -e ${TESTDIR}/editme -q ci" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1\.1
-done"
- dotest editor-5 "${testcvs} -q tag -b br" "T file1
-T file2"
- dotest editor-6 "$testcvs -q update -r br" \
-'U file1
-U file2'
- echo modify >>file1
- dotest editor-7 "${testcvs} -e ${TESTDIR}/editme -q ci" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
- # OK, now we want to make sure "ci -r" puts in the branch
- # where appropriate. Note that we can check in on the branch
- # without being on the branch, because there is not a revision
- # already on the branch. If there were a revision on the branch,
- # CVS would correctly give an up-to-date check failed.
- dotest editor-8 "$testcvs -q update -A" \
-'U file1
-U file2'
- echo add a line >>file2
- dotest editor-9 "${testcvs} -q -e ${TESTDIR}/editme ci -rbr file2" \
-"Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
-
- dotest editor-log-file1 "${testcvs} log -N file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
-keyword substitution: kv
-total revisions: 2; selected revisions: 2
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-branches: 1\.1\.2;
-xCVS: ----------------------------------------------------------------------
-xCVS: Enter Log. Lines beginning with .CVS:. are removed automatically
-xCVS:
-xCVS: Committing in .
-xCVS:
-xCVS: Added Files:
-xCVS: file1 file2
-xCVS: ----------------------------------------------------------------------
-----------------------------
-revision 1\.1\.2\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-xCVS: ----------------------------------------------------------------------
-xCVS: Enter Log. Lines beginning with .CVS:. are removed automatically
-xCVS:
-xCVS: Committing in .
-xCVS:
-xCVS: Modified Files:
-xCVS: Tag: br
-xCVS: file1
-xCVS: ----------------------------------------------------------------------
-============================================================================="
-
- # The only difference between the two expect strings is the
- # presence or absence of "Committing in ." for 1.1.2.1.
- dotest editor-log-file2 "${testcvs} log -N file2" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-Working file: file2
-head: 1\.1
-branch:
-locks: strict
-access list:
-keyword substitution: kv
-total revisions: 2; selected revisions: 2
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-branches: 1\.1\.2;
-xCVS: ----------------------------------------------------------------------
-xCVS: Enter Log. Lines beginning with .CVS:. are removed automatically
-xCVS:
-xCVS: Committing in .
-xCVS:
-xCVS: Added Files:
-xCVS: file1 file2
-xCVS: ----------------------------------------------------------------------
-----------------------------
-revision 1\.1\.2\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-xCVS: ----------------------------------------------------------------------
-xCVS: Enter Log. Lines beginning with .CVS:. are removed automatically
-xCVS:
-xCVS: Modified Files:
-xCVS: Tag: br
-xCVS: file2
-xCVS: ----------------------------------------------------------------------
-=============================================================================" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-Working file: file2
-head: 1\.1
-branch:
-locks: strict
-access list:
-keyword substitution: kv
-total revisions: 2; selected revisions: 2
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-branches: 1\.1\.2;
-xCVS: ----------------------------------------------------------------------
-xCVS: Enter Log. Lines beginning with .CVS:. are removed automatically
-xCVS:
-xCVS: Committing in .
-xCVS:
-xCVS: Added Files:
-xCVS: file1 file2
-xCVS: ----------------------------------------------------------------------
-----------------------------
-revision 1\.1\.2\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-xCVS: ----------------------------------------------------------------------
-xCVS: Enter Log. Lines beginning with .CVS:. are removed automatically
-xCVS:
-xCVS: Committing in .
-xCVS:
-xCVS: Modified Files:
-xCVS: Tag: br
-xCVS: file2
-xCVS: ----------------------------------------------------------------------
-============================================================================="
-
- # Test CVS's response to an unchanged log message
- cat >${TESTDIR}/editme <<EOF
-#!${TESTSHELL}
-sleep 1
-exit 0
-EOF
- chmod +x ${TESTDIR}/editme
- dotest_fail editor-emptylog-1 "echo a |${testcvs} -e ${TESTDIR}/editme ci -f file1" \
-"
-Log message unchanged or not specified
-a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs
-Action: (continue) ${PROG} \[[a-z]* aborted\]: aborted by user"
-
- # Test CVS's response to an empty log message
- cat >${TESTDIR}/editme <<EOF
-#!${TESTSHELL}
-sleep 1
-cat /dev/null >\$1
-exit 0
-EOF
- chmod +x ${TESTDIR}/editme
- dotest_fail editor-emptylog-1 "echo a |${testcvs} -e ${TESTDIR}/editme ci -f file1" \
-"
-Log message unchanged or not specified
-a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs
-Action: (continue) ${PROG} \[[a-z]* aborted\]: aborted by user"
-
- # Test CVS's response to a log message with one blank line
- cat >${TESTDIR}/editme <<EOF
-#!${TESTSHELL}
-sleep 1
-echo >\$1
-exit 0
-EOF
- chmod +x ${TESTDIR}/editme
- dotest_fail editor-emptylog-1 "echo a |${testcvs} -e ${TESTDIR}/editme ci -f file1" \
-"
-Log message unchanged or not specified
-a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs
-Action: (continue) ${PROG} \[[a-z]* aborted\]: aborted by user"
-
- # Test CVS's response to a log message with only comments
- cat >${TESTDIR}/editme <<EOF
-#!${TESTSHELL}
-sleep 1
-cat \$1 >${TESTDIR}/edit.new
-mv ${TESTDIR}/edit.new \$1
-exit 0
-EOF
- chmod +x ${TESTDIR}/editme
- dotest_fail editor-emptylog-1 "echo a |${testcvs} -e ${TESTDIR}/editme ci -f file1" \
-"
-Log message unchanged or not specified
-a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs
-Action: (continue) ${PROG} \[[a-z]* aborted\]: aborted by user"
-
- # Test CVS's response to a log message that is zero bytes
- # in length. This caused core dumps in cvs 1.11.5 on Solaris
- # hosts.
- cd ..
- dotest editor-emptylog-continue-1 "${testcvs} -q co CVSROOT/loginfo" \
-"U CVSROOT/loginfo"
-
- cd CVSROOT
- echo 'DEFAULT (echo Start-Log;cat;echo End-Log) >> \$CVSROOT/CVSROOT/commitlog' > loginfo
- dotest editor-emptylog-continue-2 "${testcvs} commit -m add loginfo" \
-"Checking in loginfo;
-${CVSROOT_DIRNAME}/CVSROOT/loginfo,v <-- loginfo
-new revision: 1\.2; previous revision: 1\.1
-done
-${PROG} commit: Rebuilding administrative file database"
-
- cd ../first-dir
- cat >${TESTDIR}/editme <<EOF
-#!${TESTSHELL}
-sleep 1
-cp /dev/null \$1
-exit 1
-EOF
- chmod +x ${TESTDIR}/editme
- dotest editor-emptylog-continue-3 "echo c |${testcvs} -e ${TESTDIR}/editme ci -f file1" \
-"${PROG} [a-z]*: warning: editor session failed
-
-Log message unchanged or not specified
-a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs
-Action: (continue) Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
- # The loginfo Log message should be an empty line and not "(null)"
- # which is what some fprintf() implementations do with "%s"
- # format and a NULL pointer...
- if $remote; then
- dotest editor-emptylog-continue-4r \
-"cat ${CVSROOT_DIRNAME}/CVSROOT/commitlog" \
-"Start-Log
-Update of ${CVSROOT_DIRNAME}/first-dir
-In directory ${hostname}:${TMPDIR}/cvs-serv[0-9a-z]*
-
-Modified Files:
- file1
-Log Message:
-
-End-Log"
- else
- dotest editor-emptylog-continue-4 \
-"cat ${CVSROOT_DIRNAME}/CVSROOT/commitlog" \
-"Start-Log
-Update of ${CVSROOT_DIRNAME}/first-dir
-In directory ${hostname}:${TESTDIR}/1/first-dir
-
-Modified Files:
- file1
-Log Message:
-
-End-Log"
- fi
- # There should have an empty log message at this point
- dotest editor-emptylog-continue-5 "${testcvs} log -N -r1.2 file1" \
-"
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.2
-branch:
-locks: strict
-access list:
-keyword substitution: kv
-total revisions: 3; selected revisions: 1
-description:
-----------------------------
-revision 1\.2
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: +0 -0
-\*\*\* empty log message \*\*\*
-============================================================================="
-
- # clean up
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- restore_adm
- cd ../..
- rm -r 1
- rm ${TESTDIR}/editme
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- errmsg1)
- mkdir ${CVSROOT_DIRNAME}/1dir
- mkdir 1
- cd 1
- if ${testcvs} -q co 1dir; then
- pass 162
- else
- fail 162
- fi
- cd 1dir
- touch foo
- if ${testcvs} add foo 2>>${LOGFILE}; then
- pass 163
- else
- fail 163
- fi
- if ${testcvs} ci -m added >>${LOGFILE} 2>&1; then
- pass 164
- else
- fail 164
- fi
- cd ../..
- mkdir 2
- cd 2
- if ${testcvs} -q co 1dir >>${LOGFILE}; then
- pass 165
- else
- fail 165
- fi
- chmod a-w 1dir
- cd ../1/1dir
- rm foo;
- if ${testcvs} rm foo >>${LOGFILE} 2>&1; then
- pass 166
- else
- fail 166
- fi
- if ${testcvs} ci -m removed >>${LOGFILE} 2>&1; then
- pass 167
- else
- fail 167
- fi
-
- cd ../../2/1dir
- # The second case in the local and remote versions of errmsg1-168
- # below happens on Cygwin under Windows, where write privileges
- # aren't enforced properly.
- if $remote; then
- dotest errmsg1-168r "${testcvs} -q update" \
-"${PROG} update: foo is no longer in the repository
-${PROG} update: unable to remove \./foo: Permission denied" \
-"${PROG} update: foo is no longer in the repository"
- else
- dotest errmsg1-168 "${testcvs} -q update" \
-"${PROG} update: foo is no longer in the repository
-${PROG} update: unable to remove foo: Permission denied" \
-"${PROG} update: foo is no longer in the repository"
- fi
-
- cd ..
- chmod u+w 1dir
- cd ..
- rm -r 1 2
- rm -rf ${CVSROOT_DIRNAME}/1dir
- ;;
-
- errmsg2)
- # More tests of various miscellaneous error handling,
- # and cvs add behavior in general.
- # See also test basicb-4a, concerning "cvs ci CVS".
- # Too many tests to mention test the simple cases of
- # adding files and directories.
- # Test basicb-2a10 tests cvs -n add.
-
- # First the usual setup; create a directory first-dir.
- mkdir 1; cd 1
- dotest errmsg2-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest errmsg2-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- dotest_fail errmsg2-3 "${testcvs} add CVS" \
-"${PROG} [a-z]*: cannot add special file .CVS.; skipping"
- touch file1
- # For the most part add returns a failure exitstatus if
- # there are any errors, even if the remaining files are
- # processed without incident. The "cannot add
- # special file" message fits this pattern, at
- # least currently.
- dotest_fail errmsg2-4 "${testcvs} add CVS file1" \
-"${PROG} add: cannot add special file .CVS.; skipping
-${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- # I'm not sure these tests completely convey the various strange
- # behaviors that CVS had before it specially checked for "." and
- # "..". Suffice it to say that these are unlikely to work right
- # without a special case.
- dotest_fail errmsg2-5 "${testcvs} add ." \
-"${PROG} [a-z]*: cannot add special file .\..; skipping"
- dotest_fail errmsg2-6 "${testcvs} add .." \
-"${PROG} [a-z]*: cannot add special file .\.\..; skipping"
- # Make sure that none of the error messages left droppings
- # which interfere with normal operation.
- dotest errmsg2-7 "${testcvs} -q ci -m add-file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- mkdir sdir
- cd ..
- dotest errmsg2-8 "${testcvs} add first-dir/sdir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/sdir added to the repository"
- # while we're here... check commit with no CVS directory
- dotest_fail errmsg2-8a "${testcvs} -q ci first-dir nonexistant" \
-"${PROG} [a-z]*: nothing known about .nonexistant'
-${PROG} \[[a-z]* aborted\]: correct above errors first!"
- dotest_fail errmsg2-8b "${testcvs} -q ci nonexistant first-dir" \
-"${PROG} [a-z]*: nothing known about .nonexistant'
-${PROG} \[[a-z]* aborted\]: correct above errors first!"
- dotest errmsg2-8c "${testcvs} -q ci first-dir" ""
-
- cd first-dir
-
- touch file10
- mkdir sdir10
- dotest errmsg2-10 "${testcvs} add file10 sdir10" \
-"${PROG} add: scheduling file .file10. for addition
-Directory ${CVSROOT_DIRNAME}/first-dir/sdir10 added to the repository
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest errmsg2-11 "${testcvs} -q ci -m add-file10" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file10,v
-done
-Checking in file10;
-${CVSROOT_DIRNAME}/first-dir/file10,v <-- file10
-initial revision: 1\.1
-done"
- # Try to see that there are no droppings left by
- # any of the previous tests.
- dotest errmsg2-12 "${testcvs} -q update" ""
-
- # Now test adding files with '/' in the name, both one level
- # down and more than one level down.
- cd ..
- mkdir first-dir/sdir10/ssdir
- dotest errmsg2-13 "${testcvs} add first-dir/sdir10/ssdir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/sdir10/ssdir added to the repository"
-
- touch first-dir/sdir10/ssdir/ssfile
- dotest errmsg2-14 \
- "${testcvs} add first-dir/sdir10/ssdir/ssfile" \
-"${PROG} add: scheduling file .first-dir/sdir10/ssdir/ssfile. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- touch first-dir/file15
- dotest errmsg2-15 "${testcvs} add first-dir/file15" \
-"${PROG} add: scheduling file .first-dir/file15. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
-
- # Now the case where we try to give it a directory which is not
- # under CVS control.
- mkdir bogus-dir
- touch bogus-dir/file16
- # The first message, from local CVS, is nice. The second one
- # is not nice; would be good to fix remote CVS to give a clearer
- # message (e.g. the one from local CVS). But at least it is an
- # error message.
- dotest_fail errmsg2-16 "${testcvs} add bogus-dir/file16" \
-"${PROG} add: in directory bogus-dir:
-${PROG} \[add aborted\]: there is no version here; do .${PROG} checkout. first" \
-"${PROG} add: cannot open CVS/Entries for reading: No such file or directory
-${PROG} \[add aborted\]: no repository"
- rm -r bogus-dir
-
- # One error condition we don't test for is trying to add a file
- # or directory which already is there.
-
- dotest errmsg2-17 "${testcvs} -q ci -m checkin" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file15,v
-done
-Checking in first-dir/file15;
-${CVSROOT_DIRNAME}/first-dir/file15,v <-- file15
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/sdir10/ssdir/ssfile,v
-done
-Checking in first-dir/sdir10/ssdir/ssfile;
-${CVSROOT_DIRNAME}/first-dir/sdir10/ssdir/ssfile,v <-- ssfile
-initial revision: 1\.1
-done"
- dotest errmsg2-18 "${testcvs} -Q tag test" ''
-
- # trying to import the repository
-
- if $remote; then :; else
- cd ${CVSROOT_DIRNAME}
- dotest_fail errmsg2-20 "${testcvs} import -mtest . A B" \
-"${PROG} \[import aborted\]: attempt to import the repository"
- dotest_fail errmsg2-21 "${testcvs} import -mtest first-dir A B" \
-"${PROG} \[import aborted\]: attempt to import the repository"
- fi
-
- cd ..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- adderrmsg)
- # Test some of the error messages the 'add' command can return and
- # their reactions to '-q'.
-
- # First the usual setup; create a directory first-dir.
- mkdir 1; cd 1
- dotest adderrmsg-init1 "${testcvs} -q co -l ." ''
- mkdir adderrmsg-dir
- dotest adderrmsg-init2 "${testcvs} add adderrmsg-dir" \
-"Directory ${CVSROOT_DIRNAME}/adderrmsg-dir added to the repository"
- cd adderrmsg-dir
-
- # try to add the admin dir
- dotest_fail adderrmsg-1 "${testcvs} add CVS" \
-"${PROG} [a-z]*: cannot add special file .CVS.; skipping"
- # might not want to see this message when you 'cvs add *'
- dotest_fail adderrmsg-2 "${testcvs} -q add CVS" ""
-
- # to test some other messages
- touch file1
- dotest adderrmsg-3 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
-
- # add it twice
- dotest_fail adderrmsg-4 "${testcvs} add file1" \
-"${PROG} add: file1 has already been entered"
- dotest_fail adderrmsg-5 "${testcvs} -q add file1" ""
-
- dotest adderrmsg-6 "${testcvs} -q ci -madd" \
-"RCS file: ${CVSROOT_DIRNAME}/adderrmsg-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/adderrmsg-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
-
- # file in Entries & repository
- dotest_fail adderrmsg-7 "${testcvs} add file1" \
-"${PROG} add: file1 already exists, with version number 1\.1"
- dotest_fail adderrmsg-8 "${testcvs} -q add file1" ""
-
- # clean up
- cd ../..
- if $keep; then :; else
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/adderrmsg-dir
- fi
- ;;
-
- opterrmsg)
- # Test some option parsing error messages
-
- # No init is necessary since these error messages are printed b4
- # CVS looks for a sandbox or repository
-
- # -z used to accept non-numeric arguments. This bit someone who
- # attempted `cvs -z -n up' when the -n was read as the argument to
- # -z.
- dotest_fail opterrmsg-1 "${testcvs} -z -n up" \
-"${PROG}: gzip compression level must be between 0 and 9"
-
- # Some general -z checks
- dotest_fail opterrmsg-2 "${testcvs} -z -1 up" \
-"${PROG}: gzip compression level must be between 0 and 9"
- dotest_fail opterrmsg-3 "${testcvs} -z10 up" \
-"${PROG}: gzip compression level must be between 0 and 9"
- ;;
-
- devcom)
- mkdir ${CVSROOT_DIRNAME}/first-dir
- mkdir 1
- cd 1
- dotest devcom-1 "${testcvs} -q co first-dir"
-
- cd first-dir
- echo abb >abb
- dotest devcom-2 "${testcvs} add abb" \
-"$PROG add: scheduling file \`abb' for addition
-$PROG add: use '$PROG commit' to add this file permanently"
-
- dotest devcom-3 "${testcvs} -q ci -m added" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/abb,v
-done
-Checking in abb;
-${CVSROOT_DIRNAME}/first-dir/abb,v <-- abb
-initial revision: 1\.1
-done"
-
- dotest_fail devcom-4 "${testcvs} watch" "Usage${DOTSTAR}"
-
- dotest devcom-5 "${testcvs} watch on"
-
- echo abc >abc
- dotest devcom-6 "${testcvs} add abc" \
-"$PROG add: scheduling file \`abc' for addition
-$PROG add: use '$PROG commit' to add this file permanently"
-
- dotest devcom-7 "${testcvs} -q ci -m added" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/abc,v
-done
-Checking in abc;
-${CVSROOT_DIRNAME}/first-dir/abc,v <-- abc
-initial revision: 1\.1
-done"
-
- cd ../..
- mkdir 2
- cd 2
-
- dotest devcom-8 "${testcvs} -q co first-dir" \
-"U first-dir/abb
-U first-dir/abc"
-
- cd first-dir
- dotest_fail devcom-9 "test -w abb"
- dotest_fail devcom-9 "test -w abc"
-
- dotest devcom-10 "${testcvs} editors" ""
-
- dotest devcom-11 "${testcvs} edit abb"
-
- # 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-12 "${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
- dotest devcom-13 "${testcvs} ci -m modify abb" \
-"Checking in abb;
-${CVSROOT_DIRNAME}/first-dir/abb,v <-- abb
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # Unedit of a file not being edited should be a noop.
- dotest devcom-14 "${testcvs} unedit abb" ''
-
- dotest devcom-15 "${testcvs} editors" ""
-
- dotest_fail devcom-16 "test -w abb"
-
- dotest devcom-17 "${testcvs} edit abc"
-
- # Unedit of an unmodified file.
- dotest devcom-18 "${testcvs} unedit abc"
- dotest devcom-19 "${testcvs} edit abc"
-
- echo changedabc >abc
- # Try to unedit a modified file; cvs should ask for confirmation
- dotest devcom-20 "echo no | ${testcvs} unedit abc" \
-"abc has been modified; revert changes? "
-
- dotest devcom-21 "echo changedabc | cmp - abc"
-
- # OK, now confirm the unedit
- dotest devcom-22 "echo yes | ${testcvs} unedit abc" \
-"abc has been modified; revert changes? "
-
- dotest devcom-23 "echo abc | cmp - abc"
-
- dotest devcom-24 "${testcvs} watchers" ''
-
- # FIXME: This probably should be an error message instead
- # of silently succeeding and printing nothing.
- dotest devcom-a-nonexist "${testcvs} watchers nonexist" ''
-
- dotest devcom-a1 "${testcvs} watch add" ''
- dotest devcom-a2 "${testcvs} watchers" \
-"abb ${username} edit unedit commit
-abc ${username} edit unedit commit"
- dotest devcom-a3 "${testcvs} watch remove -a unedit abb" ''
- dotest devcom-a4 "${testcvs} watchers abb" \
-"abb ${username} edit commit"
-
- # Check tagging and checking out while we have a CVS
- # directory in the repository.
- dotest devcom-t0 "${testcvs} -q tag tag" \
-'T abb
-T abc'
- cd ../..
- mkdir 3
- cd 3
-
- # Test commented out because the bug it tests for is not fixed
- # The error is:
- # cvs watchers: cannot open CVS/Entries for reading: No such file or directory
- # cvs: ../../work/ccvs/src/fileattr.c:75: fileattr_read: Assertion `fileattr_stored_repos != ((void *)0)' failed.
-: dotest devcom-t-nonexist "${testcvs} watchers nonexist" fixme
-
- dotest devcom-t1 "${testcvs} -q co -rtag first-dir/abb" \
-'U first-dir/abb'
- cd ..
- # Since first-dir/abb is readonly, use -f.
- rm -rf 3
-
- # Test checking out the directory rather than the file.
- mkdir 3
- cd 3
- dotest devcom-t2 "${testcvs} -q co -rtag first-dir" \
-'U first-dir/abb
-U first-dir/abc'
- cd ..
- # Since the files are readonly, use -f.
- rm -rf 3
-
- # Now do it again, after removing the val-tags file created
- # by devcom-t1 to force CVS to search the repository
- # containing CVS directories.
- rm -f ${CVSROOT_DIRNAME}/CVSROOT/val-tags
- mkdir 3
- cd 3
- dotest devcom-t3 "${testcvs} -q co -rtag first-dir" \
-'U first-dir/abb
-U first-dir/abc'
- cd ..
- # Since the files are readonly, use -f.
- rm -rf 3
-
- # Now remove all the file attributes
- cd 2/first-dir
- dotest devcom-b0 "${testcvs} watch off" ''
- dotest devcom-b1 "${testcvs} watch remove" ''
- # Test that CVS 1.6 and earlier can handle the repository.
- dotest_fail devcom-b2 "test -d ${CVSROOT_DIRNAME}/first-dir/CVS"
-
- # Now test watching just some, not all, files.
- dotest devcom-some0 "${testcvs} watch on abc" ''
- cd ../..
- mkdir 3
- cd 3
- dotest devcom-some1 "${testcvs} -q co first-dir" 'U first-dir/abb
-U first-dir/abc'
- dotest devcom-some2 "test -w first-dir/abb" ''
- dotest_fail devcom-some3 "test -w first-dir/abc" ''
- cd ..
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- # Use -f because of the readonly files.
- rm -rf 1 2 3
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- devcom2)
- # More watch tests, most notably setting watches on
- # files in various different states.
- mkdir ${CVSROOT_DIRNAME}/first-dir
- mkdir 1
- cd 1
- dotest devcom2-1 "${testcvs} -q co first-dir" ''
- cd first-dir
-
- # This should probably be an error; setting a watch on a totally
- # unknown file is more likely to be a typo than intentional.
- # But that isn't the currently implemented behavior.
- dotest devcom2-2 "${testcvs} watch on w1" ''
-
- touch w1 w2 w3 nw1
- dotest devcom2-3 "${testcvs} add w1 w2 w3 nw1" "${DOTSTAR}"
- # Letting the user set the watch here probably can be considered
- # a feature--although it leads to a few potentially strange
- # consequences like one user can set the watch and another actually
- # adds the file.
- dotest devcom2-4 "${testcvs} watch on w2" ''
- dotest devcom2-5 "${testcvs} -q ci -m add-them" "${DOTSTAR}"
-
- # Note that this test differs in a subtle way from devcom-some0;
- # in devcom-some0 the watch is creating a new fileattr file, and
- # here we are modifying an existing one.
- dotest devcom2-6 "${testcvs} watch on w3" ''
-
- # Now test that all the watches got set on the correct files
- # FIXME: CVS should have a way to report whether watches are
- # set, I think. The "check it out and see if it read-only" is
- # sort of OK, but is complicated by CVSREAD and doesn't help
- # if the file is added and not yet committed or some such.
- # Probably "cvs status" should report "watch: on" if watch is on
- # (and nothing if watch is off, so existing behavior is preserved).
- cd ../..
- mkdir 2
- cd 2
- dotest devcom2-7 "${testcvs} -q co first-dir" 'U first-dir/nw1
-U first-dir/w1
-U first-dir/w2
-U first-dir/w3'
- dotest devcom2-8 "test -w first-dir/nw1" ''
- dotest_fail devcom2-9 "test -w first-dir/w1" ''
- dotest_fail devcom2-10 "test -w first-dir/w2" ''
- dotest_fail devcom2-11 "test -w first-dir/w3" ''
-
- cd first-dir
- # OK, now we want to try files in various states with cvs edit.
- dotest devcom2-12 "${testcvs} edit w4" \
-"${PROG} edit: no such file w4; ignored"
- # Try the same thing with a per-directory watch set.
- dotest devcom2-13 "${testcvs} watch on" ''
- dotest devcom2-14 "${testcvs} edit w5" \
-"${PROG} edit: no such file w5; ignored"
- dotest devcom2-15 "${testcvs} editors" ''
- dotest devcom2-16 "${testcvs} editors w4" ''
- # Make sure there are no droppings lying around
- dotest devcom2-17 "cat ${CVSROOT_DIRNAME}/first-dir/CVS/fileattr" \
-"Fw1 _watched=
-Fw2 _watched=
-Fw3 _watched=
-Fnw1 _watched=
-D _watched="
- cd ..
-
- # Do a little error testing
- dotest devcom2-18 "${testcvs} -q co -d first+dir first-dir" \
-"U first${PLUS}dir/nw1
-U first${PLUS}dir/w1
-U first${PLUS}dir/w2
-U first${PLUS}dir/w3"
- cd first+dir
- dotest_fail devcom2-19 "${testcvs} edit" \
-"${PROG} \[[a-z]* aborted\]: current directory (${TESTDIR}/2/first${PLUS}dir) contains an invalid character (${PLUS},>;=\\\\t\\\\n)"
-
- # Make sure there are no droppings lying around
- dotest devcom2-20 "cat ${CVSROOT_DIRNAME}/first-dir/CVS/fileattr" \
-"Fw1 _watched=
-Fw2 _watched=
-Fw3 _watched=
-Fnw1 _watched=
-D _watched="
-
- cd ../..
-
- # Use -f because of the readonly files.
- rm -rf 1 2
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- devcom3)
- # More watch tests, most notably handling of features designed
- # for future expansion.
- mkdir ${CVSROOT_DIRNAME}/first-dir
- mkdir 1
- cd 1
- dotest devcom3-1 "${testcvs} -q co first-dir" ''
- cd first-dir
-
- touch w1 w2
- dotest devcom3-2 "${testcvs} add w1 w2" "${DOTSTAR}"
- dotest devcom3-3 "${testcvs} watch on w1 w2" ''
- dotest devcom3-4 "${testcvs} -q ci -m add-them" "${DOTSTAR}"
-
- # OK, since we are about to delve into CVS's internals, make
- # sure that we seem to be correct about how they work.
- dotest devcom3-5 "cat ${CVSROOT_DIRNAME}/first-dir/CVS/fileattr" \
-"Fw1 _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
-Enew line here
-G@#$^!@#=&
-EOF
- # Now get CVS to write to the fileattr file....
- dotest devcom3-6 "${testcvs} watch off w1" ''
- # ...and make sure that it hasn't clobbered our new lines.
- # Note that writing these lines in another order would be OK
- # too.
- dotest devcom3-7 "cat ${CVSROOT_DIRNAME}/first-dir/CVS/fileattr" \
-"Fw2 _watched=
-G@#..!@#=&
-Enew line here"
-
- # See what CVS does when a file name is duplicated. The
- # behavior of all versions of CVS since file attributes were
- # implemented is that it nukes the duplications. This seems
- # reasonable enough, although it means it isn't clear how
- # useful duplicates would be for purposes of future
- # expansion. But in the interests of keeping behaviors
- # predictable, might as well test for it, I guess.
- echo 'Fw2 duplicate=' >>${CVSROOT_DIRNAME}/first-dir/CVS/fileattr
- dotest devcom3-8 "${testcvs} watch on w1" ''
- dotest devcom3-9 "cat ${CVSROOT_DIRNAME}/first-dir/CVS/fileattr" \
-"Fw2 _watched=
-Fw1 _watched=
-Enew line here
-G@#..!@#=&"
-
- # Now test disconnected "cvs edit" and the format of the
- # CVS/Notify file.
- if $remote; then
- CVS_SERVER_save=${CVS_SERVER}
- CVS_SERVER=${TESTDIR}/cvs-none; export CVS_SERVER
-
- # The ${DOTSTAR} below matches the exact CVS server error message,
- # which in :fork: mode is:
- # "$PROG \[edit aborted\]: cannot exec $TESTDIR/cvs-none: ${DOTSTAR}",
- # but which is:
- # "bash2: line 1: $TESTDIR/cvs-none: No such file or directory"
- # when testing across an :ext:/ssh link to my Linux 2.4 box.
- #
- # I can't even test for the second part of the error message,
- # from the client, which varies more consistently, usually either
- # "end of file from server" (if the process doing the exec exits
- # before the parent gets around to sending data to it) or
- # "received broken pipe signal" (if it is the other way around),
- # since HP-UX fails to output it.
- dotest_fail devcom3-9ar "${testcvs} edit w1 2>/dev/null"
- dotest devcom3-9br "test -w w1" ""
- dotest devcom3-9cr "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_save}; export CVS_SERVER
- dotest devcom3-9dr "${testcvs} -q update" ""
- dotest_fail devcom3-9er "test -f CVS/Notify" ""
- dotest devcom3-9fr "${testcvs} watchers w1" \
-"w1 ${username} tedit tunedit tcommit"
- dotest devcom3-9gr "${testcvs} unedit w1" ""
- dotest devcom3-9hr "${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
- # not lose its mind).
- sed -e 's/Fw2 /Fw2 /' <${CVSROOT_DIRNAME}/first-dir/CVS/fileattr \
- >${CVSROOT_DIRNAME}/first-dir/CVS/fileattr.new
- mv ${CVSROOT_DIRNAME}/first-dir/CVS/fileattr.new \
- ${CVSROOT_DIRNAME}/first-dir/CVS/fileattr
- mkdir 2; cd 2
- dotest_fail devcom3-10 "${testcvs} -Q co ." \
-"${PROG} \[checkout aborted\]: file attribute database corruption: tab missing in ${CVSROOT_DIRNAME}/first-dir/CVS/fileattr"
- cd ..
-
- # Use -f because of the readonly files.
- rm -rf 1 2
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- watch4)
- # More watch tests, including adding directories.
- mkdir 1; cd 1
- dotest watch4-0a "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest watch4-0b "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
-
- cd first-dir
- dotest watch4-1 "${testcvs} watch on" ''
- # This is just like the 173 test
- touch file1
- dotest watch4-2 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest watch4-3 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- # Now test the analogous behavior for directories.
- mkdir subdir
- dotest watch4-4 "${testcvs} add subdir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/subdir added to the repository"
- cd subdir
- touch sfile
- dotest watch4-5 "${testcvs} add sfile" \
-"${PROG} add: scheduling file .sfile. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest watch4-6 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/subdir/sfile,v
-done
-Checking in sfile;
-${CVSROOT_DIRNAME}/first-dir/subdir/sfile,v <-- sfile
-initial revision: 1\.1
-done"
- cd ../../..
- mkdir 2; cd 2
- dotest watch4-7 "${testcvs} -q co first-dir" "U first-dir/file1
-U first-dir/subdir/sfile"
- dotest_fail watch4-8 "test -w first-dir/file1" ''
- dotest_fail watch4-9 "test -w first-dir/subdir/sfile" ''
- cd first-dir
- dotest watch4-10 "${testcvs} edit file1" ''
- echo 'edited in 2' >file1
- cd ../..
-
- cd 1/first-dir
- dotest watch4-11 "${testcvs} edit file1" ''
- echo 'edited in 1' >file1
- dotest watch4-12 "${testcvs} -q ci -m edit-in-1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
- cd ../..
- cd 2/first-dir
- dotest watch4-13 "${testcvs} -q update" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-retrieving revision 1\.1
-retrieving revision 1\.2
-Merging differences between 1\.1 and 1\.2 into file1
-rcsmerge: warning: conflicts during merge
-${PROG} update: conflicts found in file1
-C file1"
- if (echo yes | ${testcvs} unedit file1) >>${LOGFILE}; then
- pass watch4-14
- else
- fail watch4-15
- fi
- # This could plausibly be defined to either go back to the revision
- # which was cvs edit'd (the status quo), or back to revision 1.2
- # (that is, the merge could update CVS/Base/file1). We pick the
- # former because it is easier to implement, not because we have
- # thought much about which is better.
- dotest watch4-16 "cat file1" ''
- # Make sure CVS really thinks we are at 1.1.
- dotest watch4-17 "${testcvs} -q update" "U file1"
- dotest watch4-18 "cat file1" "edited in 1"
- cd ../..
-
- # As a sanity check, make sure we are in the right place.
- dotest watch4-cleanup-1 "test -d 1" ''
- dotest watch4-cleanup-1 "test -d 2" ''
- # Specify -f because of the readonly files.
- rm -rf 1 2
- 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 ${CVSROOT_DIRNAME}/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} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest watch5-3 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/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
- ;;
-
-
-
- watch6)
- # Check that `cvs watch on' does not reset the fileattr file.
- mkdir watch6; cd watch6
-
- dotest watch6-setup-1 "$testcvs -Q co -ldtop ."
- cd top
- mkdir watch6
- dotest watch6-setup-2 "$testcvs -Q add watch6"
-
- cd ..
- dotest watch6-setup-3 "$testcvs -Q co watch6"
- cd watch6
-
- mkdir subdir
- dotest watch6-setup-4 "$testcvs -Q add subdir"
- cd subdir
-
- # START watch add/remove sequence
- dotest watch6-1 "$testcvs -Q watch add"
- dotest watch6-2 \
-"grep '_watchers' $CVSROOT_DIRNAME/watch6/subdir/CVS/fileattr >/dev/null"
-
- dotest watch6-3 "$testcvs watch on"
- dotest watch6-4 \
-"grep '_watchers' $CVSROOT_DIRNAME/watch6/subdir/CVS/fileattr >/dev/null"
- dotest watch6-5 \
-"grep '_watched' $CVSROOT_DIRNAME/watch6/subdir/CVS/fileattr >/dev/null"
-
- dotest watch6-6 "$testcvs watch off"
- dotest watch6-7 \
-"grep '_watchers' $CVSROOT_DIRNAME/watch6/subdir/CVS/fileattr >/dev/null"
- dotest_fail watch6-8 \
-"grep '_watched' $CVSROOT_DIRNAME/watch6/subdir/CVS/fileattr >/dev/null"
-
- dotest watch6-9 "$testcvs watch remove"
- dotest_fail watch6-10 \
-"test -d $CVSROOT_DIRNAME/test-directory/subdir/CVS"
- dotest_fail watch6-11 \
-"test -f $CVSROOT_DIRNAME/test-directory/subdir/CVS/fileattr"
- # END watch add/remove sequence
-
- echo Hi there >afile
- dotest watch6-12 "$testcvs -Q add afile"
- dotest watch6-13 "$testcvs ci -m 'A file' afile" \
-"RCS file: $CVSROOT_DIRNAME/watch6/subdir/afile,v
-done
-Checking in afile;
-$CVSROOT_DIRNAME/watch6/subdir/afile,v <-- afile
-initial revision: 1\.1
-done"
-
- # START watch add/remove sequence
- dotest watch6-14 "$testcvs -Q watch add"
- dotest watch6-15 \
-"grep '_watchers' $CVSROOT_DIRNAME/watch6/subdir/CVS/fileattr >/dev/null"
-
- dotest watch6-16 "$testcvs watch on"
- dotest watch6-17 \
-"grep '_watchers' $CVSROOT_DIRNAME/watch6/subdir/CVS/fileattr >/dev/null"
- dotest watch6-18 \
-"grep '_watched' $CVSROOT_DIRNAME/watch6/subdir/CVS/fileattr >/dev/null"
-
- dotest watch6-19 "$testcvs watch off"
- dotest watch6-20 \
-"grep '_watchers' $CVSROOT_DIRNAME/watch6/subdir/CVS/fileattr >/dev/null"
- dotest_fail watch6-21 \
-"grep '_watched' $CVSROOT_DIRNAME/watch6/subdir/CVS/fileattr >/dev/null"
-
- dotest watch6-22 "$testcvs watch remove"
- dotest_fail watch6-23 \
-"test -d $CVSROOT_DIRNAME/test-directory/subdir/CVS"
- dotest_fail watch6-24 \
-"test -f $CVSROOT_DIRNAME/test-directory/subdir/CVS/fileattr"
- # END watch add/remove sequence
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
- cd ../../..
- rm -r watch6
- rm -rf $CVSROOT_DIRNAME/watch6
- ;;
-
-
-
- unedit-without-baserev)
- mkdir 1; cd 1
- module=x
-
- file=m
- echo foo > $file
- dotest unedit-without-baserev-1 \
- "$testcvs -Q import -m . $module X Y" ''
- dotest unedit-without-baserev-2 "$testcvs -Q co $module" ''
- cd $module
-
- dotest unedit-without-baserev-3 "$testcvs -Q edit $file" ''
-
- echo add a line >> $file
- rm -f CVS/Baserev
-
- # This will fail on most systems.
- echo "yes" | dotest unedit-without-baserev-4 "${testcvs} -Q unedit $file" \
-"m has been modified; revert changes${QUESTION} ${PROG} unedit: m not mentioned in CVS/Baserev
-${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/${DOTSTAR}"
-
- dotest unedit-without-baserev-6 "${testcvs} -q update" \
-"${PROG} update: warning: m was lost
-U m"
-
- # OK, those were the easy cases. Now tackle the hard one
- # (the reason that CVS/Baserev was invented rather than just
- # getting the revision from CVS/Entries). This is very
- # similar to watch4-10 through watch4-18 but with Baserev
- # missing.
- cd ../..
- mkdir 2; cd 2
- dotest unedit-without-baserev-7 "${testcvs} -Q co x" ''
- cd x
-
- dotest unedit-without-baserev-10 "${testcvs} edit m" ''
- echo 'edited in 2' >m
- cd ../..
-
- cd 1/x
- dotest unedit-without-baserev-11 "${testcvs} edit m" ''
- echo 'edited in 1' >m
- dotest unedit-without-baserev-12 "${testcvs} -q ci -m edit-in-1" \
-"Checking in m;
-${CVSROOT_DIRNAME}/x/m,v <-- m
-new revision: 1\.2; previous revision: 1\.1
-done"
- cd ../..
- cd 2/x
- dotest unedit-without-baserev-13 "${testcvs} -q update" \
-"RCS file: ${CVSROOT_DIRNAME}/x/m,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.2
-Merging differences between 1\.1\.1\.1 and 1\.2 into m
-rcsmerge: warning: conflicts during merge
-${PROG} update: conflicts found in m
-C m"
- rm CVS/Baserev
- dotest unedit-without-baserev-14 "echo yes | ${testcvs} unedit m" \
-"m has been modified; revert changes${QUESTION} ${PROG} unedit: m not mentioned in CVS/Baserev
-${PROG} unedit: run update to complete the unedit"
- dotest unedit-without-baserev-15 "${testcvs} -q update" \
-"${PROG} update: warning: m was lost
-U m"
- # The following tests are kind of degenerate compared with
- # watch4-16 through watch4-18 but might as well make sure that
- # nothing seriously wrong has happened to the working directory.
- dotest unedit-without-baserev-16 "cat m" 'edited in 1'
- # Make sure CVS really thinks we are at 1.2.
- dotest unedit-without-baserev-17 "${testcvs} -q update" ""
- dotest unedit-without-baserev-18 "cat m" "edited in 1"
-
- cd ../..
- rm -rf 1
- rm -r 2
- rm -rf ${CVSROOT_DIRNAME}/$module
- ;;
-
- ignore)
- # On Windows, we can't check out CVSROOT, because the case
- # insensitivity means that this conflicts with cvsroot.
- mkdir ignore
- cd ignore
-
- dotest ignore-1 "${testcvs} -q co CVSROOT" "U CVSROOT/${DOTSTAR}"
- cd CVSROOT
- echo rootig.c >cvsignore
- dotest ignore-2 "${testcvs} add cvsignore" \
-"${PROG}"' add: scheduling file `cvsignore'"'"' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
-
- # As of Jan 96, local CVS prints "Examining ." and remote doesn't.
- # Accept either.
- dotest ignore-3 " ${testcvs} ci -m added" \
-"${PROG} [a-z]*: Examining \.
-RCS file: ${CVSROOT_DIRNAME}/CVSROOT/cvsignore,v
-done
-Checking in cvsignore;
-${CVSROOT_DIRNAME}/CVSROOT/cvsignore,v <-- cvsignore
-initial revision: 1\.1
-done
-${PROG} commit: Rebuilding administrative file database"
-
- cd ..
- if echo "yes" | ${testcvs} release -d CVSROOT >>${LOGFILE} ; then
- pass ignore-4
- else
- fail ignore-4
- fi
-
- # CVS looks at the home dir from getpwuid, not HOME (is that correct
- # behavior?), so this is hard to test and we won't try.
- # echo foobar.c >${HOME}/.cvsignore
- CVSIGNORE=envig.c; export CVSIGNORE
- mkdir dir-to-import
- cd dir-to-import
- touch foobar.c bar.c rootig.c defig.o envig.c optig.c
- # We use sort because we can't predict the order in which
- # the files will be listed.
- dotest_sort ignore-5 "${testcvs} import -m m -I optig.c ignore/first-dir tag1 tag2" \
-'
-
-I ignore/first-dir/defig.o
-I ignore/first-dir/envig.c
-I ignore/first-dir/optig.c
-I ignore/first-dir/rootig.c
-N ignore/first-dir/bar.c
-N ignore/first-dir/foobar.c
-No conflicts created by this import'
- dotest_sort ignore-6 "${testcvs} import -m m -I ! ignore/second-dir tag3 tag4" \
-'
-
-N ignore/second-dir/bar.c
-N ignore/second-dir/defig.o
-N ignore/second-dir/envig.c
-N ignore/second-dir/foobar.c
-N ignore/second-dir/optig.c
-N ignore/second-dir/rootig.c
-No conflicts created by this import'
- cd ..
- rm -r dir-to-import
-
- mkdir 1
- cd 1
- dotest ignore-7 "${testcvs} -q co -dsecond-dir ignore/second-dir" \
-'U second-dir/bar.c
-U second-dir/defig.o
-U second-dir/envig.c
-U second-dir/foobar.c
-U second-dir/optig.c
-U second-dir/rootig.c'
- dotest ignore-8 "${testcvs} -q co -dfirst-dir ignore/first-dir" 'U first-dir/bar.c
-U first-dir/foobar.c'
- cd first-dir
- touch rootig.c defig.o envig.c optig.c notig.c
- dotest ignore-9 "${testcvs} -q update -I optig.c" "${QUESTION} notig.c"
- # The fact that CVS requires us to specify -I CVS here strikes me
- # as a bug.
- dotest_sort ignore-10 "${testcvs} -q update -I ! -I CVS" \
-"${QUESTION} defig.o
-${QUESTION} envig.c
-${QUESTION} notig.c
-${QUESTION} optig.c
-${QUESTION} rootig.c"
-
- # Now test that commands other than update also print "? notig.c"
- # where appropriate. Only test this for remote, because local
- # CVS only prints it on update.
- rm optig.c
- if $remote; then
- dotest ignore-11r "${testcvs} -q diff" "${QUESTION} notig.c"
-
- # Force the server to be contacted. Ugh. Having CVS
- # contact the server for the sole purpose of checking
- # the CVSROOT/cvsignore file does not seem like such a
- # good idea, so I imagine this will continue to be
- # necessary. Oh well, at least we test CVS's ablity to
- # handle a file with a modified timestamp but unmodified
- # contents.
- touch bar.c
-
- dotest ignore-11r "${testcvs} -q ci -m commit-it" "${QUESTION} notig.c"
- fi
-
- # now test .cvsignore files
- cd ..
- echo notig.c >first-dir/.cvsignore
- echo foobar.c >second-dir/.cvsignore
- touch first-dir/notig.c second-dir/notig.c second-dir/foobar.c
- dotest_sort ignore-12 "${testcvs} -qn update" \
-"${QUESTION} first-dir/.cvsignore
-${QUESTION} second-dir/.cvsignore
-${QUESTION} second-dir/notig.c"
- dotest_sort ignore-13 "${testcvs} -qn update -I! -I CVS" \
-"${QUESTION} first-dir/.cvsignore
-${QUESTION} first-dir/defig.o
-${QUESTION} first-dir/envig.c
-${QUESTION} first-dir/rootig.c
-${QUESTION} second-dir/.cvsignore
-${QUESTION} second-dir/notig.c"
-
- echo yes | dotest ignore-14 "${testcvs} release -d first-dir" \
-"${QUESTION} \.cvsignore
-You have \[0\] altered files in this repository.
-Are you sure you want to release (and delete) directory .first-dir': "
-
- echo add a line >>second-dir/foobar.c
- rm second-dir/notig.c second-dir/.cvsignore
- echo yes | dotest ignore-15 "${testcvs} release -d second-dir" \
-"M foobar.c
-You have \[1\] altered files in this repository.
-Are you sure you want to release (and delete) directory .second-dir': "
-
- cd ../..
- if $keep; then :; else
- rm -r ignore
- rm -rf ${CVSROOT_DIRNAME}/ignore
- fi
- ;;
-
- ignore-on-branch)
- # Test that CVS _doesn't_ ignore files on branches because they were
- # added to the trunk.
- mkdir ignore-on-branch; cd ignore-on-branch
- mkdir $CVSROOT_DIRNAME/ignore-on-branch
-
- # create file1 & file2 on trunk
- dotest ignore-on-branch-setup-1 "$testcvs -q co -dsetup ignore-on-branch" ''
- cd setup
- echo file1 >file1
- dotest ignore-on-branch-setup-2 "$testcvs -q add file1" \
-"${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest ignore-on-branch-setup-3 "$testcvs -q ci -mfile1 file1" \
-"RCS file: $CVSROOT_DIRNAME/ignore-on-branch/file1,v
-done
-Checking in file1;
-$CVSROOT_DIRNAME/ignore-on-branch/file1,v <-- file1
-initial revision: 1\.1
-done"
- dotest ignore-on-branch-setup-4 "$testcvs -q tag -b branch" 'T file1'
- echo file2 >file2
- dotest ignore-on-branch-setup-5 "$testcvs -q add file2" \
-"${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest ignore-on-branch-setup-6 "$testcvs -q ci -mtrunk file2" \
-"RCS file: $CVSROOT_DIRNAME/ignore-on-branch/file2,v
-done
-Checking in file2;
-$CVSROOT_DIRNAME/ignore-on-branch/file2,v <-- file2
-initial revision: 1\.1
-done"
-
- cd ..
-
- # Check out branch.
- #
- # - This was the original failure case - file2 would not be flagged
- # with a '?'
- dotest ignore-on-branch-1 "$testcvs -q co -rbranch ignore-on-branch" \
-'U ignore-on-branch/file1'
- cd ignore-on-branch
- echo file2 on branch >file2
- dotest ignore-on-branch-2 "$testcvs -nq update" '? file2'
-
- # Now set up for a join. One of the original fixes for this would
- # print out a 'U' and a '?' during a join which added a file.
- if $remote; then
- dotest ignore-on-branch-3 "$testcvs -q tag -b branch2" \
-'? file2
-T file1'
- else
- dotest ignore-on-branch-3 "$testcvs -q tag -b branch2" 'T file1'
- fi
- dotest ignore-on-branch-4 "$testcvs -q add file2" \
-"${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest ignore-on-branch-5 "$testcvs -q ci -mbranch file2" \
-"Checking in file2;
-$CVSROOT_DIRNAME/ignore-on-branch/file2,v <-- file2
-new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
-done"
- dotest ignore-on-branch-6 "$testcvs -q up -rbranch2" \
-"[UP] file1
-$PROG update: file2 is no longer in the repository"
- dotest ignore-on-branch-7 "$testcvs -q up -jbranch" 'U file2'
-
- cd ../..
- if $keep; then :; else
- rm -r ignore-on-branch
- rm -rf $CVSROOT_DIRNAME/ignore-on-branch
- fi
- ;;
-
- 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", 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
- dotest binfiles-2 "${testcvs} add -kb binfile" \
-"${PROG}"' add: scheduling file `binfile'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest binfiles-3 "${testcvs} -q ci -m add-it" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/binfile,v
-done
-Checking in binfile;
-${CVSROOT_DIRNAME}/first-dir/binfile,v <-- binfile
-initial revision: 1\.1
-done"
- cd ../..
- mkdir 2; cd 2
- dotest binfiles-4 "${testcvs} -q co first-dir" 'U first-dir/binfile'
- cd first-dir
- dotest binfiles-5 "cmp ../../1/binfile.dat binfile" ''
- # Testing that sticky options is -kb is the closest thing we have
- # to testing that binary files work right on non-unix machines
- # (until there is automated testing for such machines, of course).
- dotest binfiles-5.5 "${testcvs} status binfile" \
-"===================================================================
-File: binfile Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/binfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: -kb"
-
- # Test that "-kk" does not override "-kb"
- cd ../..
- mkdir 2a; cd 2a
- dotest binfiles-5.5a0 "${testcvs} -q co -kk first-dir" 'U first-dir/binfile'
- cd first-dir
- # Testing that sticky options is -kb is the closest thing we have
- # to testing that binary files work right on non-unix machines
- # (until there is automated testing for such machines, of course).
- dotest binfiles-5.5a1 "${testcvs} status binfile" \
-"===================================================================
-File: binfile Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/binfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: -kb"
-
- # Test whether the default options from the RCS file are
- # also used when operating on files instead of whole
- # directories
- cd ../..
- mkdir 3; cd 3
- dotest binfiles-5.5b0 "${testcvs} -q co first-dir/binfile" \
-'U first-dir/binfile'
- cd first-dir
- dotest binfiles-5.5b1 "${testcvs} status binfile" \
-"===================================================================
-File: binfile Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/binfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: -kb"
- cd ../..
- rm -r 3
- # test that "-kk" does not override "-kb"
- mkdir 3; cd 3
- dotest binfiles-5.5c0 "${testcvs} -q co -kk first-dir/binfile" \
-'U first-dir/binfile'
- cd first-dir
- dotest binfiles-5.5c1 "${testcvs} status binfile" \
-"===================================================================
-File: binfile Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/binfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: -kb"
- cd ../..
- rm -r 3
- cd 2/first-dir
-
- cp ../../1/binfile2.dat binfile
- dotest binfiles-6 "${testcvs} -q ci -m modify-it" \
-"Checking in binfile;
-${CVSROOT_DIRNAME}/first-dir/binfile,v <-- binfile
-new revision: 1\.2; previous revision: 1\.1
-done"
- cd ../../1/first-dir
- dotest binfiles-7 "${testcvs} -q update" '[UP] binfile'
- dotest binfiles-8 "cmp ../binfile2.dat binfile" ''
-
- # Now test handling of conflicts with binary files.
- cp ../binfile.dat binfile
- dotest binfiles-con0 "${testcvs} -q ci -m modify-it" \
-"Checking in binfile;
-${CVSROOT_DIRNAME}/first-dir/binfile,v <-- binfile
-new revision: 1\.3; previous revision: 1\.2
-done"
- cd ../../2/first-dir
- echo 'edits in dir 2' >binfile
- dotest binfiles-con1 "${testcvs} -q update" \
-"$PROG update: nonmergeable file needs merge
-${PROG} update: revision 1\.3 from repository is now in binfile
-${PROG} update: file from working directory is now in \.#binfile\.1\.2
-C binfile"
-
- dotest_fail binfiles-con1b "$testcvs -q up" "C binfile"
-
- dotest binfiles-con2 "cmp binfile ../../1/binfile.dat" ''
- dotest binfiles-con3 "cat .#binfile.1.2" 'edits in dir 2'
-
- cp ../../1/binfile2.dat binfile
- dotest binfiles-con4 "${testcvs} -q ci -m resolve-it" \
-"Checking in binfile;
-${CVSROOT_DIRNAME}/first-dir/binfile,v <-- binfile
-new revision: 1\.4; previous revision: 1\.3
-done"
- cd ../../1/first-dir
- dotest binfiles-con5 "${testcvs} -q update" '[UP] binfile'
-
- dotest binfiles-9 "${testcvs} -q update -A" ''
- # "-kk" no longer does anything with "-kb"
- dotest binfiles-10 "${testcvs} -q update -kk" ''
- dotest binfiles-11 "${testcvs} -q update" ''
- # "-kk" no longer does anything with "-kb"
- dotest binfiles-12 "${testcvs} -q update -A" ''
- dotest binfiles-13 "${testcvs} -q update -A" ''
-
- cd ../..
-
- mkdir 3
- cd 3
- dotest binfiles-13a0 "${testcvs} -q co -r HEAD first-dir" \
-'U first-dir/binfile'
- cd first-dir
- dotest binfiles-13a1 "${testcvs} status binfile" \
-"===================================================================
-File: binfile Status: Up-to-date
-
- Working revision: 1\.4.*
- Repository revision: 1\.4 ${CVSROOT_DIRNAME}/first-dir/binfile,v
- Sticky Tag: HEAD (revision: 1\.4)
- Sticky Date: (none)
- Sticky Options: -kb"
- cd ../..
- rm -r 3
-
- cd 2/first-dir
- echo 'this file is $''RCSfile$' >binfile
- dotest binfiles-14a "${testcvs} -q ci -m modify-it" \
-"Checking in binfile;
-${CVSROOT_DIRNAME}/first-dir/binfile,v <-- binfile
-new revision: 1\.5; previous revision: 1\.4
-done"
- dotest binfiles-14b "cat binfile" 'this file is $''RCSfile$'
- # See binfiles-5.5 for discussion of -kb.
- dotest binfiles-14c "${testcvs} status binfile" \
-"===================================================================
-File: binfile Status: Up-to-date
-
- Working revision: 1\.5.*
- Repository revision: 1\.5 ${CVSROOT_DIRNAME}/first-dir/binfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: -kb"
- dotest binfiles-14d "${testcvs} admin -kv binfile" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/binfile,v
-done"
- # cvs admin doesn't change the checked-out file or its sticky
- # kopts. There probably should be a way which does (but
- # what if the file is modified? And do we try to version
- # control the kopt setting?)
- dotest binfiles-14e "cat binfile" 'this file is $''RCSfile$'
- dotest binfiles-14f "${testcvs} status binfile" \
-"===================================================================
-File: binfile Status: Up-to-date
-
- Working revision: 1\.5.*
- Repository revision: 1\.5 ${CVSROOT_DIRNAME}/first-dir/binfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: -kb"
- dotest binfiles-14g "${testcvs} -q update -A" '[UP] binfile'
- dotest binfiles-14h "cat binfile" 'this file is binfile,v'
- dotest binfiles-14i "${testcvs} status binfile" \
-"===================================================================
-File: binfile Status: Up-to-date
-
- Working revision: 1\.5.*
- Repository revision: 1\.5 ${CVSROOT_DIRNAME}/first-dir/binfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: -kv"
-
- # Do sticky options work when used with 'cvs update'?
- echo "Not a binary file." > nibfile
- dotest binfiles-sticky1 "${testcvs} -q add nibfile" \
-"${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest binfiles-sticky2 "${testcvs} -q ci -m add-it nibfile" \
- "RCS file: ${CVSROOT_DIRNAME}/first-dir/nibfile,v
-done
-Checking in nibfile;
-${CVSROOT_DIRNAME}/first-dir/nibfile,v <-- nibfile
-initial revision: 1\.1
-done"
- dotest binfiles-sticky3 "${testcvs} -q update -kb nibfile" \
- '[UP] nibfile'
- dotest binfiles-sticky4 "${testcvs} -q status nibfile" \
-"===================================================================
-File: nibfile Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/nibfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: -kb"
-
- # Now test that -A can clear the sticky option.
- dotest binfiles-sticky5 "${testcvs} -q update -A nibfile" \
-"[UP] nibfile"
- dotest binfiles-sticky6 "${testcvs} -q status nibfile" \
-"===================================================================
-File: nibfile Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/nibfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest binfiles-15 "${testcvs} -q admin -kb nibfile" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/nibfile,v
-done"
- dotest binfiles-16 "${testcvs} -q update nibfile" "[UP] nibfile"
- dotest binfiles-17 "${testcvs} -q status nibfile" \
-"===================================================================
-File: nibfile Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/nibfile,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: -kb"
-
- dotest binfiles-o1 "${testcvs} admin -o1.3:: binfile" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/binfile,v
-deleting revision 1\.5
-deleting revision 1\.4
-done"
- dotest binfiles-o2 "${testcvs} admin -o::1.3 binfile" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/binfile,v
-deleting revision 1\.2
-deleting revision 1\.1
-done"
- dotest binfiles-o3 "${testcvs} -q log -h -N binfile" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/binfile,v
-Working file: binfile
-head: 1\.3
-branch:
-locks: strict
-access list:
-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
- ;;
-
- binfiles2)
- # Test cvs's ability to handle binary files, particularly branching
- # and joining. The key thing we are worrying about is that CVS
- # doesn't print "cannot merge binary files" or some such, in
- # situations where no merging is required.
- # See also "join" which does this with non-binary files.
- #
- # Cases (we are merging from the branch to the trunk):
- # binfile.dat) File added on branch, not on trunk.
- # File should be marked for addition.
- # brmod) File modified on branch, not on trunk.
- # File should be copied over to trunk (no merging is needed).
- # brmod-trmod) File modified on branch, also on trunk.
- # This is a conflict. Present the user with both files and
- # let them figure it out.
- # brmod-wdmod) File modified on branch, not modified in the trunk
- # repository, but modified in the (trunk) working directory.
- # This is also a conflict.
-
- mkdir ${CVSROOT_DIRNAME}/first-dir
- mkdir 1; cd 1
- dotest binfiles2-1 "${testcvs} -q co first-dir" ''
- cd first-dir
-
- # The most important thing here is that binfile, binfile2, &c
- # 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", 2, 10, 137, 13, 10 }' \
- </dev/null | ${TR} '@' '\000' >../binfile
- cat ../binfile ../binfile >../binfile2
- cat ../binfile2 ../binfile >../binfile3
-
- # FIXCVS: unless a branch has at least one file on it,
- # tag_check_valid won't know it exists. So if brmod didn't
- # exist, we would have to invent it.
- cp ../binfile brmod
- cp ../binfile brmod-trmod
- cp ../binfile brmod-wdmod
- dotest binfiles2-1a \
-"${testcvs} add -kb brmod brmod-trmod brmod-wdmod" \
-"${PROG} add: scheduling file .brmod. for addition
-${PROG} add: scheduling file .brmod-trmod. for addition
-${PROG} add: scheduling file .brmod-wdmod. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest binfiles2-1b "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/brmod,v
-done
-Checking in brmod;
-${CVSROOT_DIRNAME}/first-dir/brmod,v <-- brmod
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v
-done
-Checking in brmod-trmod;
-${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v <-- brmod-trmod
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/brmod-wdmod,v
-done
-Checking in brmod-wdmod;
-${CVSROOT_DIRNAME}/first-dir/brmod-wdmod,v <-- brmod-wdmod
-initial revision: 1\.1
-done"
- dotest binfiles2-2 "${testcvs} -q tag -b br" 'T brmod
-T brmod-trmod
-T brmod-wdmod'
- dotest binfiles2-3 "$testcvs -q update -r br" \
-'U brmod
-U brmod-trmod
-U brmod-wdmod'
- cp ../binfile binfile.dat
- dotest binfiles2-4 "${testcvs} add -kb binfile.dat" \
-"${PROG} add: scheduling file .binfile\.dat. for addition on branch .br.
-${PROG} add: use .${PROG} commit. to add this file permanently"
- cp ../binfile2 brmod
- cp ../binfile2 brmod-trmod
- cp ../binfile2 brmod-wdmod
- dotest binfiles2-5 "${testcvs} -q ci -m br-changes" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/binfile\.dat,v
-done
-Checking in binfile\.dat;
-${CVSROOT_DIRNAME}/first-dir/Attic/binfile\.dat,v <-- binfile\.dat
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in brmod;
-${CVSROOT_DIRNAME}/first-dir/brmod,v <-- brmod
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in brmod-trmod;
-${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v <-- brmod-trmod
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in brmod-wdmod;
-${CVSROOT_DIRNAME}/first-dir/brmod-wdmod,v <-- brmod-wdmod
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
- dotest binfiles2-6 "${testcvs} -q update -A" \
-"${PROG} update: binfile\.dat is no longer in the repository
-[UP] brmod
-[UP] brmod-trmod
-[UP] brmod-wdmod"
- dotest_fail binfiles2-7 "test -f binfile.dat" ''
- dotest binfiles2-7-brmod "cmp ../binfile brmod"
- cp ../binfile3 brmod-trmod
- dotest binfiles2-7a "${testcvs} -q ci -m tr-modify" \
-"Checking in brmod-trmod;
-${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v <-- brmod-trmod
-new revision: 1\.2; previous revision: 1\.1
-done"
- cp ../binfile3 brmod-wdmod
-
- dotest binfiles2-8 "${testcvs} -q update -j br" \
-"U binfile\.dat
-U brmod
-${PROG} update: nonmergeable file needs merge
-${PROG} update: revision 1.1.2.1 from repository is now in brmod-trmod
-${PROG} update: file from working directory is now in .#brmod-trmod.1.2
-C brmod-trmod
-M brmod-wdmod
-${PROG} update: nonmergeable file needs merge
-${PROG} update: revision 1.1.2.1 from repository is now in brmod-wdmod
-${PROG} update: file from working directory is now in .#brmod-wdmod.1.1
-C brmod-wdmod"
-
- dotest binfiles2-9 "cmp ../binfile binfile.dat"
- dotest binfiles2-9-brmod "cmp ../binfile2 brmod"
- dotest binfiles2-9-brmod-trmod "cmp ../binfile2 brmod-trmod"
- dotest binfiles2-9-brmod-trmod "cmp ../binfile2 brmod-wdmod"
- dotest binfiles2-9a-brmod-trmod "cmp ../binfile3 .#brmod-trmod.1.2"
- dotest binfiles2-9a-brmod-wdmod "cmp ../binfile3 .#brmod-wdmod.1.1"
-
- # Test that everything was properly scheduled.
- dotest binfiles2-10 "${testcvs} -q ci -m checkin" \
-"Checking in binfile\.dat;
-${CVSROOT_DIRNAME}/first-dir/binfile\.dat,v <-- binfile\.dat
-new revision: 1\.2; previous revision: 1\.1
-done
-Checking in brmod;
-${CVSROOT_DIRNAME}/first-dir/brmod,v <-- brmod
-new revision: 1\.2; previous revision: 1\.1
-done
-Checking in brmod-trmod;
-${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v <-- brmod-trmod
-new revision: 1\.3; previous revision: 1\.2
-done
-Checking in brmod-wdmod;
-${CVSROOT_DIRNAME}/first-dir/brmod-wdmod,v <-- brmod-wdmod
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- dotest_fail binfiles2-o1 "${testcvs} -q admin -o :1.2 brmod-trmod" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v
-deleting revision 1\.2
-${PROG} admin: ${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v: can't remove branch point 1\.1
-${PROG} admin: RCS file for .brmod-trmod. not modified\."
- dotest binfiles2-o2 "${testcvs} -q admin -o 1.1.2.1: brmod-trmod" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v
-deleting revision 1\.1\.2\.1
-done"
- dotest binfiles2-o3 "${testcvs} -q admin -o :1.2 brmod-trmod" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v
-deleting revision 1\.2
-deleting revision 1\.1
-done"
- dotest binfiles2-o4 "${testcvs} -q log -N brmod-trmod" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v
-Working file: brmod-trmod
-head: 1\.3
-branch:
-locks: strict
-access list:
-keyword substitution: b
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.3
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-checkin
-============================================================================="
- cd ..
- cd ..
-
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- 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} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest binfiles3-3 "${testcvs} -q ci -m add-it" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- rm file1
- dotest binfiles3-4 "${testcvs} rm file1" \
-"${PROG} remove: scheduling .file1. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest binfiles3-5 "${testcvs} -q ci -m remove-it" \
-"Removing file1;
-${CVSROOT_DIRNAME}/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} add: Re-adding file .file1. (in place of dead revision 1\.2)\.
-${PROG} add: 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} commit: changing keyword expansion mode to -kb
-Checking in file1;
-${CVSROOT_DIRNAME}/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: ${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/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: ${CVSROOT_DIRNAME}/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
- # -m 'COPY' in wrappers. Similar to the binfiles2 test,
- # which tests the same thing for binary files
- # (which are non-mergeable in the same sense).
- #
- # Cases (we are merging from the branch to the trunk):
- # brmod) File modified on branch, not on trunk.
- # File should be copied over to trunk (no merging is needed).
- # brmod-trmod) File modified on branch, also on trunk.
- # This is a conflict. Present the user with both files and
- # let them figure it out.
- # brmod-wdmod) File modified on branch, not modified in the trunk
- # repository, but modified in the (trunk) working directory.
- # This is also a conflict.
-
- # For the moment, remote CVS can't pass wrappers from CVSWRAPPERS
- # (see wrap_send). So skip these tests for remote.
- if $remote; then :; else
-
- mkdir ${CVSROOT_DIRNAME}/first-dir
- mkdir 1; cd 1
- dotest mcopy-1 "${testcvs} -q co first-dir" ''
- cd first-dir
-
- # FIXCVS: unless a branch has at least one file on it,
- # tag_check_valid won't know it exists. So if brmod didn't
- # exist, we would have to invent it.
- echo 'brmod initial contents' >brmod
- echo 'brmod-trmod initial contents' >brmod-trmod
- echo 'brmod-wdmod initial contents' >brmod-wdmod
- echo "* -m 'COPY'" >.cvswrappers
- dotest mcopy-1a \
-"${testcvs} add .cvswrappers brmod brmod-trmod brmod-wdmod" \
-"${PROG} add: scheduling file .\.cvswrappers. for addition
-${PROG} add: scheduling file .brmod. for addition
-${PROG} add: scheduling file .brmod-trmod. for addition
-${PROG} add: scheduling file .brmod-wdmod. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest mcopy-1b "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/\.cvswrappers,v
-done
-Checking in \.cvswrappers;
-${CVSROOT_DIRNAME}/first-dir/\.cvswrappers,v <-- \.cvswrappers
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/brmod,v
-done
-Checking in brmod;
-${CVSROOT_DIRNAME}/first-dir/brmod,v <-- brmod
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v
-done
-Checking in brmod-trmod;
-${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v <-- brmod-trmod
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/brmod-wdmod,v
-done
-Checking in brmod-wdmod;
-${CVSROOT_DIRNAME}/first-dir/brmod-wdmod,v <-- brmod-wdmod
-initial revision: 1\.1
-done"
-
- # NOTE: .cvswrappers files are broken (see comment in
- # src/wrapper.c). So doing everything via the environment
- # variable is a workaround. Better would be to test them
- # both.
- CVSWRAPPERS="* -m 'COPY'"
- export CVSWRAPPERS
- dotest mcopy-2 "${testcvs} -q tag -b br" 'T \.cvswrappers
-T brmod
-T brmod-trmod
-T brmod-wdmod'
- dotest mcopy-3 "$testcvs -q update -r br" \
-'U .cvswrappers
-U brmod
-U brmod-trmod
-U brmod-wdmod'
- echo 'modify brmod on br' >brmod
- echo 'modify brmod-trmod on br' >brmod-trmod
- echo 'modify brmod-wdmod on br' >brmod-wdmod
- dotest mcopy-5 "${testcvs} -q ci -m br-changes" \
-"Checking in brmod;
-${CVSROOT_DIRNAME}/first-dir/brmod,v <-- brmod
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in brmod-trmod;
-${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v <-- brmod-trmod
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-Checking in brmod-wdmod;
-${CVSROOT_DIRNAME}/first-dir/brmod-wdmod,v <-- brmod-wdmod
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
- dotest mcopy-6 "$testcvs -q update -A" \
-'U .cvswrappers
-U brmod
-U brmod-trmod
-U brmod-wdmod'
- dotest mcopy-7 "cat brmod brmod-trmod brmod-wdmod" \
-"brmod initial contents
-brmod-trmod initial contents
-brmod-wdmod initial contents"
-
- echo 'modify brmod-trmod again on trunk' >brmod-trmod
- dotest mcopy-7a "${testcvs} -q ci -m tr-modify" \
-"Checking in brmod-trmod;
-${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v <-- brmod-trmod
-new revision: 1\.2; previous revision: 1\.1
-done"
- echo 'modify brmod-wdmod in working dir' >brmod-wdmod
-
- dotest mcopy-8 "${testcvs} -q update -j br" \
-"U brmod
-${PROG} update: nonmergeable file needs merge
-${PROG} update: revision 1.1.2.1 from repository is now in brmod-trmod
-${PROG} update: file from working directory is now in .#brmod-trmod.1.2
-C brmod-trmod
-M brmod-wdmod
-${PROG} update: nonmergeable file needs merge
-${PROG} update: revision 1.1.2.1 from repository is now in brmod-wdmod
-${PROG} update: file from working directory is now in .#brmod-wdmod.1.1
-C brmod-wdmod"
-
- dotest mcopy-9 "cat brmod brmod-trmod brmod-wdmod" \
-"modify brmod on br
-modify brmod-trmod on br
-modify brmod-wdmod on br"
- dotest mcopy-9a "cat .#brmod-trmod.1.2 .#brmod-wdmod.1.1" \
-"modify brmod-trmod again on trunk
-modify brmod-wdmod in working dir"
-
- # Test that everything was properly scheduled.
- dotest mcopy-10 "${testcvs} -q ci -m checkin" \
-"Checking in brmod;
-${CVSROOT_DIRNAME}/first-dir/brmod,v <-- brmod
-new revision: 1\.2; previous revision: 1\.1
-done
-Checking in brmod-trmod;
-${CVSROOT_DIRNAME}/first-dir/brmod-trmod,v <-- brmod-trmod
-new revision: 1\.3; previous revision: 1\.2
-done
-Checking in brmod-wdmod;
-${CVSROOT_DIRNAME}/first-dir/brmod-wdmod,v <-- brmod-wdmod
-new revision: 1\.2; previous revision: 1\.1
-done"
- cd ..
- cd ..
-
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- rm -r 1
- unset CVSWRAPPERS
-
- fi # end of tests to be skipped for remote
-
- ;;
-
- binwrap)
- # Test the ability to specify binary-ness based on file name.
- # See "mwrap" for a list of other wrappers tests.
-
- mkdir dir-to-import
- cd dir-to-import
- touch foo.c foo.exe
-
- # While we're here, test for rejection of duplicate tag names.
- dotest_fail binwrap-0 \
- "${testcvs} import -m msg -I ! first-dir dup dup" \
-"${PROG} \[[a-z]* aborted\]: tag .dup. was specified more than once"
-
- if ${testcvs} import -m message -I ! -W "*.exe -k 'b'" \
- first-dir tag1 tag2 >>${LOGFILE}; then
- pass binwrap-1
- else
- fail binwrap-1
- fi
- cd ..
- rm -r dir-to-import
- dotest binwrap-2 "${testcvs} -q co first-dir" 'U first-dir/foo.c
-U first-dir/foo.exe'
- dotest binwrap-3 "${testcvs} -q status first-dir" \
-"===================================================================
-File: foo\.c Status: Up-to-date
-
- Working revision: 1\.1\.1\.1.*
- Repository revision: 1\.1\.1\.1 ${CVSROOT_DIRNAME}/first-dir/foo\.c,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: foo\.exe Status: Up-to-date
-
- Working revision: 1\.1\.1\.1.*
- Repository revision: 1\.1\.1\.1 ${CVSROOT_DIRNAME}/first-dir/foo\.exe,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: -kb"
- rm -r first-dir
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- binwrap2)
- # Test the ability to specify binary-ness based on file name.
- # See "mwrap" for a list of other wrappers tests.
-
- mkdir dir-to-import
- cd dir-to-import
- touch foo.c foo.exe
-
- # Specify that all files are binary except *.c.
- # The order seems to matter, with the earlier rules taking
- # precedence. I'm not sure whether that is good or not,
- # but it is the current behavior.
- if ${testcvs} import -m message -I ! \
- -W "*.c -k 'o'" -W "* -k 'b'" \
- first-dir tag1 tag2 >>${LOGFILE}; then
- pass binwrap2-1
- else
- fail binwrap2-1
- fi
- cd ..
- rm -r dir-to-import
- dotest binwrap2-2 "${testcvs} -q co first-dir" 'U first-dir/foo.c
-U first-dir/foo.exe'
- dotest binwrap2-3 "${testcvs} -q status first-dir" \
-"===================================================================
-File: foo\.c Status: Up-to-date
-
- Working revision: 1\.1\.1\.1.*
- Repository revision: 1\.1\.1\.1 ${CVSROOT_DIRNAME}/first-dir/foo\.c,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: -ko
-
-===================================================================
-File: foo\.exe Status: Up-to-date
-
- Working revision: 1\.1\.1\.1.*
- Repository revision: 1\.1\.1\.1 ${CVSROOT_DIRNAME}/first-dir/foo\.exe,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: -kb"
- rm -r first-dir
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- binwrap3)
- # Test communication of file-specified -k wrappers between
- # client and server, in `import':
- #
- # 1. Set up a directory tree, populate it with files.
- # 2. Give each directory a different .cvswrappers file.
- # 3. Give the server its own .cvswrappers file.
- # 4. Import the whole tree, see if the right files got set
- # to binary.
- #
- # The tree has a top ("0th") level, and two subdirs, sub1/
- # and sub2/; sub2/ contains directory subsub/. Every
- # directory has a .cvswrappers file as well as regular
- # files.
- #
- # In the file names, "foo-b.*" should end up binary, and
- # "foo-t.*" should end up text. Don't worry about the two
- # letter extensions; they're just there to help me keep
- # things straight.
- #
- # Here's the directory tree:
- #
- # ./
- # .cvswrappers
- # foo-b.c0
- # foo-b.sb
- # foo-t.c1
- # foo-t.st
- #
- # sub1/ sub2/
- # .cvswrappers .cvswrappers
- # foo-b.c1 foo-b.sb
- # foo-b.sb foo-b.st
- # foo-t.c0 foo-t.c0
- # foo-t.st foo-t.c1
- # foo-t.c2
- # foo-t.c3
- #
- # subsub/
- # .cvswrappers
- # foo-b.c3
- # foo-b.sb
- # foo-t.c0
- # foo-t.c1
- # foo-t.c2
- # foo-t.st
-
- binwrap3_line1="This is a test file "
- binwrap3_line2="containing little of use "
- binwrap3_line3="except this non-haiku"
-
- binwrap3_text="${binwrap3_line1}${binwrap3_line2}${binwrap3_line3}"
-
- cd ${TESTDIR}
-
- # On Windows, we can't check out CVSROOT, because the case
- # insensitivity means that this conflicts with cvsroot.
- mkdir wnt
- cd wnt
-
- mkdir binwrap3 # the 0th dir
- mkdir binwrap3/sub1
- mkdir binwrap3/sub2
- mkdir binwrap3/sub2/subsub
-
- echo "bar*" > binwrap3/.cvswrappers
- echo "*.c0 -k 'b'" >> binwrap3/.cvswrappers
- echo "whatever -k 'b'" >> binwrap3/.cvswrappers
- echo ${binwrap3_text} > binwrap3/foo-b.c0
- echo ${binwrap3_text} > binwrap3/bar-t.c0
- echo ${binwrap3_text} > binwrap3/foo-b.sb
- echo ${binwrap3_text} > binwrap3/foo-t.sb
- echo ${binwrap3_text} > binwrap3/foo-t.c1
- echo ${binwrap3_text} > binwrap3/foo-t.st
-
- echo "bar* -k 'kv'" > binwrap3/sub1/.cvswrappers
- echo "*.c1 -k 'b'" >> binwrap3/sub1/.cvswrappers
- echo "whatever -k 'b'" >> binwrap3/sub1/.cvswrappers
- echo ${binwrap3_text} > binwrap3/sub1/foo-b.c1
- echo ${binwrap3_text} > binwrap3/sub1/bar-t.c1
- echo ${binwrap3_text} > binwrap3/sub1/foo-b.sb
- echo ${binwrap3_text} > binwrap3/sub1/foo-t.sb
- echo ${binwrap3_text} > binwrap3/sub1/foo-t.c0
- echo ${binwrap3_text} > binwrap3/sub1/foo-t.st
-
- echo "bar*" > binwrap3/sub2/.cvswrappers
- echo "*.st -k 'b'" >> binwrap3/sub2/.cvswrappers
- echo ${binwrap3_text} > binwrap3/sub2/foo-b.sb
- echo ${binwrap3_text} > binwrap3/sub2/foo-t.sb
- echo ${binwrap3_text} > binwrap3/sub2/foo-b.st
- echo ${binwrap3_text} > binwrap3/sub2/bar-t.st
- echo ${binwrap3_text} > binwrap3/sub2/foo-t.c0
- echo ${binwrap3_text} > binwrap3/sub2/foo-t.c1
- echo ${binwrap3_text} > binwrap3/sub2/foo-t.c2
- echo ${binwrap3_text} > binwrap3/sub2/foo-t.c3
-
- echo "bar* -k 'kv'" > binwrap3/sub2/subsub/.cvswrappers
- echo "*.c3 -k 'b'" >> binwrap3/sub2/subsub/.cvswrappers
- echo "foo -k 'b'" >> binwrap3/sub2/subsub/.cvswrappers
- echo "c0* -k 'b'" >> binwrap3/sub2/subsub/.cvswrappers
- echo ${binwrap3_text} > binwrap3/sub2/subsub/foo-b.c3
- echo ${binwrap3_text} > binwrap3/sub2/subsub/bar-t.c3
- echo ${binwrap3_text} > binwrap3/sub2/subsub/foo-b.sb
- echo ${binwrap3_text} > binwrap3/sub2/subsub/foo-t.sb
- echo ${binwrap3_text} > binwrap3/sub2/subsub/foo-t.c0
- echo ${binwrap3_text} > binwrap3/sub2/subsub/foo-t.c1
- echo ${binwrap3_text} > binwrap3/sub2/subsub/foo-t.c2
- echo ${binwrap3_text} > binwrap3/sub2/subsub/foo-t.st
-
- # Now set up CVSROOT/cvswrappers, the easy way:
- dotest binwrap3-1 "${testcvs} -q co CVSROOT" "[UP] CVSROOT${DOTSTAR}"
- cd CVSROOT
- # This destroys anything currently in cvswrappers, but
- # presumably other tests will take care of it themselves if
- # they use cvswrappers:
- echo "foo-t.sb" > cvswrappers
- echo "foo*.sb -k 'b'" >> cvswrappers
- dotest binwrap3-2 "${testcvs} -q ci -m cvswrappers-mod" \
-"Checking in cvswrappers;
-${CVSROOT_DIRNAME}/CVSROOT/cvswrappers,v <-- cvswrappers
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ..
-
- # Avoid environmental interference
- CVSWRAPPERS_save=${CVSWRAPPERS}
- unset CVSWRAPPERS
-
- # Do the import
- cd binwrap3
- # Not importing .cvswrappers tests whether the client is really
- # letting the server know "honestly" whether the file is binary,
- # rather than just letting the server see the .cvswrappers file.
- dotest binwrap3-2a \
-"${testcvs} import -m . -I .cvswrappers binwrap3 tag1 tag2" \
-"[NI] ${DOTSTAR}"
-
- # OK, now test "cvs add".
- cd ..
- rm -r binwrap3
- dotest binwrap3-2b "${testcvs} co binwrap3" "${DOTSTAR}"
- cd binwrap3
- cd sub2
- echo "*.newbin -k 'b'" > .cvswrappers
- echo .cvswrappers >.cvsignore
- echo .cvsignore >>.cvsignore
- touch file1.newbin file1.txt
- dotest binwrap3-2c "${testcvs} add file1.newbin file1.txt" \
-"${PROG} add: scheduling file .file1\.newbin. for addition
-${PROG} add: scheduling file .file1\.txt. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest binwrap3-2d "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/binwrap3/sub2/file1\.newbin,v
-done
-Checking in file1\.newbin;
-${CVSROOT_DIRNAME}/binwrap3/sub2/file1\.newbin,v <-- file1\.newbin
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/binwrap3/sub2/file1\.txt,v
-done
-Checking in file1\.txt;
-${CVSROOT_DIRNAME}/binwrap3/sub2/file1\.txt,v <-- file1\.txt
-initial revision: 1\.1
-done"
- cd ..
-
- # Now check out the module and see which files are binary.
- cd ..
- rm -r binwrap3
- dotest binwrap3-3 "${testcvs} co binwrap3" "${DOTSTAR}"
- cd binwrap3
-
- # Running "cvs status" and matching output is too
- # error-prone, too likely to falsely fail. Instead, we'll
- # just grep the Entries lines:
-
- dotest binwrap3-top1 "grep foo-b.c0 ./CVS/Entries" \
- "/foo-b.c0/1.1.1.1/[A-Za-z0-9 :]*/-kb/"
-
- dotest binwrap3-top2 "grep foo-b.sb ./CVS/Entries" \
- "/foo-b.sb/1.1.1.1/[A-Za-z0-9 :]*/-kb/"
-
- dotest binwrap3-top3 "grep foo-t.c1 ./CVS/Entries" \
- "/foo-t.c1/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-top4 "grep foo-t.st ./CVS/Entries" \
- "/foo-t.st/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-top5 "grep foo-t.sb ./CVS/Entries" \
- "/foo-t.sb/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-top6 "grep bar-t.c0 ./CVS/Entries" \
- "/bar-t.c0/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-sub1-1 "grep foo-b.c1 sub1/CVS/Entries" \
- "/foo-b.c1/1.1.1.1/[A-Za-z0-9 :]*/-kb/"
-
- dotest binwrap3-sub1-2 "grep foo-b.sb sub1/CVS/Entries" \
- "/foo-b.sb/1.1.1.1/[A-Za-z0-9 :]*/-kb/"
-
- dotest binwrap3-sub1-3 "grep foo-t.c0 sub1/CVS/Entries" \
- "/foo-t.c0/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-sub1-4 "grep foo-t.st sub1/CVS/Entries" \
- "/foo-t.st/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-sub1-5 "grep foo-t.sb sub1/CVS/Entries" \
- "/foo-t.sb/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-sub1-6 "grep bar-t.c1 sub1/CVS/Entries" \
- "/bar-t.c1/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-sub2-1 "grep foo-b.sb sub2/CVS/Entries" \
- "/foo-b.sb/1.1.1.1/[A-Za-z0-9 :]*/-kb/"
-
- dotest binwrap3-sub2-2 "grep foo-b.st sub2/CVS/Entries" \
- "/foo-b.st/1.1.1.1/[A-Za-z0-9 :]*/-kb/"
-
- dotest binwrap3-sub2-3 "grep foo-t.c0 sub2/CVS/Entries" \
- "/foo-t.c0/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-sub2-4 "grep foo-t.c1 sub2/CVS/Entries" \
- "/foo-t.c1/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-sub2-5 "grep foo-t.c2 sub2/CVS/Entries" \
- "/foo-t.c2/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-sub2-6 "grep foo-t.c3 sub2/CVS/Entries" \
- "/foo-t.c3/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-sub2-7 "grep foo-t.sb sub2/CVS/Entries" \
- "/foo-t.sb/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-sub2-8 "grep bar-t.st sub2/CVS/Entries" \
- "/bar-t.st/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-subsub1 "grep foo-b.c3 sub2/subsub/CVS/Entries" \
- "/foo-b.c3/1.1.1.1/[A-Za-z0-9 :]*/-kb/"
-
- dotest binwrap3-subsub2 "grep foo-b.sb sub2/subsub/CVS/Entries" \
- "/foo-b.sb/1.1.1.1/[A-Za-z0-9 :]*/-kb/"
-
- dotest binwrap3-subsub3 "grep foo-t.c0 sub2/subsub/CVS/Entries" \
- "/foo-t.c0/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-subsub4 "grep foo-t.c1 sub2/subsub/CVS/Entries" \
- "/foo-t.c1/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-subsub5 "grep foo-t.c2 sub2/subsub/CVS/Entries" \
- "/foo-t.c2/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-subsub6 "grep foo-t.st sub2/subsub/CVS/Entries" \
- "/foo-t.st/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-subsub7 "grep foo-t.sb sub2/subsub/CVS/Entries" \
- "/foo-t.sb/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-subsub8 "grep bar-t.c3 sub2/subsub/CVS/Entries" \
- "/bar-t.c3/1.1.1.1/[A-Za-z0-9 :]*//"
-
- dotest binwrap3-sub2-add1 "grep file1.newbin sub2/CVS/Entries" \
- "/file1.newbin/1.1/[A-Za-z0-9 :]*/-kb/"
- dotest binwrap3-sub2-add2 "grep file1.txt sub2/CVS/Entries" \
- "/file1.txt/1.1/[A-Za-z0-9 :]*//"
-
- # Restore and clean up
- cd ..
- rm -r binwrap3 CVSROOT
- cd ..
- rm -r wnt
- rm -rf ${CVSROOT_DIRNAME}/binwrap3
- CVSWRAPPERS=${CVSWRAPPERS_save}
- ;;
-
- mwrap)
- # Tests of various wrappers features:
- # -m 'COPY' and cvs update: mwrap
- # -m 'COPY' and joining: mcopy
- # -k: binwrap, binwrap2
- # -t/-f: hasn't been written yet.
- #
- # Tests of different ways of specifying wrappers:
- # CVSROOT/cvswrappers: mwrap
- # -W: binwrap, binwrap2
- # .cvswrappers in working directory, local: mcopy
- # CVSROOT/cvswrappers, .cvswrappers remote: binwrap3
- # CVSWRAPPERS environment variable: mcopy
-
- # This test is similar to binfiles-con1; -m 'COPY' specifies
- # non-mergeableness the same way that -kb does.
-
- # On Windows, we can't check out CVSROOT, because the case
- # insensitivity means that this conflicts with cvsroot.
- mkdir wnt
- cd wnt
-
- dotest mwrap-c1 "${testcvs} -q co CVSROOT" "[UP] CVSROOT${DOTSTAR}"
- cd CVSROOT
- echo "* -m 'COPY'" >>cvswrappers
- dotest mwrap-c2 "${testcvs} -q ci -m wrapper-mod" \
-"Checking in cvswrappers;
-${CVSROOT_DIRNAME}/CVSROOT/cvswrappers,v <-- cvswrappers
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ..
- mkdir m1; cd m1
- dotest mwrap-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest mwrap-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- touch aa
- dotest mwrap-3 "${testcvs} add aa" \
-"${PROG} add: scheduling file .aa. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest mwrap-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/aa,v
-done
-Checking in aa;
-${CVSROOT_DIRNAME}/first-dir/aa,v <-- aa
-initial revision: 1\.1
-done"
- cd ../..
- mkdir m2; cd m2
- dotest mwrap-5 "${testcvs} -q co first-dir" "U first-dir/aa"
- cd first-dir
- echo "changed in m2" >aa
- dotest mwrap-6 "${testcvs} -q ci -m m2-mod" \
-"Checking in aa;
-${CVSROOT_DIRNAME}/first-dir/aa,v <-- aa
-new revision: 1\.2; previous revision: 1\.1
-done"
- cd ../..
- cd m1/first-dir
- echo "changed in m1" >aa
- dotest mwrap-7 "$testcvs -nq update" \
-"${PROG} update: nonmergeable file needs merge
-${PROG} update: revision 1\.2 from repository is now in aa
-${PROG} update: file from working directory is now in \.#aa\.1\.1
-C aa"
- dotest mwrap-8 "${testcvs} -q update" \
-"$PROG update: nonmergeable file needs merge
-${PROG} update: revision 1\.2 from repository is now in aa
-${PROG} update: file from working directory is now in \.#aa\.1\.1
-C aa"
- dotest mwrap-9 "cat aa" "changed in m2"
- dotest mwrap-10 "cat .#aa.1.1" "changed in m1"
- cd ../..
- cd CVSROOT
- echo '# comment out' >cvswrappers
- dotest mwrap-ce "${testcvs} -q ci -m wrapper-mod" \
-"Checking in cvswrappers;
-${CVSROOT_DIRNAME}/CVSROOT/cvswrappers,v <-- cvswrappers
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ..
- rm -r CVSROOT
- rm -r m1 m2
- cd ..
- rm -r wnt
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- info)
- # Administrative file tests.
- # Here is a list of where each administrative file is tested:
- # loginfo: info
- # modules: modules, modules2, modules3
- # cvsignore: ignore
- # verifymsg: info
- # cvswrappers: mwrap
- # taginfo: taginfo
- # config: config
-
- # On Windows, we can't check out CVSROOT, because the case
- # insensitivity means that this conflicts with cvsroot.
- mkdir wnt
- cd wnt
-
- dotest info-1 "${testcvs} -q co CVSROOT" "[UP] CVSROOT${DOTSTAR}"
- cd CVSROOT
- rm -f $TESTDIR/testlog $TESTDIR/testlog2
- echo "ALL sh -c \"echo x\${=MYENV}\${=OTHER}y\${=ZEE}=\$USER=\$CVSROOT= >>$TESTDIR/testlog; cat >/dev/null\"" > loginfo
- # The following cases test the format string substitution
- echo "ALL echo %{sVv} >>$TESTDIR/testlog2; cat >/dev/null" >> loginfo
- echo "ALL echo %{v} >>$TESTDIR/testlog2; cat >/dev/null" >> loginfo
- echo "ALL echo %s >>$TESTDIR/testlog2; cat >/dev/null" >> loginfo
- echo "ALL echo %{V}AX >>$TESTDIR/testlog2; cat >/dev/null" >> loginfo
- echo "first-dir echo %sux >>$TESTDIR/testlog2; cat >/dev/null" \
- >> loginfo
-
- # Might be nice to move this to crerepos tests; it should
- # work to create a loginfo file if you didn't create one
- # with "cvs init".
- : dotest info-2 "${testcvs} add loginfo" \
-"${PROG}"' add: scheduling file `loginfo'"'"' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
-
- dotest info-3 "${testcvs} -q ci -m new-loginfo" \
-"Checking in loginfo;
-${CVSROOT_DIRNAME}/CVSROOT/loginfo,v <-- loginfo
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ..
-
- mkdir ${CVSROOT_DIRNAME}/first-dir
- dotest info-5 "${testcvs} -q co first-dir" ''
- cd first-dir
- touch file1
- dotest info-6 "${testcvs} add file1" \
-"${PROG}"' add: scheduling file `file1'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- echo "cvs -s OTHER=not-this -s MYENV=env-" >>$HOME/.cvsrc
- dotest info-6a "${testcvs} -q -s OTHER=value ci -m add-it" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done
-${PROG} commit: loginfo:1: no such user variable \${=ZEE}"
- echo line0 >>file1
- dotest info-6b "${testcvs} -q -sOTHER=foo ci -m mod-it" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done
-${PROG} commit: loginfo:1: no such user variable \${=ZEE}"
- echo line1 >>file1
- dotest info-7 "${testcvs} -q -s OTHER=value -s ZEE=z ci -m mod-it" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.3; previous revision: 1\.2
-done"
- cd ..
- dotest info-9 "cat $TESTDIR/testlog" "xenv-valueyz=${username}=${CVSROOT_DIRNAME}="
- dotest info-10 "cat $TESTDIR/testlog2" \
-'first-dir file1,NONE,1.1
-first-dir 1.1
-first-dir file1
-first-dir NONEAX
-first-dir file1ux
-first-dir file1,1.1,1.2
-first-dir 1.2
-first-dir file1
-first-dir 1.1AX
-first-dir file1ux
-first-dir file1,1.2,1.3
-first-dir 1.3
-first-dir file1
-first-dir 1.2AX
-first-dir file1ux'
-
- cd CVSROOT
- echo '# do nothing' >loginfo
- dotest info-11 "${testcvs} -q -s ZEE=garbage ci -m nuke-loginfo" \
-"Checking in loginfo;
-${CVSROOT_DIRNAME}/CVSROOT/loginfo,v <-- loginfo
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
-
- # Now test verifymsg
- cat >${TESTDIR}/vscript <<EOF
-#!${TESTSHELL}
-if sed 1q < \$1 | grep '^BugId:[ ]*[0-9][0-9]*$' > /dev/null; then
- exit 0
-elif sed 1q < \$1 | grep '^BugId:[ ]*new$' > /dev/null; then
- echo A new bugid was found. >> \$1
- exit 0
-else
- echo "No BugId found."
- sleep 1
- exit 1
-fi
-EOF
- cat >${TESTDIR}/vscript2 <<EOF
-#!${TESTSHELL}
-if test -f CVS/Repository; then
- repo=\`cat CVS/Repository\`
-else
- repo=\`pwd\`
-fi
-echo \$repo
-if echo "\$repo" |grep yet-another/ >/dev/null 2>&1; then
- exit 1
-else
- exit 0
-fi
-EOF
- # Grumble, grumble, mumble, search for "Cygwin".
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost "chmod +x ${TESTDIR}/vscript*"
- else
- chmod +x ${TESTDIR}/vscript*
- fi
- echo "^first-dir/yet-another\\(/\\|\$\\) ${TESTDIR}/vscript2" >>verifymsg
- echo "^first-dir\\(/\\|\$\\) ${TESTDIR}/vscript" >>verifymsg
- echo "^missing-script\$ ${TESTDIR}/bogus" >>verifymsg
- echo "^missing-var\$ ${TESTDIR}/vscript \${=Bogus}" >>verifymsg
- # first test the directory independant verifymsg
- dotest info-v1 "${testcvs} -q ci -m add-verification" \
-"Checking in verifymsg;
-${CVSROOT_DIRNAME}/CVSROOT/verifymsg,v <-- verifymsg
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
-
- cd ../first-dir
- echo line2 >>file1
- dotest_fail info-v2 "${testcvs} -q ci -m bogus" \
-"No BugId found\.
-${PROG} \[commit aborted\]: Message verification failed"
-
- cat >${TESTDIR}/comment.tmp <<EOF
-BugId: 42
-and many more lines after it
-EOF
- dotest info-v3 "${testcvs} -q ci -F ${TESTDIR}/comment.tmp" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.4; previous revision: 1\.3
-done"
- rm ${TESTDIR}/comment.tmp
-
- cd ..
- mkdir another-dir
- cd another-dir
- touch file2
- dotest_fail info-v4 \
- "${testcvs} import -m bogus first-dir/another x y" \
-"No BugId found\.
-${PROG} \[import aborted\]: Message verification failed"
-
- # now verify that directory dependent verifymsgs work
- dotest info-v5 \
- "${testcvs} import -m bogus first-dir/yet-another x y" \
-"${TESTDIR}/wnt/another-dir
-N first-dir/yet-another/file2
-
-No conflicts created by this import" \
-"${CVSROOT_DIRNAME}/first-dir/yet-another
-N first-dir/yet-another/file2
-
-No conflicts created by this import"
-
- # FIXMECVS
- #
- # note that in the local case the error message is the same as
- # info-v5
- #
- # This means that the verifymsg scripts cannot reliably and
- # consistantly obtain information on which directory is being
- # committed to. Thus it is currently useless for them to be
- # running in every dir. They should either be run once or
- # directory information should be passed.
- if $remote; then
- dotest_fail info-v6r \
- "${testcvs} import -m bogus first-dir/yet-another/and-another x y" \
-"${CVSROOT_DIRNAME}/first-dir/yet-another/and-another
-${PROG} \[import aborted\]: Message verification failed"
- else
- dotest info-v6 \
- "${testcvs} import -m bogus first-dir/yet-another/and-another x y" \
-"${TESTDIR}/wnt/another-dir
-N first-dir/yet-another/and-another/file2
-
-No conflicts created by this import"
- fi
-
- # check that errors invoking the script cause verification failure
- #
- # The second text below occurs on Cygwin, where I assume execvp
- # does not return to let CVS print the error message when its
- # argument does not exist.
- dotest_fail info-v7 "${testcvs} import -m bogus missing-script x y" \
-"${PROG} import: cannot exec ${TESTDIR}/bogus: No such file or directory
-${PROG} \[import aborted\]: Message verification failed" \
-"${PROG} \[import aborted\]: Message verification failed"
-
- dotest_fail info-v8 "${testcvs} import -m bogus missing-var x y" \
-"${PROG} import: verifymsg:25: no such user variable \${=Bogus}
-${PROG} \[import aborted\]: Message verification failed"
-
- rm file2
- cd ..
- rmdir another-dir
-
- cd CVSROOT
- echo "RereadLogAfterVerify=always" >>config
- dotest info-rereadlog-1 "${testcvs} -q ci -m add-RereadLogAfterVerify=always" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ../first-dir
- echo line3 >>file1
- cat >${TESTDIR}/comment.tmp <<EOF
-BugId: new
-See what happens next.
-EOF
- dotest info-reread-2 "${testcvs} -q ci -F ${TESTDIR}/comment.tmp" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.5; previous revision: 1\.4
-done"
- dotest info-reread-3 "${testcvs} -q log -N -r1.5 file1" "
-.*
-BugId: new
-See what happens next.
-A new bugid was found.
-============================================================================="
-
- cd ../CVSROOT
- grep -v "RereadLogAfterVerify" config > config.new
- mv config.new config
- echo "RereadLogAfterVerify=stat" >>config
- dotest info-reread-4 "${testcvs} -q ci -m add-RereadLogAfterVerify=stat" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ../first-dir
- echo line4 >>file1
- cat >${TESTDIR}/comment.tmp <<EOF
-BugId: new
-See what happens next with stat.
-EOF
- dotest info-reread-5 "${testcvs} -q ci -F ${TESTDIR}/comment.tmp" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.6; previous revision: 1\.5
-done"
- dotest info-reread-6 "${testcvs} -q log -N -r1.6 file1" "
-.*
-BugId: new
-See what happens next with stat.
-A new bugid was found.
-============================================================================="
-
- cd ../CVSROOT
- grep -v "RereadLogAfterVerify" config > config.new
- mv config.new config
- echo "RereadLogAfterVerify=never" >>config
- dotest info-reread-7 "${testcvs} -q ci -m add-RereadLogAfterVerify=never" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ../first-dir
- echo line5 >>file1
- cat >${TESTDIR}/comment.tmp <<EOF
-BugId: new
-See what happens next.
-EOF
- dotest info-reread-8 "${testcvs} -q ci -F ${TESTDIR}/comment.tmp" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.7; previous revision: 1\.6
-done"
- dotest info-reread-6 "${testcvs} -q log -N -r1.7 file1" "
-.*
-BugId: new
-See what happens next.
-============================================================================="
-
- cd ../CVSROOT
- echo 'DEFAULT false' >verifymsg
- echo 'DEFAULT true' >>verifymsg
- echo '# defaults' >config
- dotest info-multdef "${testcvs} -q ci -m multdef" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-Checking in verifymsg;
-${CVSROOT_DIRNAME}/CVSROOT/verifymsg,v <-- verifymsg
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
-
- cd ../CVSROOT
- echo '# do nothing' >verifymsg
- dotest info-cleanup-verifymsg "${testcvs} -q ci -m nuke-verifymsg" \
-"${PROG} commit: Multiple .DEFAULT. lines (1 and 2) in verifymsg file
-Checking in verifymsg;
-${CVSROOT_DIRNAME}/CVSROOT/verifymsg,v <-- verifymsg
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- rm ${TESTDIR}/vscript*
- cd ..
-
- dotest_fail info-cleanup-0 "${testcvs} -n release -d CVSROOT" \
-"${PROG} \[release aborted\]: cannot run command ${DOTSTAR}"
-
- if echo "yes" | ${testcvs} release -d CVSROOT >>${LOGFILE} ; then
- pass info-cleanup
- else
- fail info-cleanup
- fi
- if echo "yes" | ${testcvs} release -d first-dir >>${LOGFILE} ; then
- pass info-cleanup-2
- else
- fail info-cleanup-2
- fi
- cd ..
- rm -r wnt
- rm $HOME/.cvsrc
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- taginfo)
- # Tests of the CVSROOT/taginfo file. See the comment at the
- # "info" tests for a full list of administrative file tests.
-
- # Tests to add:
- # -F to move
-
- mkdir 1; cd 1
- dotest taginfo-1 "${testcvs} -q co CVSROOT" "U CVSROOT/${DOTSTAR}"
- cd CVSROOT
- cat >${TESTDIR}/1/loggit <<EOF
-#!${TESTSHELL}
-if test "\$1" = rejectme; then
- exit 1
-else
- echo "\$@" >>${TESTDIR}/1/taglog
- exit 0
-fi
-EOF
- # #^@&!^@ Cygwin.
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost "chmod +x ${TESTDIR}/1/loggit"
- else
- chmod +x ${TESTDIR}/1/loggit
- fi
- echo "ALL ${TESTDIR}/1/loggit" >taginfo
- dotest taginfo-2 "${testcvs} -q ci -m check-in-taginfo" \
-"Checking in taginfo;
-${CVSROOT_DIRNAME}/CVSROOT/taginfo,v <-- taginfo
-new revision: 1\.2; previous revision: 1\.1
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ..
-
- # taginfo-3 used to rely on the top-level CVS directory
- # being created to add "first-dir" to the repository. Since
- # that won't happen anymore, we create the directory in the
- # repository.
- mkdir ${CVSROOT_DIRNAME}/first-dir
- dotest taginfo-3 "${testcvs} -q co first-dir" ''
-
- cd first-dir
- echo first >file1
- dotest taginfo-4 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest taginfo-5 "${testcvs} -q ci -m add-it" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- dotest taginfo-6 "${testcvs} -q tag tag1" "T file1"
- dotest taginfo-7 "${testcvs} -q tag -b br" "T file1"
- dotest taginfo-8 "$testcvs -q update -r br" '[UP] file1'
- echo add text on branch >>file1
- dotest taginfo-9 "${testcvs} -q ci -m modify-on-br" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
- dotest taginfo-10 "${testcvs} -q tag -F -c brtag" "T file1"
-
- dotest_fail taginfo-11 "${testcvs} -q tag rejectme" \
-"${PROG} tag: Pre-tag check failed
-${PROG} \[tag aborted\]: correct the above errors first!"
-
- # When we are using taginfo to allow/disallow, it would be
- # convenient to be able to use "cvs -n tag" to test whether
- # the allow/disallow functionality is working as expected.
- dotest taginfo-12 "${testcvs} -nq tag rejectme" "T file1"
-
- # But when taginfo is used for logging, it is a pain for -n
- # to call taginfo, since taginfo doesn't know whether -n was
- # 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
- # get. Probably the whole thing should be re-architected
- # so that taginfo only allows/denies tagging, and a new
- # hook, which is done from tag_fileproc, does logging.
- # That would solve this, some more subtle races, and also
- # the fact that it is nice for users to run "-n tag foo" to
- # see whether a tag would be allowed. Failing that,
- # I suppose passing "1.1.branch" or "branch" for "br"
- # would be an improvement.
- dotest taginfo-examine "cat ${TESTDIR}/1/taglog" \
-"tag1 add ${CVSROOT_DIRNAME}/first-dir file1 1.1
-br add ${CVSROOT_DIRNAME}/first-dir file1 1.1
-brtag mov ${CVSROOT_DIRNAME}/first-dir file1 1.1.2.1
-tag1 del ${CVSROOT_DIRNAME}/first-dir file1 1.1
-tag1 del ${CVSROOT_DIRNAME}/first-dir
-tag1 add ${CVSROOT_DIRNAME}/first-dir file1 1.1
-tag1 del ${CVSROOT_DIRNAME}/first-dir file1 1.1
-tag1 del ${CVSROOT_DIRNAME}/first-dir"
-
- cd ..
- cd CVSROOT
- echo '# Keep life simple' > taginfo
- dotest taginfo-cleanup-1 "${testcvs} -q ci -m check-in-taginfo" \
-"Checking in taginfo;
-${CVSROOT_DIRNAME}/CVSROOT/taginfo,v <-- taginfo
-new revision: 1\.3; previous revision: 1\.2
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ..
- cd ..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- config)
- # Tests of the CVSROOT/config file. See the comment at the
- # "info" tests for a full list of administrative file tests.
-
- # On Windows, we can't check out CVSROOT, because the case
- # insensitivity means that this conflicts with cvsroot.
- mkdir wnt
- cd wnt
-
- dotest config-1 "${testcvs} -q co CVSROOT" "U CVSROOT/${DOTSTAR}"
- cd CVSROOT
- echo 'bogus line' >config
- # We can't rely on specific revisions, since other tests
- # might need to modify CVSROOT/config
- dotest config-3 "${testcvs} -q ci -m change-to-bogus-line" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- echo 'BogusOption=yes' >config
- dotest config-4 "${testcvs} -q ci -m change-to-bogus-opt" \
-"${PROG} [a-z]*: syntax error in ${CVSROOT_DIRNAME}/CVSROOT/config: line 'bogus line' is missing '='
-Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- echo '# No config is a good config' > config
- dotest config-5 "${testcvs} -q ci -m change-to-comment" \
-"${PROG} [a-z]*: ${CVSROOT_DIRNAME}/CVSROOT/config: unrecognized keyword 'BogusOption'
-Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- dotest config-6 "${testcvs} -q update" ''
- echo 'IgnoreUnknownConfigKeys=yes' > config
- echo 'BogusOption=yes' >> config
- dotest config-7 "${testcvs} -q ci -m change-to-comment" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- dotest config-8 "${testcvs} -q update" ''
- echo '# No config is a good config' > config
- dotest config-9 "${testcvs} -q ci -m change-to-comment" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- dotest config-10 "${testcvs} -q update" ''
-
- cd ..
- rm -r CVSROOT
- cd ..
- rm -r wnt
- ;;
-
- serverpatch)
- # Test remote CVS handling of unpatchable files. This isn't
- # much of a test for local CVS.
- # We test this with some keyword expansion games, but the situation
- # also arises if the user modifies the file while CVS is running.
- mkdir ${CVSROOT_DIRNAME}/first-dir
- mkdir 1
- cd 1
- dotest serverpatch-1 "${testcvs} -q co first-dir" ''
-
- cd first-dir
-
- # Add a file with an RCS keyword.
- echo '$''Name$' > file1
- echo '1' >> file1
- dotest serverpatch-2 "${testcvs} add file1" \
-"${PROG}"' add: scheduling file `file1'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
-
- dotest serverpatch-3 "${testcvs} -q commit -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
-
- # Tag the file.
- dotest serverpatch-4 "${testcvs} -q tag tag file1" 'T file1'
-
- # Check out a tagged copy of the file.
- cd ../..
- mkdir 2
- cd 2
- dotest serverpatch-5 "${testcvs} -q co -r tag first-dir" \
-'U first-dir/file1'
-
- # Remove the tag. Prior to 1.11.23, this left the tag string in the
- # expansion of the Name keyword.
- dotest serverpatch-6 "$testcvs -q update -A first-dir" \
-'U first-dir/file1'
-
- # Modify and check in the first copy.
- cd ../1/first-dir
- echo '2' >> file1
- dotest serverpatch-7 "${testcvs} -q ci -mx file1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # Now update the second copy. Prior to 1.11.23, the patch would fail
- # using remote CVS, forcing the file to be refetched.
- cd ../../2/first-dir
- dotest serverpatch-8 "${testcvs} -q update" \
-'[UP] file1'
-
- cd ../..
- rm -r 1 2
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- log)
- # Test selecting revisions with cvs log.
- # See also log2 tests for more tests.
- # See also branches-14.3 for logging with a branch off of a branch.
- # See also multibranch-14 for logging with several branches off the
- # same branchpoint.
- # Tests of each option to cvs log:
- # -h: admin-19a-log
- # -N: log, log2, admin-19a-log
- # -b, -r: log
- # -d: logopt, rcs
- # -s: logopt, rcs3
- # -R: logopt, rcs3
- # -w, -t: not tested yet (TODO)
-
- # Check in a file with a few revisions and branches.
- mkdir ${CVSROOT_DIRNAME}/first-dir
- dotest log-1 "${testcvs} -q co first-dir" ''
- cd first-dir
- echo 'first revision' > file1
- echo 'first revision' > file2
- dotest log-2 "${testcvs} add file1 file2" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
-
- # While we're at it, check multi-line comments, input from file,
- # and trailing whitespace trimming
- echo 'line 1 ' >${TESTDIR}/comment.tmp
- echo ' ' >>${TESTDIR}/comment.tmp
- echo 'line 2 ' >>${TESTDIR}/comment.tmp
- echo ' ' >>${TESTDIR}/comment.tmp
- echo ' ' >>${TESTDIR}/comment.tmp
- dotest log-3 "${testcvs} -q commit -F ${TESTDIR}/comment.tmp" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1\.1
-done"
- rm -f ${TESTDIR}/comment.tmp
-
- echo 'second revision' > file1
- echo 'second revision' > file2
- dotest log-4 "${testcvs} -q ci -m2 file1 file2" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- dotest log-5 "${testcvs} -q tag -b branch file1" 'T file1'
- dotest log-5a "${testcvs} -q tag tag1 file2" 'T file2'
-
- echo 'third revision' > file1
- echo 'third revision' > file2
- dotest log-6 "${testcvs} -q ci -m3 file1 file2" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.3; previous revision: 1\.2
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.3; previous revision: 1\.2
-done"
-
- dotest log-6a "${testcvs} -q tag tag2 file2" 'T file2'
-
- dotest log-7 "${testcvs} -q update -r branch" \
-"[UP] file1
-${PROG} update: file2 is no longer in the repository"
-
- echo 'first branch revision' > file1
- dotest log-8 "${testcvs} -q ci -m1b file1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2\.2\.1; previous revision: 1\.2
-done"
-
- dotest log-9 "${testcvs} -q tag tag file1" 'T file1'
-
- echo 'second branch revision' > file1
- dotest log-10 "${testcvs} -q ci -m2b file1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2\.2\.2; previous revision: 1\.2\.2\.1
-done"
-
- # Set up a bunch of shell variables to make the later tests
- # easier to describe.=
- log_header1="
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.3
-branch:
-locks: strict
-access list:"
- rlog_header1="
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-head: 1\.3
-branch:
-locks: strict
-access list:"
- log_tags1='symbolic names:
- tag: 1\.2\.2\.1
- branch: 1\.2\.0\.2'
- log_keyword='keyword substitution: kv'
- log_dash='----------------------------
-revision'
- log_date="date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;"
- log_lines=" lines: ${PLUS}1 -1"
- log_rev1="${log_dash} 1\.1
-${log_date}
-line 1
-
-line 2"
- log_rev2="${log_dash} 1\.2
-${log_date}${log_lines}
-branches: 1\.2\.2;
-2"
- log_rev3="${log_dash} 1\.3
-${log_date}${log_lines}
-3"
- log_rev1b="${log_dash} 1\.2\.2\.1
-${log_date}${log_lines}
-1b"
- log_rev2b="${log_dash} 1\.2\.2\.2
-${log_date}${log_lines}
-2b"
- log_trailer='============================================================================='
-
- # Now, finally, test the log output.
-
- dotest log-11 "${testcvs} log file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 5
-description:
-${log_rev3}
-${log_rev2}
-${log_rev1}
-${log_rev2b}
-${log_rev1b}
-${log_trailer}"
-
- dotest log-12 "${testcvs} log -N file1" \
-"${log_header1}
-${log_keyword}
-total revisions: 5; selected revisions: 5
-description:
-${log_rev3}
-${log_rev2}
-${log_rev1}
-${log_rev2b}
-${log_rev1b}
-${log_trailer}"
-
- dotest log-13 "${testcvs} log -b file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 3
-description:
-${log_rev3}
-${log_rev2}
-${log_rev1}
-${log_trailer}"
-
- dotest log-14 "${testcvs} log -r file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev3}
-${log_trailer}"
-
- dotest log-14a "${testcvs} log -rHEAD file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-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} log: nothing known about HEAD
-${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev3}
-${log_trailer}"
-
-# Check that unusual syntax works correctly.
-
- dotest log-14c "${testcvs} log -r: file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev3}
-${log_trailer}"
- dotest log-14d "${testcvs} log -r, file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev3}
-${log_trailer}"
- dotest log-14e "${testcvs} log -r. file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev3}
-${log_trailer}"
- dotest log-14f "${testcvs} log -r:: file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 0
-description:
-${log_trailer}"
-
- dotest log-15 "${testcvs} log -r1.2 file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev2}
-${log_trailer}"
-
- dotest log-16 "${testcvs} log -r1.2.2 file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev2b}
-${log_rev1b}
-${log_trailer}"
-
- # This test would fail with the old invocation of rlog, but it
- # works with the builtin log support.
- dotest log-17 "${testcvs} log -rbranch file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev2b}
-${log_rev1b}
-${log_trailer}"
-
- dotest log-18 "${testcvs} log -r1.2.2. file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev2b}
-${log_trailer}"
-
- # Multiple -r options are undocumented; see comments in
- # cvs.texinfo about whether they should be deprecated.
- dotest log-18a "${testcvs} log -r1.2.2.2 -r1.3:1.3 file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev3}
-${log_rev2b}
-${log_trailer}"
-
- # This test would fail with the old invocation of rlog, but it
- # works with the builtin log support.
- dotest log-19 "${testcvs} log -rbranch. file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev2b}
-${log_trailer}"
-
- dotest log-20 "${testcvs} log -r1.2: file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev3}
-${log_rev2}
-${log_trailer}"
-
- dotest log-20a "${testcvs} log -r1.2:: file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev3}
-${log_trailer}"
-
- dotest log-21 "${testcvs} log -r:1.2 file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev2}
-${log_rev1}
-${log_trailer}"
-
- dotest log-21a "${testcvs} log -r::1.2 file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev2}
-${log_rev1}
-${log_trailer}"
-
- dotest log-22 "${testcvs} log -r1.1:1.2 file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev2}
-${log_rev1}
-${log_trailer}"
-
- dotest log-22a "${testcvs} log -r1.1::1.2 file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev2}
-${log_trailer}"
-
- dotest log-22b "${testcvs} log -r1.1::1.3 file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev3}
-${log_rev2}
-${log_trailer}"
-
- # Test BASE pseudotag
- dotest log-23 "${testcvs} log -rBASE file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev2b}
-${log_trailer}"
-
- dotest log-24 "${testcvs} -q up -r1.2 file1" "[UP] file1"
- dotest log-25 "${testcvs} log -rBASE file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev2}
-${log_trailer}"
-
- dotest log-26 "${testcvs} -q up -rbranch file1" "[UP] file1"
-
- # Now the same tests but with rlog
-
- dotest log-r11 "${testcvs} rlog first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 5
-description:
-${log_rev3}
-${log_rev2}
-${log_rev1}
-${log_rev2b}
-${log_rev1b}
-${log_trailer}"
-
- dotest log-r12 "${testcvs} rlog -N first-dir/file1" \
-"${rlog_header1}
-${log_keyword}
-total revisions: 5; selected revisions: 5
-description:
-${log_rev3}
-${log_rev2}
-${log_rev1}
-${log_rev2b}
-${log_rev1b}
-${log_trailer}"
-
- dotest log-r13 "${testcvs} rlog -b first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 3
-description:
-${log_rev3}
-${log_rev2}
-${log_rev1}
-${log_trailer}"
-
- dotest log-r14 "${testcvs} rlog -r first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev3}
-${log_trailer}"
-
- dotest log-r14a "${testcvs} rlog -rHEAD first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev3}
-${log_trailer}"
-
- dotest_fail log-r14b "${testcvs} rlog -r HEAD first-dir/file1" \
-"${PROG} rlog: cannot find module .HEAD. - ignored
-${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev3}
-${log_trailer}"
-
- dotest log-r14c "${testcvs} rlog -r: first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev3}
-${log_trailer}"
- dotest log-r14d "${testcvs} rlog -r, first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev3}
-${log_trailer}"
- dotest log-r14e "${testcvs} rlog -r. first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev3}
-${log_trailer}"
- dotest log-r14f "${testcvs} rlog -r:: first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 0
-description:
-${log_trailer}"
-
- dotest log-r15 "${testcvs} rlog -r1.2 first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev2}
-${log_trailer}"
-
- dotest log-r16 "${testcvs} rlog -r1.2.2 first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev2b}
-${log_rev1b}
-${log_trailer}"
-
- dotest log-r17 "${testcvs} rlog -rbranch first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev2b}
-${log_rev1b}
-${log_trailer}"
-
- dotest log-r18 "${testcvs} rlog -r1.2.2. first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev2b}
-${log_trailer}"
-
- dotest log-r18a "${testcvs} rlog -r1.2.2.2 -r1.3:1.3 first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev3}
-${log_rev2b}
-${log_trailer}"
-
- dotest log-r19 "${testcvs} rlog -rbranch. first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev2b}
-${log_trailer}"
-
- dotest log-r20 "${testcvs} rlog -r1.2: first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev3}
-${log_rev2}
-${log_trailer}"
-
- dotest log-r20a "${testcvs} rlog -r1.2:: first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev3}
-${log_trailer}"
-
- dotest log-r21 "${testcvs} rlog -r:1.2 first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev2}
-${log_rev1}
-${log_trailer}"
-
- dotest log-r21a "${testcvs} rlog -r::1.2 first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev2}
-${log_rev1}
-${log_trailer}"
-
- dotest log-r22 "${testcvs} rlog -r1.1:1.2 first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev2}
-${log_rev1}
-${log_trailer}"
-
- dotest log-r22a "${testcvs} rlog -r1.1::1.2 first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 1
-description:
-${log_rev2}
-${log_trailer}"
-
- dotest log-r22b "${testcvs} rlog -r1.1::1.3 first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 2
-description:
-${log_rev3}
-${log_rev2}
-${log_trailer}"
-
- # Test BASE pseudotag
- dotest log-r23 "${testcvs} rlog -rBASE first-dir/file1" \
-"${PROG} rlog: warning: no revision .BASE. in .${CVSROOT_DIRNAME}/first-dir/file1,v.
-${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 0
-description:
-${log_trailer}"
-
- dotest log-r24 "${testcvs} -q up -r1.2 file1" "[UP] file1"
- dotest log-r25 "${testcvs} rlog -rBASE first-dir/file1" \
-"${PROG} rlog: warning: no revision .BASE. in .${CVSROOT_DIRNAME}/first-dir/file1,v.
-${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 0
-description:
-${log_trailer}"
-
- # Test when head is dead
-
- dotest log-d0 "${testcvs} -q up -A" \
-"[UP] file1
-U file2"
- dotest log-d1 "${testcvs} -q rm -f file1" \
-"${PROG} remove: use .${PROG} commit. to remove this file permanently"
- dotest log-d2 "${testcvs} -q ci -m4" \
-"Removing file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: delete; previous revision: 1\.3
-done"
-
- log_header1="
-RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
-Working file: file1
-head: 1\.4
-branch:
-locks: strict
-access list:"
- rlog_header1="
-RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
-head: 1\.4
-branch:
-locks: strict
-access list:"
- log_header2="
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-Working file: file2
-head: 1\.3
-branch:
-locks: strict
-access list:"
- rlog_header2="
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-head: 1\.3
-branch:
-locks: strict
-access list:"
- log_tags2='symbolic names:
- tag2: 1\.3
- tag1: 1\.2'
- log_rev4="${log_dash} 1\.4
-date: [0-9/]* [0-9:]*; author: ${username}; state: dead; lines: ${PLUS}0 -0
-4"
- log_rev22="${log_dash} 1\.2
-${log_date}${log_lines}
-2"
-
- dotest log-d3 "${testcvs} log -rbranch file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 2
-description:
-${log_rev2b}
-${log_rev1b}
-${log_trailer}"
- dotest log-rd3 "${testcvs} rlog -rbranch first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 2
-description:
-${log_rev2b}
-${log_rev1b}
-${log_trailer}"
- dotest log-d4 "${testcvs} -q log -rbranch" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 2
-description:
-${log_rev2b}
-${log_rev1b}
-${log_trailer}
-${PROG} log: warning: no revision .branch. in .${CVSROOT_DIRNAME}/first-dir/file2,v.
-${log_header2}
-${log_tags2}
-${log_keyword}
-total revisions: 3; selected revisions: 0
-description:
-${log_trailer}"
- dotest log-d4a "${testcvs} -q log -t -rbranch" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6
-description:
-${log_trailer}
-${PROG} log: warning: no revision .branch. in .${CVSROOT_DIRNAME}/first-dir/file2,v.
-${log_header2}
-${log_tags2}
-${log_keyword}
-total revisions: 3
-description:
-${log_trailer}"
- dotest log-d4b "${testcvs} -q log -tS -rbranch" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 2
-description:
-${log_trailer}
-${PROG} log: warning: no revision .branch. in .${CVSROOT_DIRNAME}/first-dir/file2,v."
- dotest log-d4c "${testcvs} -q log -h -rbranch" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6
-${log_trailer}
-${PROG} log: warning: no revision .branch. in .${CVSROOT_DIRNAME}/first-dir/file2,v.
-${log_header2}
-${log_tags2}
-${log_keyword}
-total revisions: 3
-${log_trailer}"
- dotest log-d4d "${testcvs} -q log -hS -rbranch" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 2
-${log_trailer}
-${PROG} log: warning: no revision .branch. in .${CVSROOT_DIRNAME}/first-dir/file2,v."
- dotest log-d4e "${testcvs} -q log -R -rbranch" \
-"${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
-${CVSROOT_DIRNAME}/first-dir/file2,v"
- dotest log-d4f "${testcvs} -q log -R -S -rbranch" \
-"${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
-${PROG} log: warning: no revision .branch. in .${CVSROOT_DIRNAME}/first-dir/file2,v."
- dotest log-rd4 "${testcvs} -q rlog -rbranch first-dir" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 2
-description:
-${log_rev2b}
-${log_rev1b}
-${log_trailer}
-${PROG} rlog: warning: no revision .branch. in .${CVSROOT_DIRNAME}/first-dir/file2,v.
-${rlog_header2}
-${log_tags2}
-${log_keyword}
-total revisions: 3; selected revisions: 0
-description:
-${log_trailer}"
- dotest log-rd4a "${testcvs} -q rlog -t -rbranch first-dir" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6
-description:
-${log_trailer}
-${PROG} rlog: warning: no revision .branch. in .${CVSROOT_DIRNAME}/first-dir/file2,v.
-${rlog_header2}
-${log_tags2}
-${log_keyword}
-total revisions: 3
-description:
-${log_trailer}"
- dotest log-rd4b "${testcvs} -q rlog -St -rbranch first-dir" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 2
-description:
-${log_trailer}
-${PROG} rlog: warning: no revision .branch. in .${CVSROOT_DIRNAME}/first-dir/file2,v."
- dotest log-rd4c "${testcvs} -q rlog -h -rbranch first-dir" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6
-${log_trailer}
-${PROG} rlog: warning: no revision .branch. in .${CVSROOT_DIRNAME}/first-dir/file2,v.
-${rlog_header2}
-${log_tags2}
-${log_keyword}
-total revisions: 3
-${log_trailer}"
- dotest log-rd4d "${testcvs} -q rlog -Sh -rbranch first-dir" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 2
-${log_trailer}
-${PROG} rlog: warning: no revision .branch. in .${CVSROOT_DIRNAME}/first-dir/file2,v."
- dotest log-rd4e "${testcvs} -q rlog -R -rbranch first-dir" \
-"${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
-${CVSROOT_DIRNAME}/first-dir/file2,v"
- dotest log-rd4f "${testcvs} -q rlog -R -S -rbranch first-dir" \
-"${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
-${PROG} rlog: warning: no revision .branch. in .${CVSROOT_DIRNAME}/first-dir/file2,v."
- dotest log-d5 "${testcvs} log -r1.2.2.1:1.2.2.2 file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 2
-description:
-${log_rev2b}
-${log_rev1b}
-${log_trailer}"
- dotest log-rd5 "${testcvs} rlog -r1.2.2.1:1.2.2.2 first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 2
-description:
-${log_rev2b}
-${log_rev1b}
-${log_trailer}"
- dotest log-d6 "${testcvs} -q log -r1.2.2.1:1.2.2.2" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 2
-description:
-${log_rev2b}
-${log_rev1b}
-${log_trailer}
-${log_header2}
-${log_tags2}
-${log_keyword}
-total revisions: 3; selected revisions: 0
-description:
-${log_trailer}"
- dotest log-rd6 "${testcvs} -q rlog -r1.2.2.1:1.2.2.2 first-dir" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 2
-description:
-${log_rev2b}
-${log_rev1b}
-${log_trailer}
-${rlog_header2}
-${log_tags2}
-${log_keyword}
-total revisions: 3; selected revisions: 0
-description:
-${log_trailer}"
- dotest log-d7 "${testcvs} log -r1.2:1.3 file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 2
-description:
-${log_rev3}
-${log_rev2}
-${log_trailer}"
- dotest log-rd7 "${testcvs} -q rlog -r1.2:1.3 first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 2
-description:
-${log_rev3}
-${log_rev2}
-${log_trailer}"
- dotest log-d8 "${testcvs} -q log -rtag1:tag2" \
-"${PROG} log: warning: no revision .tag1. in .${CVSROOT_DIRNAME}/first-dir/Attic/file1,v.
-${PROG} log: warning: no revision .tag2. in .${CVSROOT_DIRNAME}/first-dir/Attic/file1,v.
-${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 0
-description:
-${log_trailer}
-${log_header2}
-${log_tags2}
-${log_keyword}
-total revisions: 3; selected revisions: 2
-description:
-${log_rev3}
-${log_rev22}
-${log_trailer}"
- dotest log-d8a "${testcvs} -q log -rtag1:tag2 -S" \
-"${PROG} log: warning: no revision .tag1. in .${CVSROOT_DIRNAME}/first-dir/Attic/file1,v.
-${PROG} log: warning: no revision .tag2. in .${CVSROOT_DIRNAME}/first-dir/Attic/file1,v.
-${log_header2}
-${log_tags2}
-${log_keyword}
-total revisions: 3; selected revisions: 2
-description:
-${log_rev3}
-${log_rev22}
-${log_trailer}"
- dotest log-rd8 "${testcvs} -q rlog -rtag1:tag2 first-dir" \
-"${PROG} rlog: warning: no revision .tag1. in .${CVSROOT_DIRNAME}/first-dir/Attic/file1,v.
-${PROG} rlog: warning: no revision .tag2. in .${CVSROOT_DIRNAME}/first-dir/Attic/file1,v.
-${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 6; selected revisions: 0
-description:
-${log_trailer}
-${rlog_header2}
-${log_tags2}
-${log_keyword}
-total revisions: 3; selected revisions: 2
-description:
-${log_rev3}
-${log_rev22}
-${log_trailer}"
- dotest log-rd8a "${testcvs} -q rlog -rtag1:tag2 -S first-dir" \
-"${PROG} rlog: warning: no revision .tag1. in .${CVSROOT_DIRNAME}/first-dir/Attic/file1,v.
-${PROG} rlog: warning: no revision .tag2. in .${CVSROOT_DIRNAME}/first-dir/Attic/file1,v.
-${rlog_header2}
-${log_tags2}
-${log_keyword}
-total revisions: 3; selected revisions: 2
-description:
-${log_rev3}
-${log_rev22}
-${log_trailer}"
-
- dotest log-d99 "${testcvs} -q up -rbranch" \
-"[UP] file1
-${PROG} update: file2 is no longer in the repository"
-
- # Now test outdating revisions
-
- dotest log-o0 "${testcvs} admin -o 1.2.2.2:: file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
-done"
- dotest log-o1 "${testcvs} admin -o ::1.2.2.1 file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
-done"
- dotest log-o2 "${testcvs} admin -o 1.2.2.1:: file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file1,v
-deleting revision 1\.2\.2\.2
-done"
- dotest log-o3 "${testcvs} log file1" \
-"${log_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 5
-description:
-${log_rev4}
-${log_rev3}
-${log_rev2}
-${log_rev1}
-${log_rev1b}
-${log_trailer}"
- dotest log-ro3 "${testcvs} rlog first-dir/file1" \
-"${rlog_header1}
-${log_tags1}
-${log_keyword}
-total revisions: 5; selected revisions: 5
-description:
-${log_rev4}
-${log_rev3}
-${log_rev2}
-${log_rev1}
-${log_rev1b}
-${log_trailer}"
- dotest log-o4 "${testcvs} -q update -p -r 1.2.2.1 file1" \
-"first branch revision"
-
- cd ..
- rm -r first-dir
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- log2)
- # More "cvs log" tests, for example the file description.
-
- # Check in a file
- mkdir ${CVSROOT_DIRNAME}/first-dir
- dotest log2-1 "${testcvs} -q co first-dir" ''
- cd first-dir
- echo 'first revision' > file1
- dotest log2-2 "${testcvs} add -m file1-is-for-testing file1" \
-"${PROG}"' add: scheduling file `file1'\'' for addition
-'"${PROG}"' add: use .'"${PROG}"' commit. to add this file permanently'
- dotest log2-3 "${testcvs} -q commit -m 1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- # Setting the file description with add -m doesn't yet work
- # client/server, so skip log2-4 for remote.
- if $remote; then :; else
-
- dotest log2-4 "${testcvs} log -N file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-file1-is-for-testing
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-1
-============================================================================="
-
- fi # end of tests skipped for remote
-
- dotest log2-5 "${testcvs} admin -t-change-description file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done"
- dotest log2-6 "${testcvs} log -N file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-change-description
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-1
-============================================================================="
-
- echo 'longer description' >${TESTDIR}/descrip
- echo 'with two lines' >>${TESTDIR}/descrip
- dotest log2-7 "${testcvs} admin -t${TESTDIR}/descrip file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done"
- dotest_fail log2-7a "${testcvs} admin -t${TESTDIR}/nonexist file1" \
-"${PROG} \[[a-z]* aborted\]: can't stat ${TESTDIR}/nonexist: No such file or directory"
- dotest log2-8 "${testcvs} log -N file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-longer description
-with two lines
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-1
-============================================================================="
-
- # 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.
-
- dotest log2-9 "echo change from stdin | ${testcvs} admin -t -q file1" ""
- dotest log2-10 "${testcvs} log -N file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-change from stdin
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-1
-============================================================================="
-
- cd ..
- rm ${TESTDIR}/descrip
- rm -r first-dir
- rm -rf ${CVSROOT_DIRNAME}/first-dir
-
- ;;
-
- logopt)
- # Some tests of log.c's option parsing and such things.
- mkdir 1; cd 1
- dotest logopt-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest logopt-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- echo hi >file1
- dotest logopt-3 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest logopt-4 "${testcvs} -q ci -m add file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- cd ..
-
- dotest logopt-5 "${testcvs} log -R -d 2038-01-01" \
-"${PROG} log: Logging \.
-${PROG} log: Logging first-dir
-${CVSROOT_DIRNAME}/first-dir/file1,v"
- dotest logopt-6 "${testcvs} log -d 2038-01-01 -R" \
-"${PROG} log: Logging \.
-${PROG} log: Logging first-dir
-${CVSROOT_DIRNAME}/first-dir/file1,v"
- dotest logopt-6a "${testcvs} log -Rd 2038-01-01" \
-"${PROG} log: Logging \.
-${PROG} log: Logging first-dir
-${CVSROOT_DIRNAME}/first-dir/file1,v"
- dotest logopt-7 "${testcvs} log -s Exp -R" \
-"${PROG} log: Logging \.
-${PROG} log: Logging first-dir
-${CVSROOT_DIRNAME}/first-dir/file1,v"
-
- cd ..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- ann)
- # 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
- dotest ann-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- cat >file1 <<EOF
-this
-is
-the
-ancestral
-file
-EOF
- dotest ann-3 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest ann-4 "${testcvs} -q ci -m add file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- cat >file1 <<EOF
-this
-is
-a
-file
-
-with
-a
-blank
-line
-EOF
- dotest ann-5 "${testcvs} -q ci -m modify file1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
- dotest ann-6 "${testcvs} -q tag -b br" "T file1"
- cat >file1 <<EOF
-this
-is
-a
-trunk file
-
-with
-a
-blank
-line
-EOF
- dotest ann-7 "${testcvs} -q ci -m modify file1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.3; previous revision: 1\.2
-done"
- dotest ann-8 "${testcvs} -q update -r br" "[UP] file1"
- cat >file1 <<EOF
-this
-is
-a
-file
-
-with
-a
-blank
-line
-and some
-branched content
-EOF
- dotest ann-9 "${testcvs} -q ci -m modify" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2\.2\.1; previous revision: 1\.2
-done"
- # Note that this annotates the trunk despite the presence
- # of a sticky tag in the current directory. This is
- # fairly bogus, but it is the longstanding behavior for
- # whatever that is worth.
- dotest ann-10 "${testcvs} ann" \
-"
-Annotations for file1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-1\.1 ($username8 *[0-9a-zA-Z-]*): this
-1\.1 ($username8 *[0-9a-zA-Z-]*): is
-1\.2 ($username8 *[0-9a-zA-Z-]*): a
-1\.3 ($username8 *[0-9a-zA-Z-]*): trunk file
-1\.2 ($username8 *[0-9a-zA-Z-]*):
-1\.2 ($username8 *[0-9a-zA-Z-]*): with
-1\.2 ($username8 *[0-9a-zA-Z-]*): a
-1\.2 ($username8 *[0-9a-zA-Z-]*): blank
-1\.2 ($username8 *[0-9a-zA-Z-]*): line"
- dotest ann-10blame "${testcvs} blame" \
-"
-Annotations for file1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-1\.1 ($username8 *[0-9a-zA-Z-]*): this
-1\.1 ($username8 *[0-9a-zA-Z-]*): is
-1\.2 ($username8 *[0-9a-zA-Z-]*): a
-1\.3 ($username8 *[0-9a-zA-Z-]*): trunk file
-1\.2 ($username8 *[0-9a-zA-Z-]*):
-1\.2 ($username8 *[0-9a-zA-Z-]*): with
-1\.2 ($username8 *[0-9a-zA-Z-]*): a
-1\.2 ($username8 *[0-9a-zA-Z-]*): blank
-1\.2 ($username8 *[0-9a-zA-Z-]*): line"
- dotest ann-11 "${testcvs} ann -r br" \
-"
-Annotations for file1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-1\.1 ($username8 *[0-9a-zA-Z-]*): this
-1\.1 ($username8 *[0-9a-zA-Z-]*): is
-1\.2 ($username8 *[0-9a-zA-Z-]*): a
-1\.1 ($username8 *[0-9a-zA-Z-]*): file
-1\.2 ($username8 *[0-9a-zA-Z-]*):
-1\.2 ($username8 *[0-9a-zA-Z-]*): with
-1\.2 ($username8 *[0-9a-zA-Z-]*): a
-1\.2 ($username8 *[0-9a-zA-Z-]*): blank
-1\.2 ($username8 *[0-9a-zA-Z-]*): line
-1\.2\.2\.1 ($username8 *[0-9a-zA-Z-]*): and some
-1\.2\.2\.1 ($username8 *[0-9a-zA-Z-]*): branched content"
- # FIXCVS: shouldn't "-r 1.2.0.2" be the same as "-r br"?
- dotest ann-12 "${testcvs} ann -r 1.2.0.2 file1" ""
- dotest ann-13 "${testcvs} ann -r 1.2.2 file1" \
-"
-Annotations for file1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-1\.1 ($username8 *[0-9a-zA-Z-]*): this
-1\.1 ($username8 *[0-9a-zA-Z-]*): is
-1\.2 ($username8 *[0-9a-zA-Z-]*): a
-1\.1 ($username8 *[0-9a-zA-Z-]*): file
-1\.2 ($username8 *[0-9a-zA-Z-]*):
-1\.2 ($username8 *[0-9a-zA-Z-]*): with
-1\.2 ($username8 *[0-9a-zA-Z-]*): a
-1\.2 ($username8 *[0-9a-zA-Z-]*): blank
-1\.2 ($username8 *[0-9a-zA-Z-]*): line
-1\.2\.2\.1 ($username8 *[0-9a-zA-Z-]*): and some
-1\.2\.2\.1 ($username8 *[0-9a-zA-Z-]*): branched content"
- dotest_fail ann-14 "${testcvs} ann -r bill-clintons-chastity file1" \
-"${PROG} \[annotate aborted\]: no such tag bill-clintons-chastity"
-
- # Now get rid of the working directory and test rannotate
-
- cd ../..
- rm -r 1
- dotest ann-r10 "${testcvs} rann first-dir" \
-"
-Annotations for first-dir/file1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-1\.1 ($username8 *[0-9a-zA-Z-]*): this
-1\.1 ($username8 *[0-9a-zA-Z-]*): is
-1\.2 ($username8 *[0-9a-zA-Z-]*): a
-1\.3 ($username8 *[0-9a-zA-Z-]*): trunk file
-1\.2 ($username8 *[0-9a-zA-Z-]*):
-1\.2 ($username8 *[0-9a-zA-Z-]*): with
-1\.2 ($username8 *[0-9a-zA-Z-]*): a
-1\.2 ($username8 *[0-9a-zA-Z-]*): blank
-1\.2 ($username8 *[0-9a-zA-Z-]*): line"
- dotest ann-r11 "${testcvs} rann -r br first-dir" \
-"
-Annotations for first-dir/file1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-1\.1 ($username8 *[0-9a-zA-Z-]*): this
-1\.1 ($username8 *[0-9a-zA-Z-]*): is
-1\.2 ($username8 *[0-9a-zA-Z-]*): a
-1\.1 ($username8 *[0-9a-zA-Z-]*): file
-1\.2 ($username8 *[0-9a-zA-Z-]*):
-1\.2 ($username8 *[0-9a-zA-Z-]*): with
-1\.2 ($username8 *[0-9a-zA-Z-]*): a
-1\.2 ($username8 *[0-9a-zA-Z-]*): blank
-1\.2 ($username8 *[0-9a-zA-Z-]*): line
-1\.2\.2\.1 ($username8 *[0-9a-zA-Z-]*): and some
-1\.2\.2\.1 ($username8 *[0-9a-zA-Z-]*): branched content"
- dotest ann-r12 "${testcvs} rann -r 1.2.0.2 first-dir/file1" ""
- dotest ann-r13 "${testcvs} rann -r 1.2.2 first-dir/file1" \
-"
-Annotations for first-dir/file1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-1\.1 ($username8 *[0-9a-zA-Z-]*): this
-1\.1 ($username8 *[0-9a-zA-Z-]*): is
-1\.2 ($username8 *[0-9a-zA-Z-]*): a
-1\.1 ($username8 *[0-9a-zA-Z-]*): file
-1\.2 ($username8 *[0-9a-zA-Z-]*):
-1\.2 ($username8 *[0-9a-zA-Z-]*): with
-1\.2 ($username8 *[0-9a-zA-Z-]*): a
-1\.2 ($username8 *[0-9a-zA-Z-]*): blank
-1\.2 ($username8 *[0-9a-zA-Z-]*): line
-1\.2\.2\.1 ($username8 *[0-9a-zA-Z-]*): and some
-1\.2\.2\.1 ($username8 *[0-9a-zA-Z-]*): branched content"
- dotest_fail ann-r14 "${testcvs} rann -r bill-clintons-chastity first-dir/file1" \
-"${PROG} \[rannotate aborted\]: no such tag bill-clintons-chastity"
-
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- ann-id)
- # Demonstrate that cvs-1.9.28.1 improperly expands rcs keywords in
- # the output of `cvs annotate' -- it uses values from the previous
- # delta. In this case, `1.1' instead of `1.2', even though it puts
- # the proper version number on the prefix to each line of output.
- mkdir 1; cd 1
- dotest ann-id-1 "${testcvs} -q co -l ." ''
- module=x
- mkdir $module
- dotest ann-id-2 "${testcvs} add $module" \
-"Directory ${CVSROOT_DIRNAME}/$module added to the repository"
- cd $module
-
- file=m
- echo '$Id''$' > $file
-
- dotest ann-id-3 "$testcvs add $file" \
-"${PROG} add: scheduling file .$file. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest ann-id-4 "$testcvs -Q ci -m . $file" \
-"RCS file: ${CVSROOT_DIRNAME}/$module/$file,v
-done
-Checking in $file;
-${CVSROOT_DIRNAME}/$module/$file,v <-- $file
-initial revision: 1\.1
-done"
-
- echo line2 >> $file
- dotest ann-id-5 "$testcvs -Q ci -m . $file" \
-"Checking in $file;
-${CVSROOT_DIRNAME}/$module/$file,v <-- $file
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # The version number after $file,v should be `1.2'.
- # 1.9.28.1 puts `1.1' there.
- dotest ann-id-6 "$testcvs -Q ann $file" \
-"
-Annotations for $file
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-1.2 ($username8 *[0-9a-zA-Z-]*): "'\$'"Id: $file,v 1.1 [0-9/]* [0-9:]* $username Exp "'\$'"
-1.2 ($username8 *[0-9a-zA-Z-]*): line2"
-
- cd ../..
- rm -rf 1
- rm -rf ${CVSROOT_DIRNAME}/$module
- ;;
-
- crerepos)
- # Various tests relating to creating repositories, operating
- # on repositories created with old versions of CVS, etc.
-
- CVS_SERVER_save=$CVS_SERVER
-
- # Because this test is all about -d options and such, it
- # at least to some extent needs to be different for remote vs.
- # local.
- if $remote; then
-
- # Use :ext: rather than :fork:. Most of the tests use :fork:,
- # so we want to make sure that we test :ext: _somewhere_.
- # Make sure 'rsh' works first.
- depends_on_rsh "$CVS_RSH"
- if test $? -eq 77; then
- skip crerepos "$skipreason"
- continue
- fi
-
- # For remote, just create the repository. We don't yet do
- # the various other tests above for remote but that should be
- # changed.
- mkdir crerepos
- mkdir crerepos/CVSROOT
-
- # Make sure server ignores real ${HOME}/.cvsrc:
- cat >$TESTDIR/cvs-setHome <<EOF
-#!/bin/sh
-HOME=$HOME
-export HOME
-exec $CVS_SERVER_save "\$@"
-EOF
- chmod a+x $TESTDIR/cvs-setHome
-
- # Note that we set CVS_SERVER at the beginning.
- CVS_SERVER=$TESTDIR/cvs-setHome; export CVS_SERVER
- CREREPOS_ROOT=:ext:$host$TESTDIR/crerepos
- else
-
- # First, if the repository doesn't exist at all...
- dotest_fail crerepos-1 \
-"${testcvs} -d ${TESTDIR}/crerepos co cvs-sanity" \
-"${PROG} \[checkout aborted\]: ${TESTDIR}/crerepos/CVSROOT: .*"
- mkdir crerepos
-
- # The repository exists but CVSROOT doesn't.
- dotest_fail crerepos-2 \
-"${testcvs} -d ${TESTDIR}/crerepos co cvs-sanity" \
-"${PROG} \[checkout aborted\]: ${TESTDIR}/crerepos/CVSROOT: .*"
- mkdir crerepos/CVSROOT
-
- # Checkout of nonexistent module
- dotest_fail crerepos-3 \
-"${testcvs} -d ${TESTDIR}/crerepos co cvs-sanity" \
-"${PROG} checkout: cannot find module .cvs-sanity. - ignored"
-
- # Now test that CVS works correctly without a modules file
- # or any of that other stuff. In particular, it *must*
- # function if administrative files added to CVS recently (since
- # CVS 1.3) do not exist, because the repository might have
- # been created with an old version of CVS.
- mkdir 1; cd 1
- dotest crerepos-4 \
-"${testcvs} -q -d ${TESTDIR}/crerepos co CVSROOT" \
-''
- if echo yes | \
-${testcvs} -d ${TESTDIR}/crerepos release -d CVSROOT >>${LOGFILE}; then
- pass crerepos-5
- else
- fail crerepos-5
- fi
- rm -rf CVS
- cd ..
- # The directory 1 should be empty
- dotest crerepos-6 "rmdir 1"
-
- CREREPOS_ROOT=${TESTDIR}/crerepos
-
- fi
-
- if $remote; then
- # 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-r \
-"${testcvs} -q -d :ext:`hostname`:../crerepos get ." \
-"${PROG} [a-z]*: CVSROOT may only specify a positive, non-zero, integer port (not .\.\..)\.
-${PROG} [a-z]*: Perhaps you entered a relative pathname${QUESTION}
-${PROG} \[[a-z]* aborted\]: Bad CVSROOT: .:ext:${hostname}:\.\./crerepos.\."
- cd ..
- rm -r 1
- else # local
- # Test that CVS rejects a relative path in CVSROOT.
-
- mkdir 1; cd 1
- # Set CVS_RSH=false since ocassionally (e.g. when CVS_RSH=ssh on
- # some systems) some rsh implementations will block because they
- # can look up '..' and want to ask the user about the unknown host
- # key or somesuch. Which error message we get depends on whether
- # false finishes running before we try to talk to it or not.
- dotest_fail crerepos-6a "CVS_RSH=false ${testcvs} -q -d ../crerepos get ." \
-"${PROG} \[checkout aborted\]: .*" \
-"${PROG} checkout: CVSROOT is set for a remote access method but your
-${PROG} checkout: CVS executable doesn't support it\.
-${PROG} \[checkout aborted\]: Bad CVSROOT: .\.\./crerepos.\."
- cd ..
- rm -r 1
-
- mkdir 1; cd 1
- dotest_fail crerepos-6b "${testcvs} -d crerepos init" \
-"${PROG} init: CVSROOT must be an absolute pathname (not .crerepos.)
-${PROG} init: when using local access method\.
-${PROG} \[init aborted\]: Bad CVSROOT: .crerepos.\."
- cd ..
- rm -r 1
- fi # end of tests to be skipped for remote
-
- # CVS better not create a history file--if the administrator
- # doesn't need it and wants to save on disk space, they just
- # delete it.
- dotest_fail crerepos-7 \
-"test -f ${TESTDIR}/crerepos/CVSROOT/history" ''
-
- # Now test mixing repositories. This kind of thing tends to
- # happen accidentally when people work with several repositories.
- mkdir 1; cd 1
- dotest crerepos-8 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest crerepos-9 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- touch file1
- dotest crerepos-10 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest crerepos-11 "${testcvs} -q ci -m add-it" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- cd ../..
- rm -r 1
-
- mkdir 1; cd 1
- dotest crerepos-12 "${testcvs} -d ${CREREPOS_ROOT} -q co -l ." ''
- mkdir crerepos-dir
- dotest crerepos-13 "${testcvs} add crerepos-dir" \
-"Directory ${TESTDIR}/crerepos/crerepos-dir added to the repository"
- cd crerepos-dir
- touch cfile
- dotest crerepos-14 "${testcvs} add cfile" \
-"${PROG} add: scheduling file .cfile. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest crerepos-15 "${testcvs} -q ci -m add-it" \
-"RCS file: ${TESTDIR}/crerepos/crerepos-dir/cfile,v
-done
-Checking in cfile;
-${TESTDIR}/crerepos/crerepos-dir/cfile,v <-- cfile
-initial revision: 1\.1
-done"
- cd ../..
- rm -r 1
-
- mkdir 1; cd 1
- dotest crerepos-16 "${testcvs} co first-dir" \
-"${PROG} checkout: Updating first-dir
-U first-dir/file1"
- dotest crerepos-17 "${testcvs} -d ${CREREPOS_ROOT} co crerepos-dir" \
-"${PROG} checkout: Updating crerepos-dir
-U crerepos-dir/cfile"
- dotest crerepos-18 "${testcvs} update" \
-"${PROG} update: Updating first-dir
-${PROG} update: Updating crerepos-dir"
-
- cd ..
-
- CVS_SERVER=$CVS_SERVER_save; export CVS_SERVER
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- rm -f $TESTDIR/cvs-setHome
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir ${TESTDIR}/crerepos
- ;;
-
-
-
- crerepos-extssh)
- # Various tests relating to creating repositories, operating
- # on repositories created with old versions of CVS, etc.
-
- CVS_SERVER_save=$CVS_SERVER
-
- # Because this test is all about -d options and such, it
- # at least to some extent needs to be different for remote vs.
- # local.
- if $remote; then
-
- # Use :extssh: rather than :fork:. Most of the tests use :fork:,
- # so we want to make sure that we test :extssh: _somewhere_.
- # Make sure 'ssh' works first.
- depends_on_rsh "$CVS_RSH"
- if test $? -eq 77; then
- skip crerepos "$skipreason"
- continue
- fi
-
- # For remote, just create the repository. We don't yet do
- # the various other tests above for remote but that should be
- # changed.
- mkdir crerepos
- mkdir crerepos/CVSROOT
-
- # Make sure server ignores real ${HOME}/.cvsrc:
- cat >$TESTDIR/cvs-setHome <<EOF
-#!/bin/sh
-HOME=$HOME
-export HOME
-exec $CVS_SERVER_save "\$@"
-EOF
- chmod a+x $TESTDIR/cvs-setHome
-
- # Note that we set CVS_SERVER at the beginning.
- CVS_SERVER=$TESTDIR/cvs-setHome; export CVS_SERVER
- CREREPOS_ROOT=:extssh:$host$TESTDIR/crerepos
- else
-
- # First, if the repository doesn't exist at all...
- dotest_fail crerepos-extssh-1 \
-"${testcvs} -d ${TESTDIR}/crerepos co cvs-sanity" \
-"${PROG} \[checkout aborted\]: ${TESTDIR}/crerepos/CVSROOT: .*"
- mkdir crerepos
-
- # The repository exists but CVSROOT doesn't.
- dotest_fail crerepos-extssh-2 \
-"${testcvs} -d ${TESTDIR}/crerepos co cvs-sanity" \
-"${PROG} \[checkout aborted\]: ${TESTDIR}/crerepos/CVSROOT: .*"
- mkdir crerepos/CVSROOT
-
- # Checkout of nonexistent module
- dotest_fail crerepos-extssh-3 \
-"${testcvs} -d ${TESTDIR}/crerepos co cvs-sanity" \
-"${PROG} checkout: cannot find module .cvs-sanity. - ignored"
-
- # Now test that CVS works correctly without a modules file
- # or any of that other stuff. In particular, it *must*
- # function if administrative files added to CVS recently (since
- # CVS 1.3) do not exist, because the repository might have
- # been created with an old version of CVS.
- mkdir 1; cd 1
- dotest crerepos-extssh-4 \
-"${testcvs} -q -d ${TESTDIR}/crerepos co CVSROOT" \
-''
- if echo yes | \
-${testcvs} -d ${TESTDIR}/crerepos release -d CVSROOT >>${LOGFILE}; then
- pass crerepos-extssh-5
- else
- fail crerepos-extssh-5
- fi
- rm -rf CVS
- cd ..
- # The directory 1 should be empty
- dotest crerepos-extssh-6 "rmdir 1"
-
- CREREPOS_ROOT=${TESTDIR}/crerepos
-
- fi
-
- if $remote; then
- # 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-extssh-6a-r \
-"${testcvs} -q -d :extssh:`hostname`:../crerepos get ." \
-"${PROG} [a-z]*: CVSROOT may only specify a positive, non-zero, integer port (not .\.\..)\.
-${PROG} [a-z]*: Perhaps you entered a relative pathname${QUESTION}
-${PROG} \[[a-z]* aborted\]: Bad CVSROOT: .:extssh:${hostname}:\.\./crerepos.\."
- cd ..
- rm -r 1
- else # local
- # Test that CVS rejects a relative path in CVSROOT.
-
- mkdir 1; cd 1
- # Set CVS_RSH=false since ocassionally (e.g. when CVS_RSH=ssh on
- # some systems) some rsh implementations will block because they
- # can look up '..' and want to ask the user about the unknown host
- # key or somesuch. Which error message we get depends on whether
- # false finishes running before we try to talk to it or not.
- dotest_fail crerepos-extssh-6a "CVS_RSH=false ${testcvs} -q -d ../crerepos get ." \
-"${PROG} \[checkout aborted\]: .*" \
-"${PROG} checkout: CVSROOT is set for a remote access method but your
-${PROG} checkout: CVS executable doesn't support it\.
-${PROG} \[checkout aborted\]: Bad CVSROOT: .\.\./crerepos.\."
- cd ..
- rm -r 1
-
- mkdir 1; cd 1
- dotest_fail crerepos-extssh-6b "${testcvs} -d crerepos init" \
-"${PROG} init: CVSROOT must be an absolute pathname (not .crerepos.)
-${PROG} init: when using local access method\.
-${PROG} \[init aborted\]: Bad CVSROOT: .crerepos.\."
- cd ..
- rm -r 1
- fi # end of tests to be skipped for remote
-
- # CVS better not create a history file--if the administrator
- # doesn't need it and wants to save on disk space, they just
- # delete it.
- dotest_fail crerepos-extssh-7 \
-"test -f ${TESTDIR}/crerepos/CVSROOT/history" ''
-
- # Now test mixing repositories. This kind of thing tends to
- # happen accidentally when people work with several repositories.
- mkdir 1; cd 1
- dotest crerepos-extssh-8 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest crerepos-extssh-9 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- touch file1
- dotest crerepos-extssh-10 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest crerepos-extssh-11 "${testcvs} -q ci -m add-it" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- cd ../..
- rm -r 1
-
- mkdir 1; cd 1
- dotest crerepos-extssh-12 "${testcvs} -d ${CREREPOS_ROOT} -q co -l ." ''
- mkdir crerepos-dir
- dotest crerepos-extssh-13 "${testcvs} add crerepos-dir" \
-"Directory ${TESTDIR}/crerepos/crerepos-dir added to the repository"
- cd crerepos-dir
- touch cfile
- dotest crerepos-extssh-14 "${testcvs} add cfile" \
-"${PROG} add: scheduling file .cfile. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest crerepos-extssh-15 "${testcvs} -q ci -m add-it" \
-"RCS file: ${TESTDIR}/crerepos/crerepos-dir/cfile,v
-done
-Checking in cfile;
-${TESTDIR}/crerepos/crerepos-dir/cfile,v <-- cfile
-initial revision: 1\.1
-done"
- cd ../..
- rm -r 1
-
- mkdir 1; cd 1
- dotest crerepos-extssh-16 "${testcvs} co first-dir" \
-"${PROG} checkout: Updating first-dir
-U first-dir/file1"
- dotest crerepos-extssh-17 "${testcvs} -d ${CREREPOS_ROOT} co crerepos-dir" \
-"${PROG} checkout: Updating crerepos-dir
-U crerepos-dir/cfile"
- dotest crerepos-extssh-18 "${testcvs} update" \
-"${PROG} update: Updating first-dir
-${PROG} update: Updating crerepos-dir"
-
- cd ..
-
- CVS_SERVER=$CVS_SERVER_save; export CVS_SERVER
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- rm -f $TESTDIR/cvs-setHome
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir ${TESTDIR}/crerepos
- ;;
-
-
-
- rcs)
- # Test ability to import an RCS file. Note that this format
- # is fixed--files written by RCS5, and other software which
- # implements this format, will be out there "forever" and
- # CVS must always be able to import such files.
-
- # See tests admin-13, admin-25 and rcs-8a for exporting RCS files.
-
- mkdir ${CVSROOT_DIRNAME}/first-dir
-
- # Currently the way to import an RCS file is to copy it
- # directly into the repository.
- #
- # This file was written by RCS 5.7, and then the dates were
- # hacked so that we test year 2000 stuff. Note also that
- # "author" names are just strings, as far as importing
- # RCS files is concerned--they need not correspond to user
- # IDs on any particular system.
- #
- # I also tried writing a file with the RCS supplied with
- # HPUX A.09.05. According to "man rcsintro" this is
- # "Revision Number: 3.0; Release Date: 83/05/11". There
- # were a few minor differences like whitespace but at least
- # in simple cases like this everything else seemed the same
- # as the file written by RCS 5.7 (so I won't try to make it
- # a separate test case).
-
- cat <<EOF >${CVSROOT_DIRNAME}/first-dir/file1,v
-head 1.3;
-access;
-symbols;
-locks; strict;
-comment @# @;
-
-
-1.3
-date 2000.11.24.15.58.37; author kingdon; state Exp;
-branches;
-next 1.2;
-
-1.2
-date 96.11.24.15.57.41; author kingdon; state Exp;
-branches;
-next 1.1;
-
-1.1
-date 96.11.24.15.56.05; author kingdon; state Exp;
-branches;
-next ;
-
-
-desc
-@file1 is for testing CVS
-@
-
-
-1.3
-log
-@delete second line; modify twelfth line
-@
-text
-@This is the first line
-This is the third line
-This is the fourth line
-This is the fifth line
-This is the sixth line
-This is the seventh line
-This is the eighth line
-This is the ninth line
-This is the tenth line
-This is the eleventh line
-This is the twelfth line (and what a line it is)
-This is the thirteenth line
-@
-
-
-1.2
-log
-@add more lines
-@
-text
-@a1 1
-This is the second line
-d11 1
-a11 1
-This is the twelfth line
-@
-
-
-1.1
-log
-@add file1
-@
-text
-@d2 12
-@
-EOF
- dotest rcs-1 "${testcvs} -q co first-dir" 'U first-dir/file1'
- cd first-dir
- dotest rcs-2 "${testcvs} -q log" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.3
-branch:
-locks: strict
-access list:
-symbolic names:
-keyword substitution: kv
-total revisions: 3; selected revisions: 3
-description:
-file1 is for testing CVS
-----------------------------
-revision 1\.3
-date: 2000/11/24 15:58:37; author: kingdon; state: Exp; lines: ${PLUS}1 -2
-delete second line; modify twelfth line
-----------------------------
-revision 1\.2
-date: 1996/11/24 15:57:41; author: kingdon; state: Exp; lines: ${PLUS}12 -0
-add more lines
-----------------------------
-revision 1\.1
-date: 1996/11/24 15:56:05; author: kingdon; state: Exp;
-add file1
-============================================================================="
-
- # Note that the dates here are chosen so that (a) we test
- # at least one date after 2000, (b) we will notice if the
- # month and day are getting mixed up with each other.
- # TODO: also test that year isn't getting mixed up with month
- # or day, for example 01-02-03.
-
- # ISO8601 format. There are many, many, other variations
- # specified by ISO8601 which we should be testing too.
- dotest rcs-3 "${testcvs} -q log -d '1996-12-11<'" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.3
-branch:
-locks: strict
-access list:
-symbolic names:
-keyword substitution: kv
-total revisions: 3; selected revisions: 1
-description:
-file1 is for testing CVS
-----------------------------
-revision 1\.3
-date: 2000/11/24 15:58:37; author: kingdon; state: Exp; lines: ${PLUS}1 -2
-delete second line; modify twelfth line
-============================================================================="
-
- # RFC822 format (as amended by RFC1123).
- dotest rcs-4 "${testcvs} -q log -d '<3 Apr 2000 00:00'" \
-"
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.3
-branch:
-locks: strict
-access list:
-symbolic names:
-keyword substitution: kv
-total revisions: 3; selected revisions: 2
-description:
-file1 is for testing CVS
-----------------------------
-revision 1\.2
-date: 1996/11/24 15:57:41; author: kingdon; state: Exp; lines: ${PLUS}12 -0
-add more lines
-----------------------------
-revision 1\.1
-date: 1996/11/24 15:56:05; author: kingdon; state: Exp;
-add file1
-============================================================================="
-
- # Intended behavior for "cvs annotate" is that it displays the
- # last two digits of the year. Make sure it does that rather
- # than some bogosity like "100".
- dotest rcs-4a "${testcvs} annotate file1" \
-"
-Annotations for file1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-1\.1 (kingdon 24-Nov-96): This is the first line
-1\.2 (kingdon 24-Nov-96): This is the third line
-1\.2 (kingdon 24-Nov-96): This is the fourth line
-1\.2 (kingdon 24-Nov-96): This is the fifth line
-1\.2 (kingdon 24-Nov-96): This is the sixth line
-1\.2 (kingdon 24-Nov-96): This is the seventh line
-1\.2 (kingdon 24-Nov-96): This is the eighth line
-1\.2 (kingdon 24-Nov-96): This is the ninth line
-1\.2 (kingdon 24-Nov-96): This is the tenth line
-1\.2 (kingdon 24-Nov-96): This is the eleventh line
-1\.3 (kingdon 24-Nov-00): This is the twelfth line (and what a line it is)
-1\.2 (kingdon 24-Nov-96): This is the thirteenth line"
-
- # Probably should split this test into two at this point (file1
- # above this line and file2 below), as the two share little
- # data/setup.
-
- # OK, here is another one. This one was written by hand based on
- # doc/RCSFILES and friends. One subtle point is that none of
- # the lines end with newlines; that is a feature which we
- # should be testing.
- cat <<EOF >${CVSROOT_DIRNAME}/first-dir/file2,v
-head 1.5 ;
- branch 1.2.6;
-access ;
-symbols branch:1.2.6;
-locks;
-testofanewphrase @without newphrase we'd have trouble extending @@ all@ ;
-1.5 date 71.01.01.01.00.00; author joe; state bogus; branches; next 1.4;
-1.4 date 71.01.01.00.00.05; author joe; state bogus; branches; next 1.3;
-1.3 date 70.12.31.15.00.05; author joe; state bogus; branches; next 1.2;
-1.2 date 70.12.31.12.15.05; author me; state bogus; branches 1.2.6.1; next 1.1;
-1.1 date 70.12.31.11.00.05; author joe; state bogus; branches; next; newph;
-1.2.6.1 date 71.01.01.08.00.05; author joe; state Exp; branches; next;
-desc @@
-1.5 log @@ newphrase1; newphrase2 42; text @head revision@
-1.4 log @@ text @d1 1
-a1 1
-new year revision@
-1.3 log @@ text @d1 1
-a1 1
-old year revision@
-1.2 log @@ text @d1 1
-a1 1
-mid revision@ 1.1
-
-log @@ text @d1 1
-a1 1
-start revision@
-1.2.6.1 log @@ text @d1 1
-a1 1
-branch revision@
-EOF
- # ' Match the single quote in above here doc -- for font-lock mode.
-
- # First test the default branch.
- dotest rcs-5 "${testcvs} -q update file2" "U file2"
- dotest rcs-6 "cat file2" "branch revision"
-
- # Check in a revision on the branch to force CVS to
- # interpret every revision in the file.
- dotest rcs-6a "$testcvs -q update -r branch file2" 'U file2'
- echo "next branch revision" > file2
- dotest rcs-6b "${testcvs} -q ci -m mod file2" \
-"Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.2\.6\.2; previous revision: 1\.2\.6\.1
-done"
-
- # Now get rid of the default branch, it will get in the way.
- dotest rcs-7 "${testcvs} admin -b file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done"
- # But we do want to make sure that "cvs admin" leaves the newphrases
- # in the file.
- # The extra whitespace regexps are for the RCS library, which does
- # not preserve whitespace in the dogmatic manner of RCS 5.7. -twp
- dotest rcs-8 \
-"grep testofanewphrase ${CVSROOT_DIRNAME}/first-dir/file2,v" \
-"testofanewphrase[ ][ ]*@without newphrase we'd have trouble extending @@ all@[ ]*;"
- # The easiest way to test for newphrases in deltas and deltatexts
- # is to just look at the whole file, I guess.
- dotest rcs-8a "cat ${CVSROOT_DIRNAME}/first-dir/file2,v" \
-"head 1\.5;
-access;
-symbols
- branch:1.2.6;
-locks;
-
-testofanewphrase @without newphrase we'd have trouble extending @@ all@;
-
-1\.5
-date 71\.01\.01\.01\.00\.00; author joe; state bogus;
-branches;
-next 1\.4;
-
-1\.4
-date 71\.01\.01\.00\.00\.05; author joe; state bogus;
-branches;
-next 1\.3;
-
-1\.3
-date 70\.12\.31\.15\.00\.05; author joe; state bogus;
-branches;
-next 1\.2;
-
-1\.2
-date 70\.12\.31\.12\.15\.05; author me; state bogus;
-branches
- 1\.2\.6\.1;
-next 1\.1;
-
-1\.1
-date 70\.12\.31\.11\.00\.05; author joe; state bogus;
-branches;
-next ;
-newph ;
-
-1\.2\.6\.1
-date 71\.01\.01\.08\.00\.05; author joe; state Exp;
-branches;
-next 1\.2\.6\.2;
-
-1\.2\.6\.2
-date [0-9.]*; author ${username}; state Exp;
-branches;
-next ;
-
-
-desc
-@@
-
-
-1\.5
-log
-@@
-newphrase1 ;
-newphrase2 42;
-text
-@head revision@
-
-
-1\.4
-log
-@@
-text
-@d1 1
-a1 1
-new year revision@
-
-
-1\.3
-log
-@@
-text
-@d1 1
-a1 1
-old year revision@
-
-
-1\.2
-log
-@@
-text
-@d1 1
-a1 1
-mid revision@
-
-
-1\.1
-log
-@@
-text
-@d1 1
-a1 1
-start revision@
-
-
-1\.2\.6\.1
-log
-@@
-text
-@d1 1
-a1 1
-branch revision@
-
-
-1\.2\.6\.2
-log
-@mod
-@
-text
-@d1 1
-a1 1
-next branch revision
-@"
-
- dotest rcs-9 "${testcvs} -q update -p -D '1970-12-31 11:30 UT' file2" \
-"start revision"
-
- dotest rcs-10 "${testcvs} -q update -p -D '1970-12-31 12:30 UT' file2" \
-"mid revision"
-
- dotest rcs-11 "${testcvs} -q update -p -D '1971-01-01 00:30 UT' file2" \
-"new year revision"
-
- # Same test as rcs-10, but with am/pm.
- dotest rcs-12 "${testcvs} -q update -p -D 'December 31, 1970 12:30pm UT' file2" \
-"mid revision"
-
- # Same test as rcs-11, but with am/pm.
- dotest rcs-13 "${testcvs} -q update -p -D 'January 1, 1971 12:30am UT' file2" \
-"new year revision"
-
- # OK, now make sure cvs log doesn't have any trouble with the
- # newphrases and such.
- dotest rcs-14 "${testcvs} -q log file2" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-Working file: file2
-head: 1\.5
-branch:
-locks:
-access list:
-symbolic names:
- branch: 1\.2\.6
-keyword substitution: kv
-total revisions: 7; selected revisions: 7
-description:
-----------------------------
-revision 1\.5
-date: 1971/01/01 01:00:00; author: joe; state: bogus; lines: ${PLUS}1 -1
-\*\*\* empty log message \*\*\*
-----------------------------
-revision 1\.4
-date: 1971/01/01 00:00:05; author: joe; state: bogus; lines: ${PLUS}1 -1
-\*\*\* empty log message \*\*\*
-----------------------------
-revision 1\.3
-date: 1970/12/31 15:00:05; author: joe; state: bogus; lines: ${PLUS}1 -1
-\*\*\* empty log message \*\*\*
-----------------------------
-revision 1\.2
-date: 1970/12/31 12:15:05; author: me; state: bogus; lines: ${PLUS}1 -1
-branches: 1\.2\.6;
-\*\*\* empty log message \*\*\*
-----------------------------
-revision 1\.1
-date: 1970/12/31 11:00:05; author: joe; state: bogus;
-\*\*\* empty log message \*\*\*
-----------------------------
-revision 1\.2\.6\.2
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -1
-mod
-----------------------------
-revision 1\.2\.6\.1
-date: 1971/01/01 08:00:05; author: joe; state: Exp; lines: ${PLUS}1 -1
-\*\*\* empty log message \*\*\*
-============================================================================="
- # Now test each date format for "cvs log -d".
- # Earlier than 1971-01-01
- dotest rcs-15 "${testcvs} -q log -d '<1971-01-01 00:00 GMT' file2 \
- | grep revision" \
-"total revisions: 7; selected revisions: 3
-revision 1\.3
-revision 1\.2
-revision 1\.1"
- # Later than 1971-01-01
- dotest rcs-16 "${testcvs} -q log -d '1971-01-01 00:00 GMT<' file2 \
- | grep revision" \
-"total revisions: 7; selected revisions: 4
-revision 1\.5
-revision 1\.4
-revision 1\.2\.6\.2
-revision 1\.2\.6\.1"
- # Alternate syntaxes for later and earlier; multiple -d options
- dotest rcs-17 "${testcvs} -q log -d '>1971-01-01 00:00 GMT' \
- -d '1970-12-31 12:15 GMT>' file2 | grep revision" \
-"total revisions: 7; selected revisions: 5
-revision 1\.5
-revision 1\.4
-revision 1\.1
-revision 1\.2\.6\.2
-revision 1\.2\.6\.1"
- # Range, and single date
- dotest rcs-18 "${testcvs} -q log -d '1970-12-31 11:30 GMT' \
- -d '1971-01-01 00:00:05 GMT<1971-01-01 01:00:01 GMT' \
- file2 | grep revision" \
-"total revisions: 7; selected revisions: 2
-revision 1\.5
-revision 1\.1"
- # Alternate range syntax; equality
- dotest rcs-19 "${testcvs} -q log \
- -d '1971-01-01 01:00:01 GMT>=1971-01-01 00:00:05 GMT' \
- file2 | grep revision" \
-"total revisions: 7; selected revisions: 2
-revision 1\.5
-revision 1\.4"
-
- cd ..
-
- rm -r first-dir
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- rcs2)
- # More date tests. Might as well do this as a separate
- # test from "rcs", so that we don't need to perturb the
- # "written by RCS 5.7" RCS file.
- mkdir ${CVSROOT_DIRNAME}/first-dir
- # Significance of various dates:
- # * At least one Y2K standard refers to recognizing 9 Sep 1999
- # (as an example of a pre-2000 date, I guess).
- # * At least one Y2K standard refers to recognizing 1 Jan 2001
- # (as an example of a post-2000 date, I guess).
- # * Many Y2K standards refer to 2000 being a leap year.
- cat <<EOF >${CVSROOT_DIRNAME}/first-dir/file1,v
-head 1.7; access; symbols; locks; strict;
-1.7 date 2004.08.31.01.01.01; author sue; state; branches; next 1.6;
-1.6 date 2004.02.29.01.01.01; author sue; state; branches; next 1.5;
-1.5 date 2003.02.28.01.01.01; author sue; state; branches; next 1.4;
-1.4 date 2001.01.01.01.01.01; author sue; state; branches; next 1.3;
-1.3 date 2000.02.29.01.01.01; author sue; state; branches; next 1.2;
-1.2 date 99.09.09.01.01.01; author sue; state; branches; next 1.1;
-1.1 date 98.09.10.01.01.01; author sue; state; branches; next;
-desc @a test file@
-1.7 log @@ text @head revision@
-1.6 log @@ text @d1 1
-a1 1
-2004 was a great year for leaping@
-1.5 log @@ text @d1 1
-a1 1
-2003 wasn't@
-1.4 log @@ text @d1 1
-a1 1
-two year hiatus@
-1.3 log @@ text @d1 1
-a1 1
-2000 is also a good year for leaping@
-1.2 log @@ text @d1 1
-a1 1
-Tonight we're going to party like it's a certain year@
-1.1 log @@ text @d1 1
-a1 1
-Need to start somewhere@
-EOF
- # ' Match the 3rd single quote in the here doc -- for font-lock mode.
-
- dotest rcs2-1 "${testcvs} -q co first-dir" 'U first-dir/file1'
- cd first-dir
-
- # 9 Sep 1999
- dotest rcs2-2 "${testcvs} -q update -p -D '1999-09-09 11:30 UT' file1" \
-"Tonight we're going to party like it's a certain year"
- # 1 Jan 2001.
- dotest rcs2-3 "${testcvs} -q update -p -D '2001-01-01 11:30 UT' file1" \
-"two year hiatus"
- # 29 Feb 2000
- dotest rcs2-4 "${testcvs} -q update -p -D '2000-02-29 11:30 UT' file1" \
-"2000 is also a good year for leaping"
- # 29 Feb 2003 is invalid
- dotest_fail rcs2-5 "${testcvs} -q update -p -D '2003-02-29 11:30 UT' file1" \
-"${PROG} \[[a-z]* aborted\]: Can't parse date/time: 2003-02-29 11:30 UT"
-
- 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).
- #
- # These tests can be expected to fail 3 times every 400 years
- # starting Feb. 29, 2096 (because 8 years from that date would
- # be Feb. 29, 2100, which is an invalid date -- 2100 isn't a
- # leap year because it's divisible by 100 but not by 400).
-
- dotest rcs2-7 "${testcvs} -q update -p -D '96 months' file1" \
-"head revision"
- dotest rcs2-8 "${testcvs} -q update -p -D '8 years' file1" \
-"head revision"
-
- cd ..
- rm -r first-dir
- 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} \[checkout aborted\]: EOF while looking for value in RCS file ${CVSROOT_DIRNAME}/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} \[checkout aborted\]: unexpected '.x6c' reading revision number in RCS file ${CVSROOT_DIRNAME}/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} \[checkout aborted\]: EOF while looking for value in RCS file ${CVSROOT_DIRNAME}/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'
-
- # 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" \
-"${DOTSTAR}ssertion.*failed${DOTSTAR}" "${DOTSTAR}failed assertion${DOTSTAR}"
- cd first-dir
- dotest_fail rcs3-5a "${testcvs} log -s nostate file1" \
-"${DOTSTAR}ssertion.*failed${DOTSTAR}" "${DOTSTAR}failed assertion${DOTSTAR}"
- cd ..
-
- # See remote code above for rationale for cd.
- cd first-dir
- dotest rcs3-6 "${testcvs} log -R file1" \
-"${CVSROOT_DIRNAME}/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} \[log aborted\]: unexpected '.x0' reading revision number in RCS file ${CVSROOT_DIRNAME}/first-dir/file1,v"
-
- cd ../..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- rcs4)
- # Fix a bug that shows up when checking out files by date with the
- # "-D date" command line option. There is code in the original to
- # handle a special case. If the date search finds revision 1.1 it
- # is supposed to check whether revision 1.1.1.1 has the same date
- # stamp, which would indicate that the file was originally brought
- # in with "cvs import". In that case it is supposed to return the
- # vendor branch version 1.1.1.1.
- #
- # However, there is a bug in the code. It actually compares
- # the date of revision 1.1 for equality with the date given
- # on the command line -- clearly wrong. This commit fixes
- # the coding bug.
- #
- # There is an additional bug which is _not_ fixed yet.
- # The date comparison should not be a strict
- # equality test. It should allow a fudge factor of, say, 2-3
- # seconds. Old versions of CVS created the two revisions
- # with two separate invocations of the RCS "ci" command. We
- # have many old files in the tree in which the dates of
- # revisions 1.1 and 1.1.1.1 differ by 1 second.
-
- mkdir rcs4
- cd rcs4
-
- mkdir imp-dir
- cd imp-dir
- echo 'OpenMunger sources' >file1
-
- # choose a time in the past to demonstrate the problem
- TZ=GMT touch -t 200012010123 file1
-
- dotest_sort rcs4-1 \
-"${testcvs} import -d -m add rcs4-dir openmunger openmunger-1_0" \
-'
-
-N rcs4-dir/file1
-No conflicts created by this import'
- echo 'OpenMunger sources release 1.1 extras' >>file1
- TZ=GMT touch -t 200112011234 file1
- dotest_sort rcs4-2 \
-"${testcvs} import -d -m add rcs4-dir openmunger openmunger-1_1" \
-'
-
-No conflicts created by this import
-U rcs4-dir/file1'
- cd ..
- # Next checkout the new module
- dotest rcs4-3 \
-"${testcvs} -q co rcs4-dir" \
-'U rcs4-dir/file1'
- cd rcs4-dir
- echo 'local change' >> file1
-
- # commit a local change
- dotest rcs4-4 \
-"${testcvs} -q commit -m hack file1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/rcs4-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
- # now see if we get version 1.1 or 1.1.1.1 when we ask for
- # a checkout by time... it really should be 1.1.1.1 as
- # that was indeed the version that was visible at the target
- # time.
- dotest rcs4-5 \
-"${testcvs} -q update -D 'October 1, 2001 UTC' file1" \
-'[UP] file1'
- dotest rcs4-6 \
-"${testcvs} -q status file1" \
-'===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.1\.1\.1.*
- Repository revision: 1\.1\.1\.1 '${CVSROOT_DIRNAME}'/rcs4-dir/file1,v
- Sticky Tag: (none)
- Sticky Date: 2001\.10\.01\.00\.00\.00
- Sticky Options: (none)'
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- cd ../..
- rm -r rcs4
- rm -rf ${CVSROOT_DIRNAME}/rcs4-dir
- ;;
-
-
-
- rcs5)
- # Some tests of the $Log keyword and log message without a trailing
- # EOL. This used to look ugly and, in the worst case, could cause
- # a seg fault due to a buffer overflow.
- #
- # Note that it should not be possible to create this situation via a
- # CVS server (and any client), since the server itself inserts the
- # trailing EOL onto log messages that are missing one. Still, we
- # shouldn't segfault due to a corrupt RCS file and I think that a log
- # message without the trailing EOL doesn't actually violate the RCS
- # spec, though it doesn't appear to be possible to create such a log
- # message using RCS 5.7.
-
- mkdir $CVSROOT_DIRNAME/rcs5
- cat <<\EOF >$CVSROOT_DIRNAME/rcs5/file1,v
-head 1.1;
-access;
-symbols;
-locks;
-expand kv;
-
-1.1 date 2007.03.20.04.03.02; author jeremiah; state Ext; branches; next;
-
-desc
-@@
-
-1.1
-log
-@he always had very fine wine@
-text
-@line1
-/*
-EOF
-echo ' * Revision history: $''Log$' >>$CVSROOT_DIRNAME/rcs5/file1,v
- cat <<\EOF >>$CVSROOT_DIRNAME/rcs5/file1,v
- */
-line5
-@
-EOF
-
- mkdir rcs5
- cd rcs5
- dotest rcs5-1 "$testcvs -Q co rcs5"
- dotest rcs5-2 "cat rcs5/file1" \
-"line1
-/\\*
- \\* Revision history: "'\$'"Log: file1,v "'\$'"
- \\* Revision history: Revision 1\.1 2007/03/20 04:03:02 jeremiah
- \\* Revision history: he always had very fine wine
- \\* Revision history:
- \\*/
-line5"
-
- cd ..
- rm -r rcs5
- rm -rf $CVSROOT_DIRNAME/rcs5
- ;;
-
-
-
- rcs6)
- # Test that CVS notices a specific type of corruption in the RCS
- # archive. In the past, this type of corruption had turned up after
- # a user ineptly attempted to delete a revision from an arcvhive
- # manually.
- mkdir rcs6; cd rcs6
-
- # Make the project.
- dotest rcs6-init-1 "$testcvs -Q co -ld top .; cd top"
- mkdir rcs6
- dotest rcs6-init-2 "$testcvs -Q add rcs6"
- cd rcs6
-
- # Populate it.
- echo some words >afile
- dotest rcs6-init-3 "$testcvs -Q add afile"
- dotest rcs6-init-4 "$testcvs -Q ci -mnewfile afile" \
-"RCS file: $CVSROOT_DIRNAME/rcs6/afile,v
-done
-Checking in afile;
-$CVSROOT_DIRNAME/rcs6/afile,v <-- afile
-initial revision: 1\.1
-done"
- echo more words >>afile
- dotest rcs6-init-5 "$testcvs -Q ci -mrev2 afile" \
-"Checking in afile;
-$CVSROOT_DIRNAME/rcs6/afile,v <-- afile
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # Corrupt the archive.
- sed -e '8,12d' \
- -e 's/^head 1\.2/head 1.1/' \
- <$CVSROOT_DIRNAME/rcs6/afile,v \
- >$CVSROOT_DIRNAME/rcs6/cfile,v
-
- # Update used to work.
- dotest_fail rcs6-1 "$testcvs -q up" \
-"$PROG \[update aborted\]: Expected head revision 1\.1, found 1\.2\."
-
- # Then a commit hosed the archive further without any warnings.
- # Updating to an old revision (e.g. 1.1) would have reported the
- # corruption. A second commit would have deleted data from the
- # file.
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- cd ../../..
- rm -r rcs6
- rm -rf $CVSROOT_DIRNAME/rcs6
- ;;
-
-
-
- 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;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: 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} \[update aborted\]: cannot stat ${TESTDIR}/locks: No such file or directory
-${PROG} \[update aborted\]: cannot stat ${TESTDIR}/locks: No such file or directory"
- mkdir ${TESTDIR}/locks
- # Grumble, mumble. Cygwin.
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost "chmod u=rwx,g=r,o= ${TESTDIR}/locks"
- else
- chmod u=rwx,g=r,o= ${TESTDIR}/locks
- fi
- 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.
- #
- # Bah! Cygwin!
- if test -n "$remotehost"; then
- dotest lockfiles-7a "$CVS_RSH $remotehost 'ls -ld ${TESTDIR}/locks/first-dir'" \
-"drwxr-----.*first-dir"
- dotest lockfiles-7b "$CVS_RSH $remotehost 'ls -ld ${TESTDIR}/locks/first-dir/sdir/ssdir'" \
-"drwxr-----.*first-dir/sdir/ssdir"
- else
- 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"
- fi
-
- cd ../../..
- dotest lockfiles-8 "${testcvs} -q update" ""
- dotest lockfiles-9 "${testcvs} -q co -l ." ""
-
- ###
- ### There are race conditions in the following tests, but hopefully
- ### the 5 seconds the first process waits to remove the lockdir and
- ### the 30 seconds CVS waits betweens checks will be significant
- ### enough to render the case moot.
- ###
- # Considers the following cases:
- #
- # Lock Present
- # Operation Allowed (case #)
- #
- # Read Write
- # _______ ______
- # Read |Yes (1) No (3)
- # Write |No (7) No (9)
- #
- # Tests do not appear in same ordering as table. The odd numbering
- # scheme maintains correspondance with a larger table on 1.12.x:
- # 1. Read when read locks are present...
- # 3. Don't read when write locks present...
- # 7. Don't write when read locks are present...
- # 9. Don't write when write locks are present...
-
- # 3. Don't read when write locks present...
- mkdir "$TESTDIR/locks/first-dir/#cvs.lock"
- (sleep 5; rmdir "$TESTDIR/locks/first-dir/#cvs.lock")&
- dotest lockfiles-10 "$testcvs -q co -l first-dir" \
-"$PROG checkout: \[[0-9:]*\] waiting for $username's lock in $CVSROOT_DIRNAME/first-dir
-$PROG checkout: \[[0-9:]*\] obtained lock in $CVSROOT_DIRNAME/first-dir"
-
- # 1. Read when read locks are present...
- touch "$TESTDIR/locks/first-dir/#cvs.rfl.test.lock"
- dotest lockfiles-11 "$testcvs -q co -l first-dir"
- rm "$TESTDIR/locks/first-dir/#cvs.rfl.test.lock"
-
- # 7. Don't write when read locks are present...
- echo I always have trouble coming up with witty text for the test files >>first-dir/sdir/ssdir/file1
- touch "$TESTDIR/locks/first-dir/sdir/ssdir/#cvs.rfl.test.lock"
- (sleep 5; rm "$TESTDIR/locks/first-dir/sdir/ssdir/#cvs.rfl.test.lock")&
- dotest lockfiles-13 "$testcvs -q ci -mconflict first-dir" \
-"$PROG commit: \[[0-9:]*\] waiting for $username's lock in $CVSROOT_DIRNAME/first-dir/sdir/ssdir
-$PROG commit: \[[0-9:]*\] obtained lock in $CVSROOT_DIRNAME/first-dir/sdir/ssdir
-Checking in first-dir/sdir/ssdir/file1;
-$CVSROOT_DIRNAME/first-dir/sdir/ssdir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # 9. Don't write when write locks are present...
- echo yet this poem would probably only give longfellow bile >>first-dir/sdir/ssdir/file1
- mkdir "$TESTDIR/locks/first-dir/sdir/ssdir/#cvs.lock"
- (sleep 5; rmdir "$TESTDIR/locks/first-dir/sdir/ssdir/#cvs.lock")&
- dotest lockfiles-19 "$testcvs -q ci -mnot-up-to-date first-dir" \
-"$PROG commit: \[[0-9:]*\] waiting for $username's lock in $CVSROOT_DIRNAME/first-dir/sdir/ssdir
-$PROG commit: \[[0-9:]*\] obtained lock in $CVSROOT_DIRNAME/first-dir/sdir/ssdir
-Checking in first-dir/sdir/ssdir/file1;
-$CVSROOT_DIRNAME/first-dir/sdir/ssdir/file1,v <-- file1
-new revision: 1\.3; previous revision: 1\.2
-done"
-
- # 10. Don't write when history locks are present...
- echo have you ever heard a poem quite so vile\? >>first-dir/sdir/ssdir/file1
- mkdir "$TESTDIR/locks/CVSROOT/#cvs.history.lock"
- (sleep 5; rmdir "$TESTDIR/locks/CVSROOT/#cvs.history.lock")&
- dotest lockfiles-20 "$testcvs -q ci -mnot-up-to-date first-dir" \
-"Checking in first-dir/sdir/ssdir/file1;
-$CVSROOT_DIRNAME/first-dir/sdir/ssdir/file1,v <-- file1
-new revision: 1\.4; previous revision: 1\.3
-done
-$PROG commit: \[[0-9:]*\] waiting for $username's lock in $CVSROOT_DIRNAME/CVSROOT
-$PROG commit: \[[0-9:]*\] obtained lock in $CVSROOT_DIRNAME/CVSROOT"
-
- dotest lockfiles-21 "$testcvs -Q tag newtag first-dir"
-
- rm -f $CVSROOT_DIRNAME/CVSROOT/val-tags
- mkdir "$TESTDIR/locks/CVSROOT/#cvs.val-tags.lock"
- (sleep 5; rmdir "$TESTDIR/locks/CVSROOT/#cvs.val-tags.lock")&
- dotest lockfiles-22 "$testcvs -q up -r newtag first-dir" \
-"$PROG update: \[[0-9:]*\] waiting for $username's lock in $CVSROOT_DIRNAME/CVSROOT
-$PROG update: \[[0-9:]*\] obtained lock in $CVSROOT_DIRNAME/CVSROOT
-[UP] first-dir/sdir/ssdir/file1"
-
- cd CVSROOT
- echo "# nobody here but us comments" >config
- dotest lockfiles-cleanup-1 "${testcvs} -q ci -m config-it" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: 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 ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- mkdir dir
- dotest backuprecover-3 "${testcvs} add dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/dir added to the repository"
- touch file1 dir/file2
- dotest backuprecover-4 "${testcvs} -q add file1 dir/file2" \
-"${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest backuprecover-5 "${testcvs} -q ci -mtest" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dir/file2,v
-done
-Checking in dir/file2;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done
-Checking in dir/file2;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.3; previous revision: 1\.2
-done
-Checking in dir/file2;
-${CVSROOT_DIRNAME}/first-dir/dir/file2,v <-- file2
-new revision: 1\.3; previous revision: 1\.2
-done"
-
- # Save a backup copy
- cp -r ${CVSROOT_DIRNAME}/first-dir ${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.4; previous revision: 1\.3
-done
-Checking in dir/file2;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.5; previous revision: 1\.4
-done
-Checking in dir/file2;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/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 ${CVSROOT_DIRNAME}/first-dir
- mv ${CVSROOT_DIRNAME}/backup ${CVSROOT_DIRNAME}/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} update: Updating .
-U file1
-${PROG} update: 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} update: Updating \.
-${PROG} \[update aborted\]: could not find desired version 1\.6 in ${CVSROOT_DIRNAME}/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 -print\`
-cd ../first-dir
-find . -name CVS -print | 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;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.4; previous revision: 1\.3
-done
-Checking in dir/file2;
-${CVSROOT_DIRNAME}/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} update: Updating \.
-RCS file: ${CVSROOT_DIRNAME}/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} update: conflicts found in file1
-C file1
-${PROG} update: Updating dir
-RCS file: ${CVSROOT_DIRNAME}/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} update: 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;
-${CVSROOT_DIRNAME}/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: ${CVSROOT_DIRNAME}/first-dir/file1,v
-retrieving revision 1\.2
-retrieving revision 1\.4
-Merging differences between 1\.2 and 1\.4 into file1
-RCS file: ${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.5; previous revision: 1\.4
-done
-Checking in dir/file2;
-${CVSROOT_DIRNAME}/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
- ;;
-
-
-
- sshstdio)
- # CVS_RSH=ssh can have a problem with a non-blocking stdio
- # in some cases. So, this test is all about testing :ext:
- # with CVS_RSH=ssh. The problem is that not all machines
- # will necessarily have ssh available, so be prepared to
- # skip this test.
-
- # Are we able to run find and use an ssh?
- if $remote; then :; else
- continue
- fi
-
- depends_on_ssh
- if test $? -eq 77; then
- skip sshstdio "$skipreason"
- continue
- fi
-
- SSHSTDIO_ROOT=:ext:$host$CVSROOT_DIRNAME
-
- mkdir sshstdio; cd sshstdio
- dotest sshstdio-1 "$testcvs -d $SSHSTDIO_ROOT -q co -l ."
- mkdir first-dir
- dotest sshstdio-2 "$testcvs add first-dir" \
- "Directory $CVSROOT_DIRNAME/first-dir added to the repository"
- cd first-dir
- a='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
- c='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
- # Generate 1024 lines of $a
- cnt=0
- echo $a > aaa
- while [ $cnt -lt 5 ] ; do
- cnt=`expr $cnt + 1` ;
- mv aaa aaa.old
- cat aaa.old aaa.old aaa.old aaa.old > aaa
- done
- dotest sshstdio-3 "$testcvs -q add aaa" \
-"$PROG add: use .$PROG commit. to add this file permanently"
- dotest sshstdio-4 "$testcvs -q ci -mcreate aaa" \
-"RCS file: $CVSROOT_DIRNAME/first-dir/aaa,v
-done
-Checking in aaa;
-$CVSROOT_DIRNAME/first-dir/aaa,v <-- aaa
-initial revision: 1\.1
-done"
- # replace lines 1, 512, 513, 1024 with $c
- sed 510q < aaa > aaa.old
- (echo $c; cat aaa.old; echo $c; \
- echo $c; cat aaa.old; echo $c) > aaa
- dotest sshstdio-5 "$testcvs -q ci -mmodify-it aaa" \
-"Checking in aaa;
-$CVSROOT_DIRNAME/first-dir/aaa,v <-- aaa
-new revision: 1\.2; previous revision: 1\.1
-done"
- cat > wrapper.sh <<EOF
-#!$TESTSHELL
-exec "\$@" 2>&1 < /dev/null | cat
-EOF
- chmod +x wrapper.sh
- ./wrapper.sh \
- $testcvs -z5 -Q diff --side-by-side -W 500 -r 1.1 -r 1.2 \
- aaa \
- |sed -e \
-'/^Write failed flushing stdout buffer\. $/d;
- /^write stdout: Broken pipe $/d;
- :retry;
- /Write failed flushing stdout buffer\. $/{
- N;
- s/Write failed flushing stdout buffer\. \n//;
- b retry;
-}
- /write stdout: Broken pipe $/{
- N;
- s/write stdout: Broken pipe \n//;
- b retry;
-}' \
- > wrapper.dif
-
- $testcvs -z5 -Q diff --side-by-side -W 500 -r 1.1 -r 1.2 \
- aaa > good.dif
-
- dotest sshstdio-6 "cmp wrapper.dif good.dif"
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- cd ../..
- CVS_RSH=$save_CVS_RSH; export CVS_RSH
- rm -r sshstdio
- rm -rf $CVSROOT_DIRNAME/first-dir
- ;;
-
-
-
- parseroot2)
- # Test some :ext: roots for consistancy.
- if $remote; then :; else
- continue
- fi
-
- depends_on_rsh "$CVS_RSH"
- if test $? -eq 77; then
- skip parseroot2 "$skipreason"
- continue
- fi
-
- # Test checking out and subsequently updating with some different
- # CVSROOTs.
-
- # A standard case, hostname:dirname.
- mkdir parseroot2; cd parseroot2
- save_CVSROOT=$CVSROOT
- CVSROOT=$host:$CVSROOT_DIRNAME
- dotest parseroot2-1 "$testcvs -Q co CVSROOT"
- cd CVSROOT
- dotest parseroot2-2 "$testcvs -Q up"
- cd ..
-
- # A degenerate remote case, just the server name and the directory
- # name, with no :'s to help parsing. It can be mistaken for a
- # relative directory name.
- rm -r CVSROOT
- CVSROOT=$host$CVSROOT_DIRNAME
- dotest parseroot2-3 "$testcvs -Q co CVSROOT"
- cd CVSROOT
- dotest parseroot2-4 "$testcvs -Q up"
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- cd ../..
- CVSROOT=$save_CVSROOT
- rm -r parseroot2
- ;;
-
-
-
- history)
- # CVSROOT/history tests:
- # history: various "cvs history" invocations
- # basic2: Generating the CVSROOT/history file via CVS commands.
-
- # Put in some data for the history file (discarding what was
- # there before). Note that this file format is fixed; the
- # user may wish to analyze data from a previous version of
- # CVS. If we phase out this format, it should be done
- # slowly and carefully.
- cat >${CVSROOT_DIRNAME}/CVSROOT/history <<EOF
-O3395c677|anonymous|<remote>/*0|ccvs||ccvs
-O3396c677|anonymous|<remote>/src|ccvs||src
-O3397c677|kingdon|<remote>/*0|ccvs||ccvs
-M339cafae|nk|<remote>|ccvs/src|1.229|sanity.sh
-M339cafff|anonymous|<remote>|ccvs/src|1.23|Makefile
-M339dc339|kingdon|~/work/*0|ccvs/src|1.231|sanity.sh
-W33a6eada|anonymous|<remote>*4|ccvs/emx||Makefile.in
-C3b235f50|kingdon|<remote>|ccvs/emx|1.3|README
-M3b23af50|kingdon|~/work/*0|ccvs/doc|1.281|cvs.texinfo
-EOF
- dotest history-1 "${testcvs} history -e -a" \
-"O 1997-06-04 19:48 ${PLUS}0000 anonymous ccvs =ccvs= <remote>/\*
-O 1997-06-05 14:00 ${PLUS}0000 anonymous ccvs =src= <remote>/\*
-M 1997-06-10 01:38 ${PLUS}0000 anonymous 1\.23 Makefile ccvs/src == <remote>
-W 1997-06-17 19:51 ${PLUS}0000 anonymous Makefile\.in ccvs/emx == <remote>/emx
-O 1997-06-06 08:12 ${PLUS}0000 kingdon ccvs =ccvs= <remote>/\*
-M 1997-06-10 21:12 ${PLUS}0000 kingdon 1\.231 sanity\.sh ccvs/src == ~/work/ccvs/src
-C 2001-06-10 11:51 ${PLUS}0000 kingdon 1\.3 README ccvs/emx == <remote>
-M 2001-06-10 17:33 ${PLUS}0000 kingdon 1\.281 cvs\.texinfo ccvs/doc == ~/work/ccvs/doc
-M 1997-06-10 01:36 ${PLUS}0000 nk 1\.229 sanity\.sh ccvs/src == <remote>"
-
- dotest history-2 "${testcvs} history -e -a -D '10 Jun 1997 13:00 UT'" \
-"W 1997-06-17 19:51 ${PLUS}0000 anonymous Makefile\.in ccvs/emx == <remote>/emx
-M 1997-06-10 21:12 ${PLUS}0000 kingdon 1\.231 sanity\.sh ccvs/src == ~/work/ccvs/src
-C 2001-06-10 11:51 ${PLUS}0000 kingdon 1\.3 README ccvs/emx == <remote>
-M 2001-06-10 17:33 ${PLUS}0000 kingdon 1\.281 cvs\.texinfo ccvs/doc == ~/work/ccvs/doc"
-
- dotest history-3 "${testcvs} history -e -a -D '10 Jun 2001 13:00 UT'" \
-"M 2001-06-10 17:33 ${PLUS}0000 kingdon 1\.281 cvs\.texinfo ccvs/doc == ~/work/ccvs/doc"
-
- dotest history-4 "${testcvs} history -ac sanity.sh" \
-"M 1997-06-10 21:12 ${PLUS}0000 kingdon 1\.231 sanity\.sh ccvs/src == ~/work/ccvs/src
-M 1997-06-10 01:36 ${PLUS}0000 nk 1\.229 sanity\.sh ccvs/src == <remote>"
-
- dotest history-5 "${testcvs} history -a -xCGUWAMR README sanity.sh" \
-"M 1997-06-10 21:12 ${PLUS}0000 kingdon 1\.231 sanity\.sh ccvs/src == ~/work/ccvs/src
-C 2001-06-10 11:51 ${PLUS}0000 kingdon 1\.3 README ccvs/emx == <remote>
-M 1997-06-10 01:36 ${PLUS}0000 nk 1\.229 sanity\.sh ccvs/src == <remote>"
-
- dotest history-6 "${testcvs} history -xCGUWAMR -a -f README -f sanity.sh" \
-"M 1997-06-10 21:12 ${PLUS}0000 kingdon 1\.231 sanity\.sh ccvs/src == ~/work/ccvs/src
-C 2001-06-10 11:51 ${PLUS}0000 kingdon 1\.3 README ccvs/emx == <remote>
-M 1997-06-10 01:36 ${PLUS}0000 nk 1\.229 sanity\.sh ccvs/src == <remote>"
-
- dotest history-7 "${testcvs} history -xCGUWAMR -a -f sanity.sh README" \
-"M 1997-06-10 21:12 ${PLUS}0000 kingdon 1\.231 sanity\.sh ccvs/src == ~/work/ccvs/src
-C 2001-06-10 11:51 ${PLUS}0000 kingdon 1\.3 README ccvs/emx == <remote>
-M 1997-06-10 01:36 ${PLUS}0000 nk 1\.229 sanity\.sh ccvs/src == <remote>"
-
- dotest history-8 "${testcvs} history -ca -D '1970-01-01 00:00 UT'" \
-"M 1997-06-10 01:36 ${PLUS}0000 nk 1\.229 sanity.sh ccvs/src == <remote>
-M 1997-06-10 01:38 ${PLUS}0000 anonymous 1\.23 Makefile ccvs/src == <remote>
-M 1997-06-10 21:12 ${PLUS}0000 kingdon 1\.231 sanity.sh ccvs/src == ~/work/ccvs/src
-M 2001-06-10 17:33 ${PLUS}0000 kingdon 1\.281 cvs.texinfo ccvs/doc == ~/work/ccvs/doc"
-
- dotest history-9 "${testcvs} history -acl" \
-"M 2001-06-10 17:33 ${PLUS}0000 kingdon 1\.281 cvs.texinfo ccvs/doc == ~/work/ccvs/doc
-M 1997-06-10 01:38 ${PLUS}0000 anonymous 1\.23 Makefile ccvs/src == <remote>
-M 1997-06-10 21:12 ${PLUS}0000 kingdon 1\.231 sanity.sh ccvs/src == ~/work/ccvs/src"
-
- dotest history-10 "${testcvs} history -lca -D '1970-01-01 00:00 UT'" \
-"M 2001-06-10 17:33 ${PLUS}0000 kingdon 1\.281 cvs.texinfo ccvs/doc == ~/work/ccvs/doc
-M 1997-06-10 01:38 ${PLUS}0000 anonymous 1\.23 Makefile ccvs/src == <remote>
-M 1997-06-10 21:12 ${PLUS}0000 kingdon 1\.231 sanity.sh ccvs/src == ~/work/ccvs/src"
-
- dotest history-11 "${testcvs} history -aw" \
-"O 1997-06-04 19:48 ${PLUS}0000 anonymous ccvs =ccvs= <remote>/\*
-O 1997-06-05 14:00 ${PLUS}0000 anonymous ccvs =src= <remote>/\*
-O 1997-06-06 08:12 ${PLUS}0000 kingdon ccvs =ccvs= <remote>/\*"
-
- dotest history-12 "${testcvs} history -aw -D'1970-01-01 00:00 UT'" \
-"O 1997-06-04 19:48 ${PLUS}0000 anonymous ccvs =ccvs= <remote>/\*
-O 1997-06-05 14:00 ${PLUS}0000 anonymous ccvs =src= <remote>/\*
-O 1997-06-06 08:12 ${PLUS}0000 kingdon ccvs =ccvs= <remote>/\*"
- ;;
-
- big)
-
- # Test ability to operate on big files. Intention is to
- # test various realloc'ing code in RCS_deltas, rcsgetkey,
- # etc. "big" is currently defined to be 1000 lines (64000
- # bytes), which in terms of files that users will use is not
- # large, merely average, but my reasoning is that this
- # should be big enough to make sure realloc'ing is going on
- # and that raising it a lot would start to stress resources
- # on machines which run the tests, without any significant
- # benefit.
-
- mkdir ${CVSROOT_DIRNAME}/first-dir
- dotest big-1 "${testcvs} -q co first-dir" ''
- cd first-dir
- for i in 0 1 2 3 4 5 6 7 8 9; do
- for j in 0 1 2 3 4 5 6 7 8 9; do
- for k in 0 1 2 3 4 5 6 7 8 9; do
- echo \
-"This is line ($i,$j,$k) which goes into the file file1 for testing" >>file1
- done
- done
- done
- dotest big-2 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest big-3 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- cd ..
- mkdir 2
- cd 2
- dotest big-4 "${testcvs} -q get first-dir" "U first-dir/file1"
- cd ../first-dir
- echo "add a line to the end" >>file1
- dotest big-5 "${testcvs} -q ci -m modify" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
- cd ../2/first-dir
- # The idea here is particularly to test the Rcs-diff response
- # and the reallocing thereof, for remote.
- dotest big-6 "${testcvs} -q update" "[UP] file1"
- cd ../..
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- rm -r first-dir 2
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- modes)
- # Test repository permissions (CVSUMASK and so on).
- # Although the tests in this section "cheat" by testing
- # repository permissions, which are sort of not a user-visible
- # sort of thing, the modes do have user-visible consequences,
- # such as whether a second user can check out the files. But
- # it would be awkward to test the consequences, so we don't.
-
- # Solaris /bin/sh doesn't support export -n. I'm not sure
- # what we can do about this, other than hope that whoever
- # is running the tests doesn't have CVSUMASK set.
- #export -n CVSUMASK # if unset, defaults to 002
-
- umask 077
- mkdir 1; cd 1
- dotest modes-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest modes-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- touch aa
- dotest modes-3 "${testcvs} add aa" \
-"${PROG} add: scheduling file .aa. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest modes-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/aa,v
-done
-Checking in aa;
-${CVSROOT_DIRNAME}/first-dir/aa,v <-- aa
-initial revision: 1\.1
-done"
- # Yawn. Cygwin.
- if test -n "$remotehost"; then
- dotest modes-5remotehost "$CVS_RSH $remotehost 'ls -l ${CVSROOT_DIRNAME}/first-dir/aa,v'" \
-"-r--r--r-- .*"
- else
- dotest modes-5 "ls -l ${CVSROOT_DIRNAME}/first-dir/aa,v" \
-"-r--r--r-- .*"
- fi
-
- # Test for whether we can set the execute bit.
- chmod +x aa
- echo change it >>aa
- dotest modes-6 "${testcvs} -q ci -m set-execute-bit" \
-"Checking in aa;
-${CVSROOT_DIRNAME}/first-dir/aa,v <-- aa
-new revision: 1\.2; previous revision: 1\.1
-done"
- # If CVS let us update the execute bit, it would be set here.
- # But it doesn't, and as far as I know that is longstanding
- # CVS behavior.
- #
- # Yeah, yeah. Search for "Cygwin".
- if test -n "$remotehost"; then
- dotest modes-7remotehost "$CVS_RSH $remotehost 'ls -l ${CVSROOT_DIRNAME}/first-dir/aa,v'" \
-"-r--r--r-- .*"
- else
- dotest modes-7 "ls -l ${CVSROOT_DIRNAME}/first-dir/aa,v" \
-"-r--r--r-- .*"
- fi
-
- # OK, now manually change the modes and see what happens.
- #
- # Cygwin, already.
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost "chmod g=r,o= ${CVSROOT_DIRNAME}/first-dir/aa,v"
- else
- chmod g=r,o= ${CVSROOT_DIRNAME}/first-dir/aa,v
- fi
- echo second line >>aa
- dotest modes-7a "${testcvs} -q ci -m set-execute-bit" \
-"Checking in aa;
-${CVSROOT_DIRNAME}/first-dir/aa,v <-- aa
-new revision: 1\.3; previous revision: 1\.2
-done"
- # Cygwin.
- if test -n "$remotehost"; then
- dotest modes-7bremotehost "$CVS_RSH $remotehost 'ls -l ${CVSROOT_DIRNAME}/first-dir/aa,v'" \
-"-r--r----- .*"
- else
- dotest modes-7b "ls -l ${CVSROOT_DIRNAME}/first-dir/aa,v" \
-"-r--r----- .*"
- fi
-
- CVSUMASK=007
- export CVSUMASK
- touch ab
- # Might as well test the execute bit too.
- chmod +x ab
- dotest modes-8 "${testcvs} add ab" \
-"${PROG} add: scheduling file .ab. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest modes-9 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/ab,v
-done
-Checking in ab;
-${CVSROOT_DIRNAME}/first-dir/ab,v <-- ab
-initial revision: 1\.1
-done"
- if $remote; 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.
- if test -n "$remotehost"; then
- dotest modes-10remotehost "$CVS_RSH $remotehost 'ls -l ${CVSROOT_DIRNAME}/first-dir/ab,v'" \
-"-r--r--r--.*"
- else
- dotest modes-10r "ls -l ${CVSROOT_DIRNAME}/first-dir/ab,v" \
-"-r-xr-x---.*" "-r-xr-xr-x.*"
- fi
- else
- dotest modes-10 "ls -l ${CVSROOT_DIRNAME}/first-dir/ab,v" \
-"-r-xr-x---.*"
- fi
-
- # OK, now add a file on a branch. Check that the mode gets
- # set the same way (it is a different code path in CVS).
- dotest modes-11 "${testcvs} -q tag -b br" 'T aa
-T ab'
- dotest modes-12 "$testcvs -q update -r br" \
-'[UP] aa
-U ab'
- touch ac
- dotest modes-13 "${testcvs} add ac" \
-"${PROG} add: scheduling file .ac. for addition on branch .br.
-${PROG} add: use .${PROG} commit. to add this file permanently"
- # Not sure it really makes sense to refer to a "previous revision"
- # when we are just now adding the file; as far as I know
- # that is longstanding CVS behavior, for what it's worth.
- dotest modes-14 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/ac,v
-done
-Checking in ac;
-${CVSROOT_DIRNAME}/first-dir/Attic/ac,v <-- ac
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
- if $remote; 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. 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).
- if test -n "$remotehost"; then
- dotest modes-15r \
-"$CVS_RSH $remotehost 'ls -l ${CVSROOT_DIRNAME}/first-dir/Attic/ac,v'" \
-"-r--r--r--.*"
- else
- dotest modes-15r \
-"ls -l ${CVSROOT_DIRNAME}/first-dir/Attic/ac,v" \
-"-r--r--r--.*" "-r--r-----.*"
- fi
- else
- dotest modes-15 \
-"ls -l ${CVSROOT_DIRNAME}/first-dir/Attic/ac,v" \
-"-r--r-----.*"
- fi
-
- cd ../..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- # Perhaps should restore the umask and CVSUMASK. But the other
- # tests "should" not care about them...
- ;;
-
- modes2)
- # More tests of file permissions in the working directory
- # and that sort of thing.
-
- # The usual setup, file first-dir/aa with two revisions.
- mkdir 1; cd 1
- dotest modes2-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest modes2-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- touch aa
- dotest modes2-3 "${testcvs} add aa" \
-"${PROG} add: scheduling file .aa. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest modes2-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/aa,v
-done
-Checking in aa;
-${CVSROOT_DIRNAME}/first-dir/aa,v <-- aa
-initial revision: 1\.1
-done"
- echo "more money" >> aa
- dotest modes2-5 "${testcvs} -q ci -m add" \
-"Checking in aa;
-${CVSROOT_DIRNAME}/first-dir/aa,v <-- aa
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # OK, here is the test. The idea is to see what
- # No_Difference does if it can't open the file.
- # If we don't change the st_mtime, CVS doesn't even try to read
- # the file. Note that some versions of "touch" require that we
- # do this while the file is still writable.
- touch aa
- chmod a= aa
- # Don't try this when permissions are broken, as with Cygwin.
- if ls ${CVSROOT_DIRNAME}/first-dir >/dev/null 2>&1; then :; else
- dotest_fail modes2-6 "${testcvs} -q update -r 1.1 aa" \
-"${PROG} \[update aborted\]: cannot open file aa for comparing: Permission denied" \
-"${PROG} \[update aborted\]: reading aa: Permission denied"
- fi
-
- chmod u+rwx aa
- cd ../..
- rm -r 1
- 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 modes3-1 "${testcvs} -q co -l ." ''
- mkdir first-dir second-dir
- dotest modes3-2 "${testcvs} add first-dir second-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository
-Directory ${CVSROOT_DIRNAME}/second-dir added to the repository"
- touch first-dir/aa second-dir/ab
- dotest modes3-3 "${testcvs} add first-dir/aa second-dir/ab" \
-"${PROG} add: scheduling file .first-dir/aa. for addition
-${PROG} add: scheduling file .second-dir/ab. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest modes3-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/aa,v
-done
-Checking in first-dir/aa;
-${CVSROOT_DIRNAME}/first-dir/aa,v <-- aa
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/second-dir/ab,v
-done
-Checking in second-dir/ab;
-${CVSROOT_DIRNAME}/second-dir/ab,v <-- ab
-initial revision: 1\.1
-done"
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost "chmod a= ${CVSROOT_DIRNAME}/first-dir"
- else
- chmod a= ${CVSROOT_DIRNAME}/first-dir
- fi
- if ls ${CVSROOT_DIRNAME}/first-dir >/dev/null 2>&1; then
- # Avoid this test under Cygwin since permissions work differently
- # there.
- #
- # This test also gets avoided under Mac OS X since the system `ls'
- # is broken and exits with a 0 status despite the permission
- # denied error.
- if test -n "$remotehost"; then
- cygwin_hack=false
- else
- cygwin_hack=:
- fi
- else
- cygwin_hack=false
- fi
-
- cd $TESTDIR/1
- if $cygwin_hack; then :; else
- dotest modes3-5 "${testcvs} update" \
-"${PROG} update: Updating \.
-${PROG} update: Updating first-dir
-${PROG} update: cannot open directory ${CVSROOT_DIRNAME}/first-dir: Permission denied
-${PROG} update: skipping directory first-dir
-${PROG} update: Updating second-dir"
- fi
-
- # 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.
- #
- # The second text string below is for Cygwin again, and again it
- # should really be XFAIL under Cygwin, but for now deal with the
- # passing opendir by accepting the alternate string.
- rm -r first-dir
- dotest modes3-6 "${testcvs} update -dP" \
-"${PROG} update: Updating .
-${PROG} update: Updating CVSROOT
-U ${DOTSTAR}
-${PROG} update: Updating first-dir
-${PROG} update: cannot open directory ${CVSROOT_DIRNAME}/first-dir: Permission denied
-${PROG} update: skipping directory first-dir
-${PROG} update: Updating second-dir" \
-"${PROG} update: Updating .
-${PROG} update: Updating CVSROOT
-U ${DOTSTAR}
-${PROG} update: Updating first-dir
-${PROG} update: Updating second-dir"
-
- cd ..
- rm -r 1
- chmod u+rwx ${CVSROOT_DIRNAME}/first-dir
- rm -rf ${CVSROOT_DIRNAME}/first-dir ${CVSROOT_DIRNAME}/second-dir
- ;;
-
- stamps)
- # Test timestamps.
- mkdir 1; cd 1
- dotest stamps-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest stamps-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- touch aa
- echo '$''Id$' >kw
- # Cygwin, *cough*, puts the year in the time column until the minute
- # is no longer the current minute. Sleep 60 seconds to avoid this
- # problem.
- sleep 60
- ls -l aa >${TESTDIR}/1/stamp.aa.touch
- ls -l kw >${TESTDIR}/1/stamp.kw.touch
- # "sleep 1" would suffice if we could assume ls --full-time, but
- # that is as far as I know unique to GNU ls. Is there some POSIX.2
- # way to get the timestamp of a file, including the seconds?
- sleep 60
- dotest stamps-3 "${testcvs} add aa kw" \
-"${PROG} add: scheduling file .aa. for addition
-${PROG} add: scheduling file .kw. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- ls -l aa >${TESTDIR}/1/stamp.aa.add
- ls -l kw >${TESTDIR}/1/stamp.kw.add
- # "cvs add" should not muck with the timestamp.
- dotest stamps-4aa \
-"cmp ${TESTDIR}/1/stamp.aa.touch ${TESTDIR}/1/stamp.aa.add" ''
- dotest stamps-4kw \
-"cmp ${TESTDIR}/1/stamp.kw.touch ${TESTDIR}/1/stamp.kw.add" ''
- sleep 60
- dotest stamps-5 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/aa,v
-done
-Checking in aa;
-${CVSROOT_DIRNAME}/first-dir/aa,v <-- aa
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/kw,v
-done
-Checking in kw;
-${CVSROOT_DIRNAME}/first-dir/kw,v <-- kw
-initial revision: 1\.1
-done"
- # Cygwin, *cough*, puts the year in the time column until the minute
- # is no longer the current minute. Sleep 60 seconds to avoid this
- # problem.
- sleep 60
- ls -l aa >${TESTDIR}/1/stamp.aa.ci
- ls -l kw >${TESTDIR}/1/stamp.kw.ci
- # If there are no keywords, "cvs ci" leaves the timestamp alone
- # If there are, it sets the timestamp to the date of the commit.
- # I'm not sure how logical this is, but it is intentional.
- # If we wanted to get fancy we would make sure the time as
- # reported in "cvs log kw" matched stamp.kw.ci. But that would
- # be a lot of work.
- dotest stamps-6aa \
- "cmp ${TESTDIR}/1/stamp.aa.add ${TESTDIR}/1/stamp.aa.ci" ''
- if cmp ${TESTDIR}/1/stamp.kw.add ${TESTDIR}/1/stamp.kw.ci >/dev/null
- then
- fail stamps-6kw
- else
- pass stamps-6kw
- fi
- cd ../..
- sleep 60
- mkdir 2
- cd 2
- dotest stamps-7 "${testcvs} -q get first-dir" "U first-dir/aa
-U first-dir/kw"
- cd first-dir
- ls -l aa >${TESTDIR}/1/stamp.aa.get
- ls -l kw >${TESTDIR}/1/stamp.kw.get
- # On checkout, CVS should set the timestamp to the date that the
- # file was committed. Could check that the time as reported in
- # "cvs log aa" matches stamp.aa.get, but that would be a lot of
- # work.
- if cmp ${TESTDIR}/1/stamp.aa.ci ${TESTDIR}/1/stamp.aa.get >/dev/null
- then
- fail stamps-8aa
- else
- pass stamps-8aa
- fi
- dotest stamps-8kw \
- "cmp ${TESTDIR}/1/stamp.kw.ci ${TESTDIR}/1/stamp.kw.get" ''
-
- # Now we want to see what "cvs update" does.
- sleep 60
- echo add a line >>aa
- echo add a line >>kw
- dotest stamps-9 "${testcvs} -q ci -m change-them" \
-"Checking in aa;
-${CVSROOT_DIRNAME}/first-dir/aa,v <-- aa
-new revision: 1\.2; previous revision: 1\.1
-done
-Checking in kw;
-${CVSROOT_DIRNAME}/first-dir/kw,v <-- kw
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # Cygwin, *cough*, puts the year in the time column until the minute
- # is no longer the current minute. Sleep 60 seconds to avoid this
- # problem.
- sleep 60
- ls -l aa >${TESTDIR}/1/stamp.aa.ci2
- ls -l kw >${TESTDIR}/1/stamp.kw.ci2
- cd ../..
- cd 1/first-dir
- sleep 60
- dotest stamps-10 "${testcvs} -q update" '[UP] aa
-[UP] kw'
- # this doesn't serve any function other than being able to
- # look at it manually, as we have no machinery for dates being
- # newer or older than other dates.
- date >${TESTDIR}/1/stamp.debug.update
- ls -l aa >${TESTDIR}/1/stamp.aa.update
- ls -l kw >${TESTDIR}/1/stamp.kw.update
- # stamp.aa.update and stamp.kw.update should both be approximately
- # the same as stamp.debug.update. Perhaps we could be testing
- # this in a more fancy fashion by "touch stamp.before" before
- # stamps-10, "touch stamp.after" after, and then using ls -t
- # to check them. But for now we just make sure that the *.update
- # stamps differ from the *.ci2 ones.
- # As for the rationale, this is so that if one updates and gets
- # a new revision, then "make" will be sure to regard those files
- # as newer than .o files which may be sitting around.
- if cmp ${TESTDIR}/1/stamp.aa.update ${TESTDIR}/1/stamp.aa.ci2 \
- >/dev/null
- then
- fail stamps-11aa
- else
- pass stamps-11aa
- fi
- if cmp ${TESTDIR}/1/stamp.kw.update ${TESTDIR}/1/stamp.kw.ci2 \
- >/dev/null
- then
- fail stamps-11kw
- else
- pass stamps-11kw
- fi
-
- cd ../..
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- rm -r 1 2
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- perms)
- # short cut around checking out and committing CVSROOT
- rm -f ${CVSROOT_DIRNAME}/CVSROOT/config
- echo 'PreservePermissions=yes' > ${CVSROOT_DIRNAME}/CVSROOT/config
- chmod 444 ${CVSROOT_DIRNAME}/CVSROOT/config
-
- mkdir 1; cd 1
- dotest perms-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest perms-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
-
- touch foo
- chmod 431 foo
- dotest perms-3 "${testcvs} add foo" \
-"${PROG} add: scheduling file .foo. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest perms-4 "${testcvs} -q ci -m ''" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/foo,v
-done
-Checking in foo;
-${CVSROOT_DIRNAME}/first-dir/foo,v <-- foo
-initial revision: 1\.1
-done"
-
- # Test checking out files with different permissions.
- cd ../..
- mkdir 2; cd 2
- dotest perms-5 "${testcvs} -q co first-dir" "U first-dir/foo"
- cd first-dir
- if $remote; then :; else
- # PreservePermissions not yet implemented for remote.
- dotest perms-6 "ls -l foo" "-r---wx--x .* foo"
- fi
-
- cd ../..
- rm -rf 1 2
- rm -rf ${CVSROOT_DIRNAME}/first-dir
-
- rm -f ${CVSROOT_DIRNAME}/CVSROOT/config
- touch ${CVSROOT_DIRNAME}/CVSROOT/config
- chmod 444 ${CVSROOT_DIRNAME}/CVSROOT/config
- ;;
-
- symlinks)
- # short cut around checking out and committing CVSROOT
- rm -f ${CVSROOT_DIRNAME}/CVSROOT/config
- echo 'PreservePermissions=yes' > ${CVSROOT_DIRNAME}/CVSROOT/config
- chmod 444 ${CVSROOT_DIRNAME}/CVSROOT/config
-
- mkdir 1; cd 1
- dotest symlinks-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest symlinks-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
-
- dotest symlinks-2.1 "ln -s ${TESTDIR}/fumble slink" ""
- dotest symlinks-3 "${testcvs} add slink" \
-"${PROG} add: scheduling file .slink. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- if $remote; then
- # Remote doesn't implement PreservePermissions, and in its
- # absence the correct behavior is to follow the symlink.
- dotest_fail symlinks-4r "${testcvs} -q ci -m ''" \
-"${PROG} \[commit aborted\]: reading slink: No such file or directory"
- else
- dotest symlinks-4 "${testcvs} -q ci -m ''" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/slink,v
-done
-Checking in slink;
-${CVSROOT_DIRNAME}/first-dir/slink,v <-- slink
-initial revision: 1\.1
-done"
-
- # Test checking out symbolic links.
- cd ../..
- mkdir 2; cd 2
- dotest symlinks-5 "${testcvs} -q co first-dir" "U first-dir/slink"
- cd first-dir
- dotest symlinks-6 "ls -l slink" \
-"l[rwx\-]* .* slink -> ${TESTDIR}/fumble"
- fi
-
- cd ../..
- rm -rf 1 2
- rm -rf ${CVSROOT_DIRNAME}/first-dir
-
- rm -f ${CVSROOT_DIRNAME}/CVSROOT/config
- touch ${CVSROOT_DIRNAME}/CVSROOT/config
- 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 ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- echo nonsymlink > slink
- dotest symlinks2-3 "${testcvs} add slink" \
-"${PROG} add: scheduling file .slink. for addition
-${PROG} add: 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;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/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
- echo 'PreservePermissions=yes' > ${CVSROOT_DIRNAME}/CVSROOT/config
- chmod 444 ${CVSROOT_DIRNAME}/CVSROOT/config
-
- mkdir 1; cd 1
- dotest hardlinks-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest hardlinks-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
-
- # Make up some ugly filenames, to test that they get
- # encoded properly in the delta nodes. Note that `dotest' screws
- # up if some arguments have embedded spaces.
- if touch aaaa
- then
- pass hardlinks-2.1
- else
- fail hardlinks-2.1
- fi
-
- if ln aaaa b.b.b.b
- then
- pass hardlinks-2.2
- else
- fail hardlinks-2.2
- fi
-
- if ln aaaa 'dd dd dd'
- then
- pass hardlinks-2.3
- else
- fail hardlinks-2.3
- fi
-
- dotest hardlinks-3 "${testcvs} add [abd]*" \
-"${PROG} add: scheduling file .aaaa. for addition
-${PROG} add: scheduling file .b\.b\.b\.b. for addition
-${PROG} add: scheduling file .dd dd dd. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest hardlinks-4 "${testcvs} -q ci -m ''" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/aaaa,v
-done
-Checking in aaaa;
-${CVSROOT_DIRNAME}/first-dir/aaaa,v <-- aaaa
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/b\.b\.b\.b,v
-done
-Checking in b\.b\.b\.b;
-${CVSROOT_DIRNAME}/first-dir/b\.b\.b\.b,v <-- b\.b\.b\.b
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/dd dd dd,v
-done
-Checking in dd dd dd;
-${CVSROOT_DIRNAME}/first-dir/dd dd dd,v <-- dd dd dd
-initial revision: 1\.1
-done"
- # Test checking out hardlinked files.
- cd ../..
- mkdir 2; cd 2
- if $remote; then
- # Remote does not implement PreservePermissions.
- dotest hardlinks-5r "${testcvs} -q co first-dir" \
-"U first-dir/aaaa
-U first-dir/b\.b\.b\.b
-U first-dir/dd dd dd"
- cd first-dir
- dotest hardlinks-6r "ls -l [abd]*" \
-"-[rwx\-]* *1 .* aaaa
--[rwx\-]* *1 .* b\.b\.b\.b
--[rwx\-]* *1 .* dd dd dd"
- else
- dotest hardlinks-5 "${testcvs} -q co first-dir" \
-"U first-dir/aaaa
-U first-dir/b\.b\.b\.b
-U first-dir/dd dd dd"
- cd first-dir
- # To make sure that the files are properly hardlinked, it
- # would be nice to do `ls -i' and make sure all the inodes
- # match. But I think that would require expr to support
- # tagged regexps, and I don't think we can rely on that.
- # So instead we just see that each file has the right
- # number of links. -twp
- dotest hardlinks-6 "ls -l [abd]*" \
-"-[rwx\-]* *3 .* aaaa
--[rwx\-]* *3 .* b\.b\.b\.b
--[rwx\-]* *3 .* dd dd dd"
- fi
-
- cd ../..
- rm -rf 1 2
- rm -rf ${CVSROOT_DIRNAME}/first-dir
-
- rm -f ${CVSROOT_DIRNAME}/CVSROOT/config
- touch ${CVSROOT_DIRNAME}/CVSROOT/config
- chmod 444 ${CVSROOT_DIRNAME}/CVSROOT/config
- ;;
-
- sticky)
- # More tests of sticky tags, particularly non-branch sticky tags.
- # See many tests (e.g. multibranch) for ordinary sticky tag
- # operations such as adding files on branches.
- # See "head" test for interaction between stick tags and HEAD.
- mkdir 1; cd 1
- dotest sticky-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest sticky-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
-
- touch file1
- dotest sticky-3 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest sticky-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- dotest sticky-5 "${testcvs} -q tag tag1" "T file1"
- echo add a line >>file1
- dotest sticky-6 "${testcvs} -q ci -m modify" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
- dotest sticky-7 "${testcvs} -q update -r tag1" "[UP] file1"
- dotest sticky-8 "cat file1" ''
- dotest sticky-9 "${testcvs} -q update" ''
- dotest sticky-10 "cat file1" ''
- touch file2
- dotest_fail sticky-11 "${testcvs} add file2" \
-"${PROG} add: cannot add file on non-branch tag tag1"
- dotest sticky-12 "${testcvs} -q update -A" "[UP] file1
-${QUESTION} file2" "${QUESTION} file2
-[UP] file1"
- dotest sticky-13 "${testcvs} add file2" \
-"${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest sticky-14 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1\.1
-done"
-
- # Now back to tag1
- dotest sticky-15 "${testcvs} -q update -r tag1" "[UP] file1
-${PROG} update: file2 is no longer in the repository"
-
- rm file1
- dotest sticky-16 "${testcvs} rm file1" \
-"${PROG} remove: scheduling .file1. for removal
-${PROG} remove: use .${PROG} commit. to remove this file permanently"
- # Hmm, this command seems to silently remove the tag from
- # the file. This appears to be intentional.
- # The silently part especially strikes me as odd, though.
- dotest sticky-17 "${testcvs} -q ci -m remove-it" ""
- dotest sticky-18 "${testcvs} -q update -A" "U file1
-U file2"
- dotest sticky-19 "${testcvs} -q update -r tag1" \
-"${PROG} update: file1 is no longer in the repository
-${PROG} update: file2 is no longer in the repository"
- dotest sticky-20 "${testcvs} -q update -A" "U file1
-U file2"
-
- # Now try with a numeric revision.
- dotest sticky-21 "${testcvs} -q update -r 1.1 file1" "U file1"
- dotest sticky-22 "${testcvs} rm -f file1" \
-"${PROG} remove: cannot remove file .file1. which has a numeric sticky tag of .1\.1."
- # The old behavior was that remove allowed this and then commit
- # gave an error, which was somewhat hard to clear. I mean, you
- # could get into a long elaborate discussion of this being a
- # conflict and two ways to resolve it, but I don't really see
- # why CVS should have a concept of conflict that arises, not from
- # parallel development, but from CVS's own sticky tags.
-
- # Ditto with a sticky date.
- #
- # I'm kind of surprised that the "file1 was lost" doesn't crop
- # up elsewhere in the testsuite. It is a long-standing
- # discrepency between local and remote CVS and should probably
- # be cleaned up at some point.
- dotest sticky-23 "${testcvs} -q update -Dnow file1" \
-"${PROG} update: warning: file1 was lost
-U file1" "U file1"
- dotest sticky-24 "${testcvs} rm -f file1" \
-"${PROG} remove: cannot remove file .file1. which has a sticky date of .[0-9.]*."
-
- dotest sticky-25 "${testcvs} -q update -A" \
-"${PROG} update: warning: file1 was lost
-U file1" "U file1"
-
- cd ../..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- keyword)
- # Test keyword expansion.
- # Various other tests relate to our ability to correctly
- # set the keyword expansion mode.
- # "binfiles" tests "cvs admin -k".
- # "binfiles" and "binfiles2" test "cvs add -k".
- # "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
- dotest keyword-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
-
- echo '$''Author$' > file1
- echo '$''Date$' >> file1
- echo '$''Header$' >> file1
- echo '$''Id$' >> file1
- echo '$''Locker$' >> file1
- echo '$''Name$' >> file1
- echo '$''RCSfile$' >> file1
- echo '$''Revision$' >> file1
- echo '$''Source$' >> file1
- echo '$''State$' >> file1
- echo '$''Nonkey$' >> file1
- # Omit the trailing dollar sign
- echo '$''Date' >> file1
- # Put two keywords on one line
- echo '$''State$' '$''State$' >> file1
- # Use a header for Log
- echo 'xx $''Log$' >> file1
-
- dotest keyword-3 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest keyword-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- dotest keyword-5 "cat file1" \
-'\$'"Author: ${username} "'\$'"
-"'\$'"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]:[0-9][0-9] "'\$'"
-"'\$'"Header: ${CVSROOT_DIRNAME}/first-dir/file1,v 1\.1 [0-9/]* [0-9:]* ${username} Exp "'\$'"
-"'\$'"Id: file1,v 1\.1 [0-9/]* [0-9:]* ${username} Exp "'\$'"
-"'\$'"Locker: "'\$'"
-"'\$'"Name: "'\$'"
-"'\$'"RCSfile: file1,v "'\$'"
-"'\$'"Revision: 1\.1 "'\$'"
-"'\$'"Source: ${CVSROOT_DIRNAME}/first-dir/file1,v "'\$'"
-"'\$'"State: Exp "'\$'"
-"'\$'"Nonkey"'\$'"
-"'\$'"Date
-"'\$'"State: Exp "'\$'" "'\$'"State: Exp "'\$'"
-xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.1 [0-9/]* [0-9:]* ${username}
-xx add
-xx"
-
- # Use cvs admin to lock the RCS file in order to check -kkvl
- # vs. -kkv. CVS does not normally lock RCS files, but some
- # people use cvs admin to enforce reserved checkouts.
- dotest keyword-6 "${testcvs} admin -l file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-1\.1 locked
-done"
-
- dotest keyword-7 "$testcvs update -kkv file1" '[UP] file1'
- dotest keyword-8 "cat file1" \
-'\$'"Author: ${username} "'\$'"
-"'\$'"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]:[0-9][0-9] "'\$'"
-"'\$'"Header: ${CVSROOT_DIRNAME}/first-dir/file1,v 1\.1 [0-9/]* [0-9:]* ${username} Exp "'\$'"
-"'\$'"Id: file1,v 1\.1 [0-9/]* [0-9:]* ${username} Exp "'\$'"
-"'\$'"Locker: "'\$'"
-"'\$'"Name: "'\$'"
-"'\$'"RCSfile: file1,v "'\$'"
-"'\$'"Revision: 1\.1 "'\$'"
-"'\$'"Source: ${CVSROOT_DIRNAME}/first-dir/file1,v "'\$'"
-"'\$'"State: Exp "'\$'"
-"'\$'"Nonkey"'\$'"
-"'\$'"Date
-"'\$'"State: Exp "'\$'" "'\$'"State: Exp "'\$'"
-xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.1 [0-9/]* [0-9:]* ${username}
-xx add
-xx"
-
- dotest keyword-9 "$testcvs update -kkvl file1" '[UP] file1'
- dotest keyword-10 "cat file1" \
-'\$'"Author: ${username} "'\$'"
-"'\$'"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]:[0-9][0-9] "'\$'"
-"'\$'"Header: ${CVSROOT_DIRNAME}/first-dir/file1,v 1\.1 [0-9/]* [0-9:]* ${username} Exp ${username} "'\$'"
-"'\$'"Id: file1,v 1\.1 [0-9/]* [0-9:]* ${username} Exp ${username} "'\$'"
-"'\$'"Locker: ${username} "'\$'"
-"'\$'"Name: "'\$'"
-"'\$'"RCSfile: file1,v "'\$'"
-"'\$'"Revision: 1\.1 "'\$'"
-"'\$'"Source: ${CVSROOT_DIRNAME}/first-dir/file1,v "'\$'"
-"'\$'"State: Exp "'\$'"
-"'\$'"Nonkey"'\$'"
-"'\$'"Date
-"'\$'"State: Exp "'\$'" "'\$'"State: Exp "'\$'"
-xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.1 [0-9/]* [0-9:]* ${username}
-xx add
-xx"
-
- dotest keyword-11 "${testcvs} update -kk file1" '[UP] file1'
- dotest keyword-12 "cat file1" \
-'\$'"Author"'\$'"
-"'\$'"Date"'\$'"
-"'\$'"Header"'\$'"
-"'\$'"Id"'\$'"
-"'\$'"Locker"'\$'"
-"'\$'"Name"'\$'"
-"'\$'"RCSfile"'\$'"
-"'\$'"Revision"'\$'"
-"'\$'"Source"'\$'"
-"'\$'"State"'\$'"
-"'\$'"Nonkey"'\$'"
-"'\$'"Date
-"'\$'"State"'\$'" "'\$'"State"'\$'"
-xx "'\$'"Log"'\$'"
-xx Revision 1\.1 [0-9/]* [0-9:]* ${username}
-xx add
-xx"
-
- dotest keyword-13 "$testcvs update -kv file1" '[UP] file1'
- dotest keyword-14 "cat file1" \
-"${username}
-[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]
-${CVSROOT_DIRNAME}/first-dir/file1,v 1\.1 [0-9/]* [0-9:]* ${username} Exp
-file1,v 1\.1 [0-9/]* [0-9:]* ${username} Exp
-
-
-file1,v
-1\.1
-${CVSROOT_DIRNAME}/first-dir/file1,v
-Exp
-"'\$'"Nonkey"'\$'"
-"'\$'"Date
-Exp Exp
-xx file1,v
-xx Revision 1\.1 [0-9/]* [0-9:]* ${username}
-xx add
-xx"
-
- dotest keyword-15 "${testcvs} update -ko file1" "U file1"
- dotest keyword-16 "cat file1" \
-'\$'"Author"'\$'"
-"'\$'"Date"'\$'"
-"'\$'"Header"'\$'"
-"'\$'"Id"'\$'"
-"'\$'"Locker"'\$'"
-"'\$'"Name"'\$'"
-"'\$'"RCSfile"'\$'"
-"'\$'"Revision"'\$'"
-"'\$'"Source"'\$'"
-"'\$'"State"'\$'"
-"'\$'"Nonkey"'\$'"
-"'\$'"Date
-"'\$'"State"'\$'" "'\$'"State"'\$'"
-xx "'\$'"Log"'\$'
-
- # Test the Name keyword. First go back to normal expansion.
-
- dotest keyword-17 "${testcvs} update -A file1" "U file1"
-
- echo '$''Name$' > file1
- dotest keyword-18 "${testcvs} ci -m modify file1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
- dotest keyword-19 "${testcvs} -q tag tag1" "T file1"
- echo "change" >> file1
- dotest keyword-20 "${testcvs} -q ci -m mod2 file1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.3; previous revision: 1\.2
-done"
-
- # Prior to 1.11.23, remote CVS would fail the patch checksum test
- # and refetch the file here, failing this test.
- dotest keyword-21 "$testcvs -q update -r tag1" 'U file1'
-
- dotest keyword-22 "cat file1" '\$'"Name: tag1 "'\$'
-
- # The update used to fail the first time with a checksum failure
- # here, then the server would send the whole failure. This was fixed
- # in 1.11.23.
- dotest keyword-23 "$testcvs update -A file1" "U file1"
- dotest keyword-24 "cat file1" '\$'"Name: "'\$'"
-change"
-
- cd ../..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- keywordlog)
- # Test the Log keyword.
- mkdir 1; cd 1
- dotest keywordlog-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest keywordlog-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- echo initial >file1
- dotest keywordlog-3 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
-
- # 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: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.3
-done"
-
- cd ../..
- mkdir 2; cd 2
- dotest keywordlog-4a "${testcvs} -q co first-dir" "U first-dir/file1"
- cd ../1/first-dir
-
- 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} commit: sticky tag .1\.3. for file .file1. is not a branch
-${PROG} \[commit 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;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-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" \
-"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
- dotest keywordlog-8 "${testcvs} -q update" "[UP] file1"
- dotest keywordlog-9 "cat 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 ../../1/first-dir
-
- echo "change" >> file1
- dotest keywordlog-10 "${testcvs} ci -m modify file1" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.5; previous revision: 1\.4
-done"
- dotest keywordlog-11 "cat file1" \
-"initial
-xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.5 [0-9/]* [0-9:]* ${username}
-xx modify
-xx
-xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
-xx First log line
-xx Second log line
-xx
-change"
-
- cd ../../2/first-dir
- dotest keywordlog-12 "${testcvs} -q update" "[UP] file1"
- dotest keywordlog-13 "cat file1" \
-"initial
-xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.5 [0-9/]* [0-9:]* ${username}
-xx modify
-xx
-xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
-xx First log line
-xx Second log line
-xx
-change"
-
- cd ../../1/first-dir
- dotest keywordlog-14 "${testcvs} -q update -r br" "[UP] file1"
- echo br-change >>file1
- dotest keywordlog-15 "${testcvs} -q ci -m br-modify" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.4\.2\.1; previous revision: 1\.4
-done"
- dotest keywordlog-16 "cat file1" \
-"initial
-xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.4\.2\.1 [0-9/]* [0-9:]* ${username}
-xx br-modify
-xx
-xx Revision 1\.4 [0-9/]* [0-9:]* ${username}
-xx First log line
-xx Second log line
-xx
-br-change"
- cd ../../2/first-dir
- dotest keywordlog-17 "${testcvs} -q update -r br" "[UP] file1"
- dotest keywordlog-18 "cat file1" \
-"initial
-xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.4\.2\.1 [0-9/]* [0-9:]* ${username}
-xx br-modify
-xx
-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" \
-"initial
-xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.4\.2\.1 [0-9/]* [0-9:]* ${username}
-xx br-modify
-xx
-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" \
-"initial
-xx "'\$'"Log: file1,v "'\$'"
-xx Revision 1\.5 [0-9/]* [0-9:]* ${username}
-xx modify
-xx
-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.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 ($username8 *[0-9a-zA-Z-]*): initial
-1\.4\.2\.1 ($username8 *[0-9a-zA-Z-]*): xx "'\$'"Log: file1,v "'\$'"
-1\.4\.2\.1 ($username8 *[0-9a-zA-Z-]*): xx Revision 1\.4 [0-9/]* [0-9:]* $username
-1\.4\.2\.1 ($username8 *[0-9a-zA-Z-]*): xx First log line
-1\.4\.2\.1 ($username8 *[0-9a-zA-Z-]*): xx Second log line
-1\.4\.2\.1 ($username8 *[0-9a-zA-Z-]*): xx
-1\.4\.2\.1 ($username8 *[0-9a-zA-Z-]*): br-change"
- dotest keywordlog-23 "${testcvs} ann -r HEAD file1" \
-"
-Annotations for file1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-1\.3 ($username8 *[0-9a-zA-Z-]*): initial
-1\.5 ($username8 *[0-9a-zA-Z-]*): xx "'\$'"Log: file1,v "'\$'"
-1\.5 ($username8 *[0-9a-zA-Z-]*): xx Revision 1\.4 [0-9/]* [0-9:]* $username
-1\.5 ($username8 *[0-9a-zA-Z-]*): xx First log line
-1\.5 ($username8 *[0-9a-zA-Z-]*): xx Second log line
-1\.5 ($username8 *[0-9a-zA-Z-]*): xx
-1\.5 ($username8 *[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: ${CVSROOT_DIRNAME}/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 $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- rm -r 1 2
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- keywordname)
- # Test the Name keyword.
- # See the keyword test for a descriptions of some other tests that
- # test keyword expansion modes.
- mkdir keywordname; cd keywordname
- mkdir 1; cd 1
- dotest keywordname-init-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest keywordname-init-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
-
- echo '$'"Name$" >file1
- echo '$'"Name$" >file2
- dotest keywordname-init-3 "${testcvs} add file1 file2" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
-
- # See "rmadd" for a list of other tests of cvs ci -r.
- dotest keywordname-init-4 "${testcvs} -q ci -r 1.3 -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.3
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1\.3
-done"
- dotest keywordname-init-5b "cat file1" \
-'\$''Name: \$'
- dotest keywordname-init-5c "cat file2" \
-'\$''Name: \$'
-
- dotest keywordname-init-6 "$testcvs -q up -A"
- dotest keywordname-init-6b "cat file1" \
-'\$''Name: \$'
- dotest keywordname-init-6c "cat file2" \
-'\$''Name: \$'
-
- dotest keywordname-init-7 "${testcvs} -q tag -b br" \
-"T file1
-T file2"
-
- echo new data >>file1
- dotest keywordname-init-8 "${testcvs} -q ci -mchange" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.4; previous revision: 1\.3
-done"
-
- # First check out a branch.
- #
- # There used to be a bug where static tags would be substituted for
- # Name keywords but not branch tags.
- #
- # Prior to 1.11.23, there also used to be a bug where keyword
- # substitutions were not performed unless the file was otherwise
- # updated. When this bug was present, keywordname-update-1 would
- # report a patch checksum failure and refetch file1 in client/server
- # mode and no `br' would have been substituted into Name's value for
- # file2, meaning keywordname-update-3 would also fail.
- dotest keywordname-update-1 "$testcvs -q up -rbr" \
-'U file1
-U file2'
- dotest keywordname-update-2 "cat file1" '\$''Name: br \$'
-
- # For the same reason keywordname-update-1 would fail above, no `br'
- # would have been substituted into Name's value here prior to
- # 1.11.23.
- dotest keywordname-update-3 "cat file2" '\$''Name: br \$'
-
- # Now verify that updating to the trunk leaves no substitution for
- # $Name
- dotest keywordname-update-4 "${testcvs} -q tag firsttag" \
-"T file1
-T file2"
- # This used to fail in the same manner as keywordname-update-1.
- dotest keywordname-update-5 "$testcvs -q up -A" \
-'U file1
-U file2'
- dotest keywordname-update-6 "cat file1" \
-'\$''Name: \$
-new data'
- dotest keywordname-update-7 "cat file2" '\$''Name: \$'
-
- # This used to fail in the same manner as keywordname-update-1.
- dotest keywordname-update-8 "$testcvs -q up -rfirsttag" \
-'U file1
-U file2'
- dotest keywordname-update-9 "cat file1" '\$''Name: firsttag \$'
-
- # This used to fail in the same manner as keywordname-update-3.
- dotest keywordname-update-10 "cat file2" '\$''Name: firsttag \$'
-
- # And reverify the trunk update when the change is actually removed.
- dotest keywordname-update-11 "$testcvs -q up -A" \
-'U file1
-U file2'
- dotest keywordname-update-12 "cat file1" \
-'\$''Name: \$
-new data'
- dotest keywordname-update-13 "cat file2" '\$''Name: \$'
-
- cd ../..
-
- # now verify that a fresh checkout substitutes all the $Name fields
- mkdir 2; cd 2
- dotest keywordname-checkout-1 \
-"${testcvs} -q co -rfirsttag first-dir" \
-"U first-dir/file1
-U first-dir/file2"
- cd first-dir
- dotest keywordname-checkout-2 "cat file1" '\$'"Name: firsttag "'\$'
- dotest keywordname-checkout-3 "cat file2" '\$'"Name: firsttag "'\$'
-
- cd ../..
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- cd ..
- rm -r keywordname
- 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 ${CVSROOT_DIRNAME}/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} add: scheduling file .file1. for addition
-${PROG} add: 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} add: scheduling file .binfile\.dat. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
-
- dotest keyword2-6 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/binfile\.dat,v
-done
-Checking in binfile\.dat;
-${CVSROOT_DIRNAME}/first-dir/binfile\.dat,v <-- binfile\.dat
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/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;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- dotest keyword2-9 "$testcvs -q update -r branch" \
-'U binfile\.dat
-[UP] file1'
-
- echo "what else do we have?" >>file1
- dotest keyword2-10 "${testcvs} -q ci -m change" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/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 binfile\.dat
-U file1
-RCS file: $CVSROOT_DIRNAME/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: ${CVSROOT_DIRNAME}/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
- dotest keyword2-13 "${testcvs} -q update -A -kk -j branch" \
-"${PROG} update: warning: file1 was lost
-U file1
-RCS file: ${CVSROOT_DIRNAME}/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"
-
- # 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;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.3; previous revision: 1\.2
-done"
-
- # "-kk" no longer corrupts binary files
- dotest keyword2-15 "cmp binfile.dat ../binfile.dat" ''
-
- # Okay, restore everything and make CVS try and merge a binary file...
- # "-kk" no longer affects binary files
- dotest keyword2-16 "${testcvs} -q update -A" \
-"[UP] file1"
- dotest keyword2-17 "${testcvs} -q tag -b branch2" \
-"T binfile\.dat
-T file1"
- dotest keyword2-18 "$testcvs -q update -r branch2" \
-'U binfile\.dat
-[UP] file1'
-
- ${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;
-${CVSROOT_DIRNAME}/first-dir/binfile\.dat,v <-- binfile\.dat
-new revision: 1\.1\.4\.1; previous revision: 1\.1
-done"
- # "-kk" no longer affects binary files
-
- # XXXX: do not ask, why we get the "U binfile.dat" line twice
- # looks like a bug!
- dotest keyword2-20 "${testcvs} -q update -A -kk -j branch2" \
-"U binfile\.dat
-U binfile\.dat
-U file1"
-
- 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
- # which we don't yet try to deal with.
- # TODO: We also could be paying much closer attention to
- # "head of the trunk" versus "head of the default branch".
- # That is what "cvs import" is doing here (but I didn't really
- # fully follow through on writing the tests for that case).
- mkdir imp-dir
- cd imp-dir
- echo 'imported contents' >file1
- # It may seem like we don't do much with file2, but do note that
- # the "cvs diff" invocations do also diff file2 (and come up empty).
- echo 'imported contents' >file2
- dotest_sort head-1 "${testcvs} import -m add first-dir tag1 tag2" \
-"
-
-N first-dir/file1
-N first-dir/file2
-No conflicts created by this import"
- cd ..
- rm -r imp-dir
- mkdir 1
- cd 1
- dotest head-2 "${testcvs} -q co first-dir" \
-"U first-dir/file1
-U first-dir/file2"
- cd first-dir
- echo 'add a line on trunk' >> file1
- dotest head-3 "${testcvs} -q ci -m modify" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
- dotest head-4 "${testcvs} -q tag trunktag" "T file1
-T file2"
- echo 'add a line on trunk after trunktag' >> file1
- dotest head-5 "${testcvs} -q ci -m modify" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.3; previous revision: 1\.2
-done"
- dotest head-6 "${testcvs} -q tag -b br1" "T file1
-T file2"
- dotest head-7 "$testcvs -q update -r br1" \
-'[UP] file1
-[UP] file2'
- echo 'modify on branch' >>file1
- dotest head-8 "${testcvs} -q ci -m modify" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.3\.2\.1; previous revision: 1\.3
-done"
- dotest head-9 "${testcvs} -q tag brtag" "T file1
-T file2"
- echo 'modify on branch after brtag' >>file1
- dotest head-10 "${testcvs} -q ci -m modify" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.3\.2\.2; previous revision: 1\.3\.2\.1
-done"
- # With no sticky tags, HEAD is the head of the trunk.
- dotest head-trunk-setup "$testcvs -q update -A" \
-'[UP] file1
-[UP] file2'
- dotest head-trunk-update "${testcvs} -q update -r HEAD -p file1" \
-"imported contents
-add a line on trunk
-add a line on trunk after trunktag"
- # and diff thinks so too. Case (a) from the comment in
- # cvs.texinfo (Common options).
- dotest_fail head-trunk-diff "${testcvs} -q diff -c -r HEAD -r br1" \
-"Index: file1
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-retrieving revision 1\.3
-retrieving revision 1\.3\.2\.2
-diff -c -r1\.3 -r1\.3\.2\.2
-\*\*\* file1 ${RFCDATE} 1\.3
---- file1 ${RFCDATE} 1\.3\.2\.2
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1,3 \*\*\*\*
---- 1,5 ----
- imported contents
- add a line on trunk
- add a line on trunk after trunktag
-${PLUS} modify on branch
-${PLUS} modify on branch after brtag"
-
- # With a branch sticky tag, HEAD is the head of the trunk.
- dotest head-br1-setup "$testcvs -q update -r br1" \
-'[UP] file1
-[UP] file2'
- dotest head-br1-update "${testcvs} -q update -r HEAD -p file1" \
-"imported contents
-add a line on trunk
-add a line on trunk after trunktag"
- # But diff thinks that HEAD is "br1". Case (b) from cvs.texinfo.
- # Probably people are relying on it.
- dotest head-br1-diff "${testcvs} -q diff -c -r HEAD -r br1" ""
-
- # With a nonbranch sticky tag on a branch,
- # HEAD is the head of the trunk
- dotest head-brtag-setup "$testcvs -q update -r brtag" \
-'[UP] file1
-[UP] file2'
- dotest head-brtag-update "${testcvs} -q update -r HEAD -p file1" \
-"imported contents
-add a line on trunk
-add a line on trunk after trunktag"
-
- # CVS 1.9 and older thought that HEAD is "brtag" (this was
- # noted as "strange, maybe accidental"). But "br1" makes a
- # whole lot more sense.
- dotest head-brtag-diff "${testcvs} -q diff -c -r HEAD -r br1" ""
-
- # With a nonbranch sticky tag on the trunk, HEAD is the head
- # of the trunk, I think.
- dotest head-trunktag-setup "$testcvs -q update -r trunktag" \
-'[UP] file1
-[UP] file2'
- dotest head-trunktag-check "cat file1" "imported contents
-add a line on trunk"
- dotest head-trunktag-update "${testcvs} -q update -r HEAD -p file1" \
-"imported contents
-add a line on trunk
-add a line on trunk after trunktag"
- # Like head-brtag-diff, there is a non-branch sticky tag.
- dotest_fail head-trunktag-diff \
- "${testcvs} -q diff -c -r HEAD -r br1" \
-"Index: file1
-===================================================================
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-retrieving revision 1\.3
-retrieving revision 1\.3\.2\.2
-diff -c -r1\.3 -r1\.3\.2\.2
-\*\*\* file1 ${RFCDATE} 1\.3
---- file1 ${RFCDATE} 1\.3\.2\.2
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1,3 \*\*\*\*
---- 1,5 ----
- imported contents
- add a line on trunk
- add a line on trunk after trunktag
-${PLUS} modify on branch
-${PLUS} modify on branch after brtag"
-
- # Also might test what happens if we setup with update -r
- # HEAD. In general, if sticky tags matter, does the
- # behavior of "update -r <foo>" (without -p) depend on the
- # sticky tags before or after the update?
-
- # Note that we are testing both the case where this deletes
- # a revision (file1) and the case where it does not (file2)
- dotest_fail head-o0a "${testcvs} admin -o ::br1" \
-"${PROG} admin: Administrating \.
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-${PROG} admin: cannot remove revision 1\.3\.2\.1 because it has tags
-${PROG} admin: RCS file for .file1. not modified\.
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done"
- dotest head-o0b "${testcvs} tag -d brtag" \
-"${PROG} tag: Untagging \.
-D file1
-D file2"
- dotest head-o1 "${testcvs} admin -o ::br1" \
-"${PROG} admin: Administrating \.
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-deleting revision 1\.3\.2\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done"
- cd ../..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- 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
- save_TZ=$TZ
- TZ=UTC; export TZ
- dotest tagdate-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest tagdate-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
-
- echo trunk-1 >file1
- dotest tagdate-3 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest tagdate-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- date_T1=`getrlogdate -r1.1 first-dir/file1`
-
- dotest tagdate-5 "${testcvs} -q tag -b br1" "T file1"
- dotest tagdate-6 "${testcvs} -q tag -b br2" "T file1"
- echo trunk-2 >file1
- dotest tagdate-7 "${testcvs} -q ci -m modify-on-trunk" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.2; previous revision: 1\.1
-done"
- date_T2=`getrlogdate -r1.2 first-dir/file1`
-
- # We are testing -r -D where br1 is a (magic) branch without
- # any revisions. First the case where br2 doesn't have any
- # revisions either:
- dotest tagdate-8 "${testcvs} -q update -p -r br1 -D now" "trunk-1"
- dotest tagdate-9 "${testcvs} -q update -r br2" "[UP] file1"
- echo br2-1 >file1
- dotest tagdate-10 "${testcvs} -q ci -m modify-on-br2" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.4\.1; previous revision: 1\.1
-done"
- date_T3=`getrlogdate -r1.1.4.1 first-dir/file1`
-
- # 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} \[update aborted\]: argument to join may not contain a date specifier without a tag"
- # And check export
-
- echo br2-2 >file1
- dotest tagdate-13 "${testcvs} -q ci -m modify-2-on-br2" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.4\.2; previous revision: 1\.1\.4\.1
-done"
- date_T4=`getrlogdate -r1.1.4.2 first-dir/file1`
-
- cd ../..
- mkdir 2; cd 2
- dotest tagdate-14 "${testcvs} -q export -r br2 -D'$date_T3' first-dir" \
-"[UP] first-dir/file1"
- dotest tagdate-15 "cat first-dir/file1" "br2-1"
-
- # Now for annotate
- cd ../1/first-dir
- dotest tagdate-16 "${testcvs} annotate -rbr2 -D'$date_T3'" \
-"
-Annotations for file1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-1\.1\.4\.1 ($username8 *[0-9a-zA-Z-]*): br2-1"
-
- dotest tagdate-17 "${testcvs} annotate -rbr2 -Dnow" \
-"
-Annotations for file1
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-1\.1\.4\.2 ($username8 *[0-9a-zA-Z-]*): br2-2"
-
- # Now check to see what happens when we add files to br2 and trunk
- echo br2-1 > file3
- dotest tagdate-18 "${testcvs} add file3" \
-"${PROG} add: scheduling file \`file3' for addition on branch \`br2'
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest tagdate-19 "${testcvs} -q ci -m add file3" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file3,v
-done
-Checking in file3;
-${CVSROOT_DIRNAME}/first-dir/Attic/file3,v <-- file3
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
- date_T5=`getrlogdate -r1.1 first-dir/file3`
- date_T6=`getrlogdate -r1.1.2.1 first-dir/file3`
-
- cd ../..
- mkdir 3; cd 3
- dotest tagdate-20 "${testcvs} -Q co first-dir" ''
- cd first-dir
- echo trunk-1 > file2
- dotest tagdate-21 "${testcvs} add file2" \
-"${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest tagdate-22 "${testcvs} -q ci -m add file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1\.1
-done"
- date_T7=`getrlogdate -r1.1 first-dir/file2`
- echo "trunk-2" >file2
- dotest tagdate-23 "${testcvs} -q ci -m update file2" \
-"Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.2; previous revision: 1\.1
-done"
- date_T8=`getrlogdate -r1.2 first-dir/file2`
-
- cd ../../1/first-dir
- echo br2-1 > file2
- dotest tagdate-24 "${testcvs} add file2" \
-"${PROG} add: scheduling file \`file2' for addition on branch \`br2'
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest tagdate-25 "${testcvs} -q ci -m add file2" \
-"Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.2\.2\.2; previous revision: 1\.2\.2\.1
-done"
- date_T9=`getrlogdate -r1.2.2.2 first-dir/file2`
- cd ../..
-
- # Time Rev Branch Comments
- # T0 trunk first-dir created
- # T1 1.1 trunk first-dir/file1 committed "trunk-1"
- # br1 branch created
- # br2 branch created
- # T2 1.2 trunk first-dir/file1 committed "trunk-2"
- # T3 1.1.4.1 br2 first-dir/file1 committed "br2-1"
- # +60s
- # T4 1.1.4.2 br2 first-dir/file1 committed "br2-2"
- # T5 1.1 trunk first-dir/file3 dead
- # T6 1.1.2.1 br2 first-dir/file3 committed "br2-1"
- # T7 1.1 trunk first-dir/file2 committed "trunk-1"
- # T8 1.2 trunk first-dir/file2 committed "trunk-2"
- # T8 1.2.2.1 br2 first-dir/file2 dead
- # T9 1.2.2.2 br2 first-dir/file2 committed "br2-1"
- #
-
- mkdir 4; cd 4
- (echo Dates for tagdate-26-* are:;\
- echo " date_T1='$date_T1'";\
- echo " date_T2='$date_T2'";\
- echo " date_T3='$date_T3'";\
- echo " date_T4='$date_T4'";\
- echo " date_T5='$date_T5'";\
- echo " date_T6='$date_T6'";\
- echo " date_T7='$date_T7'";\
- echo " date_T8='$date_T8'";\
- echo " date_T9='$date_T9'") >>$LOGFILE
- dotest tagdate-26-trunk-t1 \
-"${testcvs} co -D'$date_T1' -d first-dir-trunk-t1 first-dir" \
-"${PROG} checkout: Updating first-dir-trunk-t1
-U first-dir-trunk-t1/file1"
- dotest tagdate-26-br2-t1 \
-"${testcvs} co -r br2 -D'$date_T1' -d first-dir-br2-t1 first-dir" \
-"${PROG} checkout: Updating first-dir-br2-t1
-U first-dir-br2-t1/file1"
- dotest tagdate-26-trunk-t2 \
-"${testcvs} co -D'$date_T2' -d first-dir-trunk-t2 first-dir" \
-"${PROG} checkout: Updating first-dir-trunk-t2
-U first-dir-trunk-t2/file1"
- dotest tagdate-26-br2-t2 \
-"${testcvs} co -r br2 -D'$date_T2' -d first-dir-br2-t2 first-dir" \
-"${PROG} checkout: Updating first-dir-br2-t2
-U first-dir-br2-t2/file1"
- dotest tagdate-26-br2-t3 \
-"${testcvs} co -r br2 -D'$date_T3' -d first-dir-br2-t3 first-dir" \
-"${PROG} checkout: Updating first-dir-br2-t3
-U first-dir-br2-t3/file1"
- dotest tagdate-26-br2-t4 \
-"${testcvs} co -r br2 -D'$date_T4' -d first-dir-br2-t4 first-dir" \
-"${PROG} checkout: Updating first-dir-br2-t4
-U first-dir-br2-t4/file1"
- dotest tagdate-26-br2-t6 \
-"${testcvs} co -r br2 -D'$date_T6' -d first-dir-br2-t6 first-dir" \
-"${PROG} checkout: Updating first-dir-br2-t6
-U first-dir-br2-t6/file1
-U first-dir-br2-t6/file3"
- dotest tagdate-26-trunk-t7 \
-"${testcvs} co -D'$date_T7' -d first-dir-trunk-t7 first-dir" \
-"${PROG} checkout: Updating first-dir-trunk-t7
-U first-dir-trunk-t7/file1
-U first-dir-trunk-t7/file2"
- dotest tagdate-26-br2-t7 \
-"${testcvs} co -r br2 -D'$date_T7' -d first-dir-br2-t7 first-dir" \
-"${PROG} checkout: Updating first-dir-br2-t7
-U first-dir-br2-t7/file1
-U first-dir-br2-t7/file3"
- dotest tagdate-26-trunk-t8 \
-"${testcvs} co -D'$date_T8' -d first-dir-trunk-t8 first-dir" \
-"${PROG} checkout: Updating first-dir-trunk-t8
-U first-dir-trunk-t8/file1
-U first-dir-trunk-t8/file2"
- dotest tagdate-26-br2-t8 \
-"${testcvs} co -r br2 -D'$date_T8' -d first-dir-br2-t8 first-dir" \
-"${PROG} checkout: Updating first-dir-br2-t8
-U first-dir-br2-t8/file1
-U first-dir-br2-t8/file3"
- dotest tagdate-26-br2-t9 \
-"${testcvs} co -r br2 -D'$date_T9' -d first-dir-br2-t9 first-dir" \
-"${PROG} checkout: Updating first-dir-br2-t9
-U first-dir-br2-t9/file1
-U first-dir-br2-t9/file2
-U first-dir-br2-t9/file3"
- dotest tagdate-27-trunk-t1 \
-"${testcvs} status first-dir-trunk-t1" \
-"${PROG} status: Examining first-dir-trunk-t1
-===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.1[^.]*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: (none)
- Sticky Date: [0-9.]*
- Sticky Options: (none)"
- dotest tagdate-27-br2-t1 \
-"${testcvs} status first-dir-br2-t1" \
-"${PROG} status: Examining first-dir-br2-t1
-===================================================================
-File: file1 Status: Needs Patch
-
- Working revision: 1\.1[^.]*
- Repository revision: 1\.1\.4\.2 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: br2 (branch: 1\.1\.4)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest tagdate-27-trunk-t2 \
-"${testcvs} status first-dir-trunk-t2" \
-"${PROG} status: Examining first-dir-trunk-t2
-===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.2[^.]*
- Repository revision: 1\.2 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: (none)
- Sticky Date: [0-9.]*
- Sticky Options: (none)"
- dotest tagdate-27-br2-t2 \
-"${testcvs} status first-dir-br2-t2" \
-"${PROG} status: Examining first-dir-br2-t2
-===================================================================
-File: file1 Status: Needs Patch
-
- Working revision: 1\.1[^.]*
- Repository revision: 1\.1\.4\.2 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: br2 (branch: 1\.1\.4)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest tagdate-27-br2-t3 \
-"${testcvs} status first-dir-br2-t3" \
-"${PROG} status: Examining first-dir-br2-t3
-===================================================================
-File: file1 Status: Needs Patch
-
- Working revision: 1\.1\.4\.1[^.]*
- Repository revision: 1\.1\.4\.2 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: br2 (branch: 1\.1\.4)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest tagdate-27-br2-t4 \
-"${testcvs} status first-dir-br2-t4" \
-"${PROG} status: Examining first-dir-br2-t4
-===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.1\.4\.2[^.]*
- Repository revision: 1\.1\.4\.2 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: br2 (branch: 1\.1\.4)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest tagdate-27-br2-t6 \
-"${testcvs} status first-dir-br2-t6" \
-"${PROG} status: Examining first-dir-br2-t6
-===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.1\.4\.2[^.]*
- Repository revision: 1\.1\.4\.2 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: br2 (branch: 1\.1\.4)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file3 Status: Up-to-date
-
- Working revision: 1\.1\.2\.1[^.]*
- Repository revision: 1\.1\.2\.1 ${CVSROOT_DIRNAME}/first-dir/Attic/file3,v
- Sticky Tag: br2 (branch: 1\.1\.2)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest tagdate-27-trunk-t7 \
-"${testcvs} status first-dir-trunk-t7" \
-"${PROG} status: Examining first-dir-trunk-t7
-===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.2[^.]*
- Repository revision: 1\.2 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: (none)
- Sticky Date: [0-9.]*
- Sticky Options: (none)
-
-===================================================================
-File: file2 Status: Up-to-date
-
- Working revision: 1\.1[^.]*
- Repository revision: 1\.1 ${CVSROOT_DIRNAME}/first-dir/file2,v
- Sticky Tag: (none)
- Sticky Date: [0-9.]*
- Sticky Options: (none)"
- dotest tagdate-27-br2-t7 \
-"${testcvs} status first-dir-br2-t7" \
-"${PROG} status: Examining first-dir-br2-t7
-===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.1\.4\.2[^.]*
- Repository revision: 1\.1\.4\.2 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: br2 (branch: 1\.1\.4)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file3 Status: Up-to-date
-
- Working revision: 1\.1\.2\.1[^.]*
- Repository revision: 1\.1\.2\.1 ${CVSROOT_DIRNAME}/first-dir/Attic/file3,v
- Sticky Tag: br2 (branch: 1\.1\.2)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest tagdate-27-trunk-t8 \
-"${testcvs} status first-dir-trunk-t8" \
-"${PROG} status: Examining first-dir-trunk-t8
-===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.2[^.]*
- Repository revision: 1\.2 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: (none)
- Sticky Date: [0-9.]*
- Sticky Options: (none)
-
-===================================================================
-File: file2 Status: Up-to-date
-
- Working revision: 1\.2[^.]*
- Repository revision: 1\.2 ${CVSROOT_DIRNAME}/first-dir/file2,v
- Sticky Tag: (none)
- Sticky Date: [0-9.]*
- Sticky Options: (none)"
- dotest tagdate-27-br2-t8 \
-"${testcvs} status first-dir-br2-t8" \
-"${PROG} status: Examining first-dir-br2-t8
-===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.1\.4\.2[^.]*
- Repository revision: 1\.1\.4\.2 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: br2 (branch: 1\.1\.4)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file3 Status: Up-to-date
-
- Working revision: 1\.1\.2\.1[^.]*
- Repository revision: 1\.1\.2\.1 ${CVSROOT_DIRNAME}/first-dir/Attic/file3,v
- Sticky Tag: br2 (branch: 1\.1\.2)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest tagdate-27-br2-t9 \
-"${testcvs} status first-dir-br2-t9" \
-"${PROG} status: Examining first-dir-br2-t9
-===================================================================
-File: file1 Status: Up-to-date
-
- Working revision: 1\.1\.4\.2[^.]*
- Repository revision: 1\.1\.4\.2 ${CVSROOT_DIRNAME}/first-dir/file1,v
- Sticky Tag: br2 (branch: 1\.1\.4)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file2 Status: Up-to-date
-
- Working revision: 1\.2\.2\.2[^.]*
- Repository revision: 1\.2\.2\.2 ${CVSROOT_DIRNAME}/first-dir/file2,v
- Sticky Tag: br2 (branch: 1\.2\.2)
- Sticky Date: (none)
- Sticky Options: (none)
-
-===================================================================
-File: file3 Status: Up-to-date
-
- Working revision: 1\.1\.2\.1[^.]*
- Repository revision: 1\.1\.2\.1 ${CVSROOT_DIRNAME}/first-dir/Attic/file3,v
- Sticky Tag: br2 (branch: 1\.1\.2)
- Sticky Date: (none)
- Sticky Options: (none)"
-
- # Now check the contents of the files
- dotest tagdate-28-trunk-t1 'cat first-dir-trunk-t1/file1' 'trunk-1'
- dotest tagdate-28-br2-t1 'cat first-dir-br2-t1/file1' 'trunk-1'
- dotest tagdate-28-trunk-t2 'cat first-dir-trunk-t2/file1' 'trunk-2'
- dotest tagdate-28-br2-t2 'cat first-dir-br2-t2/file1' 'trunk-1'
- dotest tagdate-28-br2-t3 'cat first-dir-br2-t3/file1' 'br2-1'
- dotest tagdate-28-br2-t4 'cat first-dir-br2-t4/file1' 'br2-2'
- dotest tagdate-28-br2-t6a 'cat first-dir-br2-t6/file1' "br2-2"
- dotest tagdate-28-br2-t6b 'cat first-dir-br2-t6/file3' "br2-1"
- dotest tagdate-28-trunk-t7a 'cat first-dir-trunk-t7/file1' "trunk-2"
- dotest tagdate-28-trunk-t7b 'cat first-dir-trunk-t7/file2' "trunk-1"
- dotest tagdate-28-br2-t7a 'cat first-dir-br2-t7/file1' "br2-2"
- dotest tagdate-28-br2-t7b 'cat first-dir-br2-t7/file3' "br2-1"
- dotest tagdate-28-trunk-t8a 'cat first-dir-trunk-t8/file1' "trunk-2"
- dotest tagdate-28-trunk-t8b 'cat first-dir-trunk-t8/file2' "trunk-2"
- dotest tagdate-28-br2-t8a 'cat first-dir-br2-t8/file1' "br2-2"
- dotest tagdate-28-br2-t8c 'cat first-dir-br2-t8/file3' "br2-1"
- dotest tagdate-28-br2-t9a 'cat first-dir-br2-t9/file1' "br2-2"
- dotest tagdate-28-br2-t9b 'cat first-dir-br2-t9/file2' "br2-1"
- dotest tagdate-28-br2-t9c 'cat first-dir-br2-t9/file3' "br2-1"
- cd ..
-
- unset date_T1 date_T2 date_T3 date_T4 date_T5
- unset date_T6 date_T7 date_T8 date_T9
- TZ=$save_TZ
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- rm -r 1 2 3 4
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- multibranch2)
- # Commit the first delta on branch A when there is an older
- # branch, B, that already has a delta. A and B come from the
- # same branch point. Then verify that branches A and B are
- # in the right order.
- mkdir 1; cd 1
- dotest multibranch2-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest multibranch2-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
-
- echo trunk-1 >file1
- echo trunk-1 >file2
- dotest multibranch2-3 "${testcvs} add file1 file2" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest multibranch2-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1\.1
-done"
- dotest multibranch2-5 "${testcvs} -q tag -b A" "T file1
-T file2"
- dotest multibranch2-6 "${testcvs} -q tag -b B" "T file1
-T file2"
-
- dotest multibranch2-7 "$testcvs -q update -r B" \
-'[UP] file1
-[UP] file2'
- echo branch-B >file1
- echo branch-B >file2
- dotest multibranch2-8 "${testcvs} -q ci -m modify-on-B" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.4\.1; previous revision: 1\.1
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.1\.4\.1; previous revision: 1\.1
-done"
-
- dotest multibranch2-9 "${testcvs} -q update -r A" '[UP] file1
-[UP] file2'
- echo branch-A >file1
- # When using cvs-1.9.20, this commit gets a failed assertion in rcs.c.
- dotest multibranch2-10 "${testcvs} -q ci -m modify-on-A" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
-
- dotest multibranch2-11 "${testcvs} -q log file1" \
-"
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
-symbolic names:
- B: 1\.1\.0\.4
- A: 1\.1\.0\.2
-keyword substitution: kv
-total revisions: 3; selected revisions: 3
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: $username; state: Exp;
-branches: 1\.1\.2; 1\.1\.4;
-add
-----------------------------
-revision 1\.1\.4\.1
-date: [0-9/]* [0-9:]*; author: $username; state: Exp; lines: ${PLUS}1 -1
-modify-on-B
-----------------------------
-revision 1\.1\.2\.1
-date: [0-9/]* [0-9:]*; author: $username; state: Exp; lines: ${PLUS}1 -1
-modify-on-A
-============================================================================="
-
- # This one is more concise.
- dotest multibranch2-12 "${testcvs} -q log -r1.1 file1" \
-"
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
-symbolic names:
- B: 1\.1\.0\.4
- A: 1\.1\.0\.2
-keyword substitution: kv
-total revisions: 3; selected revisions: 1
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: $username; state: Exp;
-branches: 1\.1\.2; 1\.1\.4;
-add
-============================================================================="
-
- # OK, try very much the same thing except we run update -j to
- # bring the changes from B to A. Probably tests many of the
- # same code paths but might as well keep it separate, I guess.
-
- dotest multibranch2-13 "${testcvs} -q update -r B" "[UP] file1
-[UP] file2"
- dotest multibranch2-14 "${testcvs} -q update -r A -j B file2" \
-"[UP] file2
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-retrieving revision 1.1
-retrieving revision 1.1.4.1
-Merging differences between 1.1 and 1.1.4.1 into file2"
- dotest multibranch2-15 "${testcvs} -q ci -m commit-on-A file2" \
-"Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
- cd ../..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- tag8k)
- # In cvs-1.9.27, there is a bug that can cause an abort.
- # It happens when you commit a change to a ,v file that has
- # just the right amount of tag/branch info to align one of the
- # semicolons in the branch info to be on a 8k-byte boundary.
- # The result: rcsbuf_getkey got an abort. This failure doesn't
- # corrupt the ,v file -- that would be really serious. But it
- # does leave stale write locks that have to be removed manually.
-
- mkdir 1
- cd 1
-
- module=x
-
- : > junk
- dotest tag8k-1 "$testcvs -Q import -m . $module X Y" ''
- dotest tag8k-2 "$testcvs -Q co $module" ''
- cd $module
-
- file=m
- : > $file
- dotest tag8k-3 "$testcvs add $file" \
-"${PROG} add: scheduling file .$file. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest tag8k-4 "$testcvs -Q ci -m . $file" \
-"RCS file: ${CVSROOT_DIRNAME}/$module/$file,v
-done
-Checking in $file;
-${CVSROOT_DIRNAME}/$module/$file,v <-- $file
-initial revision: 1\.1
-done"
-
- # It seems there have to be at least two versions.
- echo a > $file
- dotest tag8k-5 "$testcvs -Q ci -m . $file" \
-"Checking in $file;
-${CVSROOT_DIRNAME}/$module/$file,v <-- $file
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # Add just under 8K worth of tags.
- t=TAG---------------------------------------------------------------------
- t=$t$t
- t=$t$t$t$t$t
- # Now $t is 720 bytes long.
-
- # Apply some tags with that long prefix.
- dotest tag8k-6 "$testcvs -Q tag $t-0 $file" ''
- dotest tag8k-7 "$testcvs -Q tag $t-1 $file" ''
- dotest tag8k-8 "$testcvs -Q tag $t-2 $file" ''
- dotest tag8k-9 "$testcvs -Q tag $t-3 $file" ''
- dotest tag8k-10 "$testcvs -Q tag $t-4 $file" ''
- dotest tag8k-11 "$testcvs -Q tag $t-5 $file" ''
- dotest tag8k-12 "$testcvs -Q tag $t-6 $file" ''
- dotest tag8k-13 "$testcvs -Q tag $t-7 $file" ''
- dotest tag8k-14 "$testcvs -Q tag $t-8 $file" ''
- dotest tag8k-15 "$testcvs -Q tag $t-9 $file" ''
- dotest tag8k-16 "$testcvs -Q tag $t-a $file" ''
-
- # Extract the author value.
- name=`sed -n 's/.*; author \([^;]*\);.*/\1/p' ${CVSROOT_DIRNAME}/$module/$file,v|sed 1q`
-
- # Form a suffix string of length (16 - length($name)).
- # CAREFUL: this will lose if $name is longer than 16.
- 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
- # ,v file to exactly 8192.
- dotest tag8k-17 "$testcvs -Q tag "x8bytes-$suffix" $file" ''
-
- # This commit would fail with 1.9.27.
- echo a >> $file
- dotest tag8k-18 "$testcvs -Q ci -m . $file" \
-"Checking in $file;
-${CVSROOT_DIRNAME}/$module/$file,v <-- $file
-new revision: 1\.3; previous revision: 1\.2
-done"
- cd ../..
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/$module
- ;;
-
-
- admin)
- # More "cvs admin" tests.
- # The basicb-21 test tests rejecting an illegal option.
- # For -l and -u, see "reserved" and "keyword" tests.
- # "binfiles" test has a test of "cvs admin -k".
- # "log2" test has tests of -t and -q options to cvs admin.
- # "rcs" tests -b option also.
- # For -o, see:
- # admin-22-o1 through admin-23 (various cases not involving ::)
- # binfiles2-o* (:rev, rev on trunk; rev:, deleting entire branch)
- # basicb-o* (attempt to delete all revisions)
- # basica-o1 through basica-o3 (basic :: usage)
- # 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; 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 ." ''
- mkdir first-dir
- dotest admin-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
-
- dotest_fail admin-3 "${testcvs} -q admin -i file1" \
-"${PROG} admin: the -i option to admin is not supported
-${PROG} admin: run add or import to create an RCS file
-${PROG} \[admin aborted\]: specify ${PROG} -H admin for usage information"
- dotest_fail admin-4 "${testcvs} -q log file1" \
-"${PROG} log: nothing known about file1"
- dotest_fail admin-4a "${testcvs} -q admin file1" \
-"${PROG} admin: nothing known about file1"
-
- # Set up some files, file2 a plain one and file1 with a revision
- # on a branch.
- touch file1 file2
- dotest admin-5 "${testcvs} add file1 file2" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest admin-6 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-initial revision: 1\.1
-done"
- dotest admin-7 "${testcvs} -q tag -b br" "T file1
-T file2"
- dotest admin-8 "$testcvs -q update -r br" \
-'U file1
-U file2'
- echo 'add a line on the branch' >> file1
- echo 'add a file on the branch' >> file3
- dotest admin-9a "${testcvs} -q add file3" \
-"${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest admin-9b "${testcvs} -q ci -m modify-on-branch" \
-"Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file3,v
-done
-Checking in file3;
-${CVSROOT_DIRNAME}/first-dir/Attic/file3,v <-- file3
-new revision: 1\.1\.2\.1; previous revision: 1\.1
-done"
- dotest admin-10 "$testcvs -q update -A" \
-"U file1
-U file2
-$PROG update: file3 is no longer in the repository"
-
- # Check that we can administer files in the repository that
- # aren't in the working directory.
- dotest admin-10-1 "${testcvs} admin ." \
-"${PROG} admin: Administrating .
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done"
- dotest admin-10-2 "${testcvs} -q admin file3" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file3,v
-done"
-
- # Try to recurse with a numeric revision arg.
- # If we wanted to comprehensive about this, we would also test
- # this for -l, -u, and all the different -o syntaxes.
- dotest_fail admin-10a "${testcvs} -q admin -b1.1.2" \
-"${PROG} [a-z]*: while processing more than one file:
-${PROG} \[[a-z]* aborted\]: attempt to specify a numeric revision"
- dotest_fail admin-10b "${testcvs} -q admin -m1.1:bogus file1 file2" \
-"${PROG} [a-z]*: while processing more than one file:
-${PROG} \[[a-z]* aborted\]: attempt to specify a numeric revision"
-
- # try a bad symbolic revision
- dotest_fail admin-10c "${testcvs} -q admin -bBOGUS" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-${PROG} admin: ${CVSROOT_DIRNAME}/first-dir/file1,v: Symbolic name BOGUS is undefined.
-${PROG} admin: RCS file for .file1. not modified\.
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-${PROG} admin: ${CVSROOT_DIRNAME}/first-dir/file2,v: Symbolic name BOGUS is undefined.
-${PROG} admin: RCS file for .file2. not modified\."
-
- # Note that -s option applies to the new default branch, not
- # the old one.
- # Also note that the implementation of -a via "rcs" requires
- # no space between -a and the argument. However, we expect
- # to change that once CVS parses options.
- dotest admin-11 "${testcvs} -q admin -afoo,bar -abaz \
--b1.1.2 -cxx -U -sfoo file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done"
- dotest admin-11a "${testcvs} log -N file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch: 1\.1\.2
-locks:
-access list:
- foo
- bar
- baz
-keyword substitution: kv
-total revisions: 2; selected revisions: 2
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-branches: 1\.1\.2;
-add
-----------------------------
-revision 1\.1\.2\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: foo; lines: ${PLUS}1 -0
-modify-on-branch
-============================================================================="
- dotest admin-12 "${testcvs} -q admin -bbr file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done"
- dotest admin-12a "${testcvs} log -N file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch: 1\.1\.2
-locks:
-access list:
- foo
- bar
- baz
-keyword substitution: kv
-total revisions: 2; selected revisions: 2
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-branches: 1\.1\.2;
-add
-----------------------------
-revision 1\.1\.2\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: foo; lines: ${PLUS}1 -0
-modify-on-branch
-============================================================================="
-
- # "cvs log" doesn't print the comment leader. RCS 5.7 will print
- # the comment leader only if one specifies "-V4" to rlog. So it
- # seems like the only way to test it is by looking at the RCS file
- # directly. This also serves as a test of exporting RCS files
- # (analogous to the import tests in "rcs").
- # Rather than try to write a rigorous check for whether the
- # file CVS exports is legal, we just write a simpler
- # 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;
-access
- foo
- bar
- baz;
-symbols
- br:1\.1\.0\.2;
-locks;
-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;
-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;
-branches;
-next ;
-
-
-desc
-@@
-
-
-1\.1
-log
-@add
-@
-text
-@@
-
-
-1\.1\.2\.1
-log
-@modify-on-branch
-@
-text
-@a0 1
-add a line on the branch
-@"
- dotest_fail admin-14-1 "${testcvs} -q admin \
--m1.1.1.1:changed-bogus-log-message file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-cvs admin: ${CVSROOT_DIRNAME}/first-dir/file2,v: no such revision 1\.1\.1\.1
-cvs admin: RCS file for .file2. not modified."
- dotest admin-14-2 "${testcvs} -q log file2" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-Working file: file2
-head: 1\.1
-branch:
-locks: strict
-access list:
-symbolic names:
- br: 1\.1\.0\.2
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-add
-============================================================================="
-
- dotest admin-14-3 "${testcvs} -q admin -aauth3 -aauth2,foo \
--soneone:1.1 -m1.1:changed-log-message -ntagone: file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done"
- dotest admin-15 "${testcvs} -q log file2" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-Working file: file2
-head: 1\.1
-branch:
-locks: strict
-access list:
- auth3
- auth2
- foo
-symbolic names:
- tagone: 1\.1
- br: 1\.1\.0\.2
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: oneone;
-changed-log-message
-============================================================================="
-
- dotest admin-16 "${testcvs} -q admin \
--A${CVSROOT_DIRNAME}/first-dir/file2,v -b -L -Nbr:1.1 file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done"
- dotest admin-17 "${testcvs} -q log file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
- foo
- bar
- baz
- auth3
- auth2
-symbolic names:
- br: 1\.1
-keyword substitution: kv
-total revisions: 2; selected revisions: 2
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-branches: 1\.1\.2;
-add
-----------------------------
-revision 1\.1\.2\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: foo; lines: ${PLUS}1 -0
-modify-on-branch
-============================================================================="
-
- dotest_fail admin-18 "${testcvs} -q admin -nbr:1.1.2 file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-${PROG} admin: ${CVSROOT_DIRNAME}/first-dir/file1,v: symbolic name br already bound to 1\.1
-${PROG} admin: RCS file for .file1. not modified\."
- dotest admin-19 "${testcvs} -q admin -ebaz -ebar,auth3 -nbr file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done"
- dotest admin-20 "${testcvs} -q log file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
- foo
- auth2
-symbolic names:
-keyword substitution: kv
-total revisions: 2; selected revisions: 2
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-branches: 1\.1\.2;
-add
-----------------------------
-revision 1.1.2.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: foo; lines: ${PLUS}1 -0
-modify-on-branch
-============================================================================="
-
- # OK, this is starting to get ridiculous, in terms of
- # testing a feature (access lists) which doesn't do anything
- # useful, but what about nonexistent files and
- # relative pathnames in admin -A?
- dotest_fail admin-19a-nonexist \
-"${testcvs} -q admin -A${TESTDIR}/foo/bar file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-${PROG} admin: Couldn't open rcs file .${TESTDIR}/foo/bar.: No such file or directory
-${PROG} \[admin aborted\]: cannot continue"
-
- # In the remote case, we are cd'd off into the temp directory
- # and so these tests give "No such file or directory" errors.
- if $remote; then :; else
- dotest admin-19a-admin "${testcvs} -q admin -A../../${CVSROOTDIR}/first-dir/file2,v file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done"
- dotest admin-19a-log "${testcvs} -q log -h -N file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
- foo
- auth2
- auth3
-keyword substitution: kv
-total revisions: 2
-============================================================================="
- fi # end of tests skipped for remote
-
- # Now test that plain -e works right.
- dotest admin-19a-2 "${testcvs} -q admin -e file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done"
- dotest admin-19a-3 "${testcvs} -q log -h -N file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
-keyword substitution: kv
-total revisions: 2
-============================================================================="
-
- # Put the access list back, to avoid special cases later.
- dotest admin-19a-4 "${testcvs} -q admin -afoo,auth2 file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done"
-
- # Add another revision to file2, so we can delete one.
- echo 'add a line' >> file2
- dotest admin-21 "${testcvs} -q ci -m modify file2" \
-"Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.2; previous revision: 1\.1
-done"
- dotest admin-22 "${testcvs} -q admin -o1.1 file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-deleting revision 1\.1
-done"
- # Test admin -o. More variants that we could be testing:
- # * REV: [on branch]
- # * REV1:REV2 [deleting whole branch]
- # * high branch numbers (e.g. 1.2.2.3.2.3)
- # ... and probably others. See RCS_delete_revs for ideas.
-
- echo first rev > aaa
- dotest admin-22-o1 "${testcvs} add aaa" \
-"${PROG} add: scheduling file .aaa. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest admin-22-o2 "${testcvs} -q ci -m first aaa" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/aaa,v
-done
-Checking in aaa;
-${CVSROOT_DIRNAME}/first-dir/aaa,v <-- aaa
-initial revision: 1\.1
-done"
- echo second rev >> aaa
- dotest admin-22-o3 "${testcvs} -q ci -m second aaa" \
-"Checking in aaa;
-${CVSROOT_DIRNAME}/first-dir/aaa,v <-- aaa
-new revision: 1\.2; previous revision: 1\.1
-done"
- echo third rev >> aaa
- dotest admin-22-o4 "${testcvs} -q ci -m third aaa" \
-"Checking in aaa;
-${CVSROOT_DIRNAME}/first-dir/aaa,v <-- aaa
-new revision: 1\.3; previous revision: 1\.2
-done"
- echo fourth rev >> aaa
- dotest admin-22-o5 "${testcvs} -q ci -m fourth aaa" \
-"Checking in aaa;
-${CVSROOT_DIRNAME}/first-dir/aaa,v <-- aaa
-new revision: 1\.4; previous revision: 1\.3
-done"
- echo fifth rev >>aaa
- dotest admin-22-o6 "${testcvs} -q ci -m fifth aaa" \
-"Checking in aaa;
-${CVSROOT_DIRNAME}/first-dir/aaa,v <-- aaa
-new revision: 1\.5; previous revision: 1\.4
-done"
- echo sixth rev >> aaa
- dotest admin-22-o7 "${testcvs} -q ci -m sixth aaa" \
-"Checking in aaa;
-${CVSROOT_DIRNAME}/first-dir/aaa,v <-- aaa
-new revision: 1\.6; previous revision: 1\.5
-done"
- dotest admin-22-o8 "${testcvs} admin -l1.6 aaa" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/aaa,v
-1\.6 locked
-done"
- dotest admin-22-o9 "${testcvs} log -r1.6 aaa" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/aaa,v
-Working file: aaa
-head: 1\.6
-branch:
-locks: strict
- ${username}: 1\.6
-access list:
-symbolic names:
-keyword substitution: kv
-total revisions: 6; selected revisions: 1
-description:
-----------------------------
-revision 1\.6 locked by: ${username};
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-sixth
-============================================================================="
- dotest_fail admin-22-o10 "${testcvs} admin -o1.5: aaa" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/aaa,v
-${PROG} admin: ${CVSROOT_DIRNAME}/first-dir/aaa,v: can't remove locked revision 1\.6
-${PROG} admin: RCS file for .aaa. not modified\."
- dotest admin-22-o11 "${testcvs} admin -u aaa" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/aaa,v
-1\.6 unlocked
-done"
- dotest admin-22-o12 "${testcvs} admin -o1.5: aaa" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/aaa,v
-deleting revision 1\.6
-deleting revision 1\.5
-done"
- dotest admin-22-o13 "${testcvs} log aaa" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/aaa,v
-Working file: aaa
-head: 1\.4
-branch:
-locks: strict
-access list:
-symbolic names:
-keyword substitution: kv
-total revisions: 4; selected revisions: 4
-description:
-----------------------------
-revision 1\.4
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-fourth
-----------------------------
-revision 1\.3
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-third
-----------------------------
-revision 1\.2
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-second
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-first
-============================================================================="
-
- dotest admin-22-o14 "${testcvs} tag -b -r1.3 br1 aaa" "T aaa"
- dotest admin-22-o15 "${testcvs} update -rbr1 aaa" "U aaa"
- echo new branch rev >> aaa
- dotest admin-22-o16 "${testcvs} ci -m new-branch aaa" \
-"Checking in aaa;
-${CVSROOT_DIRNAME}/first-dir/aaa,v <-- aaa
-new revision: 1\.3\.2\.1; previous revision: 1\.3
-done"
- dotest_fail admin-22-o17 "${testcvs} admin -o1.2:1.4 aaa" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/aaa,v
-deleting revision 1\.4
-${PROG} admin: ${CVSROOT_DIRNAME}/first-dir/aaa,v: can't remove branch point 1\.3
-${PROG} admin: RCS file for .aaa. not modified\."
- dotest admin-22-o18 "${testcvs} update -p -r1.4 aaa" \
-"===================================================================
-Checking out aaa
-RCS: ${CVSROOT_DIRNAME}/first-dir/aaa,v
-VERS: 1\.4
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-first rev
-second rev
-third rev
-fourth rev"
- echo second branch rev >> aaa
- dotest admin-22-o19 "${testcvs} ci -m branch-two aaa" \
-"Checking in aaa;
-${CVSROOT_DIRNAME}/first-dir/aaa,v <-- aaa
-new revision: 1\.3\.2\.2; previous revision: 1\.3\.2\.1
-done"
- echo third branch rev >> aaa
- dotest admin-22-o20 "${testcvs} ci -m branch-three aaa" \
-"Checking in aaa;
-${CVSROOT_DIRNAME}/first-dir/aaa,v <-- aaa
-new revision: 1\.3\.2\.3; previous revision: 1\.3\.2\.2
-done"
- echo fourth branch rev >> aaa
- dotest admin-22-o21 "${testcvs} ci -m branch-four aaa" \
-"Checking in aaa;
-${CVSROOT_DIRNAME}/first-dir/aaa,v <-- aaa
-new revision: 1\.3\.2\.4; previous revision: 1\.3\.2\.3
-done"
- dotest admin-22-o22 "${testcvs} admin -o:1.3.2.3 aaa" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/aaa,v
-deleting revision 1\.3\.2\.1
-deleting revision 1\.3\.2\.2
-deleting revision 1\.3\.2\.3
-done"
- dotest admin-22-o23 "${testcvs} log aaa" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/aaa,v
-Working file: aaa
-head: 1\.4
-branch:
-locks: strict
-access list:
-symbolic names:
- br1: 1\.3\.0\.2
-keyword substitution: kv
-total revisions: 5; selected revisions: 5
-description:
-----------------------------
-revision 1\.4
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-fourth
-----------------------------
-revision 1\.3
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-branches: 1\.3\.2;
-third
-----------------------------
-revision 1\.2
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-second
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-first
-----------------------------
-revision 1\.3\.2\.4
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}4 -0
-branch-four
-============================================================================="
-
- dotest admin-22-o24 "${testcvs} -q update -p -r 1.3.2.4 aaa" \
-"first rev
-second rev
-third rev
-new branch rev
-second branch rev
-third branch rev
-fourth branch rev"
-
- # The bit here about how there is a "tagone" tag pointing to
- # a nonexistent revision is documented by rcs. I dunno, I
- # wonder whether the "cvs admin -o" should give a warning in
- # this case.
- dotest admin-23 "${testcvs} -q log file2" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-Working file: file2
-head: 1\.2
-branch:
-locks: strict
-access list:
- auth3
- auth2
- foo
-symbolic names:
- tagone: 1\.1
- br: 1\.1\.0\.2
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.2
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-modify
-============================================================================="
-
- dotest admin-25 "cat ${CVSROOT_DIRNAME}/first-dir/file1,v" \
-"head 1\.1;
-access
- foo
- auth2;
-symbols;
-locks; strict;
-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;
-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;
-branches;
-next ;
-
-
-desc
-@@
-
-
-1\.1
-log
-@add
-@
-text
-@@
-
-
-1\.1\.2\.1
-log
-@modify-on-branch
-@
-text
-@a0 1
-add a line on the branch
-@"
-
- # Tests of cvs admin -n. Make use of the results of
- # admin-1 through admin-25.
- # FIXME: We probably shouldn't make use of those results;
- # this test is way too long as it is.
-
- # tagtwo should be a revision
- #
- dotest admin-26-1 "${testcvs} admin -ntagtwo:tagone file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done"
-
- # br1 should be a branch
- #
- dotest admin-26-2 "${testcvs} admin -nbr1:br file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done"
-
- # Attach some tags using RCS versions
- #
- dotest admin-26-3 "${testcvs} admin -ntagthree:1.1 file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done"
-
- dotest admin-26-4 "${testcvs} admin -nbr2:1.1.2 file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done"
-
- dotest admin-26-5 "${testcvs} admin -nbr4:1.1.0.2 file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done"
-
- # Check results so far
- #
- dotest admin-26-6 "${testcvs} status -v file2" \
-"===================================================================
-File: file2 Status: Up-to-date
-
- Working revision: 1\.2.*
- Repository revision: 1\.2 ${CVSROOT_DIRNAME}/first-dir/file2,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)
-
- Existing Tags:
- br4 (branch: 1\.1\.2)
- br2 (branch: 1\.1\.2)
- tagthree (revision: 1\.1)
- br1 (branch: 1\.1\.2)
- tagtwo (revision: 1\.1)
- tagone (revision: 1\.1)
- br (branch: 1\.1\.2)"
-
-
- # Add a couple more revisions
- #
- echo "nuthr_line" >> file2
- dotest admin-27-1 "${testcvs} commit -m nuthr_line file2" \
-"Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.3; previous revision: 1\.2
-done"
-
- echo "yet_another" >> file2
- dotest admin-27-2 "${testcvs} commit -m yet_another file2" \
-"Checking in file2;
-${CVSROOT_DIRNAME}/first-dir/file2,v <-- file2
-new revision: 1\.4; previous revision: 1\.3
-done"
-
- # Fail trying to reattach existing tag with -n
- #
- dotest admin-27-3 "${testcvs} admin -ntagfour:1.1 file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done"
-
- dotest_fail admin-27-4 "${testcvs} admin -ntagfour:1.3 file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-${PROG} admin: ${CVSROOT_DIRNAME}/first-dir/file2,v: symbolic name tagfour already bound to 1\.1
-${PROG} admin: RCS file for .file2. not modified\."
-
- # Succeed at reattaching existing tag, using -N
- #
- dotest admin-27-5 "${testcvs} admin -Ntagfour:1.3 file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done"
-
- # Fail on some bogus operations
- # Try to attach to nonexistant tag
- #
- dotest_fail admin-28-1 "${testcvs} admin -ntagsix:tagfive file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-${PROG} admin: ${CVSROOT_DIRNAME}/first-dir/file2,v: Symbolic name or revision tagfive is undefined\.
-${PROG} admin: RCS file for .file2. not modified\."
-
- # Try a some nonexisting numeric target tags
- #
- dotest_fail admin-28-2 "${testcvs} admin -ntagseven:2.1 file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-${PROG} \[admin aborted\]: revision .2\.1. does not exist"
-
- dotest_fail admin-28-3 "${testcvs} admin -ntageight:2.1.2 file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-${PROG} \[admin aborted\]: revision .2\.1\.2. does not exist"
-
- # Try some invalid targets
- #
- dotest_fail admin-28-4 "${testcvs} admin -ntagnine:1.a.2 file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-${PROG} \[admin aborted\]: tag .1\.a\.2. must start with a letter"
-
- # Confirm that a missing tag is not a fatal error.
- dotest admin-28-5.1 "${testcvs} -Q tag BO+GUS file1" ''
- dotest_fail admin-28-5.2 "${testcvs} admin -ntagten:BO+GUS file2 file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-${PROG} admin: ${CVSROOT_DIRNAME}/first-dir/file2,v: Symbolic name or revision BO${PLUS}GUS is undefined\.
-${PROG} admin: RCS file for .file2. not modified\.
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done"
-
- dotest_fail admin-28-6 "${testcvs} admin -nq.werty:tagfour file2" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-${PROG} \[admin aborted\]: tag .q\.werty. must not contain the characters ..*"
-
- # Verify the archive
- #
- dotest admin-29 "cat ${CVSROOT_DIRNAME}/first-dir/file2,v" \
-"head 1\.4;
-access
- auth3
- auth2
- foo;
-symbols
- tagfour:1\.3
- br4:1\.1\.0\.2
- br2:1\.1\.0\.2
- tagthree:1\.1
- br1:1\.1\.0\.2
- tagtwo:1\.1
- tagone:1\.1
- br:1\.1\.0\.2;
-locks; strict;
-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;
-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;
-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;
-branches;
-next ;
-
-
-desc
-@@
-
-
-1\.4
-log
-@yet_another
-@
-text
-@add a line
-nuthr_line
-yet_another
-@
-
-
-1\.3
-log
-@nuthr_line
-@
-text
-@d3 1
-@
-
-
-1\.2
-log
-@modify
-@
-text
-@d2 1
-@"
-
- dotest_fail admin-30 "${testcvs} admin -mbr:another-log-message \
-file2 aaa file3" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-${PROG} admin: ${CVSROOT_DIRNAME}/first-dir/file2,v: no such revision br: 1\.1
-${PROG} admin: RCS file for .file2. not modified.
-RCS file: ${CVSROOT_DIRNAME}/first-dir/aaa,v
-${PROG} admin: ${CVSROOT_DIRNAME}/first-dir/aaa,v: no such revision br
-${PROG} admin: RCS file for .aaa. not modified.
-RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file3,v
-done"
- dotest admin-31 "${testcvs} log" \
-"${PROG} log: Logging \.
-
-RCS file: ${CVSROOT_DIRNAME}/first-dir/aaa,v
-Working file: aaa
-head: 1\.4
-branch:
-locks: strict
-access list:
-symbolic names:
- br1: 1\.3\.0\.2
-keyword substitution: kv
-total revisions: 5; selected revisions: 5
-description:
-----------------------------
-revision 1\.4
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-fourth
-----------------------------
-revision 1\.3
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-branches: 1\.3\.2;
-third
-----------------------------
-revision 1\.2
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-second
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-first
-----------------------------
-revision 1\.3\.2\.4
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}4 -0
-branch-four
-=============================================================================
-
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
- foo
- auth2
-symbolic names:
- tagten: 1\.1
- BO${PLUS}GUS: 1\.1
-keyword substitution: kv
-total revisions: 2; selected revisions: 2
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-branches: 1\.1\.2;
-add
-----------------------------
-revision 1\.1\.2\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: foo; lines: ${PLUS}1 -0
-modify-on-branch
-=============================================================================
-
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-Working file: file2
-head: 1\.4
-branch:
-locks: strict
-access list:
- auth3
- auth2
- foo
-symbolic names:
- tagfour: 1\.3
- br4: 1\.1\.0\.2
- br2: 1\.1\.0\.2
- tagthree: 1\.1
- br1: 1\.1\.0\.2
- tagtwo: 1\.1
- tagone: 1\.1
- br: 1\.1\.0\.2
-keyword substitution: kv
-total revisions: 3; selected revisions: 3
-description:
-----------------------------
-revision 1\.4
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-yet_another
-----------------------------
-revision 1\.3
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-nuthr_line
-----------------------------
-revision 1\.2
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-modify
-=============================================================================
-
-RCS file: ${CVSROOT_DIRNAME}/first-dir/Attic/file3,v
-Working file: file3
-head: 1\.1
-branch:
-locks: strict
-access list:
-symbolic names:
- br: 1\.1\.0\.2
-keyword substitution: kv
-total revisions: 2; selected revisions: 2
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: dead;
-branches: 1\.1\.2;
-file file3 was initially added on branch br\.
-----------------------------
-revision 1\.1\.2\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp; lines: ${PLUS}1 -0
-another-log-message
-============================================================================="
-
- cd ../..
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
- # clean up our after ourselves
- rm -r 1
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- reserved)
- # Tests of reserved checkouts. Eventually this will test
- # rcslock.pl (or equivalent) and all kinds of stuff. Right
- # now it just does some very basic checks on cvs admin -u
- # and cvs admin -l.
- # Also should test locking on a branch (and making sure that
- # locks from one branch don't get mixed up with those from
- # another. Both the case where one of the branches is the
- # main branch, and in which neither one is).
- # See also test keyword, which tests that keywords and -kkvl
- # do the right thing in the presence of locks.
-
- # The usual setup, directory first-dir containing file file1.
- mkdir 1; cd 1
- dotest reserved-1 "${testcvs} -q co -l ." ''
- mkdir first-dir
- dotest reserved-2 "${testcvs} add first-dir" \
-"Directory ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- touch file1
- dotest reserved-3 "${testcvs} add file1" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest reserved-4 "${testcvs} -q ci -m add" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
-
- dotest reserved-5 "${testcvs} -q admin -l file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-1\.1 locked
-done"
- dotest reserved-6 "${testcvs} log -N file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
- ${username}: 1\.1
-access list:
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.1 locked by: ${username};
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-add
-============================================================================="
-
- # Note that this just tests the owner of the lock giving
- # it up. It doesn't test breaking a lock.
- dotest reserved-7 "${testcvs} -q admin -u file1" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-1\.1 unlocked
-done"
-
- dotest reserved-8 "${testcvs} log -N file1" "
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-Working file: file1
-head: 1\.1
-branch:
-locks: strict
-access list:
-keyword substitution: kv
-total revisions: 1; selected revisions: 1
-description:
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
-add
-============================================================================="
-
- # rcslock.pl tests. Of course, the point isn't to test
- # rcslock.pl from the distribution but equivalent
- # functionality (for example, many sites may have an old
- # rcslock.pl). The functionality of this hook falls
- # short of the real rcslock.pl though.
- # Note that we can use rlog or look at the RCS file directly,
- # but we can't use "cvs log" because "cvs commit" has a lock.
-
- cat >${TESTDIR}/lockme <<EOF
-#!${TESTSHELL}
-line=\`grep <\$1/\$2,v 'locks $anyusername:1\.[0-9];'\`
-if test -z "\$line"; then
- # It isn't locked
- exit 0
-else
- user=\`echo \$line | sed -e 's/locks \\($anyusername\\):[0-9.]*;.*/\\1/'\`
- version=\`echo \$line | sed -e 's/locks $anyusername:\\([0-9.]*\\);.*/\\1/'\`
- echo "\$user has file a-lock locked for version \$version" >&2
- exit 1
-fi
-EOF
- # Cygwin. Blaaarg.
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost "chmod +x ${TESTDIR}/lockme"
- else
- chmod +x ${TESTDIR}/lockme
- fi
-
- echo stuff > a-lock
- dotest reserved-9 "${testcvs} add a-lock" \
-"${PROG} add: scheduling file .a-lock. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- dotest reserved-10 "${testcvs} -q ci -m new a-lock" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/a-lock,v
-done
-Checking in a-lock;
-${CVSROOT_DIRNAME}/first-dir/a-lock,v <-- a-lock
-initial revision: 1\.1
-done"
- # FIXME: the contents of CVSROOT fluctuate a lot
- # here. Maybe the expect pattern should just
- # confirm that commitinfo is one of the files checked out,
- # but for now we just check that CVS exited with success.
- cd ..
- if ${testcvs} -q co CVSROOT >>${LOGFILE} ; then
- pass reserved-11
- else
- fail reserved-11
- fi
- cd CVSROOT
- echo "DEFAULT ${TESTDIR}/lockme" >>commitinfo
- dotest reserved-12 "${testcvs} -q ci -m rcslock commitinfo" \
-"Checking in commitinfo;
-${CVSROOT_DIRNAME}/CVSROOT/commitinfo,v <-- commitinfo
-new revision: 1\.2; previous revision: 1\.1
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ..; cd first-dir
-
- # Simulate (approximately) what a-lock would look like
- # if someone else had locked revision 1.1.
- sed -e 's/locks; strict;/locks fred:1.1; strict;/' ${CVSROOT_DIRNAME}/first-dir/a-lock,v > a-lock,v
- # Cygwin.
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost "chmod 644 ${CVSROOT_DIRNAME}/first-dir/a-lock,v"
- else
- chmod 644 ${CVSROOT_DIRNAME}/first-dir/a-lock,v
- fi
- dotest reserved-13 "mv a-lock,v ${CVSROOT_DIRNAME}/first-dir/a-lock,v"
- # Cygwin. Blah.
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost "chmod 444 ${CVSROOT_DIRNAME}/first-dir/a-lock,v"
- else
- chmod 444 ${CVSROOT_DIRNAME}/first-dir/a-lock,v
- fi
- echo more stuff >> a-lock
- dotest_fail reserved-13b "${testcvs} ci -m '' a-lock" \
-"fred has file a-lock locked for version 1\.1
-${PROG} commit: Pre-commit check failed
-${PROG} \[commit aborted\]: correct above errors first!"
- # OK, now test "cvs admin -l" in the case where someone
- # else has the file locked.
- dotest_fail reserved-13c "${testcvs} admin -l a-lock" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/a-lock,v
-${PROG} \[admin aborted\]: Revision 1\.1 is already locked by fred"
-
- dotest reserved-14 "${testcvs} admin -u1.1 a-lock" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/a-lock,v
-${PROG} admin: ${CVSROOT_DIRNAME}/first-dir/a-lock,v: revision 1\.1 locked by fred; breaking lock
-1\.1 unlocked
-done"
- dotest reserved-15 "${testcvs} -q ci -m success a-lock" \
-"Checking in a-lock;
-${CVSROOT_DIRNAME}/first-dir/a-lock,v <-- a-lock
-new revision: 1\.2; previous revision: 1\.1
-done"
-
- # Now test for a bug involving branches and locks
- sed -e 's/locks; strict;/locks fred:1.2; strict;/' ${CVSROOT_DIRNAME}/first-dir/a-lock,v > a-lock,v
- chmod 644 ${CVSROOT_DIRNAME}/first-dir/a-lock,v
- dotest reserved-16 \
-"mv a-lock,v ${CVSROOT_DIRNAME}/first-dir/a-lock,v" ""
- chmod 444 ${CVSROOT_DIRNAME}/first-dir/a-lock,v
- dotest reserved-17 "${testcvs} -q tag -b br a-lock" "T a-lock"
- dotest reserved-18 "$testcvs -q update -r br a-lock" '[UP] a-lock'
- echo edit it >>a-lock
- dotest reserved-19 "${testcvs} -q ci -m modify a-lock" \
-"Checking in a-lock;
-${CVSROOT_DIRNAME}/first-dir/a-lock,v <-- a-lock
-new revision: 1\.2\.2\.1; previous revision: 1\.2
-done"
-
- # undo commitinfo changes
- cd ../CVSROOT
- echo '# vanilla commitinfo' >commitinfo
- dotest reserved-cleanup-1 "${testcvs} -q ci -m back commitinfo" \
-"Checking in commitinfo;
-${CVSROOT_DIRNAME}/CVSROOT/commitinfo,v <-- commitinfo
-new revision: 1\.3; previous revision: 1\.2
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ..; rm -r CVSROOT; cd first-dir
-
- cd ../..
- rm -r 1
- rm ${TESTDIR}/lockme
- rm -rf ${CVSROOT_DIRNAME}/first-dir
- ;;
-
- diffmerge1)
- # Make sure CVS can merge correctly in circumstances where it
- # used to mess up (due to a bug which existed in diffutils 2.7
- # and 2.6, but not 2.5, and which has been fixed in CVS's diff
- # lib by Paul Eggert, bless his bitty heart).
-
- # This first test involves two working copies, "mine" and
- # "yours", checked out from the same repository at the same
- # time. In yours, you remove some text from the end of the
- # file and check it in; meanwhile, "me" has commented out some
- # lines earlier in the file, and I go to check it in right
- # after you checked yours in. CVS naturally tells me the file
- # is not up-to-date, so I run cvs update, but it updates
- # incorrectly, leaving in the lines of text you just deleted.
- # Bad! I'm in too much of a hurry to actually look at the
- # file, so I check it in and go home, and so your changes have
- # been lost. Later you discover this, and you suspect me of
- # deliberately sabotaging your work, so you let all the air
- # out of my tires. Only after a series of expensive lawsuits
- # and countersuits do we discover that this was all CVS's
- # fault.
- #
- # Luckily, this problem has been fixed now, as our test will
- # handily confirm, no doubt:
-
- # First make a repository containing the original text:
-
- # We should be here anyway, but cd to it just in case:
- cd ${TESTDIR}
-
- mkdir diffmerge1
- cd diffmerge1
-
- # These are the files we both start out with:
- mkdir import
- cd import
- diffmerge_create_older_files
-
- dotest diffmerge1_import \
- "${testcvs} import -m import diffmerge1 tag1 tag2" \
- "${DOTSTAR}No conflicts created by this import"
- cd ..
-
- # Check out two working copies, one for "you" and one for
- # "me". If no branch is used and cvs detects that only one
- # of the two people made changes, then cvs does not run the
- # merge algorithm. But if a branch is used, then cvs does run
- # the merge algorithm (even in this case of only one of the two
- # people having made changes). CVS used to have a bug in this
- # case. Therefore, it is important to test this case by
- # using a branch:
- ${testcvs} rtag -b tag diffmerge1 >/dev/null 2>&1
- ${testcvs} checkout -r tag diffmerge1 >/dev/null 2>&1
- mv diffmerge1 yours
- ${testcvs} checkout diffmerge1 >/dev/null 2>&1
- mv diffmerge1 mine
-
- # In your working copy, you'll make changes, and
- # then check in your changes before I check in mine:
- cd yours
- diffmerge_create_your_files
- dotest diffmerge1_yours "${testcvs} -q ci -m yours" \
-"Checking in testcase01;
-${CVSROOT_DIRNAME}/diffmerge1/testcase01,v <-- testcase01
-new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1
-done
-Checking in testcase02;
-${CVSROOT_DIRNAME}/diffmerge1/testcase02,v <-- testcase02
-new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1
-done
-Checking in testcase03;
-${CVSROOT_DIRNAME}/diffmerge1/testcase03,v <-- testcase03
-new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1
-done
-Checking in testcase04;
-${CVSROOT_DIRNAME}/diffmerge1/testcase04,v <-- testcase04
-new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1
-done
-Checking in testcase05;
-${CVSROOT_DIRNAME}/diffmerge1/testcase05,v <-- testcase05
-new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1
-done
-Checking in testcase06;
-${CVSROOT_DIRNAME}/diffmerge1/testcase06,v <-- testcase06
-new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1
-done
-Checking in testcase07;
-${CVSROOT_DIRNAME}/diffmerge1/testcase07,v <-- testcase07
-new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1
-done
-Checking in testcase08;
-${CVSROOT_DIRNAME}/diffmerge1/testcase08,v <-- testcase08
-new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1
-done
-Checking in testcase09;
-${CVSROOT_DIRNAME}/diffmerge1/testcase09,v <-- testcase09
-new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1
-done
-Checking in testcase10;
-${CVSROOT_DIRNAME}/diffmerge1/testcase10,v <-- testcase10
-new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1
-done"
-
- # Change my copy. Then I
- # update, after both my modifications and your checkin:
- cd ../mine
- diffmerge_create_my_files
- dotest diffmerge1_mine "${testcvs} -q update -j tag" \
-"M testcase01
-RCS file: ${CVSROOT_DIRNAME}/diffmerge1/testcase01,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.1\.1\.1\.2\.1
-Merging differences between 1\.1\.1\.1 and 1\.1\.1\.1\.2\.1 into testcase01
-M testcase02
-RCS file: ${CVSROOT_DIRNAME}/diffmerge1/testcase02,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.1\.1\.1\.2\.1
-Merging differences between 1\.1\.1\.1 and 1\.1\.1\.1\.2\.1 into testcase02
-M testcase03
-RCS file: ${CVSROOT_DIRNAME}/diffmerge1/testcase03,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.1\.1\.1\.2\.1
-Merging differences between 1\.1\.1\.1 and 1\.1\.1\.1\.2\.1 into testcase03
-M testcase04
-RCS file: ${CVSROOT_DIRNAME}/diffmerge1/testcase04,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.1\.1\.1\.2\.1
-Merging differences between 1\.1\.1\.1 and 1\.1\.1\.1\.2\.1 into testcase04
-RCS file: ${CVSROOT_DIRNAME}/diffmerge1/testcase05,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.1\.1\.1\.2\.1
-Merging differences between 1\.1\.1\.1 and 1\.1\.1\.1\.2\.1 into testcase05
-RCS file: ${CVSROOT_DIRNAME}/diffmerge1/testcase06,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.1\.1\.1\.2\.1
-Merging differences between 1\.1\.1\.1 and 1\.1\.1\.1\.2\.1 into testcase06
-M testcase07
-RCS file: ${CVSROOT_DIRNAME}/diffmerge1/testcase07,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.1\.1\.1\.2\.1
-Merging differences between 1\.1\.1\.1 and 1\.1\.1\.1\.2\.1 into testcase07
-testcase07 already contains the differences between 1\.1\.1\.1 and 1\.1\.1\.1\.2\.1
-M testcase08
-RCS file: ${CVSROOT_DIRNAME}/diffmerge1/testcase08,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.1\.1\.1\.2\.1
-Merging differences between 1\.1\.1\.1 and 1\.1\.1\.1\.2\.1 into testcase08
-M testcase09
-RCS file: ${CVSROOT_DIRNAME}/diffmerge1/testcase09,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.1\.1\.1\.2\.1
-Merging differences between 1\.1\.1\.1 and 1\.1\.1\.1\.2\.1 into testcase09
-M testcase10
-RCS file: ${CVSROOT_DIRNAME}/diffmerge1/testcase10,v
-retrieving revision 1\.1\.1\.1
-retrieving revision 1\.1\.1\.1\.2\.1
-Merging differences between 1\.1\.1\.1 and 1\.1\.1\.1\.2\.1 into testcase10"
-
- # So if your changes didn't make it into my working copy, or
- # in any case if the files do not look like the final text
- # in the files in directory comp_me, then the test flunks:
- cd ..
- mkdir comp_me
- cd comp_me
- diffmerge_create_expected_files
- cd ..
- rm mine/.#*
-
- # If you have GNU's version of diff, you may try
- # uncommenting the following line which will give more
- # fine-grained information about how cvs differed from the
- # correct result:
- #dotest diffmerge1_cmp "diff -u --recursive --exclude=CVS comp_me mine" ''
- dotest diffmerge1_cmp "directory_cmp comp_me mine"
-
- # Clean up after ourselves:
- cd ..
- if $keep; then :; else
- rm -rf diffmerge1 ${CVSROOT_DIRNAME}/diffmerge1
- fi
- ;;
-
- diffmerge2)
-
- # FIXME: This test should be rewritten to be much more concise.
- # It currently weighs in at something like 600 lines, but the
- # same thing could probably be tested in more like 50-100 lines.
- mkdir diffmerge2
-
- # This tests for another diffmerge bug reported by Martin
- # Tomes; actually, his bug was probably caused by an initial
- # fix for the bug in test diffmerge1, and likely wasn't ever
- # a problem in CVS as long as one was using a normal
- # distribution of diff or a version of CVS that has the diff
- # lib in it.
- #
- # Nevertheless, once burned twice cautious, so we test for his
- # bug here.
- #
- # Here is his report, more or less verbatim:
- # ------------------------------------------
- #
- # Put the attached file (sgrid.h,v) into your repository
- # somewhere, check out the module and do this:
- #
- # cvs update -j Review_Phase_2_Enhancements sgrid.h
- # cvs diff -r Review_V1p3 sgrid.h
- #
- # As there have been no changes made on the trunk there
- # should be no differences, however this is output:
- #
- # % cvs diff -r Review_V1p3 sgrid.h
- # Index: sgrid.h
- # ===================================================================
- # RCS file: /usr/local/repository/play/fred/sgrid.h,v
- # retrieving revision 1.1.2.1
- # diff -r1.1.2.1 sgrid.h
- # 178a179,184
- # > /*--------------------------------------------------------------
- # > INLINE FUNCTION : HORIZONTALLINES
- # > NOTES : Description at the end of the file
- # > ----------------------------------------------------------------*/
- # > uint16 horizontalLines( void );
- # >
- #
- # I did a cvs diff -c -r 1.1 -r 1.1.2.1 sgrid.h and patched those
- # differences to sgrid.h version 1.1 and got the correct result
- # so it looks like the built in patch is faulty.
- # -------------------------------------------------------------------
- #
- # This is the RCS file, sgrid.h,v, that he sent:
-
- echo "head 1.1;
-access;
-symbols
- Review_V1p3:1.1.2.1
- Review_V1p3C:1.1.2.1
- Review_1p3A:1.1.2.1
- Review_V1p3A:1.1.2.1
- Review_Phase_2_Enhancements:1.1.0.2
- Review_V1p2:1.1
- Review_V1p2B:1.1
- Review_V1p2A:1.1
- Review_V1p1:1.1
- Review_1p1:1.1;
-locks; strict;
-comment @ * @;
-
-
-1.1
-date 97.04.02.11.20.05; author colinl; state Exp;
-branches
- 1.1.2.1;
-next ;
-
-1.1.2.1
-date 97.06.09.10.00.07; author colinl; state Exp;
-branches;
-next ;
-
-
-desc
-@@
-
-
-1.1
-log
-@Project: DEV1175
-DCN:
-Tested By: Colin Law
-Reviewed By:
-Reason for Change: Initial Revision of all files
-
-Design Change Details:
-
-Implications:
-@
-text
-@/* \$""Header: L:/gpanels/dis/sgrid.h_v 1.1.1.0 24 Jan 1996 14:59:20 PAULT \$ */
-/*
- * \$""Log: L:/gpanels/dis/sgrid.h_v \$
- *
- * Rev 1.1.1.0 24 Jan 1996 14:59:20 PAULT
- * Branched
- *
- * Rev 1.1 24 Jan 1996 12:09:52 PAULT
- * Consolidated 4100 code merged to trunk
- *
- * Rev 1.0.2.0 01 Jun 1995 14:18:58 DAVEH
- * Branched
- *
- * Rev 1.0 19 Apr 1995 16:32:48 COLINL
- * Initial revision.
-*/
-/*****************************************************************************
-FILE : SGRID.H
-VERSION : 2.1
-AUTHOR : Dave Hartley
-SYSTEM : Borland C++
-DESCRIPTION : The declaration of the scrolling grid class
-
-*****************************************************************************/
-#if !defined(__SGRID_H)
-#define __SGRID_H
-
-#if !defined(__SCROLL_H)
-#include <scroll.h>
-#endif
-
-#if !defined(__GKI_H)
-#include \"gki.h\"
-#endif
-
-#if defined PRINTING_SUPPORT
-class Printer;
-#endif
-
-/*****************************************************************************
-CLASS : ScrollingGrid
-DESCRIPTION: This class inherits from a grid and a scrollable, and
- can therefore use all the PUBLIC services provided by these
- classes. A description of these can be found in
- GRID.H and SCROLL.H.
- A scrolling grid is a set of horizontal and vertical lines
- that scroll and continually update to provide a complete grid
-
-*****************************************************************************/
-
-class ScrollingGrid : public Scrollable
-{
- public:
-#if defined _WINDOWS
-/*---------------------------------------------------------------------------
-FUNCTION : CONSTRUCTOR
-DESCRIPTION : sets up the details of the grid, ready for painting
-ARGUMENTS : name : sgColour
- - the colour of the grid
- sgLineType
- - the syle of line
- sgHorizontalTotal
- - the total number of horizontal grid lines
- verticalSpacingMin
- - the min distance between the vertical grid lines
- on the scrolling axis
- currentTimestamp
- - timestamp value now
- ticksPerSecond
- - number of timestamp ticks per second
- ticksPerPixel
- - number of timestamp ticks per pixel required
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- ScrollingGrid( GkiColour sgColour, GkiLineType sgLineType,
- uint16 sgHorizontalTotal,
- uint16 verticalSpacingMin, uint32 currentTimestamp,
- uint16 ticksPerSecond, uint32 ticksPerPixel );
-#else
-/*---------------------------------------------------------------------------
-FUNCTION : CONSTRUCTOR
-DESCRIPTION : sets up the details of the grid, ready for painting
-ARGUMENTS : name : sgColour
- - the colour of the grid
- sgLineType
- - the syle of line
- sgHorizontalTotal ( THE MAX NUMBER OF LINES IS 100 )
- - the total number of horizontal grid lines
- sgVerticalSpacing
- - the distance between the vertical grid lines
- on the scrolling axis
-
-RETURN : None
-NOTES : If the caller does not get the total grid lines value, synced
- with the overall size of the viewport, the spacing between
- grid lines will not be consistent.
-
----------------------------------------------------------------------------*/
- ScrollingGrid( GkiColour sgColour, GkiLineType sgLineType
- , uint16 sgHorizontalTotal, uint16 sgVerticalSpacing );
-#endif
-/*---------------------------------------------------------------------------
-FUNCTION : DESTRUCTOR
-DESCRIPTION : tidies it all up
-ARGUMENTS : name :
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- ~ScrollingGrid( void );
-
-/*---------------------------------------------------------------------------
-FUNCTION : ATTACH
-DESCRIPTION : This service overloads the base class service, as it does
- additional work at the time of attachment.
-
-ARGUMENTS : name : tDrawingArea
- - the scrolled viewport to attach this trend to
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void attach( SViewport *tDrawingArea );
-
-#if defined _WINDOWS
-/*---------------------------------------------------------------------------
-FUNCTION : calculateVerticalSpacing
-DESCRIPTION : determines optimum spacing along time axis
-ARGUMENTS :
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void calculateVerticalSpacing();
-
-/*---------------------------------------------------------------------------
-FUNCTION : gridSpacingTicks
-DESCRIPTION : Provides the grid spacing in the time axis in ticks
-ARGUMENTS :
-RETURN : Number of ticks
-NOTES :
----------------------------------------------------------------------------*/
- uint32 gridSpacingTicks();
-
-#endif
-
-/*---------------------------------------------------------------------------
-INLINE FUNCTION : HORIZONTALLINES
-NOTES : Description at the end of the file
----------------------------------------------------------------------------*/
- uint16 horizontalLines( void );
-
-#if defined _WINDOWS
-// In Windows the OnDraw() function replaces paint()
-/*---------------------------------------------------------------------------
-FUNCTION : ScrollingGrid OnDraw
-DESCRIPTION : Paints the given area of the grid.
- Pure virtual
-ARGUMENTS : pDC pointer to the device context to use for display
- Note that the device context operates in the coords
- of the window owning the viewport
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- virtual void OnDraw( CDC *pDC );
-
-#else // not Windows
-
-/*---------------------------------------------------------------------------
-FUNCTION : PAINT
-DESCRIPTION : This extends the standard grid paint method to paint the
- viewport relative to its current position.
-
-ARGUMENTS : name :
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void paint( void );
-#endif
-
-/*---------------------------------------------------------------------------
-FUNCTION : P A I N T T E X T M A R K E R S
-DESCRIPTION : this service allow the text markers to be painted seperatley
- from the grid lines
-
-ARGUMENTS : name :
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void paintTextMarkers();
-
-#if defined PRINTING_SUPPORT
-/*---------------------------------------------------------------------------
-FUNCTION : P R I N T
-DESCRIPTION : This print service prints a grid marker ( being either a
- timestamp or a date, IF there is one at the plot position
- given
-
-ARGUMENTS : name :
- displayPosition
- - Where in the log to look to see if there is an
- entry to print
-
- - printerPtr
- the printer to print to
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void print( uint16 currentPrintPos, Printer *printerPtr );
-#endif
-
-/*---------------------------------------------------------------------------
-FUNCTION : S E T D R I V E D I R E C T I O N
-DESCRIPTION : Sets direction for update and scrolling forwards or backwards
-ARGUMENTS : direction - required direction
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void setDriveDirection( ScrollDirection direction );
-
-/*---------------------------------------------------------------------------
-FUNCTION : S E T U P
-DESCRIPTION : service that will setup the grid prior to a paint
-
-ARGUMENTS : name :
- - newTimestamp
-
-
- - newTimeBase
- the number of ticks that represent a plot point on
- the trendgraph.
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void setup( uint32 newTimestamp, uint32 newTimeBase );
-
-#if defined PRINTING_SUPPORT
-/*---------------------------------------------------------------------------
-FUNCTION : S E T U P F O R P R I N T
-DESCRIPTION : This service iis to be called prior to printing. It allows
- the grid to prepare its markers ready for the print
- commands
-
-ARGUMENTS : name :
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void setupForPrint();
-#endif
-
-/*---------------------------------------------------------------------------
-FUNCTION : UPDATE
-DESCRIPTION : When this service is called it will calculate what needs to
- be painted and fill in the display again.
-
-ARGUMENTS : name : timeStamp
- - the reference time of this update.
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void update( uint32 timeStamp );
-
-/*---------------------------------------------------------------------------
-FUNCTION : U P D A T E B U F F E R
-DESCRIPTION : When a display update is not required, use this method. It
- updates the internal data ready for a call to paint that
- will then show the grid in the right position
-
-ARGUMENTS : name :
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void updateBuffer( void );
-
- private:
-
-/*---------------------------------------------------------------------------
-FUNCTION : M A K E G R I D M A R K E R
-DESCRIPTION : service that perpares a string for display. The string will
- either be a short date, or short time. this is determined
- by the current setting of the dateMarker flag
-
-ARGUMENTS : name : timestampVal
- - the value to convert
-
- storePtr
- - the place to put the string
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void makeGridMarker( uint32 timestampVal, char *storePtr );
-
-/*---------------------------------------------------------------------------
-FUNCTION : P A I N T G R I D M A R K E R
-DESCRIPTION : given a position will put the string on the display
-
-ARGUMENTS : name :
- yPos
- - were it goes on the Y-axis
-
- gridMarkerPtr
- - what it is
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void paintGridMarker( uint16 yPos, char *gridMarkerPtr );
-
-#if defined _WINDOWS
-/*---------------------------------------------------------------------------
-FUNCTION : PAINTHORIZONTALLINES
-DESCRIPTION : responsible for painting the grids horizontal lines
-ARGUMENTS : pRectToDraw pointer to rectangle that needs refreshing.
- in viewport coords
- pDC pointer to device context to use
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void paintHorizontalLines(RectCoords* pRectToDraw, CDC* pDC );
-#else
-/*---------------------------------------------------------------------------
-FUNCTION : PAINTHORIZONTALLINES
-DESCRIPTION : responsible for painting the grids horizontal lines
-ARGUMENTS : name: xStart
- - the starting X co-ordinate for the horizontal line
- xEnd
- - the ending X co-ordinate for the horizontal line
-
-RETURN : None
-NOTES : Remember lines are drawn from origin. The origin in a
- horizontal viewport will be the top.
----------------------------------------------------------------------------*/
- void paintHorizontalLines( uint16 xStart, uint16 xEnd );
-#endif
-
-#if defined _WINDOWS
-/*---------------------------------------------------------------------------
-FUNCTION : PAINTVERTICALLINES
-DESCRIPTION : responsible for painting the grids vertical lines
-ARGUMENTS : pRectToDraw pointer to rectangle that needs refreshing.
- in viewport coords
- offset offset from rhs that rightmost line would be
- drawn if rectangle included whole viewport
- pDC pointer to device context to use
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void paintVerticalLines( RectCoords* pRectToDraw, uint16 offset,
- CDC* pDC );
-#else
-/*---------------------------------------------------------------------------
-FUNCTION : PAINTVERTICALLINES
-DESCRIPTION : responsible for painting the grids vertical lines
-ARGUMENTS : name : yStart
- - the starting Y co-ordinate for the vertical line
- yEnd
- - the ending Y co-ordinate for the vertical line
- offset
- - a starting point offset that determines at what X
- position the first line will be drawn
-
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void paintVerticalLines( uint16 yStart, uint16 yEnd, uint16 offset );
-#endif
-
-#if defined _WINDOWS
-/*---------------------------------------------------------------------------
-FUNCTION : PAINTVERTICALLINE
-DESCRIPTION : paints one line at the position specified, and length
-ARGUMENTS : name : yStart
- - the starting point on the y axis for the line
- yEnd
- - the end point on the y axis for the line
- xPosition
- - The horizontal offset from the start of the viewport
- pDC pointer to device context to use
-
-RETURN : None
-NOTES : There is not an equivalent horizontal method as yet. This
- is a seperate method because the service is useful to a
- derivation of this class
----------------------------------------------------------------------------*/
- void paintVerticalLine( uint16 yStart, uint16 yEnd
- , uint16 xPosition, CDC *pDC );
-#else
-/*---------------------------------------------------------------------------
-FUNCTION : PAINTVERTICALLINE
-DESCRIPTION : paints one line at the position specified, and length
-ARGUMENTS : name : yStart
- - the starting point on the y axis for the line
- yEnd
- - the end point on the y axis for the line
- xPosition
- - The horizontal offset from the start of the viewport
-
-RETURN : None
-NOTES : There is not an equivalent horizontal method as yet. This
- is a seperate method because the service is useful to a
- derivation of this class
----------------------------------------------------------------------------*/
- void paintVerticalLine( uint16 yStart, uint16 yEnd
- , uint16 xPosition );
-#endif
-
-/*---------------------------------------------------------------------------
-INLINE FUNCTION : VERTICALSPACING
-NOTES : Description at the end of the file
----------------------------------------------------------------------------*/
- uint16 verticalSpacing( void );
-
-
- // Position in viewport that we are now writing to if going forwards
- // Note that if this is greater than viewport length then we have
- // just scrolled and value must be adjusted before use.
- sint16 forwardsOutputPosition;
-
- // Position in viewport that we are now writing to if going backwards
- // Note that if this is less than zero then we have
- // just scrolled and value must be adjusted before use.
- sint16 backwardsOutputPosition;
-
- // position in grid cycle of forwards output position.
- // if zero then it is time to output a grid line
- sint16 forwardsIntervalCount;
-
- // position in grid cycle of forwards output position.
- // if zero then it is time to output a grid line
- sint16 backwardsIntervalCount;
-
- uint32 lastUpdateTimestamp;
- uint32 timeBase; // ticks per pixel
- uint16 currentOutputPosition;
- uint16 gridTimestampSpacing;
- uint16 intervalCount;
- uint16 horizontalTotal;
- uint16 vSpacing;
-#if defined PRINTING_SUPPORT
- uint16 numberOfGridMarkersPrinted;
-#endif
- bool firstTime; // indicates first time through
- bool dateMarker;
-
- GkiLineType lineType;
- GkiColour gridColour;
-
- #if defined _WINDOWS
- uint16 ticksPerSec; // number of time ticks per second
- uint16 vSpacingMin; // minimum pixels per division along time axis
- CPen *pPen; // the pen to use for drawing in windows
- #endif
-
-};
-
-
-/*****************************************************************************
- I N L I N E F U N C T I O N S
-*****************************************************************************/
-
-/*---------------------------------------------------------------------------
-FUNCTION : HORIZONTALLINES
-DESCRIPTION : supplies the number of horizontal lines in the grid
-ARGUMENTS : name :
-
-RETURN :
-NOTES :
----------------------------------------------------------------------------*/
-inline uint16 ScrollingGrid::horizontalLines( void )
-{
- return( horizontalTotal );
-}
-/*---------------------------------------------------------------------------
-FUNCTION : VERTICALSPACING
-DESCRIPTION : returns the distance between adjacent vertical lines
-ARGUMENTS : name :
-
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
-inline uint16 ScrollingGrid::verticalSpacing( void )
-{
- return( vSpacing );
-}
-
-#endif
-@
-
-
-1.1.2.1
-log
-@DEV1194:DS4 Provision of major and minor grid lines
-@
-text
-@d1 1
-a1 1
-/* \$""Header: /usr/local/repository/cmnsrc/review/src/sgrid.h,v 1.1 1997/04/02 11:20:05 colinl Exp \$ */
-d3 1
-a3 12
- * \$""Log: sgrid.h,v \$
- * Revision 1.1 1997/04/02 11:20:05 colinl
- * Project: DEV1175
- * DCN:
- * Tested By: Colin Law
- * Reviewed By:
- * Reason for Change: Initial Revision of all files
- *
- * Design Change Details:
- *
- * Implications:
- *
-d58 6
-a63 5
-ARGUMENTS : name : majorColour colour for major grid lines
- minorColour colour for minor grid lines
- sgLineType line type for minor grid lines
- yMajorGridLines number of major y lines on grid
- yMinorGridLines number of major y lines on grid
-d77 2
-a78 3
- ScrollingGrid( GkiColour majorColour, GkiColour minorColour,
- GkiLineType sgLineType,
- uint16 yMajorGridLines, uint16 yMinorGridLines,
-a137 17
-FUNCTION : DrawHorizontalGridLines
-
-DESCRIPTION : Draws major or minor grid lines
-ARGUMENTS : pDC device context
- pPen pen to use
- numLines total lines required
- yLow, yHigh, xLow, xHigh rectangle to draw in
- yMax max y value
-RETURN : None
-NOTES :
----------------------------------------------------------------------------*/
- void DrawHorizontalGridLines( CDC* pDC, CPen* pPen,
- uint16 numLines,
- uint16 yLow, uint16 yHigh, uint16 xLow, uint16 xHigh,
- uint16 yMax );
-
-/*---------------------------------------------------------------------------
-d148 6
-d448 1
-a448 2
- uint16 m_yMajorGridLines;
- uint16 m_yMinorGridLines;
-d456 2
-a457 3
- GkiLineType lineType; // line type for minor grid lines
- GkiColour m_majorColour;
- GkiColour m_minorColour;
-d462 1
-a462 2
- CPen *pMajorPen; // pen to use for drawing major grid lines
- CPen *pMinorPen; // pen to use for drawing minor grid lines
-d472 12
-@" > diffmerge2/sgrid.h,v
-
- # We have to put the RCS file in the repository by hand for
- # this test:
- mkdir ${CVSROOT_DIRNAME}/diffmerge2
- cp diffmerge2/sgrid.h,v ${CVSROOT_DIRNAME}/diffmerge2/sgrid.h,v
- rm -rf diffmerge2
- dotest diffmerge2_co \
- "${testcvs} co diffmerge2" "${DOTSTAR}U ${DOTSTAR}"
- cd diffmerge2
- dotest diffmerge2_update \
- "${testcvs} update -j Review_Phase_2_Enhancements sgrid.h" \
- "${DOTSTAR}erging ${DOTSTAR}"
- # This is the one that counts -- there should be no output:
- dotest diffmerge2_diff \
- "${testcvs} diff -r Review_V1p3 sgrid.h" ''
-
- cd ..
- rm -rf diffmerge2
- 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 ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- mkdir dir1
- dotest release-3 "${testcvs} add dir1" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/dir1 added to the repository"
- mkdir dir2
- dotest release-4 "${testcvs} add dir2" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/dir2 added to the repository"
- cd dir2
- mkdir dir3
- dotest release-5 "${testcvs} add dir3" \
-"Directory ${CVSROOT_DIRNAME}/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} update: Updating \.
-${PROG} update: Updating first-dir
-${PROG} update: Updating first-dir/dir2"
-
- cd first-dir
- mkdir dir1
- dotest release-10 "${testcvs} add dir1" \
-"Directory ${CVSROOT_DIRNAME}/first-dir/dir1 added to the repository"
- cd dir2
- mkdir dir3
- dotest release-11 "${testcvs} add dir3" \
-"Directory ${CVSROOT_DIRNAME}/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} update: Updating \.
-${PROG} update: Updating first-dir"
-
- # Check to make sure release isn't overwriting a
- # CVS/Entries file in the current directory (using data
- # from the released directory).
-
- # cvs 1.11 (remote) fails on release-21 (a message about
- # chdir into the removed directory), although it seemingly
- # unedits and removes the directory correctly. If
- # you manually continue, it then fails on release-22 do
- # to the messed up CVS/Entries file from release-21.
- cd first-dir
- mkdir second-dir
- dotest release-18 "$testcvs add second-dir" \
-"Directory $CVSROOT_DIRNAME/first-dir/second-dir added to the repository"
-
- cd second-dir
- touch file1
- dotest release-19 "$testcvs -Q add file1"
- dotest release-20 '$testcvs -q ci -m add' \
-"RCS file: $CVSROOT_DIRNAME/first-dir/second-dir/file1,v
-done
-Checking in file1;
-$CVSROOT_DIRNAME/first-dir/second-dir/file1,v <-- file1
-initial revision: 1\.1
-done"
- dotest release-21 "$testcvs edit file1"
- cd ..
- dotest release-22 "echo yes | $testcvs release -d second-dir" \
-"You have \[0\] altered files in this repository.
-Are you sure you want to release (and delete) directory \`second-dir': "
- dotest release-23 "$testcvs -q update -d" "U second-dir/file1"
- dotest release-24 "$testcvs edit"
-
- cd ../..
- rm -rf 1 $CVSROOT_DIRNAME/first-dir
- ;;
-
-
-
- recase)
- #
- # Some tests of behavior which broke at one time or another when run
- # from case insensitive clients against case sensitive servers.
- #
- # These tests are namned according to the following convention:
- #
- # ci Client (sandbox filesystem) case Insensitive
- # cs Client (sandbox filesystem) case Sensitive
- # si Server (repository filesystem) case Insensitive
- # ss Server (repository filesystem) case Sensitive
- #
-
- mkdir 1; cd 1
-
- # First, we will expect different results for a few of these tests
- # based on whether the repository is on a case sensitive filesystem
- # or not and whether the sandbox is on a case sensitive filesystem or
- # not, so determine which cases we are dealing with:
- echo file >file
- echo FiLe >FiLe
- if cmp file FiLe >/dev/null; then
- client_sensitive=false
- else
- client_sensitive=:
- fi
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost 'echo file >file'
- $CVS_RSH $remotehost 'echo FiLe >FiLe'
- if $CVS_RSH $remotehost 'cmp file FiLe >/dev/null'; then
- server_sensitive=false
- else
- server_sensitive=:
- fi
- else
- server_sensitive=$client_sensitive
- fi
-
- # The first test (recase-1 & recase-2) is for a remove of a file then
- # a readd in a different case.
- mkdir $CVSROOT_DIRNAME/first-dir
- dotest recase-init-1 "$testcvs -Q co first-dir"
- cd first-dir
-
- echo this file has no content >file
- dotest recase-init-2 "$testcvs -Q add file"
- dotest recase-init-3 "$testcvs -Q ci -madd" \
-"RCS file: $CVSROOT_DIRNAME/first-dir/file,v
-done
-Checking in file;
-$CVSROOT_DIRNAME/first-dir/file,v <-- file
-initial revision: 1\.1
-done"
- dotest recase-init-4 "$testcvs -Q tag first"
-
- # Now remove the file.
- dotest recase-init-5 "$testcvs -Q rm -f file"
- dotest recase-init-6 "$testcvs -Q ci -mrm" \
-"Removing file;
-$CVSROOT_DIRNAME/first-dir/file,v <-- file
-new revision: delete; previous revision: 1\.1
-done"
-
- # Now the test - readd in a different case.
- echo this file needs some content >FiLe
- if $server_sensitive; then
- dotest recase-1ss "$testcvs add FiLe" \
-"$PROG add: scheduling file \`FiLe' for addition
-$PROG add: use '$PROG commit' to add this file permanently"
- dotest recase-2ss "$testcvs -q ci -mrecase" \
-"RCS file: $CVSROOT_DIRNAME/first-dir/FiLe,v
-done
-Checking in FiLe;
-$CVSROOT_DIRNAME/first-dir/FiLe,v <-- FiLe
-initial revision: 1\.1
-done"
- else # server insensitive
- dotest recase-1si "$testcvs add FiLe" \
-"$PROG add: Re-adding file \`FiLe' (in place of dead revision 1\.2)\.
-$PROG add: use '$PROG commit' to add this file permanently"
- dotest recase-2si "$testcvs -q ci -mrecase" \
-"Checking in FiLe;
-$CVSROOT_DIRNAME/first-dir/FiLe,v <-- FiLe
-new revision: 1\.3; previous revision: 1\.2
-done"
- fi
-
- # Now verify that a checkout will still work
- cd ../..
- mkdir 2; cd 2
- dotest recase-3 "$testcvs -q co first-dir" \
-"U first-dir/FiLe"
-
- cd first-dir
- # Prove that we can still get status and log information on
- # conflicting case files (1 in Attic, one in parent).
- if $remote; then
- if $client_sensitive; then
- file=file
- fIlE=fIlE
- else # client insensitive
- # Because FiLe is present on a case insensitive client, it is the
- # only one ever found and queried or altered.
- file=FiLe
- fIlE=FiLe
- fi
- else # ! $remote
- file=file
- fIlE=fIlE
- fi
- if $server_sensitive; then
- if $client_sensitive; then
- # Client finds Entry only for FiLe. Others returned by server.
- dotest recase-4sscs "$testcvs status file" \
-"===================================================================
-File: no file file Status: Up-to-date
-
- Working revision: No entry for file
- Repository revision: 1\.2 $CVSROOT_DIRNAME/first-dir/Attic/file,v"
- dotest recase-5sscs "$testcvs log file" \
-"
-RCS file: $CVSROOT_DIRNAME/first-dir/Attic/file,v
-Working file: file
-head: 1\.2
-branch:
-locks: strict
-access list:
-symbolic names:
- first: 1\.1
-keyword substitution: kv
-total revisions: 2; selected revisions: 2
-description:
-----------------------------
-revision 1\.2
-date: [0-9/]* [0-9:]*; author: $username; state: dead; lines: +0 -0
-rm
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: $username; state: Exp;
-add
-============================================================================="
- dotest recase-6sscs "$testcvs status FiLe" \
-"===================================================================
-File: FiLe Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 $CVSROOT_DIRNAME/first-dir/FiLe,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest recase-7sscs "$testcvs log FiLe" \
-"
-RCS file: $CVSROOT_DIRNAME/first-dir/FiLe,v
-Working file: FiLe
-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;
-recase
-============================================================================="
- else # server sensitive && client insensitive
- # Client finds same Entry for file & FiLe.
- dotest recase-4ssci "$testcvs status file" \
-"===================================================================
-File: FiLe Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 $CVSROOT_DIRNAME/first-dir/FiLe,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest recase-5ssci "$testcvs log file" \
-"
-RCS file: $CVSROOT_DIRNAME/first-dir/FiLe,v
-Working file: FiLe
-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;
-recase
-============================================================================="
- dotest recase-6ss "$testcvs status FiLe" \
-"===================================================================
-File: FiLe Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 $CVSROOT_DIRNAME/first-dir/FiLe,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest recase-7ss "$testcvs log FiLe" \
-"
-RCS file: $CVSROOT_DIRNAME/first-dir/FiLe,v
-Working file: FiLe
-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;
-recase
-============================================================================="
- fi
- else # server insensitive
- # There is only one archive when the server is insensitive, but the
- # printed file/archive name can vary.
- dotest recase-4si "$testcvs status file" \
-"===================================================================
-File: $file Status: Up-to-date
-
- Working revision: 1\.3.*
- Repository revision: 1\.3 $CVSROOT_DIRNAME/first-dir/$file,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest recase-5si "$testcvs log file" \
-"
-RCS file: $CVSROOT_DIRNAME/first-dir/$file,v
-Working file: $file
-head: 1\.3
-branch:
-locks: strict
-access list:
-symbolic names:
- first: 1\.1
-keyword substitution: kv
-total revisions: 3; selected revisions: 3
-description:
-----------------------------
-revision 1\.3
-date: [0-9/]* [0-9:]*; author: $username; state: Exp; lines: +1 -1
-recase
-----------------------------
-revision 1\.2
-date: [0-9/]* [0-9:]*; author: $username; state: dead; lines: +0 -0
-rm
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: $username; state: Exp;
-add
-============================================================================="
- dotest recase-6si "$testcvs status FiLe" \
-"===================================================================
-File: FiLe Status: Up-to-date
-
- Working revision: 1\.3.*
- Repository revision: 1\.3 $CVSROOT_DIRNAME/first-dir/FiLe,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest recase-7si "$testcvs log FiLe" \
-"
-RCS file: $CVSROOT_DIRNAME/first-dir/FiLe,v
-Working file: FiLe
-head: 1\.3
-branch:
-locks: strict
-access list:
-symbolic names:
- first: 1\.1
-keyword substitution: kv
-total revisions: 3; selected revisions: 3
-description:
-----------------------------
-revision 1\.3
-date: [0-9/]* [0-9:]*; author: $username; state: Exp; lines: +1 -1
-recase
-----------------------------
-revision 1\.2
-date: [0-9/]* [0-9:]*; author: $username; state: dead; lines: +0 -0
-rm
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: $username; state: Exp;
-add
-============================================================================="
- fi
-
- # And when the file does not exist on the client, we go with the
- # client Entries match.
- if $client_sensitive && $server_sensitive; then
- dotest recase-8sscs "$testcvs status fIlE" \
-"$PROG status: nothing known about fIlE
-===================================================================
-File: no file fIlE Status: Unknown
-
- Working revision: No entry for fIlE
- Repository revision: No revision control file"
- else # !$client_sensitive || !$server_sensitive
- dotest recase-8anyi "$testcvs status fIlE" \
-"===================================================================
-File: $fIlE Status: Up-to-date
-
- Working revision: 1\.[0-9]*.*
- Repository revision: 1\.[0-9]* $CVSROOT_DIRNAME/first-dir/$fIlE,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- fi
-
- # and an update
- if $server_sensitive; then
- dotest recase-9ss "$testcvs -q up -rfirst" \
-"$PROG update: FiLe is no longer in the repository
-U file"
-
- if $client_sensitive; then
- dotest recase-10sscs "$testcvs -q up -A" \
-"U FiLe
-$PROG update: file is no longer in the repository"
- else # client insensitive
- # FIXCVS: This should remove the offending file first.
- dotest_fail recase-10ssci "$testcvs -q up -A" \
-"$PROG update: move away \./FiLe; it is in the way
-C FiLe
-$PROG update: file is no longer in the repository"
-
- cd ..
- rm -r first-dir
- dotest recase-11ssci "$testcvs -q co first-dir" \
-"U first-dir/FiLe"
- cd first-dir
- fi
-
- #
- # See what happens when cased names clash.
- #
-
- # Copy the archive
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost "cp $CVSROOT_DIRNAME/first-dir/FiLe,v \
- $CVSROOT_DIRNAME/first-dir/FILE,v"
- else
- cp $CVSROOT_DIRNAME/first-dir/FiLe,v \
- $CVSROOT_DIRNAME/first-dir/FILE,v
- fi
-
- if $client_sensitive; then
- dotest recase-12sscs "$testcvs -q up" "U FILE"
- else # client insensitive
- dotest_fail recase-12ssci "$testcvs -q up" \
-"$PROG update: move away \./FILE; it is in the way
-C FILE"
- fi
- else # server insensitive
- dotest recase-9si "$testcvs -q up -rfirst" "U FiLe"
- dotest recase-10si "$testcvs -q up -A" "U FiLe"
- fi
-
- # Prove that we can still get status and log information on
- # conflicting case files (1 in Attic, two in parent).
- if $server_sensitive; then
- if $client_sensitive; then
- # Client finds Entry only for FiLe. Others returned by server.
- dotest recase-13sscs "$testcvs status file" \
-"===================================================================
-File: no file file Status: Up-to-date
-
- Working revision: No entry for file
- Repository revision: 1\.2 $CVSROOT_DIRNAME/first-dir/Attic/file,v"
- dotest recase-14sscs "$testcvs log file" \
-"
-RCS file: $CVSROOT_DIRNAME/first-dir/Attic/file,v
-Working file: file
-head: 1\.2
-branch:
-locks: strict
-access list:
-symbolic names:
- first: 1\.1
-keyword substitution: kv
-total revisions: 2; selected revisions: 2
-description:
-----------------------------
-revision 1\.2
-date: [0-9/]* [0-9:]*; author: $username; state: dead; lines: +0 -0
-rm
-----------------------------
-revision 1\.1
-date: [0-9/]* [0-9:]*; author: $username; state: Exp;
-add
-============================================================================="
- dotest recase-15sscs "$testcvs status FiLe" \
-"===================================================================
-File: FiLe Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 $CVSROOT_DIRNAME/first-dir/FiLe,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest recase-16sscs "$testcvs log FiLe" \
-"
-RCS file: $CVSROOT_DIRNAME/first-dir/FiLe,v
-Working file: FiLe
-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;
-recase
-============================================================================="
- dotest recase-17sscs "$testcvs status FILE" \
-"===================================================================
-File: FILE Status: Up-to-date
-
- Working revision: 1.1.*
- Repository revision: 1.1 ${CVSROOT_DIRNAME}/first-dir/FILE,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest recase-18sscs "$testcvs log FILE" \
-"
-RCS file: $CVSROOT_DIRNAME/first-dir/FILE,v
-Working file: FILE
-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;
-recase
-============================================================================="
- else # $server_sensitive && !$client_sensitive
- # Client finds same Entry for file & FiLe.
- dotest recase-13ssci "$testcvs status file" \
-"===================================================================
-File: FiLe Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 $CVSROOT_DIRNAME/first-dir/FiLe,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest recase-16ssci "$testcvs log FiLe" \
-"
-RCS file: $CVSROOT_DIRNAME/first-dir/FiLe,v
-Working file: FiLe
-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;
-recase
-============================================================================="
- dotest recase-17ssci "$testcvs status FILE" \
-"===================================================================
-File: FiLe Status: Up-to-date
-
- Working revision: 1\.1.*
- Repository revision: 1\.1 $CVSROOT_DIRNAME/first-dir/FiLe,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- dotest recase-18ssci "$testcvs log FILE" \
-"
-RCS file: $CVSROOT_DIRNAME/first-dir/FiLe,v
-Working file: FiLe
-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;
-recase
-============================================================================="
- fi
- else # !$server_sensitive
- # Skip these when the server is case insensitive - nothing
- # has changed since recase-[4-7]si
- :
- fi
-
- if $client_sensitive && $server_sensitive; then
- dotest recase-19sscs "$testcvs status fIlE" \
-"$PROG status: nothing known about fIlE
-===================================================================
-File: no file fIlE Status: Unknown
-
- Working revision: No entry for fIlE
- Repository revision: No revision control file"
- else # !$client_sensitive || !$server_sensitive
- dotest recase-19anyi "$testcvs status fIlE" \
-"===================================================================
-File: $fIlE Status: Up-to-date
-
- Working revision: 1\.[0-9]*.*
- Repository revision: 1\.[0-9]* $CVSROOT_DIRNAME/first-dir/$fIlE,v
- Sticky Tag: (none)
- Sticky Date: (none)
- Sticky Options: (none)"
- fi
-
- # And last but not least, prove that a checkout is still possible.
- cd ../..
- mkdir 3; cd 3
- if $server_sensitive; then
- if $client_sensitive; then
- dotest recase-20sscs "$testcvs -q co first-dir" \
-"U first-dir/FILE
-U first-dir/FiLe"
- else # $server_senstive && !$client_sensitive
- dotest_fail recase-20ssci "$testcvs -q co first-dir" \
-"U first-dir/FILE
-$PROG checkout: move away first-dir/FiLe; it is in the way
-C first-dir/FiLe"
- fi
- else # !$server_sensitive
- # Skip these since nothing has changed.
- :
- fi
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- cd ..
- rm -r 1 2 3
- if $server_sensitive && test -n "$remotehost"; then
- # It is necessary to remove one of the case-conflicted files before
- # recursively removing the rest under Cygwin on a Samba share or
- # Samba returns a permission denied error due to its case
- # confusion.
- $CVS_RSH $remotehost "rm -f $CVSROOT_DIRNAME/first-dir/FILE,v"
- fi
- rm -rf $CVSROOT_DIRNAME/first-dir
- ;;
-
-
-
- multiroot)
- #
- # set up two repositories
- #
-
- CVSROOT1_DIRNAME=${TESTDIR}/root1
- CVSROOT2_DIRNAME=${TESTDIR}/root2
- CVSROOT1=`newroot $CVSROOT1_DIRNAME`
- CVSROOT2=`newroot $CVSROOT2_DIRNAME`
- testcvs1="${testcvs} -d ${CVSROOT1}"
- testcvs2="${testcvs} -d ${CVSROOT2}"
-
- dotest multiroot-setup-1 "mkdir $CVSROOT1_DIRNAME $CVSROOT2_DIRNAME"
- dotest multiroot-setup-2 "$testcvs -d$CVSROOT1_DIRNAME init"
- dotest multiroot-setup-3 "$testcvs -d$CVSROOT2_DIRNAME init"
-
- #
- # create some directories in root1
- #
- mkdir 1; cd 1
- dotest multiroot-setup-4 "${testcvs1} co -l ." \
-"${PROG} checkout: 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} add: scheduling file .mod1-1/file1-1. for addition
-${PROG} add: scheduling file .mod1-2/file1-2. for addition
-${PROG} add: 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} checkout: 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} add: scheduling file .mod2-1/file2-1. for addition
-${PROG} add: scheduling file .mod2-2/file2-2. for addition
-${PROG} add: 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} checkout: Updating mod1-1
-U mod1-1/file1-1
-${PROG} checkout: Updating mod1-2
-U mod1-2/file1-2"
- dotest multiroot-setup-12 "${testcvs2} co mod2-1 mod2-2" \
-"${PROG} checkout: Updating mod2-1
-U mod2-1/file2-1
-${PROG} checkout: Updating mod2-2
-U mod2-2/file2-2"
- cd mod1-2
- dotest multiroot-setup-13 "${testcvs2} co mod2-2" \
-"${PROG} checkout: Updating mod2-2
-U mod2-2/file2-2"
- cd ..
- cd mod2-2
- dotest multiroot-setup-14 "${testcvs1} co mod1-2" \
-"${PROG} checkout: Updating mod1-2
-U mod1-2/file1-2"
- cd ..
-
- #
- # 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" "mod1-1"
- dotest multiroot-cvsadm-2a "cat mod2-1/CVS/Root" "${CVSROOT2}"
- dotest multiroot-cvsadm-2b "cat mod2-1/CVS/Repository" "mod2-1"
- dotest multiroot-cvsadm-3a "cat mod1-2/CVS/Root" "${CVSROOT1}"
- dotest multiroot-cvsadm-3b "cat mod1-2/CVS/Repository" "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" "mod2-2"
- dotest multiroot-cvsadm-4a "cat mod2-2/CVS/Root" "${CVSROOT2}"
- dotest multiroot-cvsadm-4b "cat mod2-2/CVS/Repository" "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" "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.
-
- dotest multiroot-update-1a "${testcvs1} update" \
-"${PROG} update: Updating \.
-${PROG} update: Updating mod1-1
-${PROG} update: Updating mod1-2
-${PROG} update: Updating mod1-2/mod2-2
-${PROG} update: cannot open directory ${CVSROOT1_DIRNAME}/mod2-2: No such file or directory
-${PROG} update: skipping directory mod1-2/mod2-2
-${PROG} update: Updating mod2-1
-${PROG} update: cannot open directory ${CVSROOT1_DIRNAME}/mod2-1: No such file or directory
-${PROG} update: skipping directory mod2-1
-${PROG} update: Updating mod2-2
-${PROG} update: cannot open directory ${CVSROOT1_DIRNAME}/mod2-2: No such file or directory
-${PROG} update: skipping directory mod2-2"
-
- # Same deal but with -d ${CVSROOT2}.
- dotest multiroot-update-1b "${testcvs2} update" \
-"${PROG} update: Updating \.
-${PROG} update: Updating mod1-1
-${PROG} update: cannot open directory ${CVSROOT2_DIRNAME}/mod1-1: No such file or directory
-${PROG} update: skipping directory mod1-1
-${PROG} update: Updating mod1-2
-${PROG} update: cannot open directory ${CVSROOT2_DIRNAME}/mod1-2: No such file or directory
-${PROG} update: skipping directory mod1-2
-${PROG} update: Updating mod2-1
-${PROG} update: Updating mod2-2
-${PROG} update: Updating mod2-2/mod1-2
-${PROG} update: cannot open directory ${CVSROOT2_DIRNAME}/mod1-2: No such file or directory
-${PROG} update: skipping directory mod2-2/mod1-2"
-
- # 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_fail multiroot-diff-1 "${testcvs} diff" \
-"${PROG} diff: Diffing \.
-${PROG} diff: 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} diff: 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} diff: Diffing mod2-2/mod1-2
-${PROG} diff: Diffing mod1-2/mod2-2
-${PROG} diff: 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} diff: 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} diff: Diffing \.
-${PROG} diff: 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} diff: 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} diff: Diffing mod2-2
-${PROG} diff: Diffing mod2-2/mod1-2
-${PROG} diff: Diffing mod1-2
-${PROG} diff: Diffing mod1-2/mod2-2
-${PROG} diff: 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} diff: 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} update: Updating mod2-1
-${PROG} update: Updating mod2-2" \
-"${PROG} update: Updating \.
-${PROG} update: Updating mod1-1
-${PROG} update: Updating mod1-2
-${PROG} update: Updating mod2-2
-${PROG} update: Updating mod2-2/mod1-2
-P mod2-2/mod1-2/file1-2
-${PROG} update: Updating mod1-2
-${PROG} update: Updating mod1-2/mod2-2
-P mod1-2/mod2-2/file2-2
-${PROG} update: Updating mod2-1
-${PROG} update: Updating mod2-2"
-
- dotest multiroot-tag-1 "${testcvs} tag cattle" \
-"${PROG} tag: Tagging \.
-${PROG} tag: Tagging mod1-1
-T mod1-1/file1-1
-${PROG} tag: Tagging mod1-2
-T mod1-2/file1-2
-${PROG} tag: Tagging mod2-2/mod1-2
-${PROG} tag: Tagging mod1-2/mod2-2
-T mod1-2/mod2-2/file2-2
-${PROG} tag: Tagging mod2-1
-T mod2-1/file2-1
-${PROG} tag: Tagging mod2-2" \
-"${PROG} tag: Tagging \.
-${PROG} tag: Tagging mod1-1
-T mod1-1/file1-1
-${PROG} tag: Tagging mod1-2
-T mod1-2/file1-2
-${PROG} tag: Tagging mod2-2
-${PROG} tag: Tagging mod2-2/mod1-2
-${PROG} tag: Tagging mod1-2
-${PROG} tag: Tagging mod1-2/mod2-2
-T mod1-2/mod2-2/file2-2
-${PROG} tag: Tagging mod2-1
-T mod2-1/file2-1
-${PROG} tag: 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 $remote; then
- cd mod1-1
- dotest multiroot-add-1ar "${testcvs} add anotherfile1-1" \
-"${PROG} add: scheduling file .anotherfile1-1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- cd ../mod2-1
- dotest multiroot-add-1br "${testcvs} add anotherfile2-1" \
-"${PROG} add: scheduling file .anotherfile2-1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- cd ../mod2-2/mod1-2
- dotest multiroot-add-1cr "${testcvs} add anotherfile1-2" \
-"${PROG} add: scheduling file .anotherfile1-2. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- cd ../../mod1-2/mod2-2
- dotest multiroot-add-1dr "${testcvs} add anotherfile2-2" \
-"${PROG} add: scheduling file .anotherfile2-2. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- cd ../..
- else
- 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} add: scheduling file .mod1-1/anotherfile1-1. for addition
-${PROG} add: scheduling file .mod2-1/anotherfile2-1. for addition
-${PROG} add: scheduling file .mod2-2/mod1-2/anotherfile1-2. for addition
-${PROG} add: scheduling file .mod1-2/mod2-2/anotherfile2-2. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- fi
-
- dotest multiroot-status-1 "${testcvs} status -v" \
-"${PROG} status: Examining \.
-${PROG} status: 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} status: 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} status: 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} status: 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} status: 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} status: 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} status: Examining \.
-${PROG} status: 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} status: 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} status: Examining mod2-2
-${PROG} status: 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} status: Examining mod1-2
-${PROG} status: 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} status: 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} status: 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} update: Updating \.
-${PROG} update: Updating mod1-1
-${PROG} update: Updating mod1-2
-U mod1-2/anotherfile1-2
-${PROG} update: Updating mod2-2
-${PROG} update: Updating mod2-2/mod1-2
-${PROG} update: Updating mod1-2
-${PROG} update: Updating mod1-2/mod2-2
-${PROG} update: Updating mod2-1
-${PROG} update: Updating mod2-2
-U mod2-2/anotherfile2-2"
-
- dotest multiroot-log-1 "${testcvs} log" \
-"${PROG} log: Logging \.
-${PROG} log: 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} log: 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} log: 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} log: 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} log: 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} log: 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} log: Logging \.
-${PROG} log: 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} log: 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} log: Logging mod2-2
-${PROG} log: 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} log: Logging mod1-2
-${PROG} log: 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} log: 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} log: 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 $keep; 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=`newroot $CVSROOT1_DIRNAME`
- CVSROOT2=`newroot $CVSROOT2_DIRNAME`
-
- dotest multiroot2-1 "$testcvs -d$CVSROOT1_DIRNAME init"
- dotest multiroot2-2 "$testcvs -d$CVSROOT2_DIRNAME 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} import: Importing ${TESTDIR}/root1/dir1/sdir
-${PROG} import: 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} import: 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} update: Updating \.
-${PROG} update: Updating dir1
-${PROG} update: Updating dir1
-${PROG} update: Updating dir1/sdir
-${PROG} update: 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 $remote; then :; else
- dotest multiroot2-9a "${testcvs} -t update" \
-" *-> main loop with CVSROOT=${TESTDIR}/root1
-${PROG} update: Updating \.
- *-> Reader_Lock(${TESTDIR}/root1)
- *-> Lock_Cleanup()
-${PROG} update: Updating dir1
- *-> Reader_Lock(${TESTDIR}/root1/dir1)
- *-> Lock_Cleanup()
- *-> main loop with CVSROOT=${TESTDIR}/root2
-${PROG} update: Updating dir1/sdir
- *-> Reader_Lock(${TESTDIR}/root2/sdir)
- *-> Lock_Cleanup()
-${PROG} update: Updating dir1/sdir/ssdir
- *-> Reader_Lock(${TESTDIR}/root2/sdir/ssdir)
- *-> Lock_Cleanup()
- *-> Lock_Cleanup()"
- 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_fail multiroot2-12 \
-"${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 ${RFCDATE} 1\.1\.1\.1
-${PLUS}${PLUS}${PLUS} dir1/file1 ${RFCDATE} 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 ${RFCDATE} 1\.1\.1\.1
-${PLUS}${PLUS}${PLUS} dir1/sdir/sfile ${RFCDATE} 1\.2
-@@ -1 ${PLUS}1,2 @@
- sfile
-${PLUS}change him too"
-
- if $keep; 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.
-
- CVSROOT1=`newroot ${TESTDIR}/root1`
- CVSROOT2=`newroot ${TESTDIR}/root2`
-
- mkdir 1; cd 1
- dotest multiroot3-1 "$testcvs -d$TESTDIR/root1 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$TESTDIR/root2 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 $remote; 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 $remote; 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} add: scheduling file .file1. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- cd ..
- dotest multiroot3-8a "${testcvs} add dir2/file2" \
-"${PROG} add: scheduling file .dir2/file2. for addition
-${PROG} add: use .${PROG} commit. to add this file permanently"
- else
- dotest multiroot3-8 "${testcvs} add dir1/file1 dir2/file2" \
-"${PROG} add: scheduling file .dir1/file1. for addition
-${PROG} add: scheduling file .dir2/file2. for addition
-${PROG} add: 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"
-
- # 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} diff: failed to create lock directory for .${TESTDIR}/root1/dir2' (${TESTDIR}/root1/dir2/#cvs.lock): No such file or directory
-${PROG} diff: failed to obtain dir lock in repository .${TESTDIR}/root1/dir2'
-${PROG} \[diff aborted\]: read lock failed - giving up"
-
- # This one is supposed to work.
- dotest multiroot3-11 "${testcvs} -q diff dir1/file1 dir2/file2" ""
-
- # make sure we can't access across repositories
- mkdir 1a
- cd 1a
- dotest_fail multiroot3-12 \
-"$testcvs -d $CVSROOT1 -q co ../root2/dir2" \
-"$PROG \[checkout aborted\]: up-level in module reference (\`..') invalid: \`\.\./root2/dir2'\." \
-"$PROG \[server aborted\]: up-level in module reference (\`..') invalid: \`\.\./root2/dir2'\.
-$PROG \[checkout aborted\]: end of file from server (consult above messages if any)"
- dotest_fail multiroot3-13 \
-"$testcvs -d $CVSROOT2 -q co ../root1/dir1" \
-"$PROG \[checkout aborted\]: up-level in module reference (\`..') invalid: \`\.\./root1/dir1'\." \
-"$PROG \[server aborted\]: up-level in module reference (\`..') invalid: \`\.\./root1/dir1'\.
-$PROG \[checkout aborted\]: end of file from server (consult above messages if any)"
- dotest_fail multiroot3-14 \
-"$testcvs -d $CVSROOT1 -q co ./../root2/dir2" \
-"$PROG \[checkout aborted\]: up-level in module reference (\`..') invalid: \`\./\.\./root2/dir2'\." \
-"$PROG \[server aborted\]: up-level in module reference (\`..') invalid: \`\./\.\./root2/dir2'\.
-$PROG \[checkout aborted\]: end of file from server (consult above messages if any)"
- dotest_fail multiroot3-15 \
-"$testcvs -d $CVSROOT2 -q co ./../root1/dir1" \
-"$PROG \[checkout aborted\]: up-level in module reference (\`..') invalid: \`\./\.\./root1/dir1'\." \
-"$PROG \[server aborted\]: up-level in module reference (\`..') invalid: \`\./\.\./root1/dir1'\.
-$PROG \[checkout aborted\]: end of file from server (consult above messages if any)"
- dotest_fail multiroot3-16 \
-"$testcvs -d $CVSROOT1 -q co -p ../root2/dir2" \
-"$PROG \[checkout aborted\]: up-level in module reference (\`..') invalid: \`\.\./root2/dir2'\." \
-"$PROG \[server aborted\]: up-level in module reference (\`..') invalid: \`\.\./root2/dir2'\.
-$PROG \[checkout aborted\]: end of file from server (consult above messages if any)"
- dotest_fail multiroot3-17 \
-"$testcvs -d $CVSROOT1 -q co -p ./../root1/dir1" \
-"$PROG \[checkout aborted\]: up-level in module reference (\`..') invalid: \`\./\.\./root1/dir1'\." \
-"$PROG \[server aborted\]: up-level in module reference (\`..') invalid: \`\./\.\./root1/dir1'\.
-$PROG \[checkout aborted\]: end of file from server (consult above messages if any)"
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- cd ../..
-
- 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.
-
- CVSROOT1=`newroot ${TESTDIR}/root1`
- CVSROOT2=`newroot ${TESTDIR}/root2`
-
- mkdir 1; cd 1
- dotest multiroot4-1 "$testcvs -d$TESTDIR/root1 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} add: scheduling file .file1. for addition
-${PROG} add: 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$TESTDIR/root2 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} add: scheduling file .file2. for addition
-${PROG} add: 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 ${CVSROOT_DIRNAME}/first-dir added to the repository"
- cd first-dir
- touch file1 file2
- dotest rmroot-setup-3 "${testcvs} add file1 file2" \
-"${PROG} add: scheduling file .file1. for addition
-${PROG} add: scheduling file .file2. for addition
-${PROG} add: use .${PROG} commit. to add these files permanently"
- dotest rmroot-setup-4 "${testcvs} -q commit -minit" \
-"RCS file: ${CVSROOT_DIRNAME}/first-dir/file1,v
-done
-Checking in file1;
-${CVSROOT_DIRNAME}/first-dir/file1,v <-- file1
-initial revision: 1\.1
-done
-RCS file: ${CVSROOT_DIRNAME}/first-dir/file2,v
-done
-Checking in file2;
-${CVSROOT_DIRNAME}/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.
- CVSROOT1=`newroot ${TESTDIR}/root1`
- CVSROOT_MOVED=`newroot ${TESTDIR}/root-moved`
-
- dotest reposmv-setup-1 "$testcvs -d$TESTDIR/root1 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 $remote; then
- dotest_fail reposmv-2r "${testcvs} update" \
-"Cannot access ${TESTDIR}/root1/CVSROOT
-No such file or directory"
- else
- 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 ${CVSROOT_DIRNAME}/dir1: No such file or directory
-${PROG} update: skipping directory "
- fi
-
- # CVS/Root overrides $CVSROOT
- if $remote; then
- CVSROOT_save=${CVSROOT}
- CVSROOT=:fork:${TESTDIR}/root-moved; export CVSROOT
- dotest_fail reposmv-3r "${testcvs} update" \
-"Cannot access ${TESTDIR}/root1/CVSROOT
-No such file or directory"
- CVSROOT=${CVSROOT_save}; export CVSROOT
- else
- CVSROOT_save=${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_save}; export CVSROOT
- fi
-
- if $remote; then
- CVSROOT_save=${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_save}; export CVSROOT
- else
- # CVS/Root doesn't seem to quite completely override $CVSROOT
- # Bug? Not necessarily a big deal if it only affects error
- # messages.
- CVSROOT_save=${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_save}; 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} update: 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 $remote; 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;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cat >${CVSROOT_DIRNAME}/CVSROOT/passwd <<EOF
-testme:q6WV9d2t848B2:$username
-dontroot:q6WV9d2t848B2:root
-anonymous::$username
-$username:
-willfail: :whocares
-EOF
- dotest_fail pserver-3 "${testcvs} pserver" \
-"error 0 Server configuration missing --allow-root in inetd.conf" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-testme
-Ay::'d
-END AUTH REQUEST
-EOF
-
- dotest_fail pserver-3a "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"error 0 ${CVSROOT_DIRNAME}XXX: no such repository
-I HATE YOU" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}XXX
-testme
-Ay::'d
-END AUTH REQUEST
-EOF
-
- # Confirm that not sending a newline during auth cannot constitute
- # a denial-of-service attack. This assumes that PATH_MAX is less
- # than 65536 bytes. If PATH_MAX is larger than 65535 bytes, this
- # test could hang indefinitely.
- ${AWK} 'BEGIN { printf "0123456789abcdef" }' </dev/null >garbageseg
- echo "BEGIN AUTH REQUEST" >garbageinput
- i=0
- while test $i -lt 64; do
- cat <garbageseg >>garbageseg2
- i=`expr $i + 1`
- done
- i=0
- while test $i -lt 64; do
- cat <garbageseg2 >>garbageinput
- i=`expr $i + 1`
- done
- dotest_fail pserver-auth-no-dos \
-"${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${PROG} \\[pserver aborted\\]: Maximum line length exceeded during authentication\." <garbageinput
- unset i
- rm garbageseg garbageseg2 garbageinput
-
- # Sending the Root and noop before waiting for the
- # "I LOVE YOU" is bogus, but hopefully we can get
- # away with it.
- dotest pserver-4 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU
-ok" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-testme
-Ay::'d
-END AUTH REQUEST
-Root ${CVSROOT_DIRNAME}
-noop
-EOF
-
- # The "no such system user" error is occurring on at least one of
- # our BSD 2.0.2 nightly test platforms.
- dotest_fail pserver-4.2 \
-"${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"error 0: root not allowed" \
-"E Fatal error, aborting\.
-error 0 root: no such system user" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-dontroot
-Ay::'d
-END AUTH REQUEST
-EOF
-
- dotest pserver-5 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU
-E Protocol error: Root says \"${TESTDIR}/1\" but pserver says \"${CVSROOT_DIRNAME}\"
-error " <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-testme
-Ay::'d
-END AUTH REQUEST
-Root ${TESTDIR}/1
-noop
-EOF
-
- dotest pserver-5a "$testcvs --allow-root=$CVSROOT_DIRNAME pserver" \
-"$DOTSTAR LOVE YOU
-E init may not be run remotely
-error " <<EOF
-BEGIN AUTH REQUEST
-$CVSROOT_DIRNAME
-testme
-Ay::'d
-END AUTH REQUEST
-init $TESTDIR/2
-EOF
- dotest_fail pserver-5b "test -d $TESTDIR/2"
-
- dotest_fail pserver-6 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"I HATE YOU" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-testme
-Ay::'d^b?hd
-END AUTH REQUEST
-EOF
-
- dotest_fail pserver-7 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"I HATE YOU" <<EOF
-BEGIN VERIFICATION REQUEST
-${CVSROOT_DIRNAME}
-testme
-Ay::'d^b?hd
-END VERIFICATION REQUEST
-EOF
-
- dotest pserver-8 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU" <<EOF
-BEGIN VERIFICATION REQUEST
-${CVSROOT_DIRNAME}
-testme
-Ay::'d
-END VERIFICATION REQUEST
-EOF
-
-# Tests pserver-9 through pserver-13 are about empty passwords
-
- # Test empty password (both sides) for aliased user
- dotest pserver-9 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-anonymous
-A
-END AUTH REQUEST
-EOF
-
- # Test empty password (server side only) for aliased user
- dotest pserver-10 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-anonymous
-Aanythingwouldworkhereittrulydoesnotmatter
-END AUTH REQUEST
-EOF
-
- # Test empty (both sides) password for non-aliased user
- dotest pserver-11 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-${username}
-A
-END AUTH REQUEST
-EOF
-
- # Test empty (server side only) password for non-aliased user
- dotest pserver-12 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-${username}
-Anypasswordwouldworkwhynotthisonethen
-END AUTH REQUEST
-EOF
-
- # Test failure of whitespace password
- dotest_fail pserver-13 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} HATE YOU" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-willfail
-Amquiteunabletocomeupwithinterestingpasswordsanymore
-END AUTH REQUEST
-EOF
-
- # The following tests are for read-only access
-
- # Check that readers can only read, everyone else can write
-
- cat >${CVSROOT_DIRNAME}/CVSROOT/readers <<EOF
-anonymous
-EOF
-
- dotest pserver-14 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU
-M Concurrent Versions System (CVS) .*
-ok" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-anonymous
-Ay::'d
-END AUTH REQUEST
-Root ${CVSROOT_DIRNAME}
-version
-EOF
-
- dotest pserver-16 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU
-M Concurrent Versions System (CVS) .*
-ok" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-testme
-Ay::'d
-END AUTH REQUEST
-Root ${CVSROOT_DIRNAME}
-version
-EOF
-
- dotest pserver-18 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU
-M Concurrent Versions System (CVS) .*
-ok" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-${username}
-Ay::'d
-END AUTH REQUEST
-Root ${CVSROOT_DIRNAME}
-version
-EOF
-
- # Check that writers can write, everyone else can only read
- # even if not listed in readers
-
- cat >${CVSROOT_DIRNAME}/CVSROOT/writers <<EOF
-testme
-EOF
-
- dotest pserver-20 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU
-M Concurrent Versions System (CVS) .*
-ok" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-anonymous
-Ay::'d
-END AUTH REQUEST
-Root ${CVSROOT_DIRNAME}
-version
-EOF
-
- dotest pserver-22 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU
-M Concurrent Versions System (CVS) .*
-ok" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-testme
-Ay::'d
-END AUTH REQUEST
-Root ${CVSROOT_DIRNAME}
-version
-EOF
-
- dotest pserver-24 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU
-M Concurrent Versions System (CVS) .*
-ok" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-${username}
-Ay::'d
-END AUTH REQUEST
-Root ${CVSROOT_DIRNAME}
-version
-EOF
-
- # Should work the same without readers
-
- rm ${CVSROOT_DIRNAME}/CVSROOT/readers
-
- dotest pserver-26 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU
-M Concurrent Versions System (CVS) .*
-ok" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-anonymous
-Ay::'d
-END AUTH REQUEST
-Root ${CVSROOT_DIRNAME}
-version
-EOF
-
- dotest pserver-28 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU
-M Concurrent Versions System (CVS) .*
-ok" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-testme
-Ay::'d
-END AUTH REQUEST
-Root ${CVSROOT_DIRNAME}
-version
-EOF
-
- dotest pserver-30 "${testcvs} --allow-root=${CVSROOT_DIRNAME} pserver" \
-"${DOTSTAR} LOVE YOU
-M Concurrent Versions System (CVS) .*
-ok" <<EOF
-BEGIN AUTH REQUEST
-${CVSROOT_DIRNAME}
-${username}
-Ay::'d
-END AUTH REQUEST
-Root ${CVSROOT_DIRNAME}
-version
-EOF
-
- # pserver used to try and print from the NULL pointer
- # in this error message in this case
- dotest_fail pserver-bufinit "${testcvs} pserver" \
-"${PROG} \[pserver aborted\]: bad auth protocol start: EOF" </dev/null
-
- # Clean up.
- echo "# comments only" >config
- dotest pserver-cleanup-1 "${testcvs} -q ci -m config-it" \
-"Checking in config;
-${CVSROOT_DIRNAME}/CVSROOT/config,v <-- config
-new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
-done
-${PROG} commit: Rebuilding administrative file database"
- cd ../..
- rm -r 1
- rm ${CVSROOT_DIRNAME}/CVSROOT/passwd ${CVSROOT_DIRNAME}/CVSROOT/writers
- fi # skip the whole thing for local
- ;;
-
- server)
- # Some tests of the server (independent of the client).
- if $remote; then
- dotest server-1 "${testcvs} server" \
-"E Protocol error: Root request missing
-error " <<EOF
-Directory bogus
-mumble/bar
-update
-EOF
-
- # Could also test for relative pathnames here (so that crerepos-6a
- # and crerepos-6b can use :fork:).
- dotest server-2 "$testcvs server" \
-"E init may not be run remotely
-error " <<EOF
-Set OTHER=variable
-Set MYENV=env-value
-init ${TESTDIR}/crerepos
-EOF
- dotest_fail server-3 "test -d $TESTDIR/crerepos/CVSROOT"
-
- dotest server-3a "$testcvs -d$TESTDIR/crerepos init"
-
- # 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
- dotest server-4 "${testcvs} server" \
-"M N dir1/file1
-M
-M No conflicts created by this import
-M
-ok" <session.dat
- dotest server-5 \
-"${testcvs} -q -d ${TESTDIR}/crerepos co -p dir1/file1" "test"
-
- # OK, here are some notify tests.
- dotest server-6 "${testcvs} server" \
-"Notified \./
-${TESTDIR}/crerepos/dir1/file1
-ok" <<EOF
-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
- # Sending the second "noop" before waiting for the output
- # from the first is bogus but hopefully we can get away
- # with it.
- dotest server-7 "${testcvs} server" \
-"Notified \./
-${TESTDIR}/crerepos/dir1/file1
-ok
-Notified \./
-${TESTDIR}/crerepos/dir1/file1
-ok" <<EOF
-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
-
- # OK, now test a few error conditions.
- # FIXCVS: should give "error" and no "Notified", like server-9
- dotest server-8 "${testcvs} server" \
-"E ${PROG} server: invalid character in editor value
-Notified \./
-${TESTDIR}/crerepos/dir1/file1
-ok" <<EOF
-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
-
- dotest server-9 "${testcvs} server" \
-"E Protocol error; misformed Notify request
-error " <<EOF
-Root ${TESTDIR}/crerepos
-Directory .
-${TESTDIR}/crerepos/dir1
-Notify file1
-E Setting Orange+57th day of Discord myhost some-work-dir EUC
-noop
-EOF
-
- # 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...
- dotest server-10 "${testcvs} server" "ok" <<EOF
-Root ${TESTDIR}/crerepos
-Directory .
-${TESTDIR}/crerepos/dir1
-watchers
-EOF
- # See if "watchers" and "editors" display the right thing.
- dotest server-11 "${testcvs} server" \
-"M file1 ${username} tedit tunedit tcommit
-ok" <<EOF
-Root ${TESTDIR}/crerepos
-Directory .
-${TESTDIR}/crerepos/dir1
-Entry /file1/1.1////
-watchers
-EOF
- dotest server-12 "${testcvs} server" \
-"M file1 ${username} The 57th day of Discord in the YOLD 3165 myhost some-work-dir
-ok" <<EOF
-Root ${TESTDIR}/crerepos
-Directory .
-${TESTDIR}/crerepos/dir1
-Entry /file1/1.1////
-editors
-EOF
-
- # Now do an unedit.
- dotest server-13 "${testcvs} server" \
-"Notified \./
-${TESTDIR}/crerepos/dir1/file1
-ok" <<EOF
-Root ${TESTDIR}/crerepos
-Directory .
-${TESTDIR}/crerepos/dir1
-Notify file1
-U 7 May 1999 15:00 GMT myhost some-work-dir EUC
-noop
-EOF
-
- # Now try "watchers" and "editors" again.
- dotest server-14 "${testcvs} server" "ok" <<EOF
-Root ${TESTDIR}/crerepos
-Directory .
-${TESTDIR}/crerepos/dir1
-watchers
-EOF
- dotest server-15 "${testcvs} server" "ok" <<EOF
-Root ${TESTDIR}/crerepos
-Directory .
-${TESTDIR}/crerepos/dir1
-editors
-EOF
-
- # Test that the global `-l' option is ignored nonfatally.
- dotest server-16 "${testcvs} server" \
-"E cvs server: WARNING: global \`-l' option ignored\.
-ok" <<EOF
-Global_option -l
-noop
-EOF
-
- # There used to be some exploits based on malformed Entry requests
- dotest server-17 "$testcvs server" \
-"E protocol error: Malformed Entry
-error " <<EOF
-Root $TESTDIR/crerepos
-Directory .
-$TESTDIR/crerepos/dir1
-Entry X/file1/1.1////
-noop
-EOF
-
- dotest server-18 "$testcvs server" \
-"E protocol error: Malformed Entry
-error " <<EOF
-Root $TESTDIR/crerepos
-Directory .
-$TESTDIR/crerepos/dir1
-Entry /CC/CC/CC
-noop
-EOF
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- rm -rf ${TESTDIR}/crerepos
- rm gzipped.dat session.dat
- fi # skip the whole thing for local
- ;;
-
- server2)
- # More server tests, in particular testing that various
- # possible security holes are plugged.
- if $remote; then
- dotest server2-1 "${testcvs} server" \
-"E protocol error: directory '${CVSROOT_DIRNAME}/\.\./dir1' not within root '${CVSROOT_DIRNAME}'
-error " <<EOF
-Root ${CVSROOT_DIRNAME}
-Directory .
-${CVSROOT_DIRNAME}/../dir1
-noop
-EOF
-
- dotest server2-2 "${testcvs} server" \
-"E protocol error: directory '${CVSROOT_DIRNAME}dir1' not within root '${CVSROOT_DIRNAME}'
-error " <<EOF
-Root ${CVSROOT_DIRNAME}
-Directory .
-${CVSROOT_DIRNAME}dir1
-noop
-EOF
-
- dotest server2-3 "${testcvs} server" \
-"E protocol error: directory '${TESTDIR}' not within root '${CVSROOT_DIRNAME}'
-error " <<EOF
-Root ${CVSROOT_DIRNAME}
-Directory .
-${TESTDIR}
-noop
-EOF
-
- # 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.
- dotest server2-4 "${testcvs} server" \
-"E protocol error: directory 'foo/bar' not within current directory
-error " <<EOF
-Root ${CVSROOT_DIRNAME}
-Directory .
-${CVSROOT_DIRNAME}
-Unchanged foo/bar
-noop
-EOF
- dotest server2-5 \
-"$testcvs --allow-root=$CVSROOT_DIRNAME.bad server" \
-"E Bad root $CVSROOT_DIRNAME
-error " <<EOF
-Root $CVSROOT_DIRNAME
-noop
-EOF
- dotest server2-6 \
-"$testcvs --allow-root=$CVSROOT_DIRNAME server" \
-"ok" <<EOF
-Root $CVSROOT_DIRNAME
-noop
-EOF
- fi
- ;;
-
-
-
- server3)
- # Test that various checks on the Root request generate the correct
- # error messages.
- if $remote; then
- # As a control, a valid request.
- dotest server3-1 "$testcvs server" 'ok' <<EOF
-Root $CVSROOT_DIRNAME
-Directory .
-$CVSROOT_DIRNAME
-Unchanged foo
-noop
-EOF
-
- dotest server3-2 "$testcvs server" \
-"E Root somewhere/over/the/rainbow must be an absolute pathname
-error " <<EOF
-Root somewhere/over/the/rainbow
-noop
-EOF
-
- dotest server3-3 "$testcvs server" \
-"E Protocol error: Duplicate Root request, for $CVSROOT_DIRNAME
-error " <<EOF
-Root $CVSROOT_DIRNAME
-Root $CVSROOT_DIRNAME
-noop
-EOF
-
- dotest server3-4 "$testcvs server" \
-"E Protocol error: Duplicate Root request, for $CVSROOT_DIRNAME
-error " <<EOF
-Root $CVSROOT_DIRNAME
-Root $CVSROOT_DIRNAME
-Directory .
-$CVSROOT_DIRNAME
-Unchanged foo
-noop
-EOF
-
- # These cascading errors seem odd, but the client should have hung
- # up after the first.
- dotest server3-5 "$testcvs server" \
-"E Root somewhere/over/the/rainbow must be an absolute pathname
-error
-E Protocol error: Root request missing
-error " <<EOF
-Root somewhere/over/the/rainbow
-Directory .
-somewhere/over/the/rainbow
-Unchanged foo
-noop
-EOF
- fi
- ;;
-
-
-
- client)
- # Some tests of the client (independent of the server).
- if $remote; 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 "${CVSROOT_DIRNAME}/first-dir/file1"
-echo "/file1/1.1///"
-echo "u=rw,g=rw,o=rw"
-echo "4"
-echo "xyz"
-echo "ok"
-cat >/dev/null
-EOF
- # Cygwin. Pthffffffffft!
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost "chmod +x ${TESTDIR}/serveme"
- else
- chmod +x ${TESTDIR}/serveme
- fi
- save_CVS_SERVER=$CVS_SERVER
- 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${DOTSTAR}"
- 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 "${CVSROOT_DIRNAME}/first-dir/file1"
-echo "${TESTDIR}/bogus/.#file1.1.1"
-echo "Merged ./"
-echo "${CVSROOT_DIRNAME}/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
- # The ${DOTSTAR} is to match a potential "broken pipe" if the
- # client exits before the server script sends everything
- dotest_fail client-3 "${testcvs} update" "merge-it
-${PROG} \[update aborted\]: protocol error: Copy-file tried to specify director${DOTSTAR}"
- 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 "${CVSROOT_DIRNAME}/first-dir/file1"
-echo ".#file1.1.1"
-echo "Merged ./"
-echo "${CVSROOT_DIRNAME}/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"
- # String 2 below is Cygwin again - ptoooey.
- dotest client-9 "cat ${TESTDIR}/client.tmp" \
-"Root ${CVSROOT_DIRNAME}
-Valid-responses [-a-zA-Z ]*
-valid-requests
-Argument -D
-Argument [34] Oct 1999 [0-9][0-9]:00:00 -0000
-Argument --
-Directory \.
-${CVSROOT_DIRNAME}/first-dir
-Entry /file1/1\.2///
-Modified file1
-u=rw,g=,o=
-4
-abc
-update" \
-"Root ${CVSROOT_DIRNAME}
-Valid-responses [-a-zA-Z ]*
-valid-requests
-Argument -D
-Argument [34] Oct 1999 [0-9][0-9]:00:00 -0000
-Argument --
-Directory \.
-${CVSROOT_DIRNAME}/first-dir
-Entry /file1/1\.2///
-Modified file1
-u=rw,g=r,o=r
-4
-abc
-update"
-
- # The following test tests what was a potential client update in
- # CVS versions 1.11.14 and CVS versions 1.12.6 and earlier. This
- # exploit would allow a trojan server to create arbitrary files,
- # anywhere the user had write permissions, even outside of the
- # user's sandbox.
- cat >$HOME/.bashrc <<EOF
-#!$TESTSHELL
-# This is where login scripts would usually be
-# stored.
-EOF
- 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 "Rcs-diff $HOME/"
-echo "$HOME/.bashrc"
-echo "/.bashrc/73.50///"
-echo "u=rw,g=rw,o=rw"
-echo "20"
-echo "a1 1"
-echo "echo 'gotcha!'"
-echo "ok"
-cat >/dev/null
-EOF
-
- # If I don't run the following sleep between the above cat and
- # the following calls to dotest, sometimes the serveme file isn't
- # completely written yet by the time CVS tries to execute it,
- # causing the shell to intermittantly report syntax errors (usually
- # early EOF). There's probably a new race condition here, but this
- # works.
- #
- # Incidentally, I can reproduce this behavior with Linux 2.4.20 and
- # Bash 2.05 or Bash 2.05b.
- sleep 1
- dotest_fail client-10 "$testcvs update" \
-"$PROG update: Server attempted to update a file via an invalid pathname:
-$PROG \[update aborted\]: \`$HOME/.bashrc'\."
-
- # A second try at a client exploit. This one never actually
- # failed in the past, but I thought it wouldn't hurt to add a test.
- 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 "Rcs-diff ./"
-echo "$HOME/.bashrc"
-echo "/.bashrc/73.50///"
-echo "u=rw,g=rw,o=rw"
-echo "20"
-echo "a1 1"
-echo "echo 'gotcha!'"
-echo "ok"
-cat >/dev/null
-EOF
- sleep 1
- dotest_fail client-11 "$testcvs update" \
-"$PROG \[update aborted\]: patch original file \./\.bashrc does not exist"
-
- # A third try at a client exploit. This one did used to fail like
- # client-10.
- 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 "Rcs-diff ../../home/"
-echo "../../.bashrc"
-echo "/.bashrc/73.50///"
-echo "u=rw,g=rw,o=rw"
-echo "20"
-echo "a1 1"
-echo "echo 'gotcha!'"
-echo "ok"
-cat >/dev/null
-EOF
- sleep 1
- dotest_fail client-12 "$testcvs update" \
-"$PROG update: Server attempted to update a file via an invalid pathname:
-$PROG \[update aborted\]: \`\.\./\.\./home/.bashrc'\."
-
- # Try the same exploit using the Created response.
- 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 "Created $HOME/"
-echo "$HOME/.bashrc"
-echo "/.bashrc/73.50///"
-echo "u=rw,g=rw,o=rw"
-echo "26"
-echo "#! /bin/sh"
-echo "echo 'gotcha!'"
-echo "ok"
-cat >/dev/null
-EOF
- sleep 1
- dotest_fail client-13 "$testcvs update" \
-"$PROG update: Server attempted to update a file via an invalid pathname:
-$PROG \[update aborted\]: \`$HOME/.bashrc'\."
-
- # Now try using the Update-existing response
- 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 "Update-existing ../../home/"
-echo "../../home/.bashrc"
-echo "/.bashrc/73.50///"
-echo "u=rw,g=rw,o=rw"
-echo "26"
-echo "#! /bin/sh"
-echo "echo 'gotcha!'"
-echo "ok"
-cat >/dev/null
-EOF
- sleep 1
- dotest_fail client-14 "$testcvs update" \
-"$PROG update: Server attempted to update a file via an invalid pathname:
-$PROG \[update aborted\]: \`\.\./\.\./home/.bashrc'\."
-
- # Try the same exploit using the Merged response.
- 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 "Merged $HOME/"
-echo "$HOME/.bashrc"
-echo "/.bashrc/73.50///"
-echo "u=rw,g=rw,o=rw"
-echo "26"
-echo "#! /bin/sh"
-echo "echo 'gotcha!'"
-echo "ok"
-cat >/dev/null
-EOF
- sleep 1
- dotest_fail client-15 "$testcvs update" \
-"$PROG update: Server attempted to update a file via an invalid pathname:
-$PROG \[update aborted\]: \`$HOME/.bashrc'\."
-
- # Now try using the Updated response
- 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 "Updated ../../home/"
-echo "../../home/.bashrc"
-echo "/.bashrc/73.50///"
-echo "u=rw,g=rw,o=rw"
-echo "26"
-echo "#! /bin/sh"
-echo "echo 'gotcha!'"
-echo "ok"
-cat >/dev/null
-EOF
- sleep 1
- dotest_fail client-16 "$testcvs update" \
-"$PROG update: Server attempted to update a file via an invalid pathname:
-$PROG \[update aborted\]: \`\.\./\.\./home/.bashrc'\."
-
- # Try the same exploit using the Copy-file response.
- # As far as I know, Copy-file was never exploitable either.
- 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 "Created ."
-echo "./innocuous"
-echo "/innocuous/73.50///"
-echo "u=rw,g=rw,o=rw"
-echo "26"
-echo "#! /bin/sh"
-echo "echo 'gotcha!'"
-echo "Copy-file ."
-echo "./innocuous"
-echo "$HOME/innocuous"
-echo "ok"
-cat >/dev/null
-EOF
- sleep 1
- dotest_fail client-18 "$testcvs update" \
-"$PROG \[update aborted\]: protocol error: Copy-file tried to specify directory"
-
- # And verify that none of the exploits was successful.
- dotest client-19 "cat $HOME/.bashrc" \
-"#!$TESTSHELL
-# This is where login scripts would usually be
-# stored\."
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
-
- cd ../..
- rm -r 1
- rmdir ${TESTDIR}/bogus
- rm $TESTDIR/serveme $HOME/.bashrc
- CVS_SERVER=${save_CVS_SERVER}; export CVS_SERVER
- fi # skip the whole thing for local
- ;;
-
-
-
- client2)
- # Test how the client handles error messages from the server.
- if $remote; then
- cat >$TESTDIR/serveme <<EOF
-#!$TESTSHELL
-# This is just as cheesy as the "client" tests made it out to be.
-echo "Valid-requests Root Valid-responses valid-requests Directory Entry Modified Unchanged Argument Argumentx ci co update"
-echo "E Root somewhere/over/the/rainbow must be an absolute pathname"
-echo "error "
-echo "E Protocol error: Root request missing"
-echo "error "
-cat >/dev/null
-EOF
- # Cygwin. Pthffffffffft!
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost "chmod +x $TESTDIR/serveme"
- else
- chmod +x $TESTDIR/serveme
- fi
- save_CVS_SERVER=$CVS_SERVER
- CVS_SERVER=$TESTDIR/serveme; export CVS_SERVER
- mkdir client2; cd client2
- dotest_fail client2-1 "$testcvs co first-dir" \
-"Root somewhere/over/the/rainbow must be an absolute pathname"
-
- cat >$TESTDIR/serveme <<EOF
-#!$TESTSHELL
-# This is just as cheesy as the "client" tests made it out to be.
-echo "Valid-requests Root Valid-responses valid-requests Directory Entry Modified Unchanged Argument Argumentx ci co update"
-echo "E Root somewhere/over/the/rainbow must be an absolute pathname"
-echo
-echo "error "
-echo "E Protocol error: Root request missing"
-echo "error "
-cat >/dev/null
-EOF
- # Cygwin. Pthffffffffft!
- if test -n "$remotehost"; then
- $CVS_RSH $remotehost "chmod +x $TESTDIR/serveme"
- else
- chmod +x $TESTDIR/serveme
- fi
- dotest_fail client2-2 "$testcvs co first-dir" \
-"Root somewhere/over/the/rainbow must be an absolute pathname
-$PROG checkout: warning: unrecognized response \`' from cvs server"
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- cd ..
- rm -r client2
- rm $TESTDIR/serveme
- CVS_SERVER=$save_CVS_SERVER; export CVS_SERVER
- fi # skip the whole thing for local
- ;;
-
-
-
- dottedroot)
- # Check that a CVSROOT with a "." in the name will work.
- CVSROOT_save=${CVSROOT}
- CVSROOT_DIRNAME_save=${CVSROOT_DIRNAME}
- CVSROOT_DIRNAME=${TESTDIR}/cvs.root
- CVSROOT=`newroot ${CVSROOT_DIRNAME}`
-
- dotest dottedroot-init-1 "$testcvs -d$CVSROOT_DIRNAME init"
- mkdir dir1
- mkdir dir1/dir2
- echo version1 >dir1/dir2/file1
- cd dir1
- dotest dottedroot-1 "${testcvs} import -m '' module1 AUTHOR INITIAL" \
-"${PROG} [a-z]*: Importing ${CVSROOT_DIRNAME}/module1/dir2
-N module1/dir2/file1
-
-No conflicts created by this import"
- cd ..
-
- # This is the test that used to cause an assertion failure
- # in recurse.c:do_recursion().
- dotest dottedroot-2 "${testcvs} co -rINITIAL module1" \
-"${PROG} [a-z]*: Updating module1
-${PROG} [a-z]*: Updating module1/dir2
-U module1/dir2/file1"
-
- # This also triggered the assertion failure above prior to 1.11.23.
- dotest dottedroot-3 \
-"$testcvs -q co -prINITIAL module1/./dir2/file1" \
-'version1'
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
-
- rm -rf ${CVSROOT_DIRNAME}
- rm -r dir1 module1
- CVSROOT_DIRNAME=${CVSROOT_DIRNAME_save}
- CVSROOT=${CVSROOT_save}
- ;;
-
- fork)
- # Test that the server defaults to the correct executable in :fork:
- # mode. See the note in the TODO at the end of this file about this.
- #
- # This test and client should be left after all other references to
- # CVS_SERVER are removed from this script.
- #
- # The client series of tests already tests that CVS_SERVER is
- # working, but that test might be better here.
- if $remote; then
- mkdir fork; cd fork
- save_CVS_SERVER=$CVS_SERVER
- unset CVS_SERVER
- # So looking through $PATH for cvs won't work...
- echo "echo junk" >cvs
- chmod a+x cvs
- save_PATH=$PATH; PATH=.:$PATH
- dotest fork-1 "$testcvs -d:fork:$CVSROOT_DIRNAME version" \
-'Client: \(.*\)
-Server: \1'
- CVS_SERVER=${save_CVS_SERVER}; export CVS_SERVER
- unset save_CVS_SERVER
- PATH=$save_PATH; unset save_PATH
- cd ..
-
- if $keep; then
- echo Keeping ${TESTDIR} and exiting due to --keep
- exit 0
- fi
- fi
- ;;
-
- commit-add-missing)
- # Make sure that a commit fails when a `cvs add'ed file has
- # been removed from the working directory.
-
- mkdir 1; cd 1
- module=c-a-m
- echo > unused-file
- dotest commit-add-missing-1 \
- "$testcvs -Q import -m. $module X Y" ''
-
- file=F
- # Check it out and tag it.
- dotest commit-add-missing-2 "$testcvs -Q co $module" ''
- cd $module
- dotest commit-add-missing-3 "$testcvs -Q tag -b B" ''
- echo v1 > $file
- dotest commit-add-missing-4 "$testcvs -Q add $file" ''
- rm -f $file
- dotest_fail commit-add-missing-5 "$testcvs -Q ci -m. $file" \
-"${PROG} commit: Up-to-date check failed for .$file'
-${PROG} \[commit aborted\]: correct above errors first!"
-
- cd ../..
- rm -rf 1
- rm -rf ${CVSROOT_DIRNAME}/$module
- ;;
-
- add-restricted)
- # Verify that `sdir/CVS' may not be explicitly added.
- mkdir add-restricted; cd add-restricted
-
- mkdir import; cd import
- : > junk
- dotest add-restricted-init-1 \
-"$testcvs -Q import -m. add-restricted X Y"
- cd ..
-
- dotest add-restricted-init-2 "$testcvs -Q co add-restricted"
- cd add-restricted
-
- # errmsg2-3 tests the specific message here.
- dotest_fail add-restricted-1 "$testcvs -Q add CVS"
-
- mkdir sdir
- dotest add-restricted-2 "$testcvs -Q add sdir"
- dotest_fail add-restricted-3 "$testcvs add sdir/CVS" \
-"$PROG add: cannot add special file \`sdir/CVS'; skipping"
-
- if $keep; then
- echo Keeping $TESTDIR and exiting due to --keep
- exit 0
- fi
- cd ../..
- rm -rf add-restricted $CVSROOT_DIRNAME/add-restricted
- ;;
-
-
-
- commit-d)
- # Check that top-level commits work when CVS/Root
- # is overridden by cvs -d.
-
- mkdir -p 1/subdir; cd 1
- touch file1 subdir/file2
- dotest commit-d-1 "$testcvs -Q import -m. c-d-c X Y" ""
- dotest commit-d-2 "$testcvs -Q co c-d-c" ""
- cd c-d-c
- echo change >>file1; echo another change >>subdir/file2
- # Changing working root, then override with -d
- echo nosuchhost:/cvs > CVS/Root
- dotest commit-d-3 "$testcvs -Q -d $CVSROOT commit -m." \
-"Checking in file1;
-${CVSROOT_DIRNAME}/c-d-c/file1,v <-- file1
-new revision: 1.2; previous revision: 1.1
-done
-Checking in subdir/file2;
-${CVSROOT_DIRNAME}/c-d-c/subdir/file2,v <-- file2
-new revision: 1.2; previous revision: 1.1
-done"
- cd ../..
- rm -rf 1 cvsroot/c-d-c
- ;;
-
- *)
- echo $what is not the name of a test -- ignored
- ;;
- esac
-
- # Sanity check sanity.sh. :)
- #
- # Test our exit directory so that tests that exit in an incorrect directory
- # are noticed during single test runs.
- #
- # FIXME?
- # Sparc Solaris 9 is dereferencing paths here as if /bin/pwd were
- # called when /tmp is a symlink. This might be a new problem with this
- # test, but since this was recently tested I think it more likely to be
- # A Solaris issue.
- if test "x$TESTDIR" != "x`pwd`"; then
- fail "cleanup: PWD != TESTDIR (\``pwd`' != \`$TESTDIR')"
- fi
-
- # Reset val-tags to a pristine state.
- rm -f $CVSROOT_DIRNAME/CVSROOT/val-tags
-
- verify_tmp_empty "post $what"
-
-done # The big loop
-
-# Set up summary data for output.
-skippedoutput=
-warningsoutput=
-extendedinfo=
-if test $skipped -ne 0; then
- skippedoutput="$skipped test group"
- if test $skipped -ne 1; then
- skippedoutput="${skippedoutput}s"
- fi
- skippedoutput="$skippedoutput skipped"
-fi
-if test $warnings -ne 0; then
- warningsoutput="$warnings test"
- if test $warnings -ne 1; then
- warningsoutput="${warningsoutput}s"
- fi
- warningsoutput="$warningsoutput passed with warnings"
-fi
-if test -n "$skippedoutput" || test -n "$warningsoutput"; then
- extendedinfo=" ("
- if test -n "$skippedoutput"; then
- extendedinfo="$extendedinfo$skippedoutput"
- fi
- if test -n "$skippedoutput" && test -n "$warningsoutput"; then
- extendedinfo="$extendedinfo and "
- fi
- if test -n "$warningsoutput"; then
- extendedinfo="$extendedinfo$warningsoutput"
- fi
- extendedinfo="$extendedinfo)"
-fi
-
-echo "OK, all $passed tests passed$extendedinfo."
-
-# TODO:
-# * Test `cvs update -d foo' (where foo does not exist).
-# * Test `cvs update foo bar' (where foo and bar are both from the
-# same directory in the repository). Suppose one is a branch--make
-# sure that both directories get updated with the respective correct
-# thing.
-# * `cvs update ../foo'. Also ../../foo ./../foo foo/../../bar /foo/bar
-# foo/.././../bar foo/../bar etc.
-# * Test all flags in modules file.
-# Test that ciprog gets run both on checkin in that directory, or a
-# higher-level checkin which recurses into it.
-# * Test operations on a directory that contains other directories but has
-# no files of its own.
-# * -t global option
-# * cvs rm followed by cvs add or vice versa (with no checkin in between).
-# * cvs rm twice (should be a nice error message).
-# * -P option to checkout--(a) refrains from checking out new empty dirs,
-# (b) prunes empty dirs already there.
-# * Test that cvs -d `hostname`:${TESTDIR}/non/existent co foo
-# gives an appropriate error (e.g.
-# Cannot access ${TESTDIR}/non-existent/CVSROOT
-# No such file or directory).
-# (like basica-9, but for remote).
-# * 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 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).
-# - Test 'cvs history' with symlinks in the path to the working directory.
-# - Remove most of the CVS_SERVER stuff after a reasonable amount of time.
-# The "fork" & "client" series of tests should be left. 4/2/00, CVS
-# 1.11.0.1 was altered so that it would default to program_name (set from
-# argv[0]) rather than "cvs", but I'd like this script to work on legacy
-# versions of CVS for awhile.
-# - Testsuite doesn't work with usernames over eight characters in length.
-# Fix it.
-# End of TODO list.
-
-# Exit if keep set
-if $keep; then
- echo "Keeping ${TESTDIR} and exiting due to -k (keep) option."
- exit 0
-fi
-
-# Remove the test directory, but first change out of it.
-cd `dirname ${TESTDIR}`
-rm -rf ${TESTDIR}
-
-# end of sanity.sh
diff --git a/contrib/cvs/src/scramble.c b/contrib/cvs/src/scramble.c
deleted file mode 100644
index 487cbf4c91e7..000000000000
--- a/contrib/cvs/src/scramble.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Trivially encode strings to protect them from innocent eyes (i.e.,
- * inadvertent password compromises, like a network administrator
- * who's watching packets for legitimate reasons and accidentally sees
- * the password protocol go by).
- *
- * This is NOT secure encryption.
- *
- * It would be tempting to encode the password according to username
- * and repository, so that the same password would encode to a
- * different string when used with different usernames and/or
- * repositories. However, then users would not be able to cut and
- * paste passwords around. They're not supposed to anyway, but we all
- * know they will, and there's no reason to make it harder for them if
- * we're not trying to provide real security anyway.
- */
-
-/* Set this to test as a standalone program. */
-/* #define DIAGNOSTIC */
-
-#ifndef DIAGNOSTIC
-#include "cvs.h"
-#else /* ! DIAGNOSTIC */
-/* cvs.h won't define this for us */
-#define AUTH_CLIENT_SUPPORT
-#define xmalloc malloc
-/* Use "gcc -fwritable-strings". */
-#include <stdio.h>
-#include <stdio.h>
-#include <string.h>
-#endif /* ! DIAGNOSTIC */
-
-#if defined(AUTH_CLIENT_SUPPORT) || defined(AUTH_SERVER_SUPPORT)
-
-/* Map characters to each other randomly and symmetrically, A <--> B.
- *
- * We divide the ASCII character set into 3 domains: control chars (0
- * thru 31), printing chars (32 through 126), and "meta"-chars (127
- * through 255). The control chars map _to_ themselves, the printing
- * chars map _among_ themselves, and the meta chars map _among_
- * themselves. Why is this thus?
- *
- * No character in any of these domains maps to a character in another
- * domain, because I'm not sure what characters are legal in
- * passwords, or what tools people are likely to use to cut and paste
- * them. It seems prudent not to introduce control or meta chars,
- * unless the user introduced them first. And having the control
- * chars all map to themselves insures that newline and
- * carriage-return are safely handled.
- */
-
-static unsigned char
-shifts[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 114,120, 53, 79, 96,109, 72,108, 70, 64, 76, 67,116, 74, 68, 87,
- 111, 52, 75,119, 49, 34, 82, 81, 95, 65,112, 86,118,110,122,105,
- 41, 57, 83, 43, 46,102, 40, 89, 38,103, 45, 50, 42,123, 91, 35,
- 125, 55, 54, 66,124,126, 59, 47, 92, 71,115, 78, 88,107,106, 56,
- 36,121,117,104,101,100, 69, 73, 99, 63, 94, 93, 39, 37, 61, 48,
- 58,113, 32, 90, 44, 98, 60, 51, 33, 97, 62, 77, 84, 80, 85,223,
- 225,216,187,166,229,189,222,188,141,249,148,200,184,136,248,190,
- 199,170,181,204,138,232,218,183,255,234,220,247,213,203,226,193,
- 174,172,228,252,217,201,131,230,197,211,145,238,161,179,160,212,
- 207,221,254,173,202,146,224,151,140,196,205,130,135,133,143,246,
- 192,159,244,239,185,168,215,144,139,165,180,157,147,186,214,176,
- 227,231,219,169,175,156,206,198,129,164,150,210,154,177,134,127,
- 182,128,158,208,162,132,167,209,149,241,153,251,237,236,171,195,
- 243,233,253,240,194,250,191,155,142,137,245,235,163,242,178,152 };
-
-
-/* SCRAMBLE and DESCRAMBLE work like this:
- *
- * scramble(STR) returns SCRM, a scrambled copy of STR. SCRM[0] is a
- * single letter indicating the scrambling method. As of this
- * writing, the only legal method is 'A', but check the code for more
- * up-to-date information. The copy will have been allocated with
- * xmalloc().
- *
- * descramble(SCRM) returns STR, again in its own xmalloc'd space.
- * descramble() uses SCRM[0] to determine which method of unscrambling
- * to use. If it does not recognize the method, it dies with error.
- */
-
-/* Return a xmalloc'd, scrambled version of STR. */
-char *
-scramble (str)
- char *str;
-{
- int i;
- char *s;
-
- /* +2 to hold the 'A' prefix that indicates which version of
- scrambling this is (the first, obviously, since we only do one
- kind of scrambling so far), and then the '\0' of course. */
- s = (char *) xmalloc (strlen (str) + 2);
-
- /* Scramble (TM) version prefix. */
- s[0] = 'A';
- strcpy (s + 1, str);
-
- for (i = 1; s[i]; i++)
- s[i] = shifts[(unsigned char)(s[i])];
-
- return s;
-}
-
-/* Decode the string in place. */
-char *
-descramble (str)
- char *str;
-{
- char *s;
- int i;
-
- /* For now we can only handle one kind of scrambling. In the future
- there may be other kinds, and this `if' will become a `switch'. */
- if (str[0] != 'A')
-#ifndef DIAGNOSTIC
- error (1, 0, "descramble: unknown scrambling method");
-#else /* DIAGNOSTIC */
- {
- fprintf (stderr, "descramble: unknown scrambling method\n", str);
- fflush (stderr);
- exit (EXIT_FAILURE);
- }
-#endif /* DIAGNOSTIC */
-
- /* Method `A' is symmetrical, so scramble again to decrypt. */
- s = scramble (str + 1);
-
- /* Shift the whole string one char to the left, pushing the unwanted
- 'A' off the left end. Safe, because s is null-terminated. */
- for (i = 0; s[i]; i++)
- s[i] = s[i + 1];
-
- return s;
-}
-
-#endif /* (AUTH_CLIENT_SUPPORT || AUTH_SERVER_SUPPORT) from top of file */
-
-#ifdef DIAGNOSTIC
-int
-main ()
-{
- int i;
- char *e, *m, biggie[256];
-
- char *cleartexts[5];
- cleartexts[0] = "first";
- cleartexts[1] = "the second";
- cleartexts[2] = "this is the third";
- cleartexts[3] = "$#% !!\\3";
- cleartexts[4] = biggie;
-
- /* Set up the most important test string: */
- /* Can't have a real ASCII zero in the string, because we want to
- use printf, so we substitute the character zero. */
- biggie[0] = '0';
- /* The rest of the string gets straight ascending ASCII. */
- for (i = 1; i < 256; i++)
- biggie[i] = i;
-
- /* Test all the strings. */
- for (i = 0; i < 5; i++)
- {
- printf ("clear%d: %s\n", i, cleartexts[i]);
- e = scramble (cleartexts[i]);
- printf ("scram%d: %s\n", i, e);
- m = descramble (e);
- free (e);
- printf ("clear%d: %s\n\n", i, m);
- free (m);
- }
-
- fflush (stdout);
- return 0;
-}
-#endif /* DIAGNOSTIC */
-
-/*
- * ;;; The Emacs Lisp that did the dirty work ;;;
- * (progn
- *
- * ;; Helper func.
- * (defun random-elt (lst)
- * (let* ((len (length lst))
- * (rnd (random len)))
- * (nth rnd lst)))
- *
- * ;; A list of all characters under 127, each appearing once.
- * (setq non-meta-chars
- * (let ((i 0)
- * (l nil))
- * (while (< i 127)
- * (setq l (cons i l)
- * i (1+ i)))
- * l))
- *
- * ;; A list of all characters 127 and above, each appearing once.
- * (setq meta-chars
- * (let ((i 127)
- * (l nil))
- * (while (< i 256)
- * (setq l (cons i l)
- * i (1+ i)))
- * l))
- *
- * ;; A vector that will hold the chars in a random order.
- * (setq scrambled-chars (make-vector 256 0))
- *
- * ;; These characters should map to themselves.
- * (let ((i 0))
- * (while (< i 32)
- * (aset scrambled-chars i i)
- * (setq non-meta-chars (delete i non-meta-chars)
- * i (1+ i))))
- *
- * ;; Assign random (but unique) values, within the non-meta chars.
- * (let ((i 32))
- * (while (< i 127)
- * (let ((ch (random-elt non-meta-chars)))
- * (if (= 0 (aref scrambled-chars i))
- * (progn
- * (aset scrambled-chars i ch)
- * (aset scrambled-chars ch i)
- * (setq non-meta-chars (delete ch non-meta-chars)
- * non-meta-chars (delete i non-meta-chars))))
- * (setq i (1+ i)))))
- *
- * ;; Assign random (but unique) values, within the non-meta chars.
- * (let ((i 127))
- * (while (< i 256)
- * (let ((ch (random-elt meta-chars)))
- * (if (= 0 (aref scrambled-chars i))
- * (progn
- * (aset scrambled-chars i ch)
- * (aset scrambled-chars ch i)
- * (setq meta-chars (delete ch meta-chars)
- * meta-chars (delete i meta-chars))))
- * (setq i (1+ i)))))
- *
- * ;; Now use the `scrambled-chars' vector to get your C array.
- * )
- */
diff --git a/contrib/cvs/src/server.c b/contrib/cvs/src/server.c
deleted file mode 100644
index cace89d50437..000000000000
--- a/contrib/cvs/src/server.c
+++ /dev/null
@@ -1,6760 +0,0 @@
-/* This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-/*
- * $FreeBSD$
- */
-
-#include <assert.h>
-#include "cvs.h"
-#include "watch.h"
-#include "edit.h"
-#include "fileattr.h"
-#include "getline.h"
-#include "buffer.h"
-
-int server_active = 0;
-
-#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
-# ifdef HAVE_GSSAPI
-/* This stuff isn't included solely with SERVER_SUPPORT since some of these
- * functions (encryption & the like) get compiled with or without server
- * support.
- *
- * FIXME - They should be in a different file.
- */
-# include <netdb.h>
-# include "xgssapi.h"
-/* We use Kerberos 5 routines to map the GSSAPI credential to a user
- name. */
-# include <krb5.h>
-
-/* We need this to wrap data. */
-static gss_ctx_id_t gcontext;
-
-static void gserver_authenticate_connection PROTO((void));
-
-/* Whether we are already wrapping GSSAPI communication. */
-static int cvs_gssapi_wrapping;
-
-# ifdef ENCRYPTION
-/* Whether to encrypt GSSAPI communication. We use a global variable
- like this because we use the same buffer type (gssapi_wrap) to
- handle both authentication and encryption, and we don't want
- multiple instances of that buffer in the communication stream. */
-int cvs_gssapi_encrypt;
-# endif
-# endif /* HAVE_GSSAPI */
-#endif /* defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT) */
-
-#ifdef SERVER_SUPPORT
-
-#ifdef HAVE_WINSOCK_H
-#include <winsock.h>
-#endif
-
-#if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI)
-#include <sys/socket.h>
-#endif
-
-#ifdef HAVE_SYSLOG_H
-# include <syslog.h>
-# ifndef LOG_DAEMON /* for ancient syslogs */
-# define LOG_DAEMON 0
-# endif
-#endif
-
-#ifdef HAVE_KERBEROS
-# include <netinet/in.h>
-# include <krb.h>
-# ifndef HAVE_KRB_GET_ERR_TEXT
-# define krb_get_err_text(status) krb_err_txt[status]
-# endif
-
-/* Information we need if we are going to use Kerberos encryption. */
-static C_Block kblock;
-static Key_schedule sched;
-
-#endif
-
-/* for select */
-#include "xselect.h"
-
-#ifndef O_NONBLOCK
-#define O_NONBLOCK O_NDELAY
-#endif
-
-/* EWOULDBLOCK is not defined by POSIX, but some BSD systems will
- return it, rather than EAGAIN, for nonblocking writes. */
-#ifdef EWOULDBLOCK
-#define blocking_error(err) ((err) == EWOULDBLOCK || (err) == EAGAIN)
-#else
-#define blocking_error(err) ((err) == EAGAIN)
-#endif
-
-/* For initgroups(). */
-#if HAVE_INITGROUPS
-#include <grp.h>
-#endif /* HAVE_INITGROUPS */
-
-# ifdef AUTH_SERVER_SUPPORT
-
-# ifdef HAVE_GETSPNAM
-# include <shadow.h>
-# endif
-
-/* The cvs username sent by the client, which might or might not be
- the same as the system username the server eventually switches to
- run as. CVS_Username gets set iff password authentication is
- successful. */
-char *CVS_Username = NULL;
-
-/* Used to check that same repos is transmitted in pserver auth and in
- later CVS protocol. Exported because root.c also uses. */
-static char *Pserver_Repos = NULL;
-
-/* Should we check for system usernames/passwords? Can be changed by
- CVSROOT/config. */
-int system_auth = 1;
-
-# endif /* AUTH_SERVER_SUPPORT */
-
-
-/* While processing requests, this buffer accumulates data to be sent to
- the client, and then once we are in do_cvs_command, we use it
- for all the data to be sent. */
-static struct buffer *buf_to_net;
-
-/* This buffer is used to read input from the client. */
-static struct buffer *buf_from_net;
-
-/*
- * This is where we stash stuff we are going to use. Format string
- * which expects a single directory within it, starting with a slash.
- */
-static char *server_temp_dir;
-
-/* This is the original value of server_temp_dir, before any possible
- changes inserted by serve_max_dotdot. */
-static char *orig_server_temp_dir;
-
-/* Nonzero if we should keep the temp directory around after we exit. */
-static int dont_delete_temp;
-
-static void server_write_entries PROTO((void));
-
-/* All server communication goes through buffer structures. Most of
- the buffers are built on top of a file descriptor. This structure
- is used as the closure field in a buffer. */
-
-struct fd_buffer
-{
- /* The file descriptor. */
- int fd;
- /* Nonzero if the file descriptor is in blocking mode. */
- int blocking;
-};
-
-static struct buffer *fd_buffer_initialize
- PROTO ((int, int, void (*) (struct buffer *)));
-static int fd_buffer_input PROTO((void *, char *, int, int, int *));
-static int fd_buffer_output PROTO((void *, const char *, int, int *));
-static int fd_buffer_flush PROTO((void *));
-static int fd_buffer_block PROTO((void *, int));
-static int fd_buffer_shutdown PROTO((struct buffer *));
-
-/* Initialize a buffer built on a file descriptor. FD is the file
- descriptor. INPUT is nonzero if this is for input, zero if this is
- for output. MEMORY is the function to call when a memory error
- occurs. */
-
-static struct buffer *
-fd_buffer_initialize (fd, input, memory)
- int fd;
- int input;
- void (*memory) PROTO((struct buffer *));
-{
- struct fd_buffer *n;
-
- n = (struct fd_buffer *) xmalloc (sizeof *n);
- n->fd = fd;
- n->blocking = 1;
- return buf_initialize (input ? fd_buffer_input : NULL,
- input ? NULL : fd_buffer_output,
- input ? NULL : fd_buffer_flush,
- fd_buffer_block,
- fd_buffer_shutdown,
- memory,
- n);
-}
-
-/* The buffer input function for a buffer built on a file descriptor. */
-
-static int
-fd_buffer_input (closure, data, need, size, got)
- void *closure;
- char *data;
- int need;
- int size;
- int *got;
-{
- struct fd_buffer *fd = (struct fd_buffer *) closure;
- int nbytes;
-
- if (! fd->blocking)
- nbytes = read (fd->fd, data, size);
- else
- {
- /* This case is not efficient. Fortunately, I don't think it
- ever actually happens. */
- nbytes = read (fd->fd, data, need == 0 ? 1 : need);
- }
-
- if (nbytes > 0)
- {
- *got = nbytes;
- return 0;
- }
-
- *got = 0;
-
- if (nbytes == 0)
- {
- /* End of file. This assumes that we are using POSIX or BSD
- style nonblocking I/O. On System V we will get a zero
- return if there is no data, even when not at EOF. */
- return -1;
- }
-
- /* Some error occurred. */
-
- if (blocking_error (errno))
- {
- /* Everything's fine, we just didn't get any data. */
- return 0;
- }
-
- return errno;
-}
-
-/* The buffer output function for a buffer built on a file descriptor. */
-
-static int
-fd_buffer_output (closure, data, have, wrote)
- void *closure;
- const char *data;
- int have;
- int *wrote;
-{
- struct fd_buffer *fd = (struct fd_buffer *) closure;
-
- *wrote = 0;
-
- while (have > 0)
- {
- int nbytes;
-
- nbytes = write (fd->fd, data, have);
-
- if (nbytes <= 0)
- {
- if (! fd->blocking
- && (nbytes == 0 || blocking_error (errno)))
- {
- /* A nonblocking write failed to write any data. Just
- return. */
- return 0;
- }
-
- /* Some sort of error occurred. */
-
- if (nbytes == 0)
- return EIO;
-
- return errno;
- }
-
- *wrote += nbytes;
- data += nbytes;
- have -= nbytes;
- }
-
- return 0;
-}
-
-/* The buffer flush function for a buffer built on a file descriptor. */
-
-/*ARGSUSED*/
-static int
-fd_buffer_flush (closure)
- void *closure;
-{
- /* Nothing to do. File descriptors are always flushed. */
- return 0;
-}
-
-/* The buffer block function for a buffer built on a file descriptor. */
-
-static int
-fd_buffer_block (closure, block)
- void *closure;
- int block;
-{
- struct fd_buffer *fd = (struct fd_buffer *) closure;
- int flags;
-
- flags = fcntl (fd->fd, F_GETFL, 0);
- if (flags < 0)
- return errno;
-
- if (block)
- flags &= ~O_NONBLOCK;
- else
- flags |= O_NONBLOCK;
-
- if (fcntl (fd->fd, F_SETFL, flags) < 0)
- return errno;
-
- fd->blocking = block;
-
- return 0;
-}
-
-/* The buffer shutdown function for a buffer built on a file descriptor. */
-
-static int
-fd_buffer_shutdown (buf)
- struct buffer *buf;
-{
- free (buf->closure);
- buf->closure = NULL;
- return 0;
-}
-
-/* Populate all of the directories between BASE_DIR and its relative
- subdirectory DIR with CVSADM directories. Return 0 for success or
- errno value. */
-static int create_adm_p PROTO((char *, char *));
-
-static int
-create_adm_p (base_dir, dir)
- char *base_dir;
- char *dir;
-{
- char *dir_where_cvsadm_lives, *dir_to_register, *p, *tmp;
- int retval, done;
- FILE *f;
-
- if (strcmp (dir, ".") == 0)
- return 0; /* nothing to do */
-
- /* Allocate some space for our directory-munging string. */
- p = xmalloc (strlen (dir) + 1);
- if (p == NULL)
- return ENOMEM;
-
- dir_where_cvsadm_lives = xmalloc (strlen (base_dir) + strlen (dir) + 100);
- if (dir_where_cvsadm_lives == NULL)
- {
- free (p);
- return ENOMEM;
- }
-
- /* Allocate some space for the temporary string in which we will
- construct filenames. */
- tmp = xmalloc (strlen (base_dir) + strlen (dir) + 100);
- if (tmp == NULL)
- {
- free (p);
- free (dir_where_cvsadm_lives);
- return ENOMEM;
- }
-
-
- /* We make several passes through this loop. On the first pass,
- we simply create the CVSADM directory in the deepest directory.
- For each subsequent pass, we try to remove the last path
- element from DIR, create the CVSADM directory in the remaining
- pathname, and register the subdirectory in the newly created
- CVSADM directory. */
-
- retval = done = 0;
-
- strcpy (p, dir);
- strcpy (dir_where_cvsadm_lives, base_dir);
- strcat (dir_where_cvsadm_lives, "/");
- strcat (dir_where_cvsadm_lives, p);
- dir_to_register = NULL;
-
- while (1)
- {
- /* Create CVSADM. */
- (void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM);
- if ((CVS_MKDIR (tmp, 0777) < 0) && (errno != EEXIST))
- {
- retval = errno;
- goto finish;
- }
-
- /* Create CVSADM_REP. */
- (void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM_REP);
- if (! isfile (tmp))
- {
- /* Use Emptydir as the placeholder until the client sends
- us the real value. This code is similar to checkout.c
- (emptydir_name), but the code below returns errors
- differently. */
-
- char *empty;
- empty = xmalloc (strlen (current_parsed_root->directory)
- + sizeof (CVSROOTADM)
- + sizeof (CVSNULLREPOS)
- + 3);
- if (! empty)
- {
- retval = ENOMEM;
- goto finish;
- }
-
- /* Create the directory name. */
- (void) sprintf (empty, "%s/%s/%s", current_parsed_root->directory,
- CVSROOTADM, CVSNULLREPOS);
-
- /* Create the directory if it doesn't exist. */
- if (! isfile (empty))
- {
- mode_t omask;
- omask = umask (cvsumask);
- if (CVS_MKDIR (empty, 0777) < 0)
- {
- retval = errno;
- free (empty);
- goto finish;
- }
- (void) umask (omask);
- }
-
- f = CVS_FOPEN (tmp, "w");
- if (f == NULL)
- {
- retval = errno;
- free (empty);
- goto finish;
- }
- /* Write the directory name to CVSADM_REP. */
- if (fprintf (f, "%s\n", empty) < 0)
- {
- retval = errno;
- fclose (f);
- free (empty);
- goto finish;
- }
- if (fclose (f) == EOF)
- {
- retval = errno;
- free (empty);
- goto finish;
- }
-
- /* Clean up after ourselves. */
- free (empty);
- }
-
- /* Create CVSADM_ENT. We open in append mode because we
- don't want to clobber an existing Entries file. */
- (void) sprintf (tmp, "%s/%s", dir_where_cvsadm_lives, CVSADM_ENT);
- f = CVS_FOPEN (tmp, "a");
- if (f == NULL)
- {
- retval = errno;
- goto finish;
- }
- if (fclose (f) == EOF)
- {
- retval = errno;
- goto finish;
- }
-
- if (dir_to_register != NULL)
- {
- /* FIXME: Yes, this results in duplicate entries in the
- Entries.Log file, but it doesn't currently matter. We
- might need to change this later on to make sure that we
- only write one entry. */
-
- Subdir_Register ((List *) NULL, dir_where_cvsadm_lives,
- dir_to_register);
- }
-
- if (done)
- break;
-
- dir_to_register = strrchr (p, '/');
- if (dir_to_register == NULL)
- {
- dir_to_register = p;
- strcpy (dir_where_cvsadm_lives, base_dir);
- done = 1;
- }
- else
- {
- *dir_to_register = '\0';
- dir_to_register++;
- strcpy (dir_where_cvsadm_lives, base_dir);
- strcat (dir_where_cvsadm_lives, "/");
- strcat (dir_where_cvsadm_lives, p);
- }
- }
-
- finish:
- free (tmp);
- free (dir_where_cvsadm_lives);
- free (p);
- return retval;
-}
-
-/*
- * Make directory DIR, including all intermediate directories if necessary.
- * Returns 0 for success or errno code.
- */
-static int mkdir_p PROTO((char *));
-
-static int
-mkdir_p (dir)
- char *dir;
-{
- char *p;
- char *q = xmalloc (strlen (dir) + 1);
- int retval;
-
- if (q == NULL)
- return ENOMEM;
-
- retval = 0;
-
- /*
- * Skip over leading slash if present. We won't bother to try to
- * make '/'.
- */
- p = dir + 1;
- while (1)
- {
- while (*p != '/' && *p != '\0')
- ++p;
- if (*p == '/')
- {
- strncpy (q, dir, p - dir);
- q[p - dir] = '\0';
- if (q[p - dir - 1] != '/' && CVS_MKDIR (q, 0777) < 0)
- {
- int saved_errno = errno;
-
- if (saved_errno != EEXIST
- && ((saved_errno != EACCES && saved_errno != EROFS)
- || !isdir (q)))
- {
- retval = saved_errno;
- goto done;
- }
- }
- ++p;
- }
- else
- {
- if (CVS_MKDIR (dir, 0777) < 0)
- retval = errno;
- goto done;
- }
- }
- done:
- free (q);
- return retval;
-}
-
-/*
- * Print the error response for error code STATUS. The caller is
- * reponsible for making sure we get back to the command loop without
- * any further output occuring.
- * Must be called only in contexts where it is OK to send output.
- */
-static void
-print_error (status)
- int status;
-{
- char *msg;
- char tmpstr[80];
-
- buf_output0 (buf_to_net, "error ");
- msg = strerror (status);
- if (msg == NULL)
- {
- sprintf (tmpstr, "unknown error %d", status);
- msg = tmpstr;
- }
- buf_output0 (buf_to_net, msg);
- buf_append_char (buf_to_net, '\n');
-
- buf_flush (buf_to_net, 0);
-}
-
-static int pending_error;
-/*
- * Malloc'd text for pending error. Each line must start with "E ". The
- * last line should not end with a newline.
- */
-static char *pending_error_text;
-
-/* If an error is pending, print it and return 1. If not, return 0.
- Must be called only in contexts where it is OK to send output. */
-static int
-print_pending_error ()
-{
- if (pending_error_text)
- {
- buf_output0 (buf_to_net, pending_error_text);
- buf_append_char (buf_to_net, '\n');
- if (pending_error)
- print_error (pending_error);
- else
- buf_output0 (buf_to_net, "error \n");
-
- buf_flush (buf_to_net, 0);
-
- pending_error = 0;
- free (pending_error_text);
- pending_error_text = NULL;
- return 1;
- }
- else if (pending_error)
- {
- print_error (pending_error);
- pending_error = 0;
- return 1;
- }
- else
- return 0;
-}
-
-/* Is an error pending? */
-#define error_pending() (pending_error || pending_error_text)
-
-static int alloc_pending PROTO ((size_t size));
-
-/* Allocate SIZE bytes for pending_error_text and return nonzero
- if we could do it. */
-static int
-alloc_pending (size)
- size_t size;
-{
- if (error_pending ())
- /* Probably alloc_pending callers will have already checked for
- this case. But we might as well handle it if they don't, I
- guess. */
- return 0;
- pending_error_text = xmalloc (size);
- if (pending_error_text == NULL)
- {
- pending_error = ENOMEM;
- return 0;
- }
- return 1;
-}
-
-static void serve_is_modified PROTO ((char *));
-
-static int supported_response PROTO ((char *));
-
-static int
-supported_response (name)
- char *name;
-{
- struct response *rs;
-
- for (rs = responses; rs->name != NULL; ++rs)
- if (strcmp (rs->name, name) == 0)
- return rs->status == rs_supported;
- error (1, 0, "internal error: testing support for unknown response?");
- /* NOTREACHED */
- return 0;
-}
-
-static void
-serve_valid_responses (arg)
- char *arg;
-{
- char *p = arg;
- char *q;
- struct response *rs;
- do
- {
- q = strchr (p, ' ');
- if (q != NULL)
- *q++ = '\0';
- for (rs = responses; rs->name != NULL; ++rs)
- {
- if (strcmp (rs->name, p) == 0)
- break;
- }
- if (rs->name == NULL)
- /*
- * It is a response we have never heard of (and thus never
- * will want to use). So don't worry about it.
- */
- ;
- else
- rs->status = rs_supported;
- p = q;
- } while (q != NULL);
- for (rs = responses; rs->name != NULL; ++rs)
- {
- if (rs->status == rs_essential)
- {
- buf_output0 (buf_to_net, "E response `");
- buf_output0 (buf_to_net, rs->name);
- buf_output0 (buf_to_net, "' not supported by client\nerror \n");
-
- /* FIXME: This call to buf_flush could conceivably
- cause deadlock, as noted in server_cleanup. */
- buf_flush (buf_to_net, 1);
-
- error_exit ();
- }
- else if (rs->status == rs_optional)
- rs->status = rs_not_supported;
- }
-}
-
-static void
-serve_root (arg)
- char *arg;
-{
- char *env;
- char *path;
-
- if (error_pending()) return;
-
- if (!isabsolute (arg))
- {
- if (alloc_pending (80 + strlen (arg)))
- sprintf (pending_error_text,
- "E Root %s must be an absolute pathname", arg);
- return;
- }
-
- /* Sending "Root" twice is illegal.
-
- The other way to handle a duplicate Root requests would be as a
- request to clear out all state and start over as if it was a
- new connection. Doing this would cause interoperability
- headaches, so it should be a different request, if there is
- any reason why such a feature is needed. */
- if (current_parsed_root != NULL)
- {
- if (alloc_pending (80 + strlen (arg)))
- sprintf (pending_error_text,
- "E Protocol error: Duplicate Root request, for %s", arg);
- return;
- }
-
- /* We need to check :ext: server here, :pserver: checks happen below. */
- if (root_allow_used() && !root_allow_ok (arg)
-# ifdef AUTH_SERVER_SUPPORT
- && Pserver_Repos == NULL
-# endif
- )
- {
- if (alloc_pending (80 + strlen (arg)))
- sprintf (pending_error_text,
- "E Bad root %s", arg);
- return;
- }
-
-#ifdef AUTH_SERVER_SUPPORT
- if (Pserver_Repos != NULL)
- {
- if (strcmp (Pserver_Repos, arg) != 0)
- {
- if (alloc_pending (80 + strlen (Pserver_Repos) + strlen (arg)))
- /* The explicitness is to aid people who are writing clients.
- I don't see how this information could help an
- attacker. */
- sprintf (pending_error_text, "\
-E Protocol error: Root says \"%s\" but pserver says \"%s\"",
- arg, Pserver_Repos);
- return;
- }
- }
-#endif
-
- current_parsed_root = local_cvsroot (arg);
-
- /* For pserver, this will already have happened, and the call will do
- nothing. But for rsh, we need to do it now. */
- parse_config (current_parsed_root->directory);
-
- /* Now is a good time to read CVSROOT/options too. */
- parseopts(current_parsed_root->directory);
-
- path = xmalloc (strlen (current_parsed_root->directory)
- + sizeof (CVSROOTADM)
- + 2);
- if (path == NULL)
- {
- pending_error = ENOMEM;
- return;
- }
- (void) sprintf (path, "%s/%s", current_parsed_root->directory, CVSROOTADM);
- if (!isaccessible (path, R_OK | X_OK))
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (path)))
- sprintf (pending_error_text, "E Cannot access %s", path);
- pending_error = save_errno;
- }
- free (path);
-
-#ifdef HAVE_PUTENV
- env = xmalloc (strlen (CVSROOT_ENV) + strlen (current_parsed_root->directory) + 2);
- if (env == NULL)
- {
- pending_error = ENOMEM;
- return;
- }
- (void) sprintf (env, "%s=%s", CVSROOT_ENV, current_parsed_root->directory);
- (void) putenv (env);
- /* do not free env, as putenv has control of it */
-#endif
-}
-
-static int max_dotdot_limit = 0;
-
-/* Is this pathname OK to recurse into when we are running as the server?
- If not, call error() with a fatal error. */
-void
-server_pathname_check (path)
- char *path;
-{
- /* An absolute pathname is almost surely a path on the *client* machine,
- and is unlikely to do us any good here. It also is probably capable
- of being a security hole in the anonymous readonly case. */
- if (isabsolute (path))
- /* Giving an error is actually kind of a cop-out, in the sense
- that it would be nice for "cvs co -d /foo/bar/baz" to work.
- A quick fix in the server would be requiring Max-dotdot of
- at least one if pathnames are absolute, and then putting
- /abs/foo/bar/baz in the temp dir beside the /d/d/d stuff.
- A cleaner fix in the server might be to decouple the
- pathnames we pass back to the client from pathnames in our
- temp directory (this would also probably remove the need
- for Max-dotdot). A fix in the client would have the client
- turn it into "cd /foo/bar; cvs co -d baz" (more or less).
- This probably has some problems with pathnames which appear
- in messages. */
- error (1, 0, "absolute pathname `%s' illegal for server", path);
- if (pathname_levels (path) > max_dotdot_limit)
- {
- /* Similar to the isabsolute case in security implications. */
- error (0, 0, "protocol error: `%s' contains more leading ..", path);
- error (1, 0, "than the %d which Max-dotdot specified",
- max_dotdot_limit);
- }
-}
-
-static int outside_root PROTO ((char *));
-
-/* Is file or directory REPOS an absolute pathname within the
- current_parsed_root->directory? If yes, return 0. If no, set pending_error
- and return 1. */
-static int
-outside_root (repos)
- char *repos;
-{
- size_t repos_len = strlen (repos);
- size_t root_len = strlen (current_parsed_root->directory);
-
- /* isabsolute (repos) should always be true, but
- this is a good security precaution regardless. -DRP
- */
- if (!isabsolute (repos))
- {
- if (alloc_pending (repos_len + 80))
- sprintf (pending_error_text, "\
-E protocol error: %s is not absolute", repos);
- return 1;
- }
-
- if (repos_len < root_len
- || strncmp (current_parsed_root->directory, repos, root_len) != 0)
- {
- not_within:
- if (alloc_pending (strlen (current_parsed_root->directory)
- + strlen (repos)
- + 80))
- sprintf (pending_error_text, "\
-E protocol error: directory '%s' not within root '%s'",
- repos, current_parsed_root->directory);
- return 1;
- }
- if (repos_len > root_len)
- {
- if (repos[root_len] != '/')
- goto not_within;
- if (pathname_levels (repos + root_len + 1) > 0)
- goto not_within;
- }
- return 0;
-}
-
-static int outside_dir PROTO ((char *));
-
-/* Is file or directory FILE outside the current directory (that is, does
- it contain '/')? If no, return 0. If yes, set pending_error
- and return 1. */
-static int
-outside_dir (file)
- char *file;
-{
- if (strchr (file, '/') != NULL)
- {
- if (alloc_pending (strlen (file)
- + 80))
- sprintf (pending_error_text, "\
-E protocol error: directory '%s' not within current directory",
- file);
- return 1;
- }
- return 0;
-}
-
-/*
- * Add as many directories to the temp directory as the client tells us it
- * will use "..", so we never try to access something outside the temp
- * directory via "..".
- */
-static void
-serve_max_dotdot (arg)
- char *arg;
-{
- int lim = atoi (arg);
- int i;
- char *p;
-
- if (lim < 0 || lim > 10000)
- return;
- p = xmalloc (strlen (server_temp_dir) + 2 * lim + 10);
- if (p == NULL)
- {
- pending_error = ENOMEM;
- return;
- }
- strcpy (p, server_temp_dir);
- for (i = 0; i < lim; ++i)
- strcat (p, "/d");
- if (server_temp_dir != orig_server_temp_dir)
- free (server_temp_dir);
- server_temp_dir = p;
- max_dotdot_limit = lim;
-}
-
-static char *dir_name;
-
-static void
-dirswitch (dir, repos)
- char *dir;
- char *repos;
-{
- int status;
- FILE *f;
- size_t dir_len;
-
- server_write_entries ();
-
- if (error_pending()) return;
-
- /* Check for bad directory name.
-
- FIXME: could/should unify these checks with server_pathname_check
- except they need to report errors differently. */
- if (isabsolute (dir))
- {
- if (alloc_pending (80 + strlen (dir)))
- sprintf (pending_error_text,
- "E absolute pathname `%s' illegal for server", dir);
- return;
- }
- if (pathname_levels (dir) > max_dotdot_limit)
- {
- if (alloc_pending (80 + strlen (dir)))
- sprintf (pending_error_text,
- "E protocol error: `%s' has too many ..", dir);
- return;
- }
-
- dir_len = strlen (dir);
-
- /* Check for a trailing '/'. This is not ISDIRSEP because \ in the
- protocol is an ordinary character, not a directory separator (of
- course, it is perhaps unwise to use it in directory names, but that
- is another issue). */
- if (dir_len > 0
- && dir[dir_len - 1] == '/')
- {
- if (alloc_pending (80 + dir_len))
- sprintf (pending_error_text,
- "E protocol error: invalid directory syntax in %s", dir);
- return;
- }
-
- if (dir_name != NULL)
- free (dir_name);
-
- dir_name = xmalloc (strlen (server_temp_dir) + dir_len + 40);
- if (dir_name == NULL)
- {
- pending_error = ENOMEM;
- return;
- }
-
- strcpy (dir_name, server_temp_dir);
- strcat (dir_name, "/");
- strcat (dir_name, dir);
-
- status = mkdir_p (dir_name);
- if (status != 0
- && status != EEXIST)
- {
- if (alloc_pending (80 + strlen (dir_name)))
- sprintf (pending_error_text, "E cannot mkdir %s", dir_name);
- pending_error = status;
- return;
- }
-
- /* We need to create adm directories in all path elements because
- we want the server to descend them, even if the client hasn't
- sent the appropriate "Argument xxx" command to match the
- already-sent "Directory xxx" command. See recurse.c
- (start_recursion) for a big discussion of this. */
-
- status = create_adm_p (server_temp_dir, dir);
- if (status != 0)
- {
- if (alloc_pending (80 + strlen (dir_name)))
- sprintf (pending_error_text, "E cannot create_adm_p %s", dir_name);
- pending_error = status;
- return;
- }
-
- if ( CVS_CHDIR (dir_name) < 0)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (dir_name)))
- sprintf (pending_error_text, "E cannot change to %s", dir_name);
- pending_error = save_errno;
- return;
- }
- /*
- * This is pretty much like calling Create_Admin, but Create_Admin doesn't
- * report errors in the right way for us.
- */
- if ((CVS_MKDIR (CVSADM, 0777) < 0) && (errno != EEXIST))
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM)))
- sprintf (pending_error_text,
- "E cannot mkdir %s/%s", dir_name, CVSADM);
- pending_error = save_errno;
- return;
- }
-
- /* The following will overwrite the contents of CVSADM_REP. This
- is the correct behavior -- mkdir_p may have written a
- placeholder value to this file and we need to insert the
- correct value. */
-
- f = CVS_FOPEN (CVSADM_REP, "w");
- if (f == NULL)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP)))
- sprintf (pending_error_text,
- "E cannot open %s/%s", dir_name, CVSADM_REP);
- pending_error = save_errno;
- return;
- }
- if (fprintf (f, "%s", repos) < 0)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP)))
- sprintf (pending_error_text,
- "E error writing %s/%s", dir_name, CVSADM_REP);
- pending_error = save_errno;
- fclose (f);
- return;
- }
- /* Non-remote CVS handles a module representing the entire tree
- (e.g., an entry like ``world -a .'') by putting /. at the end
- of the Repository file, so we do the same. */
- if (strcmp (dir, ".") == 0
- && current_parsed_root != NULL
- && current_parsed_root->directory != NULL
- && strcmp (current_parsed_root->directory, repos) == 0)
- {
- if (fprintf (f, "/.") < 0)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP)))
- sprintf (pending_error_text,
- "E error writing %s/%s", dir_name, CVSADM_REP);
- pending_error = save_errno;
- fclose (f);
- return;
- }
- }
- if (fprintf (f, "\n") < 0)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP)))
- sprintf (pending_error_text,
- "E error writing %s/%s", dir_name, CVSADM_REP);
- pending_error = save_errno;
- fclose (f);
- return;
- }
- if (fclose (f) == EOF)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (dir_name) + strlen (CVSADM_REP)))
- sprintf (pending_error_text,
- "E error closing %s/%s", dir_name, CVSADM_REP);
- pending_error = save_errno;
- return;
- }
- /* We open in append mode because we don't want to clobber an
- existing Entries file. */
- f = CVS_FOPEN (CVSADM_ENT, "a");
- if (f == NULL)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (CVSADM_ENT)))
- sprintf (pending_error_text, "E cannot open %s", CVSADM_ENT);
- pending_error = save_errno;
- return;
- }
- if (fclose (f) == EOF)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (CVSADM_ENT)))
- sprintf (pending_error_text, "E cannot close %s", CVSADM_ENT);
- pending_error = save_errno;
- return;
- }
-}
-
-static void
-serve_repository (arg)
- char *arg;
-{
- if (alloc_pending (80))
- strcpy (pending_error_text,
- "E Repository request is obsolete; aborted");
- return;
-}
-
-static void
-serve_directory (arg)
- char *arg;
-{
- int status;
- char *repos;
-
- status = buf_read_line (buf_from_net, &repos, (int *) NULL);
- if (status == 0)
- {
- if (!outside_root (repos))
- dirswitch (arg, repos);
- free (repos);
- }
- else if (status == -2)
- {
- pending_error = ENOMEM;
- }
- else
- {
- pending_error_text = xmalloc (80 + strlen (arg));
- if (pending_error_text == NULL)
- {
- pending_error = ENOMEM;
- }
- else if (status == -1)
- {
- sprintf (pending_error_text,
- "E end of file reading mode for %s", arg);
- }
- else
- {
- sprintf (pending_error_text,
- "E error reading mode for %s", arg);
- pending_error = status;
- }
- }
-}
-
-static void
-serve_static_directory (arg)
- char *arg;
-{
- FILE *f;
-
- if (error_pending ()) return;
-
- f = CVS_FOPEN (CVSADM_ENTSTAT, "w+");
- if (f == NULL)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (CVSADM_ENTSTAT)))
- sprintf (pending_error_text, "E cannot open %s", CVSADM_ENTSTAT);
- pending_error = save_errno;
- return;
- }
- if (fclose (f) == EOF)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (CVSADM_ENTSTAT)))
- sprintf (pending_error_text, "E cannot close %s", CVSADM_ENTSTAT);
- pending_error = save_errno;
- return;
- }
-}
-
-static void
-serve_sticky (arg)
- char *arg;
-{
- FILE *f;
-
- if (error_pending ()) return;
-
- f = CVS_FOPEN (CVSADM_TAG, "w+");
- if (f == NULL)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (CVSADM_TAG)))
- sprintf (pending_error_text, "E cannot open %s", CVSADM_TAG);
- pending_error = save_errno;
- return;
- }
- if (fprintf (f, "%s\n", arg) < 0)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (CVSADM_TAG)))
- sprintf (pending_error_text, "E cannot write to %s", CVSADM_TAG);
- pending_error = save_errno;
- (void) fclose (f);
- return;
- }
- if (fclose (f) == EOF)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (CVSADM_TAG)))
- sprintf (pending_error_text, "E cannot close %s", CVSADM_TAG);
- pending_error = save_errno;
- return;
- }
-}
-
-/*
- * Read SIZE bytes from buf_from_net, write them to FILE.
- *
- * Currently this isn't really used for receiving parts of a file --
- * the file is still sent over in one chunk. But if/when we get
- * spiffy in-process gzip support working, perhaps the compressed
- * pieces could be sent over as they're ready, if the network is fast
- * enough. Or something.
- */
-static void
-receive_partial_file (size, file)
- int size;
- int file;
-{
- while (size > 0)
- {
- int status, nread;
- char *data;
-
- status = buf_read_data (buf_from_net, size, &data, &nread);
- if (status != 0)
- {
- if (status == -2)
- pending_error = ENOMEM;
- else
- {
- pending_error_text = xmalloc (80);
- if (pending_error_text == NULL)
- pending_error = ENOMEM;
- else if (status == -1)
- {
- sprintf (pending_error_text,
- "E premature end of file from client");
- pending_error = 0;
- }
- else
- {
- sprintf (pending_error_text,
- "E error reading from client");
- pending_error = status;
- }
- }
- return;
- }
-
- size -= nread;
-
- while (nread > 0)
- {
- int nwrote;
-
- nwrote = write (file, data, nread);
- if (nwrote < 0)
- {
- int save_errno = errno;
- if (alloc_pending (40))
- strcpy (pending_error_text, "E unable to write");
- pending_error = save_errno;
-
- /* Read and discard the file data. */
- while (size > 0)
- {
- int status, nread;
- char *data;
-
- status = buf_read_data (buf_from_net, size, &data, &nread);
- if (status != 0)
- return;
- size -= nread;
- }
-
- return;
- }
- nread -= nwrote;
- data += nwrote;
- }
- }
-}
-
-/* Receive SIZE bytes, write to filename FILE. */
-static void
-receive_file (size, file, gzipped)
- int size;
- char *file;
- int gzipped;
-{
- int fd;
- char *arg = file;
-
- /* Write the file. */
- fd = CVS_OPEN (arg, O_WRONLY | O_CREAT | O_TRUNC, 0600);
- if (fd < 0)
- {
- int save_errno = errno;
- if (alloc_pending (40 + strlen (arg)))
- sprintf (pending_error_text, "E cannot open %s", arg);
- pending_error = save_errno;
- return;
- }
-
- if (gzipped)
- {
- /* Using gunzip_and_write isn't really a high-performance
- approach, because it keeps the whole thing in memory
- (contiguous memory, worse yet). But it seems easier to
- code than the alternative (and less vulnerable to subtle
- bugs). Given that this feature is mainly for
- compatibility, that is the better tradeoff. */
-
- int toread = size;
- char *filebuf;
- char *p;
-
- filebuf = xmalloc (size);
- p = filebuf;
- /* If NULL, we still want to read the data and discard it. */
-
- while (toread > 0)
- {
- int status, nread;
- char *data;
-
- status = buf_read_data (buf_from_net, toread, &data, &nread);
- if (status != 0)
- {
- if (status == -2)
- pending_error = ENOMEM;
- else
- {
- pending_error_text = xmalloc (80);
- if (pending_error_text == NULL)
- pending_error = ENOMEM;
- else if (status == -1)
- {
- sprintf (pending_error_text,
- "E premature end of file from client");
- pending_error = 0;
- }
- else
- {
- sprintf (pending_error_text,
- "E error reading from client");
- pending_error = status;
- }
- }
- return;
- }
-
- toread -= nread;
-
- if (filebuf != NULL)
- {
- memcpy (p, data, nread);
- p += nread;
- }
- }
- if (filebuf == NULL)
- {
- pending_error = ENOMEM;
- goto out;
- }
-
- if (gunzip_and_write (fd, file, (unsigned char *) filebuf, size))
- {
- if (alloc_pending (80))
- sprintf (pending_error_text,
- "E aborting due to compression error");
- }
- free (filebuf);
- }
- else
- receive_partial_file (size, fd);
-
- if (pending_error_text)
- {
- char *p = xrealloc (pending_error_text,
- strlen (pending_error_text) + strlen (arg) + 30);
- if (p)
- {
- pending_error_text = p;
- sprintf (p + strlen (p), ", file %s", arg);
- }
- /* else original string is supposed to be unchanged */
- }
-
- out:
- if (close (fd) < 0 && !error_pending ())
- {
- int save_errno = errno;
- if (alloc_pending (40 + strlen (arg)))
- sprintf (pending_error_text, "E cannot close %s", arg);
- pending_error = save_errno;
- return;
- }
-}
-
-/* Kopt for the next file sent in Modified or Is-modified. */
-static char *kopt;
-
-/* Timestamp (Checkin-time) for next file sent in Modified or
- Is-modified. */
-static int checkin_time_valid;
-static time_t checkin_time;
-
-static void serve_modified PROTO ((char *));
-
-static void
-serve_modified (arg)
- char *arg;
-{
- int size, status;
- char *size_text;
- char *mode_text;
-
- int gzipped = 0;
-
- /*
- * This used to return immediately if error_pending () was true.
- * However, that fails, because it causes each line of the file to
- * be echoed back to the client as an unrecognized command. The
- * client isn't reading from the socket, so eventually both
- * processes block trying to write to the other. Now, we try to
- * read the file if we can.
- */
-
- status = buf_read_line (buf_from_net, &mode_text, (int *) NULL);
- if (status != 0)
- {
- if (status == -2)
- pending_error = ENOMEM;
- else
- {
- pending_error_text = xmalloc (80 + strlen (arg));
- if (pending_error_text == NULL)
- pending_error = ENOMEM;
- else
- {
- if (status == -1)
- sprintf (pending_error_text,
- "E end of file reading mode for %s", arg);
- else
- {
- sprintf (pending_error_text,
- "E error reading mode for %s", arg);
- pending_error = status;
- }
- }
- }
- return;
- }
-
- status = buf_read_line (buf_from_net, &size_text, (int *) NULL);
- if (status != 0)
- {
- if (status == -2)
- pending_error = ENOMEM;
- else
- {
- pending_error_text = xmalloc (80 + strlen (arg));
- if (pending_error_text == NULL)
- pending_error = ENOMEM;
- else
- {
- if (status == -1)
- sprintf (pending_error_text,
- "E end of file reading size for %s", arg);
- else
- {
- sprintf (pending_error_text,
- "E error reading size for %s", arg);
- pending_error = status;
- }
- }
- }
- free (mode_text);
- return;
- }
- if (size_text[0] == 'z')
- {
- gzipped = 1;
- size = atoi (size_text + 1);
- }
- else
- size = atoi (size_text);
- free (size_text);
-
- if (error_pending ())
- {
- /* Now that we know the size, read and discard the file data. */
- while (size > 0)
- {
- int status, nread;
- char *data;
-
- status = buf_read_data (buf_from_net, size, &data, &nread);
- if (status != 0)
- return;
- size -= nread;
- }
- free (mode_text);
- return;
- }
-
- if (outside_dir (arg))
- {
- free (mode_text);
- return;
- }
-
- if (size >= 0)
- {
- receive_file (size, arg, gzipped);
- if (error_pending ())
- {
- free (mode_text);
- return;
- }
- }
-
- if (checkin_time_valid)
- {
- struct utimbuf t;
-
- memset (&t, 0, sizeof (t));
- t.modtime = t.actime = checkin_time;
- if (utime (arg, &t) < 0)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (arg)))
- sprintf (pending_error_text, "E cannot utime %s", arg);
- pending_error = save_errno;
- free (mode_text);
- return;
- }
- checkin_time_valid = 0;
- }
-
- {
- int status = change_mode (arg, mode_text, 0);
- free (mode_text);
- if (status)
- {
- if (alloc_pending (40 + strlen (arg)))
- sprintf (pending_error_text,
- "E cannot change mode for %s", arg);
- pending_error = status;
- return;
- }
- }
-
- /* Make sure that the Entries indicate the right kopt. We probably
- could do this even in the non-kopt case and, I think, save a stat()
- call in time_stamp_server. But for conservatism I'm leaving the
- non-kopt case alone. */
- if (kopt != NULL)
- serve_is_modified (arg);
-}
-
-
-static void
-serve_enable_unchanged (arg)
- char *arg;
-{
-}
-
-struct an_entry {
- struct an_entry *next;
- char *entry;
-};
-
-static struct an_entry *entries;
-
-static void serve_unchanged PROTO ((char *));
-
-static void
-serve_unchanged (arg)
- char *arg;
-{
- struct an_entry *p;
- char *name;
- char *cp;
- char *timefield;
-
- if (error_pending ()) return;
-
- if (outside_dir (arg))
- return;
-
- /* Rewrite entries file to have `=' in timestamp field. */
- for (p = entries; p != NULL; p = p->next)
- {
- name = p->entry + 1;
- cp = strchr (name, '/');
- if (cp != NULL
- && strlen (arg) == cp - name
- && strncmp (arg, name, cp - name) == 0)
- {
- if (!(timefield = strchr (cp + 1, '/')) || *++timefield == '\0')
- {
- /* We didn't find the record separator or it is followed by
- * the end of the string, so just exit.
- */
- if (alloc_pending (80))
- sprintf (pending_error_text,
- "E Malformed Entry encountered.");
- return;
- }
- /* If the time field is not currently empty, then one of
- * serve_modified, serve_is_modified, & serve_unchanged were
- * already called for this file. We would like to ignore the
- * reinvocation silently or, better yet, exit with an error
- * message, but we just avoid the copy-forward and overwrite the
- * value from the last invocation instead. See the comment below
- * for more.
- */
- if (*timefield == '/')
- {
- /* Copy forward one character. Space was allocated for this
- * already in serve_entry(). */
- cp = timefield + strlen (timefield);
- cp[1] = '\0';
- while (cp > timefield)
- {
- *cp = cp[-1];
- --cp;
- }
- }
- /* If *TIMEFIELD wasn't "/", we assume that it was because of
- * multiple calls to Is-Modified & Unchanged by the client and
- * just overwrite the value from the last call. Technically, we
- * should probably either ignore calls after the first or send the
- * client an error, since the client/server protocol specification
- * specifies that only one call to either Is-Modified or Unchanged
- * is allowed, but broken versions of WinCVS & TortoiseCVS rely on
- * this behavior.
- */
- if (*timefield != '+')
- /* Skip this for entries with conflict markers. */
- *timefield = '=';
- break;
- }
- }
-}
-
-static void
-serve_is_modified (arg)
- char *arg;
-{
- struct an_entry *p;
- char *name;
- char *cp;
- char *timefield;
- /* Have we found this file in "entries" yet. */
- int found;
-
- if (error_pending ()) return;
-
- if (outside_dir (arg))
- return;
-
- /* Rewrite entries file to have `M' in timestamp field. */
- found = 0;
- for (p = entries; p != NULL; p = p->next)
- {
- name = p->entry + 1;
- cp = strchr (name, '/');
- if (cp != NULL
- && strlen (arg) == cp - name
- && strncmp (arg, name, cp - name) == 0)
- {
- if (!(timefield = strchr (cp + 1, '/')) || *++timefield == '\0')
- {
- /* We didn't find the record separator or it is followed by
- * the end of the string, so just exit.
- */
- if (alloc_pending (80))
- sprintf (pending_error_text,
- "E Malformed Entry encountered.");
- return;
- }
- /* If the time field is not currently empty, then one of
- * serve_modified, serve_is_modified, & serve_unchanged were
- * already called for this file. We would like to ignore the
- * reinvocation silently or, better yet, exit with an error
- * message, but we just avoid the copy-forward and overwrite the
- * value from the last invocation instead. See the comment below
- * for more.
- */
- if (*timefield == '/')
- {
- /* Copy forward one character. Space was allocated for this
- * already in serve_entry(). */
- cp = timefield + strlen (timefield);
- cp[1] = '\0';
- while (cp > timefield)
- {
- *cp = cp[-1];
- --cp;
- }
- }
- /* If *TIMEFIELD wasn't "/", we assume that it was because of
- * multiple calls to Is-Modified & Unchanged by the client and
- * just overwrite the value from the last call. Technically, we
- * should probably either ignore calls after the first or send the
- * client an error, since the client/server protocol specification
- * specifies that only one call to either Is-Modified or Unchanged
- * is allowed, but broken versions of WinCVS & TortoiseCVS rely on
- * this behavior.
- */
- if (*timefield != '+')
- /* Skip this for entries with conflict markers. */
- *timefield = 'M';
-
- if (kopt != NULL)
- {
- if (alloc_pending (strlen (name) + 80))
- sprintf (pending_error_text,
- "E protocol error: both Kopt and Entry for %s",
- arg);
- free (kopt);
- kopt = NULL;
- return;
- }
- found = 1;
- break;
- }
- }
- if (!found)
- {
- /* We got Is-modified but no Entry. Add a dummy entry.
- The "D" timestamp is what makes it a dummy. */
- p = (struct an_entry *) xmalloc (sizeof (struct an_entry));
- if (p == NULL)
- {
- pending_error = ENOMEM;
- return;
- }
- p->entry = xmalloc (strlen (arg) + 80);
- if (p->entry == NULL)
- {
- pending_error = ENOMEM;
- free (p);
- return;
- }
- strcpy (p->entry, "/");
- strcat (p->entry, arg);
- strcat (p->entry, "//D/");
- if (kopt != NULL)
- {
- strcat (p->entry, kopt);
- free (kopt);
- kopt = NULL;
- }
- strcat (p->entry, "/");
- p->next = entries;
- entries = p;
- }
-}
-
-static void serve_entry PROTO ((char *));
-
-static void
-serve_entry (arg)
- char *arg;
-{
- struct an_entry *p;
- char *cp;
- int i = 0;
- if (error_pending()) return;
-
- /* Verify that the entry is well-formed. This can avoid problems later.
- * At the moment we only check that the Entry contains five slashes in
- * approximately the correct locations since some of the code makes
- * assumptions about this.
- */
- cp = arg;
- if (*cp == 'D') cp++;
- while (i++ < 5)
- {
- if (!cp || *cp != '/')
- {
- if (alloc_pending (80))
- sprintf (pending_error_text,
- "E protocol error: Malformed Entry");
- return;
- }
- cp = strchr (cp + 1, '/');
- }
-
- p = xmalloc (sizeof (struct an_entry));
- if (p == NULL)
- {
- pending_error = ENOMEM;
- return;
- }
- /* Leave space for serve_unchanged to write '=' if it wants. */
- cp = xmalloc (strlen (arg) + 2);
- if (cp == NULL)
- {
- free (p);
- pending_error = ENOMEM;
- return;
- }
- strcpy (cp, arg);
- p->next = entries;
- p->entry = cp;
- entries = p;
-}
-
-static void serve_kopt PROTO ((char *));
-
-static void
-serve_kopt (arg)
- char *arg;
-{
- if (error_pending ())
- return;
-
- if (kopt != NULL)
- {
- if (alloc_pending (80 + strlen (arg)))
- sprintf (pending_error_text,
- "E protocol error: duplicate Kopt request: %s", arg);
- return;
- }
-
- /* Do some sanity checks. In particular, that it is not too long.
- This lets the rest of the code not worry so much about buffer
- overrun attacks. Probably should call RCS_check_kflag here,
- but that would mean changing RCS_check_kflag to handle errors
- other than via exit(), fprintf(), and such. */
- if (strlen (arg) > 10)
- {
- if (alloc_pending (80 + strlen (arg)))
- sprintf (pending_error_text,
- "E protocol error: invalid Kopt request: %s", arg);
- return;
- }
-
- kopt = xmalloc (strlen (arg) + 1);
- if (kopt == NULL)
- {
- pending_error = ENOMEM;
- return;
- }
- strcpy (kopt, arg);
-}
-
-static void serve_checkin_time PROTO ((char *));
-
-static void
-serve_checkin_time (arg)
- char *arg;
-{
- if (error_pending ())
- return;
-
- if (checkin_time_valid)
- {
- if (alloc_pending (80 + strlen (arg)))
- sprintf (pending_error_text,
- "E protocol error: duplicate Checkin-time request: %s",
- arg);
- return;
- }
-
- checkin_time = get_date (arg, NULL);
- if (checkin_time == (time_t)-1)
- {
- if (alloc_pending (80 + strlen (arg)))
- sprintf (pending_error_text, "E cannot parse date %s", arg);
- return;
- }
- checkin_time_valid = 1;
-}
-
-static void
-server_write_entries ()
-{
- FILE *f;
- struct an_entry *p;
- struct an_entry *q;
-
- if (entries == NULL)
- return;
-
- f = NULL;
- /* Note that we free all the entries regardless of errors. */
- if (!error_pending ())
- {
- /* We open in append mode because we don't want to clobber an
- existing Entries file. If we are checking out a module
- which explicitly lists more than one file in a particular
- directory, then we will wind up calling
- server_write_entries for each such file. */
- f = CVS_FOPEN (CVSADM_ENT, "a");
- if (f == NULL)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (CVSADM_ENT)))
- sprintf (pending_error_text, "E cannot open %s", CVSADM_ENT);
- pending_error = save_errno;
- }
- }
- for (p = entries; p != NULL;)
- {
- if (!error_pending ())
- {
- if (fprintf (f, "%s\n", p->entry) < 0)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen(CVSADM_ENT)))
- sprintf (pending_error_text,
- "E cannot write to %s", CVSADM_ENT);
- pending_error = save_errno;
- }
- }
- free (p->entry);
- q = p->next;
- free (p);
- p = q;
- }
- entries = NULL;
- if (f != NULL && fclose (f) == EOF && !error_pending ())
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (CVSADM_ENT)))
- sprintf (pending_error_text, "E cannot close %s", CVSADM_ENT);
- pending_error = save_errno;
- }
-}
-
-struct notify_note {
- /* Directory in which this notification happens. xmalloc'd*/
- char *dir;
-
- /* xmalloc'd. */
- char *filename;
-
- /* The following three all in one xmalloc'd block, pointed to by TYPE.
- Each '\0' terminated. */
- /* "E" or "U". */
- char *type;
- /* time+host+dir */
- char *val;
- char *watches;
-
- struct notify_note *next;
-};
-
-static struct notify_note *notify_list;
-/* Used while building list, to point to the last node that already exists. */
-static struct notify_note *last_node;
-
-static void serve_notify PROTO ((char *));
-
-static void
-serve_notify (arg)
- char *arg;
-{
- struct notify_note *new = NULL;
- char *data = NULL;
- int status;
-
- if (error_pending ()) return;
-
- if (outside_dir (arg))
- return;
-
- if (dir_name == NULL)
- goto error;
-
- new = (struct notify_note *) xmalloc (sizeof (struct notify_note));
- if (new == NULL)
- {
- pending_error = ENOMEM;
- return;
- }
- new->dir = xmalloc (strlen (dir_name) + 1);
- new->filename = xmalloc (strlen (arg) + 1);
- if (new->dir == NULL || new->filename == NULL)
- {
- pending_error = ENOMEM;
- if (new->dir != NULL)
- free (new->dir);
- free (new);
- return;
- }
- strcpy (new->dir, dir_name);
- strcpy (new->filename, arg);
-
- status = buf_read_line (buf_from_net, &data, (int *) NULL);
- if (status != 0)
- {
- if (status == -2)
- pending_error = ENOMEM;
- else
- {
- pending_error_text = xmalloc (80 + strlen (arg));
- if (pending_error_text == NULL)
- pending_error = ENOMEM;
- else
- {
- if (status == -1)
- sprintf (pending_error_text,
- "E end of file reading notification for %s", arg);
- else
- {
- sprintf (pending_error_text,
- "E error reading notification for %s", arg);
- pending_error = status;
- }
- }
- }
- free (new->filename);
- free (new->dir);
- free (new);
- }
- else
- {
- char *cp;
-
- if (!data[0])
- goto error;
-
- if (strchr (data, '+'))
- goto error;
-
- new->type = data;
- if (data[1] != '\t')
- goto error;
- data[1] = '\0';
- cp = data + 2;
- new->val = cp;
- cp = strchr (cp, '\t');
- if (cp == NULL)
- goto error;
- *cp++ = '+';
- cp = strchr (cp, '\t');
- if (cp == NULL)
- goto error;
- *cp++ = '+';
- cp = strchr (cp, '\t');
- if (cp == NULL)
- goto error;
- *cp++ = '\0';
- new->watches = cp;
- /* If there is another tab, ignore everything after it,
- for future expansion. */
- cp = strchr (cp, '\t');
- if (cp != NULL)
- {
- *cp = '\0';
- }
-
- new->next = NULL;
-
- if (last_node == NULL)
- {
- notify_list = new;
- }
- else
- last_node->next = new;
- last_node = new;
- }
- return;
- error:
- pending_error = 0;
- if (alloc_pending (80))
- strcpy (pending_error_text,
- "E Protocol error; misformed Notify request");
- if (data != NULL)
- free (data);
- if (new != NULL)
- {
- free (new->filename);
- free (new->dir);
- free (new);
- }
- return;
-}
-
-/* Process all the Notify requests that we have stored up. Returns 0
- if successful, if not prints error message (via error()) and
- returns negative value. */
-static int
-server_notify ()
-{
- struct notify_note *p;
- char *repos;
-
- while (notify_list != NULL)
- {
- if ( CVS_CHDIR (notify_list->dir) < 0)
- {
- error (0, errno, "cannot change to %s", notify_list->dir);
- return -1;
- }
- repos = Name_Repository (NULL, NULL);
-
- lock_dir_for_write (repos);
-
- fileattr_startdir (repos);
-
- notify_do (*notify_list->type, notify_list->filename, getcaller(),
- notify_list->val, notify_list->watches, repos);
-
- buf_output0 (buf_to_net, "Notified ");
- {
- char *dir = notify_list->dir + strlen (server_temp_dir) + 1;
- if (dir[0] == '\0')
- buf_append_char (buf_to_net, '.');
- else
- buf_output0 (buf_to_net, dir);
- buf_append_char (buf_to_net, '/');
- buf_append_char (buf_to_net, '\n');
- }
- buf_output0 (buf_to_net, repos);
- buf_append_char (buf_to_net, '/');
- buf_output0 (buf_to_net, notify_list->filename);
- buf_append_char (buf_to_net, '\n');
- free (repos);
-
- p = notify_list->next;
- free (notify_list->filename);
- free (notify_list->dir);
- free (notify_list->type);
- free (notify_list);
- notify_list = p;
-
- fileattr_write ();
- fileattr_free ();
-
- Lock_Cleanup ();
- }
-
- last_node = NULL;
-
- /* The code used to call fflush (stdout) here, but that is no
- longer necessary. The data is now buffered in buf_to_net,
- which will be flushed by the caller, do_cvs_command. */
-
- return 0;
-}
-
-static int argument_count;
-static char **argument_vector;
-static int argument_vector_size;
-
-static void
-serve_argument (arg)
- char *arg;
-{
- char *p;
-
- if (error_pending()) return;
-
- if (argument_count >= 10000)
- {
- if (alloc_pending (80))
- sprintf (pending_error_text,
- "E Protocol error: too many arguments");
- return;
- }
-
- if (argument_vector_size <= argument_count)
- {
- argument_vector_size *= 2;
- argument_vector =
- (char **) xrealloc ((char *)argument_vector,
- argument_vector_size * sizeof (char *));
- if (argument_vector == NULL)
- {
- pending_error = ENOMEM;
- return;
- }
- }
- p = xmalloc (strlen (arg) + 1);
- if (p == NULL)
- {
- pending_error = ENOMEM;
- return;
- }
- strcpy (p, arg);
- argument_vector[argument_count++] = p;
-}
-
-static void
-serve_argumentx (arg)
- char *arg;
-{
- char *p;
-
- if (error_pending()) return;
-
- if (argument_count <= 1)
- {
- if (alloc_pending (80))
- sprintf (pending_error_text,
- "E Protocol error: called argumentx without prior call to argument");
- return;
- }
-
- p = argument_vector[argument_count - 1];
- p = xrealloc (p, strlen (p) + 1 + strlen (arg) + 1);
- if (p == NULL)
- {
- pending_error = ENOMEM;
- return;
- }
- strcat (p, "\n");
- strcat (p, arg);
- argument_vector[argument_count - 1] = p;
-}
-
-static void
-serve_global_option (arg)
- char *arg;
-{
- if (arg[0] != '-' || arg[1] == '\0' || arg[2] != '\0')
- {
- error_return:
- if (alloc_pending (strlen (arg) + 80))
- sprintf (pending_error_text,
- "E Protocol error: bad global option %s",
- arg);
- return;
- }
- switch (arg[1])
- {
- case 'l':
- error(0, 0, "WARNING: global `-l' option ignored.");
- break;
- case 'n':
- noexec = 1;
- logoff = 1;
- break;
- case 'q':
- quiet = 1;
- break;
- case 'r':
- cvswrite = 0;
- break;
- case 'Q':
- really_quiet = 1;
- break;
- case 't':
- trace = 1;
- break;
- default:
- goto error_return;
- }
-}
-
-static void
-serve_set (arg)
- char *arg;
-{
- /* FIXME: This sends errors immediately (I think); they should be
- put into pending_error. */
- variable_set (arg);
-}
-
-#ifdef ENCRYPTION
-
-#ifdef HAVE_KERBEROS
-
-static void
-serve_kerberos_encrypt (arg)
- char *arg;
-{
- /* All future communication with the client will be encrypted. */
-
- buf_to_net = krb_encrypt_buffer_initialize (buf_to_net, 0, sched,
- kblock,
- buf_to_net->memory_error);
- buf_from_net = krb_encrypt_buffer_initialize (buf_from_net, 1, sched,
- kblock,
- buf_from_net->memory_error);
-}
-
-#endif /* HAVE_KERBEROS */
-
-#ifdef HAVE_GSSAPI
-
-static void
-serve_gssapi_encrypt (arg)
- char *arg;
-{
- if (cvs_gssapi_wrapping)
- {
- /* We're already using a gssapi_wrap buffer for stream
- authentication. Flush everything we've output so far, and
- turn on encryption for future data. On the input side, we
- should only have unwrapped as far as the Gssapi-encrypt
- command, so future unwrapping will become encrypted. */
- buf_flush (buf_to_net, 1);
- cvs_gssapi_encrypt = 1;
- return;
- }
-
- /* All future communication with the client will be encrypted. */
-
- cvs_gssapi_encrypt = 1;
-
- buf_to_net = cvs_gssapi_wrap_buffer_initialize (buf_to_net, 0,
- gcontext,
- buf_to_net->memory_error);
- buf_from_net = cvs_gssapi_wrap_buffer_initialize (buf_from_net, 1,
- gcontext,
- buf_from_net->memory_error);
-
- cvs_gssapi_wrapping = 1;
-}
-
-#endif /* HAVE_GSSAPI */
-
-#endif /* ENCRYPTION */
-
-#ifdef HAVE_GSSAPI
-
-static void
-serve_gssapi_authenticate (arg)
- char *arg;
-{
- if (cvs_gssapi_wrapping)
- {
- /* We're already using a gssapi_wrap buffer for encryption.
- That includes authentication, so we don't have to do
- anything further. */
- return;
- }
-
- buf_to_net = cvs_gssapi_wrap_buffer_initialize (buf_to_net, 0,
- gcontext,
- buf_to_net->memory_error);
- buf_from_net = cvs_gssapi_wrap_buffer_initialize (buf_from_net, 1,
- gcontext,
- buf_from_net->memory_error);
-
- cvs_gssapi_wrapping = 1;
-}
-
-#endif /* HAVE_GSSAPI */
-
-
-
-#ifdef SERVER_FLOWCONTROL
-/* The maximum we'll queue to the remote client before blocking. */
-# ifndef SERVER_HI_WATER
-# define SERVER_HI_WATER (2 * 1024 * 1024)
-# endif /* SERVER_HI_WATER */
-/* When the buffer drops to this, we restart the child */
-# ifndef SERVER_LO_WATER
-# define SERVER_LO_WATER (1 * 1024 * 1024)
-# endif /* SERVER_LO_WATER */
-#endif /* SERVER_FLOWCONTROL */
-
-
-
-static void serve_questionable PROTO((char *));
-
-static void
-serve_questionable (arg)
- char *arg;
-{
- static int initted;
-
- if (!initted)
- {
- /* Pick up ignores from CVSROOTADM_IGNORE, $HOME/.cvsignore on server,
- and CVSIGNORE on server. */
- ign_setup ();
- initted = 1;
- }
-
- if (dir_name == NULL)
- {
- buf_output0 (buf_to_net, "E Protocol error: 'Directory' missing");
- return;
- }
-
- if (outside_dir (arg))
- return;
-
- if (!ign_name (arg))
- {
- char *update_dir;
-
- buf_output (buf_to_net, "M ? ", 4);
- update_dir = dir_name + strlen (server_temp_dir) + 1;
- if (!(update_dir[0] == '.' && update_dir[1] == '\0'))
- {
- buf_output0 (buf_to_net, update_dir);
- buf_output (buf_to_net, "/", 1);
- }
- buf_output0 (buf_to_net, arg);
- buf_output (buf_to_net, "\n", 1);
- }
-}
-
-
-
-static struct buffer *protocol;
-
-/* This is the output which we are saving up to send to the server, in the
- child process. We will push it through, via the `protocol' buffer, when
- we have a complete line. */
-static struct buffer *saved_output;
-/* Likewise, but stuff which will go to stderr. */
-static struct buffer *saved_outerr;
-
-static void
-protocol_memory_error (buf)
- struct buffer *buf;
-{
- error (1, ENOMEM, "Virtual memory exhausted");
-}
-
-/*
- * Process IDs of the subprocess, or negative if that subprocess
- * does not exist.
- */
-static pid_t command_pid;
-
-static void
-outbuf_memory_error (buf)
- struct buffer *buf;
-{
- static const char msg[] = "E Fatal server error\n\
-error ENOMEM Virtual memory exhausted.\n";
- if (command_pid > 0)
- kill (command_pid, SIGTERM);
-
- /*
- * We have arranged things so that printing this now either will
- * be legal, or the "E fatal error" line will get glommed onto the
- * end of an existing "E" or "M" response.
- */
-
- /* If this gives an error, not much we could do. syslog() it? */
- write (STDOUT_FILENO, msg, sizeof (msg) - 1);
-#ifdef HAVE_SYSLOG_H
- syslog (LOG_DAEMON | LOG_ERR, "virtual memory exhausted");
-#endif
- error_exit ();
-}
-
-static void
-input_memory_error (buf)
- struct buffer *buf;
-{
- outbuf_memory_error (buf);
-}
-
-
-
-/* If command is legal, return 1.
- * Else if command is illegal and croak_on_illegal is set, then die.
- * Else just return 0 to indicate that command is illegal.
- */
-static int
-check_command_legal_p (cmd_name)
- char *cmd_name;
-{
- /* Right now, only pserver notices illegal commands -- namely,
- * write attempts by a read-only user. Therefore, if CVS_Username
- * is not set, this just returns 1, because CVS_Username unset
- * means pserver is not active.
- */
-#ifdef AUTH_SERVER_SUPPORT
- if (CVS_Username == NULL)
- return 1;
-
- if (lookup_command_attribute (cmd_name) & CVS_CMD_MODIFIES_REPOSITORY)
- {
- /* This command has the potential to modify the repository, so
- * we check if the user have permission to do that.
- *
- * (Only relevant for remote users -- local users can do
- * whatever normal Unix file permissions allow them to do.)
- *
- * The decision method:
- *
- * If $CVSROOT/CVSADMROOT_READERS exists and user is listed
- * in it, then read-only access for user.
- *
- * Or if $CVSROOT/CVSADMROOT_WRITERS exists and user NOT
- * listed in it, then also read-only access for user.
- *
- * Else read-write access for user.
- */
-
- char *linebuf = NULL;
- int num_red = 0;
- size_t linebuf_len = 0;
- char *fname;
- size_t flen;
- FILE *fp;
- int found_it = 0;
-
- /* else */
- flen = strlen (current_parsed_root->directory)
- + strlen (CVSROOTADM)
- + strlen (CVSROOTADM_READERS)
- + 3;
-
- fname = xmalloc (flen);
- (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
- CVSROOTADM, CVSROOTADM_READERS);
-
- fp = fopen (fname, "r");
-
- if (fp == NULL)
- {
- if (!existence_error (errno))
- {
- /* Need to deny access, so that attackers can't fool
- us with some sort of denial of service attack. */
- error (0, errno, "cannot open %s", fname);
- free (fname);
- return 0;
- }
- }
- else /* successfully opened readers file */
- {
- while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0)
- {
- /* Hmmm, is it worth importing my own readline
- library into CVS? It takes care of chopping
- leading and trailing whitespace, "#" comments, and
- newlines automatically when so requested. Would
- save some code here... -kff */
-
- /* Chop newline by hand, for strcmp()'s sake. */
- if (num_red > 0 && linebuf[num_red - 1] == '\n')
- linebuf[num_red - 1] = '\0';
-
- if (strcmp (linebuf, CVS_Username) == 0)
- goto handle_illegal;
- }
- if (num_red < 0 && !feof (fp))
- error (0, errno, "cannot read %s", fname);
-
- /* If not listed specifically as a reader, then this user
- has write access by default unless writers are also
- specified in a file . */
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", fname);
- }
- free (fname);
-
- /* Now check the writers file. */
-
- flen = strlen (current_parsed_root->directory)
- + strlen (CVSROOTADM)
- + strlen (CVSROOTADM_WRITERS)
- + 3;
-
- fname = xmalloc (flen);
- (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
- CVSROOTADM, CVSROOTADM_WRITERS);
-
- fp = fopen (fname, "r");
-
- if (fp == NULL)
- {
- if (linebuf)
- free (linebuf);
- if (existence_error (errno))
- {
- /* Writers file does not exist, so everyone is a writer,
- by default. */
- free (fname);
- return 1;
- }
- else
- {
- /* Need to deny access, so that attackers can't fool
- us with some sort of denial of service attack. */
- error (0, errno, "cannot read %s", fname);
- free (fname);
- return 0;
- }
- }
-
- found_it = 0;
- while ((num_red = getline (&linebuf, &linebuf_len, fp)) >= 0)
- {
- /* Chop newline by hand, for strcmp()'s sake. */
- if (num_red > 0 && linebuf[num_red - 1] == '\n')
- linebuf[num_red - 1] = '\0';
-
- if (strcmp (linebuf, CVS_Username) == 0)
- {
- found_it = 1;
- break;
- }
- }
- if (num_red < 0 && !feof (fp))
- error (0, errno, "cannot read %s", fname);
-
- if (found_it)
- {
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", fname);
- if (linebuf)
- free (linebuf);
- free (fname);
- return 1;
- }
- else /* writers file exists, but this user not listed in it */
- {
- handle_illegal:
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", fname);
- if (linebuf)
- free (linebuf);
- free (fname);
- return 0;
- }
- }
-#endif /* AUTH_SERVER_SUPPORT */
-
- /* If ever reach end of this function, command must be legal. */
- return 1;
-}
-
-
-
-/* Execute COMMAND in a subprocess with the approriate funky things done. */
-
-static struct fd_set_wrapper { fd_set fds; } command_fds_to_drain;
-#ifdef SUNOS_KLUDGE
-static int max_command_fd;
-#endif
-
-#ifdef SERVER_FLOWCONTROL
-static int flowcontrol_pipe[2];
-#endif /* SERVER_FLOWCONTROL */
-
-
-
-/*
- * Set buffer FD to non-blocking I/O. Returns 0 for success or errno
- * code.
- */
-int
-set_nonblock_fd (fd)
- int fd;
-{
- int flags;
-
- flags = fcntl (fd, F_GETFL, 0);
- if (flags < 0)
- return errno;
- if (fcntl (fd, F_SETFL, flags | O_NONBLOCK) < 0)
- return errno;
- return 0;
-}
-
-
-
-/*
- * Set buffer FD to blocking I/O. Returns 0 for success or errno code.
- */
-int
-set_block_fd (fd)
- int fd;
-{
- int flags;
-
- flags = fcntl (fd, F_GETFL, 0);
- if (flags < 0)
- return errno;
- if (fcntl (fd, F_SETFL, flags & ~O_NONBLOCK) < 0)
- return errno;
- return 0;
-}
-
-
-
-static void
-do_cvs_command (cmd_name, command)
- char *cmd_name;
- int (*command) PROTO((int argc, char **argv));
-{
- /*
- * The following file descriptors are set to -1 if that file is not
- * currently open.
- */
-
- /* Data on these pipes is a series of '\n'-terminated lines. */
- int stdout_pipe[2];
- int stderr_pipe[2];
-
- /*
- * Data on this pipe is a series of counted (see buf_send_counted)
- * packets. Each packet must be processed atomically (i.e. not
- * interleaved with data from stdout_pipe or stderr_pipe).
- */
- int protocol_pipe[2];
-
- int dev_null_fd = -1;
-
- int errs = 0;
-
- command_pid = -1;
- stdout_pipe[0] = -1;
- stdout_pipe[1] = -1;
- stderr_pipe[0] = -1;
- stderr_pipe[1] = -1;
- protocol_pipe[0] = -1;
- protocol_pipe[1] = -1;
-
- server_write_entries ();
-
- if (print_pending_error ())
- goto free_args_and_return;
-
- /* Global `cvs_cmd_name' is probably "server" right now -- only
- serve_export() sets it to anything else. So we will use local
- parameter `cmd_name' to determine if this command is legal for
- this user. */
- if (!check_command_legal_p (cmd_name))
- {
- buf_output0 (buf_to_net, "E ");
- buf_output0 (buf_to_net, program_name);
- buf_output0 (buf_to_net, " [server aborted]: \"");
- buf_output0 (buf_to_net, cmd_name);
- buf_output0 (buf_to_net, "\" requires write access to the repository\n\
-error \n");
- goto free_args_and_return;
- }
- cvs_cmd_name = cmd_name;
-
- (void) server_notify ();
-
- /*
- * We use a child process which actually does the operation. This
- * is so we can intercept its standard output. Even if all of CVS
- * were written to go to some special routine instead of writing
- * to stdout or stderr, we would still need to do the same thing
- * for the RCS commands.
- */
-
- if (pipe (stdout_pipe) < 0)
- {
- buf_output0 (buf_to_net, "E pipe failed\n");
- print_error (errno);
- goto error_exit;
- }
- if (pipe (stderr_pipe) < 0)
- {
- buf_output0 (buf_to_net, "E pipe failed\n");
- print_error (errno);
- goto error_exit;
- }
- if (pipe (protocol_pipe) < 0)
- {
- buf_output0 (buf_to_net, "E pipe failed\n");
- print_error (errno);
- goto error_exit;
- }
-#ifdef SERVER_FLOWCONTROL
- if (pipe (flowcontrol_pipe) < 0)
- {
- buf_output0 (buf_to_net, "E pipe failed\n");
- print_error (errno);
- goto error_exit;
- }
- set_nonblock_fd (flowcontrol_pipe[0]);
- set_nonblock_fd (flowcontrol_pipe[1]);
-#endif /* SERVER_FLOWCONTROL */
-
- dev_null_fd = CVS_OPEN (DEVNULL, O_RDONLY);
- if (dev_null_fd < 0)
- {
- buf_output0 (buf_to_net, "E open /dev/null failed\n");
- print_error (errno);
- goto error_exit;
- }
-
- /* We shouldn't have any partial lines from cvs_output and
- cvs_outerr, but we handle them here in case there is a bug. */
- /* FIXME: appending a newline, rather than using "MT" as we
- do in the child process, is probably not really a very good
- way to "handle" them. */
- if (! buf_empty_p (saved_output))
- {
- buf_append_char (saved_output, '\n');
- buf_copy_lines (buf_to_net, saved_output, 'M');
- }
- if (! buf_empty_p (saved_outerr))
- {
- buf_append_char (saved_outerr, '\n');
- buf_copy_lines (buf_to_net, saved_outerr, 'E');
- }
-
- /* Flush out any pending data. */
- buf_flush (buf_to_net, 1);
-
- /* Don't use vfork; we're not going to exec(). */
- command_pid = fork ();
- if (command_pid < 0)
- {
- buf_output0 (buf_to_net, "E fork failed\n");
- print_error (errno);
- goto error_exit;
- }
- if (command_pid == 0)
- {
- int exitstatus;
-
- /* Since we're in the child, and the parent is going to take
- care of packaging up our error messages, we can clear this
- flag. */
- error_use_protocol = 0;
-
- protocol = fd_buffer_initialize (protocol_pipe[1], 0,
- protocol_memory_error);
-
- /* At this point we should no longer be using buf_to_net and
- buf_from_net. Instead, everything should go through
- protocol. */
- if (buf_to_net != NULL)
- {
- buf_free (buf_to_net);
- buf_to_net = NULL;
- }
- if (buf_from_net != NULL)
- {
- buf_free (buf_from_net);
- buf_from_net = NULL;
- }
-
- /* These were originally set up to use outbuf_memory_error.
- Since we're now in the child, we should use the simpler
- protocol_memory_error function. */
- saved_output->memory_error = protocol_memory_error;
- saved_outerr->memory_error = protocol_memory_error;
-
- if (dup2 (dev_null_fd, STDIN_FILENO) < 0)
- error (1, errno, "can't set up pipes");
- if (dup2 (stdout_pipe[1], STDOUT_FILENO) < 0)
- error (1, errno, "can't set up pipes");
- if (dup2 (stderr_pipe[1], STDERR_FILENO) < 0)
- error (1, errno, "can't set up pipes");
- close (dev_null_fd);
- close (stdout_pipe[0]);
- close (stdout_pipe[1]);
- close (stderr_pipe[0]);
- close (stderr_pipe[1]);
- close (protocol_pipe[0]);
- close_on_exec (protocol_pipe[1]);
-#ifdef SERVER_FLOWCONTROL
- close_on_exec (flowcontrol_pipe[0]);
- close (flowcontrol_pipe[1]);
-#endif /* SERVER_FLOWCONTROL */
-
- /*
- * Set this in .bashrc if you want to give yourself time to attach
- * to the subprocess with a debugger.
- */
- if (getenv ("CVS_SERVER_SLEEP"))
- {
- int secs = atoi (getenv ("CVS_SERVER_SLEEP"));
- sleep (secs);
- }
-
- exitstatus = (*command) (argument_count, argument_vector);
-
- /* Output any partial lines. If the client doesn't support
- "MT", we go ahead and just tack on a newline since the
- protocol doesn't support anything better. */
- if (! buf_empty_p (saved_output))
- {
- buf_output0 (protocol, supported_response ("MT") ? "MT text " : "M ");
- buf_append_buffer (protocol, saved_output);
- buf_output (protocol, "\n", 1);
- buf_send_counted (protocol);
- }
- /* For now we just discard partial lines on stderr. I suspect
- that CVS can't write such lines unless there is a bug. */
-
- buf_free (protocol);
-
- /* Close the pipes explicitly in order to send an EOF to the parent,
- * then wait for the parent to close the flow control pipe. This
- * avoids a race condition where a child which dumped more than the
- * high water mark into the pipes could complete its job and exit,
- * leaving the parent process to attempt to write a stop byte to the
- * closed flow control pipe, which earned the parent a SIGPIPE, which
- * it normally only expects on the network pipe and that causes it to
- * exit with an error message, rather than the SIGCHILD that it knows
- * how to handle correctly.
- */
- /* Let exit() close STDIN - it's from /dev/null anyhow. */
- fclose (stderr);
- fclose (stdout);
- close (protocol_pipe[1]);
-#ifdef SERVER_FLOWCONTROL
- {
- char junk;
- set_block_fd (flowcontrol_pipe[0]);
- while (read (flowcontrol_pipe[0], &junk, 1) > 0);
- }
- /* FIXME: No point in printing an error message with error(),
- * as STDERR is already closed, but perhaps this could be syslogged?
- */
-#endif
-
- rcs_cleanup ();
- Lock_Cleanup ();
- /* Don't call server_cleanup - the parent will handle that. */
-#ifdef SYSTEM_CLEANUP
- /* Hook for OS-specific behavior, for example socket subsystems on
- NT and OS2 or dealing with windows and arguments on Mac. */
- SYSTEM_CLEANUP ();
-#endif
- exit (exitstatus);
- }
-
- /* OK, sit around getting all the input from the child. */
- {
- struct buffer *stdoutbuf = NULL;
- struct buffer *stderrbuf = NULL;
- struct buffer *protocol_inbuf = NULL;
- int err_exit = 0;
- /* Number of file descriptors to check in select (). */
- int num_to_check;
- int count_needed = 1;
-#ifdef SERVER_FLOWCONTROL
- int have_flowcontrolled = 0;
-#endif /* SERVER_FLOWCONTROL */
-
- FD_ZERO (&command_fds_to_drain.fds);
- num_to_check = stdout_pipe[0];
- FD_SET (stdout_pipe[0], &command_fds_to_drain.fds);
- if (stderr_pipe[0] > num_to_check)
- num_to_check = stderr_pipe[0];
- FD_SET (stderr_pipe[0], &command_fds_to_drain.fds);
- if (protocol_pipe[0] > num_to_check)
- num_to_check = protocol_pipe[0];
- FD_SET (protocol_pipe[0], &command_fds_to_drain.fds);
- if (STDOUT_FILENO > num_to_check)
- num_to_check = STDOUT_FILENO;
-#ifdef SUNOS_KLUDGE
- max_command_fd = num_to_check;
-#endif
- /*
- * File descriptors are numbered from 0, so num_to_check needs to
- * be one larger than the largest descriptor.
- */
- ++num_to_check;
- if (num_to_check > FD_SETSIZE)
- {
- buf_output0 (buf_to_net,
- "E internal error: FD_SETSIZE not big enough.\n\
-error \n");
- goto error_exit;
- }
-
- stdoutbuf = fd_buffer_initialize (stdout_pipe[0], 1,
- input_memory_error);
-
- stderrbuf = fd_buffer_initialize (stderr_pipe[0], 1,
- input_memory_error);
-
- protocol_inbuf = fd_buffer_initialize (protocol_pipe[0], 1,
- input_memory_error);
-
- set_nonblock (buf_to_net);
- set_nonblock (stdoutbuf);
- set_nonblock (stderrbuf);
- set_nonblock (protocol_inbuf);
-
- if (close (stdout_pipe[1]) < 0)
- {
- buf_output0 (buf_to_net, "E close failed\n");
- print_error (errno);
- err_exit = 1;
- goto child_finish;
- }
- stdout_pipe[1] = -1;
-
- if (close (stderr_pipe[1]) < 0)
- {
- buf_output0 (buf_to_net, "E close failed\n");
- print_error (errno);
- err_exit = 1;
- goto child_finish;
- }
- stderr_pipe[1] = -1;
-
- if (close (protocol_pipe[1]) < 0)
- {
- buf_output0 (buf_to_net, "E close failed\n");
- print_error (errno);
- err_exit = 1;
- goto child_finish;
- }
- protocol_pipe[1] = -1;
-
-#ifdef SERVER_FLOWCONTROL
- if (close (flowcontrol_pipe[0]) < 0)
- {
- buf_output0 (buf_to_net, "E close failed\n");
- print_error (errno);
- err_exit = 1;
- goto child_finish;
- }
- flowcontrol_pipe[0] = -1;
-#endif /* SERVER_FLOWCONTROL */
-
- if (close (dev_null_fd) < 0)
- {
- buf_output0 (buf_to_net, "E close failed\n");
- print_error (errno);
- dev_null_fd = -1; /* Do not try to close it again. */
- err_exit = 1;
- goto child_finish;
- }
- dev_null_fd = -1;
-
- while (stdout_pipe[0] >= 0
- || stderr_pipe[0] >= 0
- || protocol_pipe[0] >= 0
- || count_needed <= 0)
- {
- fd_set readfds;
- fd_set writefds;
- int numfds;
- struct timeval *timeout_ptr;
- struct timeval timeout;
-#ifdef SERVER_FLOWCONTROL
- int bufmemsize;
-
- /*
- * See if we are swamping the remote client and filling our VM.
- * Tell child to hold off if we do.
- */
- bufmemsize = buf_count_mem (buf_to_net);
- if (!have_flowcontrolled && (bufmemsize > SERVER_HI_WATER))
- {
- if (write(flowcontrol_pipe[1], "S", 1) == 1)
- have_flowcontrolled = 1;
- }
- else if (have_flowcontrolled && (bufmemsize < SERVER_LO_WATER))
- {
- if (write(flowcontrol_pipe[1], "G", 1) == 1)
- have_flowcontrolled = 0;
- }
-#endif /* SERVER_FLOWCONTROL */
-
- FD_ZERO (&readfds);
- FD_ZERO (&writefds);
-
- if (count_needed <= 0)
- {
- /* there is data pending which was read from the protocol pipe
- * so don't block if we don't find any data
- */
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
- timeout_ptr = &timeout;
- }
- else
- {
- /* block indefinately */
- timeout_ptr = NULL;
- }
-
- if (! buf_empty_p (buf_to_net))
- FD_SET (STDOUT_FILENO, &writefds);
-
- if (stdout_pipe[0] >= 0)
- {
- FD_SET (stdout_pipe[0], &readfds);
- }
- if (stderr_pipe[0] >= 0)
- {
- FD_SET (stderr_pipe[0], &readfds);
- }
- if (protocol_pipe[0] >= 0)
- {
- FD_SET (protocol_pipe[0], &readfds);
- }
-
- /* This process of selecting on the three pipes means that
- we might not get output in the same order in which it
- was written, thus producing the well-known
- "out-of-order" bug. If the child process uses
- cvs_output and cvs_outerr, it will send everything on
- the protocol_pipe and avoid this problem, so the
- solution is to use cvs_output and cvs_outerr in the
- child process. */
- do {
- /* This used to select on exceptions too, but as far
- as I know there was never any reason to do that and
- SCO doesn't let you select on exceptions on pipes. */
- numfds = select (num_to_check, &readfds, &writefds,
- (fd_set *)0, timeout_ptr);
- if (numfds < 0
- && errno != EINTR)
- {
- buf_output0 (buf_to_net, "E select failed\n");
- print_error (errno);
- err_exit = 1;
- goto child_finish;
- }
- } while (numfds < 0);
-
- if (numfds == 0)
- {
- FD_ZERO (&readfds);
- FD_ZERO (&writefds);
- }
-
- if (FD_ISSET (STDOUT_FILENO, &writefds))
- {
- /* What should we do with errors? syslog() them? */
- buf_send_output (buf_to_net);
- }
-
- if (protocol_pipe[0] >= 0
- && (FD_ISSET (protocol_pipe[0], &readfds)))
- {
- int status;
- int count_read;
-
- status = buf_input_data (protocol_inbuf, &count_read);
-
- if (status == -1)
- {
- close (protocol_pipe[0]);
- protocol_pipe[0] = -1;
- }
- else if (status > 0)
- {
- buf_output0 (buf_to_net, "E buf_input_data failed\n");
- print_error (status);
- err_exit = 1;
- goto child_finish;
- }
-
- /*
- * We only call buf_copy_counted if we have read
- * enough bytes to make it worthwhile. This saves us
- * from continually recounting the amount of data we
- * have.
- */
- count_needed -= count_read;
- }
- /* this is still part of the protocol pipe procedure, but it is
- * outside the above conditional so that unprocessed data can be
- * left in the buffer and stderr/stdout can be read when a flush
- * signal is received and control can return here without passing
- * through the select code and maybe blocking
- */
- while (count_needed <= 0)
- {
- int special = 0;
-
- count_needed = buf_copy_counted (buf_to_net,
- protocol_inbuf,
- &special);
-
- /* What should we do with errors? syslog() them? */
- buf_send_output (buf_to_net);
-
- /* If SPECIAL got set to <0, it means that the child
- * wants us to flush the pipe & maybe stderr or stdout.
- *
- * After that we break to read stderr & stdout again before
- * going back to the protocol pipe
- *
- * Upon breaking, count_needed = 0, so the next pass will only
- * perform a non-blocking select before returning here to finish
- * processing data we already read from the protocol buffer
- */
- if (special == -1)
- {
- cvs_flushout();
- break;
- }
- if (special == -2)
- {
- /* If the client supports the 'F' command, we send it. */
- if (supported_response ("F"))
- {
- buf_append_char (buf_to_net, 'F');
- buf_append_char (buf_to_net, '\n');
- }
- cvs_flusherr ();
- break;
- }
- }
-
- if (stdout_pipe[0] >= 0
- && (FD_ISSET (stdout_pipe[0], &readfds)))
- {
- int status;
-
- status = buf_input_data (stdoutbuf, (int *) NULL);
-
- buf_copy_lines (buf_to_net, stdoutbuf, 'M');
-
- if (status == -1)
- {
- close (stdout_pipe[0]);
- stdout_pipe[0] = -1;
- }
- else if (status > 0)
- {
- buf_output0 (buf_to_net, "E buf_input_data failed\n");
- print_error (status);
- err_exit = 1;
- goto child_finish;
- }
-
- /* What should we do with errors? syslog() them? */
- buf_send_output (buf_to_net);
- }
-
- if (stderr_pipe[0] >= 0
- && (FD_ISSET (stderr_pipe[0], &readfds)))
- {
- int status;
-
- status = buf_input_data (stderrbuf, (int *) NULL);
-
- buf_copy_lines (buf_to_net, stderrbuf, 'E');
-
- if (status == -1)
- {
- close (stderr_pipe[0]);
- stderr_pipe[0] = -1;
- }
- else if (status > 0)
- {
- buf_output0 (buf_to_net, "E buf_input_data failed\n");
- print_error (status);
- err_exit = 1;
- goto child_finish;
- }
-
- /* What should we do with errors? syslog() them? */
- buf_send_output (buf_to_net);
- }
- }
-
- /*
- * OK, we've gotten EOF on all the pipes. If there is
- * anything left on stdoutbuf or stderrbuf (this could only
- * happen if there was no trailing newline), send it over.
- */
- if (! buf_empty_p (stdoutbuf))
- {
- buf_append_char (stdoutbuf, '\n');
- buf_copy_lines (buf_to_net, stdoutbuf, 'M');
- }
- if (! buf_empty_p (stderrbuf))
- {
- buf_append_char (stderrbuf, '\n');
- buf_copy_lines (buf_to_net, stderrbuf, 'E');
- }
- if (! buf_empty_p (protocol_inbuf))
- buf_output0 (buf_to_net,
- "E Protocol error: uncounted data discarded\n");
-
-#ifdef SERVER_FLOWCONTROL
- close (flowcontrol_pipe[1]);
- flowcontrol_pipe[1] = -1;
-#endif /* SERVER_FLOWCONTROL */
-
- errs = 0;
-
- while (command_pid > 0)
- {
- int status;
- pid_t waited_pid;
- waited_pid = waitpid (command_pid, &status, 0);
- if (waited_pid < 0)
- {
- /*
- * Intentionally ignoring EINTR. Other errors
- * "can't happen".
- */
- continue;
- }
-
- if (WIFEXITED (status))
- errs += WEXITSTATUS (status);
- else
- {
- int sig = WTERMSIG (status);
- char buf[50];
- /*
- * This is really evil, because signals might be numbered
- * differently on the two systems. We should be using
- * signal names (either of the "Terminated" or the "SIGTERM"
- * variety). But cvs doesn't currently use libiberty...we
- * could roll our own.... FIXME.
- */
- buf_output0 (buf_to_net, "E Terminated with fatal signal ");
- sprintf (buf, "%d\n", sig);
- buf_output0 (buf_to_net, buf);
-
- /* Test for a core dump. */
- if (WCOREDUMP (status))
- {
- buf_output0 (buf_to_net, "E Core dumped; preserving ");
- buf_output0 (buf_to_net, orig_server_temp_dir);
- buf_output0 (buf_to_net, " on server.\n\
-E CVS locks may need cleaning up.\n");
- dont_delete_temp = 1;
- }
- ++errs;
- }
- if (waited_pid == command_pid)
- command_pid = -1;
- }
-
- child_finish:
- /*
- * OK, we've waited for the child. By now all CVS locks are free
- * and it's OK to block on the network.
- */
- set_block (buf_to_net);
- buf_flush (buf_to_net, 1);
- if (protocol_inbuf)
- {
- buf_shutdown (protocol_inbuf);
- buf_free (protocol_inbuf);
- protocol_inbuf = NULL;
- }
- if (stderrbuf)
- {
- buf_shutdown (stderrbuf);
- buf_free (stderrbuf);
- stderrbuf = NULL;
- }
- if (stdoutbuf)
- {
- buf_shutdown (stdoutbuf);
- buf_free (stdoutbuf);
- stdoutbuf = NULL;
- }
- if (err_exit)
- goto error_exit;
- }
-
- if (errs)
- /* We will have printed an error message already. */
- buf_output0 (buf_to_net, "error \n");
- else
- buf_output0 (buf_to_net, "ok\n");
- goto free_args_and_return;
-
- error_exit:
- if (command_pid > 0)
- kill (command_pid, SIGTERM);
-
- while (command_pid > 0)
- {
- pid_t waited_pid;
- waited_pid = waitpid (command_pid, (int *) 0, 0);
- if (waited_pid < 0 && errno == EINTR)
- continue;
- if (waited_pid == command_pid)
- command_pid = -1;
- }
-
- if (dev_null_fd >= 0)
- close (dev_null_fd);
- close (protocol_pipe[0]);
- close (protocol_pipe[1]);
- close (stderr_pipe[0]);
- close (stderr_pipe[1]);
- close (stdout_pipe[0]);
- close (stdout_pipe[1]);
-#ifdef SERVER_FLOWCONTROL
- close (flowcontrol_pipe[0]);
- close (flowcontrol_pipe[1]);
-#endif /* SERVER_FLOWCONTROL */
-
- free_args_and_return:
- /* Now free the arguments. */
- {
- /* argument_vector[0] is a dummy argument, we don't mess with it. */
- char **cp;
- for (cp = argument_vector + 1;
- cp < argument_vector + argument_count;
- ++cp)
- free (*cp);
-
- argument_count = 1;
- }
-
- /* Flush out any data not yet sent. */
- set_block (buf_to_net);
- buf_flush (buf_to_net, 1);
-
- return;
-}
-
-#ifdef SERVER_FLOWCONTROL
-/*
- * Called by the child at convenient points in the server's execution for
- * the server child to block.. ie: when it has no locks active.
- */
-void
-server_pause_check()
-{
- int paused = 0;
- char buf[1];
-
- while (read (flowcontrol_pipe[0], buf, 1) == 1)
- {
- if (*buf == 'S') /* Stop */
- paused = 1;
- else if (*buf == 'G') /* Go */
- paused = 0;
- else
- return; /* ??? */
- }
- while (paused) {
- int numfds, numtocheck;
- fd_set fds;
-
- FD_ZERO (&fds);
- FD_SET (flowcontrol_pipe[0], &fds);
- numtocheck = flowcontrol_pipe[0] + 1;
-
- do {
- numfds = select (numtocheck, &fds, (fd_set *)0,
- (fd_set *)0, (struct timeval *)NULL);
- if (numfds < 0
- && errno != EINTR)
- {
- buf_output0 (buf_to_net, "E select failed\n");
- print_error (errno);
- return;
- }
- } while (numfds < 0);
-
- if (FD_ISSET (flowcontrol_pipe[0], &fds))
- {
- int got;
-
- while ((got = read (flowcontrol_pipe[0], buf, 1)) == 1)
- {
- if (*buf == 'S') /* Stop */
- paused = 1;
- else if (*buf == 'G') /* Go */
- paused = 0;
- else
- return; /* ??? */
- }
-
- /* This assumes that we are using BSD or POSIX nonblocking
- I/O. System V nonblocking I/O returns zero if there is
- nothing to read. */
- if (got == 0)
- error (1, 0, "flow control EOF");
- if (got < 0 && ! blocking_error (errno))
- {
- error (1, errno, "flow control read failed");
- }
- }
- }
-}
-#endif /* SERVER_FLOWCONTROL */
-
-/* This variable commented in server.h. */
-char *server_dir = NULL;
-
-
-
-static void output_dir PROTO((const char *, const char *));
-
-static void
-output_dir (update_dir, repository)
- const char *update_dir;
- const char *repository;
-{
- if (server_dir != NULL)
- {
- buf_output0 (protocol, server_dir);
- buf_output0 (protocol, "/");
- }
- if (update_dir[0] == '\0')
- buf_output0 (protocol, ".");
- else
- buf_output0 (protocol, update_dir);
- buf_output0 (protocol, "/\n");
- buf_output0 (protocol, repository);
- buf_output0 (protocol, "/");
-}
-
-
-
-/*
- * Entries line that we are squirreling away to send to the client when
- * we are ready.
- */
-static char *entries_line;
-
-/*
- * File which has been Scratch_File'd, we are squirreling away that fact
- * to inform the client when we are ready.
- */
-static char *scratched_file;
-
-/*
- * The scratched_file will need to be removed as well as having its entry
- * removed.
- */
-static int kill_scratched_file;
-
-
-
-void
-server_register (name, version, timestamp, options, tag, date, conflict)
- const char *name;
- const char *version;
- const char *timestamp;
- const char *options;
- const char *tag;
- const char *date;
- const char *conflict;
-{
- int len;
-
- if (options == NULL)
- options = "";
-
- if (trace)
- {
- (void) fprintf (stderr,
- "%s-> server_register(%s, %s, %s, %s, %s, %s, %s)\n",
- CLIENT_SERVER_STR,
- name, version, timestamp ? timestamp : "", options,
- tag ? tag : "", date ? date : "",
- conflict ? conflict : "");
- }
-
- if (entries_line != NULL)
- {
- /*
- * If CVS decides to Register it more than once (which happens
- * on "cvs update foo/foo.c" where foo and foo.c are already
- * checked out), use the last of the entries lines Register'd.
- */
- free (entries_line);
- }
-
- /*
- * I have reports of Scratch_Entry and Register both happening, in
- * two different cases. Using the last one which happens is almost
- * surely correct; I haven't tracked down why they both happen (or
- * even verified that they are for the same file).
- */
- if (scratched_file != NULL)
- {
- free (scratched_file);
- scratched_file = NULL;
- }
-
- len = (strlen (name) + strlen (version) + strlen (options) + 80);
- if (tag)
- len += strlen (tag);
- if (date)
- len += strlen (date);
-
- entries_line = xmalloc (len);
- sprintf (entries_line, "/%s/%s/", name, version);
- if (conflict != NULL)
- {
- strcat (entries_line, "+=");
- }
- strcat (entries_line, "/");
- strcat (entries_line, options);
- strcat (entries_line, "/");
- if (tag != NULL)
- {
- strcat (entries_line, "T");
- strcat (entries_line, tag);
- }
- else if (date != NULL)
- {
- strcat (entries_line, "D");
- strcat (entries_line, date);
- }
-}
-
-
-
-void
-server_scratch (fname)
- const char *fname;
-{
- /*
- * I have reports of Scratch_Entry and Register both happening, in
- * two different cases. Using the last one which happens is almost
- * surely correct; I haven't tracked down why they both happen (or
- * even verified that they are for the same file).
- *
- * Don't know if this is what whoever wrote the above comment was
- * talking about, but this can happen in the case where a join
- * removes a file - the call to Register puts the '-vers' into the
- * Entries file after the file is removed
- */
- if (entries_line != NULL)
- {
- free (entries_line);
- entries_line = NULL;
- }
-
- if (scratched_file != NULL)
- {
- buf_output0 (protocol,
- "E CVS server internal error: duplicate Scratch_Entry\n");
- buf_send_counted (protocol);
- return;
- }
- scratched_file = xstrdup (fname);
- kill_scratched_file = 1;
-}
-
-void
-server_scratch_entry_only ()
-{
- kill_scratched_file = 0;
-}
-
-/* Print a new entries line, from a previous server_register. */
-static void
-new_entries_line ()
-{
- if (entries_line)
- {
- buf_output0 (protocol, entries_line);
- buf_output (protocol, "\n", 1);
- }
- else
- /* Return the error message as the Entries line. */
- buf_output0 (protocol,
- "CVS server internal error: Register missing\n");
- free (entries_line);
- entries_line = NULL;
-}
-
-
-static void
-serve_ci (arg)
- char *arg;
-{
- do_cvs_command ("commit", commit);
-}
-
-static void
-checked_in_response (file, update_dir, repository)
- char *file;
- char *update_dir;
- char *repository;
-{
- if (supported_response ("Mode"))
- {
- struct stat sb;
- char *mode_string;
-
- if ( CVS_STAT (file, &sb) < 0)
- {
- /* Not clear to me why the file would fail to exist, but it
- was happening somewhere in the testsuite. */
- if (!existence_error (errno))
- error (0, errno, "cannot stat %s", file);
- }
- else
- {
- buf_output0 (protocol, "Mode ");
- mode_string = mode_to_string (sb.st_mode);
- buf_output0 (protocol, mode_string);
- buf_output0 (protocol, "\n");
- free (mode_string);
- }
- }
-
- buf_output0 (protocol, "Checked-in ");
- output_dir (update_dir, repository);
- buf_output0 (protocol, file);
- buf_output (protocol, "\n", 1);
- new_entries_line ();
-}
-
-void
-server_checked_in (file, update_dir, repository)
- const char *file;
- const char *update_dir;
- const char *repository;
-{
- assert (file);
- assert (update_dir);
- assert (repository);
-
- if (noexec)
- return;
- if (scratched_file != NULL && entries_line == NULL)
- {
- /*
- * This happens if we are now doing a "cvs remove" after a previous
- * "cvs add" (without a "cvs ci" in between).
- */
- buf_output0 (protocol, "Remove-entry ");
- output_dir (update_dir, repository);
- buf_output0 (protocol, file);
- buf_output (protocol, "\n", 1);
- free (scratched_file);
- scratched_file = NULL;
- }
- else
- {
- checked_in_response (file, update_dir, repository);
- }
- buf_send_counted (protocol);
-}
-
-void
-server_update_entries (file, update_dir, repository, updated)
- const char *file;
- const char *update_dir;
- const char *repository;
- enum server_updated_arg4 updated;
-{
- if (noexec)
- return;
- if (updated == SERVER_UPDATED)
- checked_in_response (file, update_dir, repository);
- else
- {
- if (!supported_response ("New-entry"))
- return;
- buf_output0 (protocol, "New-entry ");
- output_dir (update_dir, repository);
- buf_output0 (protocol, file);
- buf_output (protocol, "\n", 1);
- new_entries_line ();
- }
-
- buf_send_counted (protocol);
-}
-
-static void
-serve_update (arg)
- char *arg;
-{
- do_cvs_command ("update", update);
-}
-
-static void
-serve_diff (arg)
- char *arg;
-{
- do_cvs_command ("diff", diff);
-}
-
-static void
-serve_log (arg)
- char *arg;
-{
- do_cvs_command ("log", cvslog);
-}
-
-static void
-serve_rlog (arg)
- char *arg;
-{
- do_cvs_command ("rlog", cvslog);
-}
-
-static void
-serve_add (arg)
- char *arg;
-{
- do_cvs_command ("add", add);
-}
-
-static void
-serve_remove (arg)
- char *arg;
-{
- do_cvs_command ("remove", cvsremove);
-}
-
-static void
-serve_status (arg)
- char *arg;
-{
- do_cvs_command ("status", cvsstatus);
-}
-
-static void
-serve_rdiff (arg)
- char *arg;
-{
- do_cvs_command ("rdiff", patch);
-}
-
-static void
-serve_tag (arg)
- char *arg;
-{
- do_cvs_command ("tag", cvstag);
-}
-
-static void
-serve_rtag (arg)
- char *arg;
-{
- do_cvs_command ("rtag", cvstag);
-}
-
-static void
-serve_import (arg)
- char *arg;
-{
- do_cvs_command ("import", import);
-}
-
-static void
-serve_admin (arg)
- char *arg;
-{
- do_cvs_command ("admin", admin);
-}
-
-static void
-serve_history (arg)
- char *arg;
-{
- do_cvs_command ("history", history);
-}
-
-static void
-serve_release (arg)
- char *arg;
-{
- do_cvs_command ("release", release);
-}
-
-static void serve_watch_on PROTO ((char *));
-
-static void
-serve_watch_on (arg)
- char *arg;
-{
- do_cvs_command ("watch", watch_on);
-}
-
-static void serve_watch_off PROTO ((char *));
-
-static void
-serve_watch_off (arg)
- char *arg;
-{
- do_cvs_command ("watch", watch_off);
-}
-
-static void serve_watch_add PROTO ((char *));
-
-static void
-serve_watch_add (arg)
- char *arg;
-{
- do_cvs_command ("watch", watch_add);
-}
-
-static void serve_watch_remove PROTO ((char *));
-
-static void
-serve_watch_remove (arg)
- char *arg;
-{
- do_cvs_command ("watch", watch_remove);
-}
-
-static void serve_watchers PROTO ((char *));
-
-static void
-serve_watchers (arg)
- char *arg;
-{
- do_cvs_command ("watchers", watchers);
-}
-
-static void serve_editors PROTO ((char *));
-
-static void
-serve_editors (arg)
- char *arg;
-{
- do_cvs_command ("editors", editors);
-}
-
-static void serve_noop PROTO ((char *));
-
-static void
-serve_noop (arg)
- char *arg;
-{
-
- server_write_entries ();
- if (!print_pending_error ())
- {
- (void) server_notify ();
- buf_output0 (buf_to_net, "ok\n");
- }
- buf_flush (buf_to_net, 1);
-}
-
-static void serve_version PROTO ((char *));
-
-static void
-serve_version (arg)
- char *arg;
-{
- do_cvs_command ("version", version);
-}
-
-static void serve_init PROTO ((char *));
-
-static void
-serve_init (arg)
- char *arg;
-{
- if (alloc_pending (80 + strlen (arg)))
- sprintf (pending_error_text, "E init may not be run remotely");
-
- if (print_pending_error ())
- return;
-}
-
-static void serve_annotate PROTO ((char *));
-
-static void
-serve_annotate (arg)
- char *arg;
-{
- do_cvs_command ("annotate", annotate);
-}
-
-static void serve_rannotate PROTO ((char *));
-
-static void
-serve_rannotate (arg)
- char *arg;
-{
- do_cvs_command ("rannotate", annotate);
-}
-
-static void
-serve_co (arg)
- char *arg;
-{
- char *tempdir;
- int status;
-
- if (print_pending_error ())
- return;
-
- if (!isdir (CVSADM))
- {
- /*
- * The client has not sent a "Repository" line. Check out
- * into a pristine directory.
- */
- tempdir = xmalloc (strlen (server_temp_dir) + 80);
- if (tempdir == NULL)
- {
- buf_output0 (buf_to_net, "E Out of memory\n");
- return;
- }
- strcpy (tempdir, server_temp_dir);
- strcat (tempdir, "/checkout-dir");
- status = mkdir_p (tempdir);
- if (status != 0 && status != EEXIST)
- {
- buf_output0 (buf_to_net, "E Cannot create ");
- buf_output0 (buf_to_net, tempdir);
- buf_append_char (buf_to_net, '\n');
- print_error (errno);
- free (tempdir);
- return;
- }
-
- if ( CVS_CHDIR (tempdir) < 0)
- {
- buf_output0 (buf_to_net, "E Cannot change to directory ");
- buf_output0 (buf_to_net, tempdir);
- buf_append_char (buf_to_net, '\n');
- print_error (errno);
- free (tempdir);
- return;
- }
- free (tempdir);
- }
-
- /* Compensate for server_export()'s setting of cvs_cmd_name.
- *
- * [It probably doesn't matter if do_cvs_command() gets "export"
- * or "checkout", but we ought to be accurate where possible.]
- */
- do_cvs_command ((strcmp (cvs_cmd_name, "export") == 0) ?
- "export" : "checkout",
- checkout);
-}
-
-static void
-serve_export (arg)
- char *arg;
-{
- /* Tell checkout() to behave like export not checkout. */
- cvs_cmd_name = "export";
- serve_co (arg);
-}
-
-
-
-void
-server_copy_file (file, update_dir, repository, newfile)
- const char *file;
- const char *update_dir;
- const char *repository;
- const char *newfile;
-{
- /* At least for now, our practice is to have the server enforce
- noexec for the repository and the client enforce it for the
- working directory. This might want more thought, and/or
- documentation in cvsclient.texi (other responses do it
- differently). */
-
- if (!supported_response ("Copy-file"))
- return;
- buf_output0 (protocol, "Copy-file ");
- output_dir (update_dir, repository);
- buf_output0 (protocol, file);
- buf_output0 (protocol, "\n");
- buf_output0 (protocol, newfile);
- buf_output0 (protocol, "\n");
-}
-
-/* See server.h for description. */
-
-void
-server_modtime (finfo, vers_ts)
- struct file_info *finfo;
- Vers_TS *vers_ts;
-{
- char date[MAXDATELEN];
- char outdate[MAXDATELEN];
-
- assert (vers_ts->vn_rcs != NULL);
-
- if (!supported_response ("Mod-time"))
- return;
-
- if (RCS_getrevtime (finfo->rcs, vers_ts->vn_rcs, date, 0) == (time_t) -1)
- /* FIXME? should we be printing some kind of warning? For one
- thing I'm not 100% sure whether this happens in non-error
- circumstances. */
- return;
- date_to_internet (outdate, date);
- buf_output0 (protocol, "Mod-time ");
- buf_output0 (protocol, outdate);
- buf_output0 (protocol, "\n");
-}
-
-/* See server.h for description. */
-
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-/* Need to prototype because mode_t might be smaller than int. */
-void
-server_updated (
- struct file_info *finfo,
- Vers_TS *vers,
- enum server_updated_arg4 updated,
- mode_t mode,
- unsigned char *checksum,
- struct buffer *filebuf)
-#else
-void
-server_updated (finfo, vers, updated, mode, checksum, filebuf)
- struct file_info *finfo;
- Vers_TS *vers;
- enum server_updated_arg4 updated;
- mode_t mode;
- unsigned char *checksum;
- struct buffer *filebuf;
-#endif
-{
- if (noexec)
- {
- /* Hmm, maybe if we did the same thing for entries_file, we
- could get rid of the kludges in server_register and
- server_scratch which refrain from warning if both
- Scratch_Entry and Register get called. Maybe. */
- if (scratched_file)
- {
- free (scratched_file);
- scratched_file = NULL;
- }
- buf_send_counted (protocol);
- return;
- }
-
- if (entries_line != NULL && scratched_file == NULL)
- {
- FILE *f;
- struct buffer_data *list, *last;
- unsigned long size;
- char size_text[80];
-
- /* The contents of the file will be in one of filebuf,
- list/last, or here. */
- unsigned char *file;
- size_t file_allocated;
- size_t file_used;
-
- if (filebuf != NULL)
- {
- size = buf_length (filebuf);
- if (mode == (mode_t) -1)
- error (1, 0, "\
-CVS server internal error: no mode in server_updated");
- }
- else
- {
- struct stat sb;
-
- if ( CVS_STAT (finfo->file, &sb) < 0)
- {
- if (existence_error (errno))
- {
- /* If we have a sticky tag for a branch on which
- the file is dead, and cvs update the directory,
- it gets a T_CHECKOUT but no file. So in this
- case just forget the whole thing. */
- free (entries_line);
- entries_line = NULL;
- goto done;
- }
- error (1, errno, "reading %s", finfo->fullname);
- }
- size = sb.st_size;
- if (mode == (mode_t) -1)
- {
- /* FIXME: When we check out files the umask of the
- server (set in .bashrc if rsh is in use) affects
- what mode we send, and it shouldn't. */
- mode = sb.st_mode;
- }
- }
-
- if (checksum != NULL)
- {
- static int checksum_supported = -1;
-
- if (checksum_supported == -1)
- {
- checksum_supported = supported_response ("Checksum");
- }
-
- if (checksum_supported)
- {
- int i;
- char buf[3];
-
- buf_output0 (protocol, "Checksum ");
- for (i = 0; i < 16; i++)
- {
- sprintf (buf, "%02x", (unsigned int) checksum[i]);
- buf_output0 (protocol, buf);
- }
- buf_append_char (protocol, '\n');
- }
- }
-
- if (updated == SERVER_UPDATED)
- {
- Node *node;
-
- if (!(supported_response ("Created")
- && supported_response ("Update-existing")))
- buf_output0 (protocol, "Updated ");
- else
- {
- assert (vers != NULL);
- if (vers->ts_user == NULL)
- buf_output0 (protocol, "Created ");
- else
- buf_output0 (protocol, "Update-existing ");
- }
-
- /* Now munge the entries to say that the file is unmodified,
- in case we end up processing it again (e.g. modules3-6
- in the testsuite). */
- node = findnode_fn (finfo->entries, finfo->file);
- assert (node != NULL);
- if (node != NULL)
- {
- Entnode *entnode = node->data;
- free (entnode->timestamp);
- entnode->timestamp = xstrdup ("=");
- }
- }
- else if (updated == SERVER_MERGED)
- buf_output0 (protocol, "Merged ");
- else if (updated == SERVER_PATCHED)
- buf_output0 (protocol, "Patched ");
- else if (updated == SERVER_RCS_DIFF)
- buf_output0 (protocol, "Rcs-diff ");
- else
- abort ();
- output_dir (finfo->update_dir, finfo->repository);
- buf_output0 (protocol, finfo->file);
- buf_output (protocol, "\n", 1);
-
- new_entries_line ();
-
- {
- char *mode_string;
-
- mode_string = mode_to_string (mode);
- buf_output0 (protocol, mode_string);
- buf_output0 (protocol, "\n");
- free (mode_string);
- }
-
- list = last = NULL;
-
- file = NULL;
- file_allocated = 0;
- file_used = 0;
-
- if (size > 0)
- {
- /* Throughout this section we use binary mode to read the
- file we are sending. The client handles any line ending
- translation if necessary. */
-
- if (file_gzip_level
- /*
- * For really tiny files, the gzip process startup
- * time will outweigh the compression savings. This
- * might be computable somehow; using 100 here is just
- * a first approximation.
- */
- && size > 100)
- {
- /* Basing this routine on read_and_gzip is not a
- high-performance approach. But it seems easier
- to code than the alternative (and less
- vulnerable to subtle bugs). Given that this feature
- is mainly for compatibility, that is the better
- tradeoff. */
-
- int fd;
-
- /* Callers must avoid passing us a buffer if
- file_gzip_level is set. We could handle this case,
- but it's not worth it since this case never arises
- with a current client and server. */
- if (filebuf != NULL)
- error (1, 0, "\
-CVS server internal error: unhandled case in server_updated");
-
- fd = CVS_OPEN (finfo->file, O_RDONLY | OPEN_BINARY, 0);
- if (fd < 0)
- error (1, errno, "reading %s", finfo->fullname);
- if (read_and_gzip (fd, finfo->fullname, &file,
- &file_allocated, &file_used,
- file_gzip_level))
- error (1, 0, "aborting due to compression error");
- size = file_used;
- if (close (fd) < 0)
- error (1, errno, "reading %s", finfo->fullname);
- /* Prepending length with "z" is flag for using gzip here. */
- buf_output0 (protocol, "z");
- }
- else if (filebuf == NULL)
- {
- long status;
-
- f = CVS_FOPEN (finfo->file, "rb");
- if (f == NULL)
- error (1, errno, "reading %s", finfo->fullname);
- status = buf_read_file (f, size, &list, &last);
- if (status == -2)
- (*protocol->memory_error) (protocol);
- else if (status != 0)
- error (1, ferror (f) ? errno : 0, "reading %s",
- finfo->fullname);
- if (fclose (f) == EOF)
- error (1, errno, "reading %s", finfo->fullname);
- }
- }
-
- sprintf (size_text, "%lu\n", size);
- buf_output0 (protocol, size_text);
-
- if (file != NULL)
- {
- buf_output (protocol, (char *) file, file_used);
- free (file);
- file = NULL;
- }
- else if (filebuf == NULL)
- buf_append_data (protocol, list, last);
- else
- {
- buf_append_buffer (protocol, filebuf);
- }
- /* Note we only send a newline here if the file ended with one. */
-
- /*
- * Avoid using up too much disk space for temporary files.
- * A file which does not exist indicates that the file is up-to-date,
- * which is now the case. If this is SERVER_MERGED, the file is
- * not up-to-date, and we indicate that by leaving the file there.
- * I'm thinking of cases like "cvs update foo/foo.c foo".
- */
- if ((updated == SERVER_UPDATED
- || updated == SERVER_PATCHED
- || updated == SERVER_RCS_DIFF)
- && filebuf == NULL
- /* But if we are joining, we'll need the file when we call
- join_file. */
- && !joining ())
- {
- if (CVS_UNLINK (finfo->file) < 0)
- error (0, errno, "cannot remove temp file for %s",
- finfo->fullname);
- }
- }
- else if (scratched_file != NULL && entries_line == NULL)
- {
- if (strcmp (scratched_file, finfo->file) != 0)
- error (1, 0,
- "CVS server internal error: `%s' vs. `%s' scratched",
- scratched_file,
- finfo->file);
- free (scratched_file);
- scratched_file = NULL;
-
- if (kill_scratched_file)
- buf_output0 (protocol, "Removed ");
- else
- buf_output0 (protocol, "Remove-entry ");
- output_dir (finfo->update_dir, finfo->repository);
- buf_output0 (protocol, finfo->file);
- buf_output (protocol, "\n", 1);
- /* keep the vers structure up to date in case we do a join
- * - if there isn't a file, it can't very well have a version number, can it?
- *
- * we do it here on the assumption that since we just told the client
- * to remove the file/entry, it will, and we want to remember that.
- * If it fails, that's the client's problem, not ours
- */
- if (vers && vers->vn_user != NULL)
- {
- free (vers->vn_user);
- vers->vn_user = NULL;
- }
- if (vers && vers->ts_user != NULL)
- {
- free (vers->ts_user);
- vers->ts_user = NULL;
- }
- }
- else if (scratched_file == NULL && entries_line == NULL)
- {
- /*
- * This can happen with death support if we were processing
- * a dead file in a checkout.
- */
- }
- else
- error (1, 0,
- "CVS server internal error: Register *and* Scratch_Entry.\n");
- buf_send_counted (protocol);
- done:;
-}
-
-/* Return whether we should send patches in RCS format. */
-
-int
-server_use_rcs_diff ()
-{
- return supported_response ("Rcs-diff");
-}
-
-
-
-void
-server_set_entstat (update_dir, repository)
- const char *update_dir;
- const char *repository;
-{
- static int set_static_supported = -1;
- if (set_static_supported == -1)
- set_static_supported = supported_response ("Set-static-directory");
- if (!set_static_supported) return;
-
- buf_output0 (protocol, "Set-static-directory ");
- output_dir (update_dir, repository);
- buf_output0 (protocol, "\n");
- buf_send_counted (protocol);
-}
-
-
-
-void
-server_clear_entstat (update_dir, repository)
- const char *update_dir;
- const char *repository;
-{
- static int clear_static_supported = -1;
- if (clear_static_supported == -1)
- clear_static_supported = supported_response ("Clear-static-directory");
- if (!clear_static_supported) return;
-
- if (noexec)
- return;
-
- buf_output0 (protocol, "Clear-static-directory ");
- output_dir (update_dir, repository);
- buf_output0 (protocol, "\n");
- buf_send_counted (protocol);
-}
-
-
-
-void
-server_set_sticky (update_dir, repository, tag, date, nonbranch)
- const char *update_dir;
- const char *repository;
- const char *tag;
- const char *date;
- int nonbranch;
-{
- static int set_sticky_supported = -1;
-
- assert (update_dir != NULL);
-
- if (set_sticky_supported == -1)
- set_sticky_supported = supported_response ("Set-sticky");
- if (!set_sticky_supported) return;
-
- if (noexec)
- return;
-
- if (tag == NULL && date == NULL)
- {
- buf_output0 (protocol, "Clear-sticky ");
- output_dir (update_dir, repository);
- buf_output0 (protocol, "\n");
- }
- else
- {
- buf_output0 (protocol, "Set-sticky ");
- output_dir (update_dir, repository);
- buf_output0 (protocol, "\n");
- if (tag != NULL)
- {
- if (nonbranch)
- buf_output0 (protocol, "N");
- else
- buf_output0 (protocol, "T");
- buf_output0 (protocol, tag);
- }
- else
- {
- buf_output0 (protocol, "D");
- buf_output0 (protocol, date);
- }
- buf_output0 (protocol, "\n");
- }
- buf_send_counted (protocol);
-}
-
-struct template_proc_data
-{
- const char *update_dir;
- const char *repository;
-};
-
-/* Here as a static until we get around to fixing Parse_Info to pass along
- a void * for it. */
-static struct template_proc_data *tpd;
-
-static int
-template_proc PROTO((const char *repository, const char *template));
-
-static int
-template_proc (repository, template)
- const char *repository;
- const char *template;
-{
- FILE *fp;
- char buf[1024];
- size_t n;
- struct stat sb;
- struct template_proc_data *data = tpd;
-
- if (!supported_response ("Template"))
- /* Might want to warn the user that the rcsinfo feature won't work. */
- return 0;
- buf_output0 (protocol, "Template ");
- output_dir (data->update_dir, data->repository);
- buf_output0 (protocol, "\n");
-
- fp = CVS_FOPEN (template, "rb");
- if (fp == NULL)
- {
- error (0, errno, "Couldn't open rcsinfo template file %s", template);
- return 1;
- }
- if (fstat (fileno (fp), &sb) < 0)
- {
- error (0, errno, "cannot stat rcsinfo template file %s", template);
- return 1;
- }
- sprintf (buf, "%ld\n", (long) sb.st_size);
- buf_output0 (protocol, buf);
- while (!feof (fp))
- {
- n = fread (buf, 1, sizeof buf, fp);
- buf_output (protocol, buf, n);
- if (ferror (fp))
- {
- error (0, errno, "cannot read rcsinfo template file %s", template);
- (void) fclose (fp);
- return 1;
- }
- }
- buf_send_counted (protocol);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close rcsinfo template file %s", template);
- return 0;
-}
-
-
-
-void
-server_template (update_dir, repository)
- const char *update_dir;
- const char *repository;
-{
- struct template_proc_data data;
- data.update_dir = update_dir;
- data.repository = repository;
- tpd = &data;
- (void) Parse_Info (CVSROOTADM_RCSINFO, repository, template_proc, 1);
-}
-
-
-
-static void
-serve_gzip_contents (arg)
- char *arg;
-{
- int level;
- level = atoi (arg);
- if (level == 0)
- level = 6;
- file_gzip_level = level;
-}
-
-static void
-serve_gzip_stream (arg)
- char *arg;
-{
- int level;
- level = atoi (arg);
- if (level == 0)
- level = 6;
-
- /* All further communication with the client will be compressed. */
-
- buf_to_net = compress_buffer_initialize (buf_to_net, 0, level,
- buf_to_net->memory_error);
- buf_from_net = compress_buffer_initialize (buf_from_net, 1, level,
- buf_from_net->memory_error);
-}
-
-/* Tell the client about RCS options set in CVSROOT/cvswrappers. */
-static void
-serve_wrapper_sendme_rcs_options (arg)
- char *arg;
-{
- /* Actually, this is kind of sdrawkcab-ssa: the client wants
- * verbatim lines from a cvswrappers file, but the server has
- * already parsed the cvswrappers file into the wrap_list struct.
- * Therefore, the server loops over wrap_list, unparsing each
- * entry before sending it.
- */
- char *wrapper_line = NULL;
-
- wrap_setup ();
-
- for (wrap_unparse_rcs_options (&wrapper_line, 1);
- wrapper_line;
- wrap_unparse_rcs_options (&wrapper_line, 0))
- {
- buf_output0 (buf_to_net, "Wrapper-rcsOption ");
- buf_output0 (buf_to_net, wrapper_line);
- buf_output0 (buf_to_net, "\012");;
- free (wrapper_line);
- }
-
- buf_output0 (buf_to_net, "ok\012");
-
- /* The client is waiting for us, so we better send the data now. */
- buf_flush (buf_to_net, 1);
-}
-
-
-static void
-serve_ignore (arg)
- char *arg;
-{
- /*
- * Just ignore this command. This is used to support the
- * update-patches command, which is not a real command, but a signal
- * to the client that update will accept the -u argument.
- */
-}
-
-static int
-expand_proc (argc, argv, where, mwhere, mfile, shorten,
- local_specified, omodule, msg)
- int argc;
- char **argv;
- char *where;
- char *mwhere;
- char *mfile;
- int shorten;
- int local_specified;
- char *omodule;
- char *msg;
-{
- int i;
- char *dir = argv[0];
-
- /* If mwhere has been specified, the thing we're expanding is a
- module -- just return its name so the client will ask for the
- right thing later. If it is an alias or a real directory,
- mwhere will not be set, so send out the appropriate
- expansion. */
-
- if (mwhere != NULL)
- {
- buf_output0 (buf_to_net, "Module-expansion ");
- if (server_dir != NULL)
- {
- buf_output0 (buf_to_net, server_dir);
- buf_output0 (buf_to_net, "/");
- }
- buf_output0 (buf_to_net, mwhere);
- if (mfile != NULL)
- {
- buf_append_char (buf_to_net, '/');
- buf_output0 (buf_to_net, mfile);
- }
- buf_append_char (buf_to_net, '\n');
- }
- else
- {
- /* We may not need to do this anymore -- check the definition
- of aliases before removing */
- if (argc == 1)
- {
- buf_output0 (buf_to_net, "Module-expansion ");
- if (server_dir != NULL)
- {
- buf_output0 (buf_to_net, server_dir);
- buf_output0 (buf_to_net, "/");
- }
- buf_output0 (buf_to_net, dir);
- buf_append_char (buf_to_net, '\n');
- }
- else
- {
- for (i = 1; i < argc; ++i)
- {
- buf_output0 (buf_to_net, "Module-expansion ");
- if (server_dir != NULL)
- {
- buf_output0 (buf_to_net, server_dir);
- buf_output0 (buf_to_net, "/");
- }
- buf_output0 (buf_to_net, dir);
- buf_append_char (buf_to_net, '/');
- buf_output0 (buf_to_net, argv[i]);
- buf_append_char (buf_to_net, '\n');
- }
- }
- }
- return 0;
-}
-
-static void
-serve_expand_modules (arg)
- char *arg;
-{
- int i;
- int err;
- DBM *db;
- err = 0;
-
- db = open_module ();
- for (i = 1; i < argument_count; i++)
- err += do_module (db, argument_vector[i],
- CHECKOUT, "Updating", expand_proc,
- NULL, 0, 0, 0, 0,
- (char *) NULL);
- close_module (db);
- {
- /* argument_vector[0] is a dummy argument, we don't mess with it. */
- char **cp;
- for (cp = argument_vector + 1;
- cp < argument_vector + argument_count;
- ++cp)
- free (*cp);
-
- argument_count = 1;
- }
- if (err)
- /* We will have printed an error message already. */
- buf_output0 (buf_to_net, "error \n");
- else
- buf_output0 (buf_to_net, "ok\n");
-
- /* The client is waiting for the module expansions, so we must
- send the output now. */
- buf_flush (buf_to_net, 1);
-}
-
-
-
-static void serve_valid_requests PROTO((char *arg));
-
-#endif /* SERVER_SUPPORT */
-#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
-
-/*
- * Parts of this table are shared with the client code,
- * but the client doesn't need to know about the handler
- * functions.
- */
-
-struct request requests[] =
-{
-#ifdef SERVER_SUPPORT
-#define REQ_LINE(n, f, s) {n, f, s}
-#else
-#define REQ_LINE(n, f, s) {n, s}
-#endif
-
- REQ_LINE("Root", serve_root, RQ_ESSENTIAL | RQ_ROOTLESS),
- REQ_LINE("Valid-responses", serve_valid_responses,
- RQ_ESSENTIAL | RQ_ROOTLESS),
- REQ_LINE("valid-requests", serve_valid_requests,
- RQ_ESSENTIAL | RQ_ROOTLESS),
- REQ_LINE("Repository", serve_repository, 0),
- REQ_LINE("Directory", serve_directory, RQ_ESSENTIAL),
- REQ_LINE("Max-dotdot", serve_max_dotdot, 0),
- REQ_LINE("Static-directory", serve_static_directory, 0),
- REQ_LINE("Sticky", serve_sticky, 0),
- REQ_LINE("Entry", serve_entry, RQ_ESSENTIAL),
- REQ_LINE("Kopt", serve_kopt, 0),
- REQ_LINE("Checkin-time", serve_checkin_time, 0),
- REQ_LINE("Modified", serve_modified, RQ_ESSENTIAL),
- REQ_LINE("Is-modified", serve_is_modified, 0),
- REQ_LINE("Empty-conflicts", serve_noop, 0),
-
- /* The client must send this request to interoperate with CVS 1.5
- through 1.9 servers. The server must support it (although it can
- be and is a noop) to interoperate with CVS 1.5 to 1.9 clients. */
- REQ_LINE("UseUnchanged", serve_enable_unchanged, RQ_ENABLEME | RQ_ROOTLESS),
-
- REQ_LINE("Unchanged", serve_unchanged, RQ_ESSENTIAL),
- REQ_LINE("Notify", serve_notify, 0),
- REQ_LINE("Questionable", serve_questionable, 0),
- REQ_LINE("Argument", serve_argument, RQ_ESSENTIAL),
- REQ_LINE("Argumentx", serve_argumentx, RQ_ESSENTIAL),
- REQ_LINE("Global_option", serve_global_option, RQ_ROOTLESS),
- REQ_LINE("Gzip-stream", serve_gzip_stream, 0),
- REQ_LINE("wrapper-sendme-rcsOptions",
- serve_wrapper_sendme_rcs_options,
- 0),
- REQ_LINE("Set", serve_set, RQ_ROOTLESS),
-#ifdef ENCRYPTION
-# ifdef HAVE_KERBEROS
- REQ_LINE("Kerberos-encrypt", serve_kerberos_encrypt, 0),
-# endif
-# ifdef HAVE_GSSAPI
- REQ_LINE("Gssapi-encrypt", serve_gssapi_encrypt, 0),
-# endif
-#endif
-#ifdef HAVE_GSSAPI
- REQ_LINE("Gssapi-authenticate", serve_gssapi_authenticate, 0),
-#endif
- REQ_LINE("expand-modules", serve_expand_modules, 0),
- REQ_LINE("ci", serve_ci, RQ_ESSENTIAL),
- REQ_LINE("co", serve_co, RQ_ESSENTIAL),
- REQ_LINE("update", serve_update, RQ_ESSENTIAL),
- REQ_LINE("diff", serve_diff, 0),
- REQ_LINE("log", serve_log, 0),
- REQ_LINE("rlog", serve_rlog, 0),
- REQ_LINE("add", serve_add, 0),
- REQ_LINE("remove", serve_remove, 0),
- REQ_LINE("update-patches", serve_ignore, 0),
- REQ_LINE("gzip-file-contents", serve_gzip_contents, 0),
- REQ_LINE("status", serve_status, 0),
- REQ_LINE("rdiff", serve_rdiff, 0),
- REQ_LINE("tag", serve_tag, 0),
- REQ_LINE("rtag", serve_rtag, 0),
- REQ_LINE("import", serve_import, 0),
- REQ_LINE("admin", serve_admin, 0),
- REQ_LINE("export", serve_export, 0),
- REQ_LINE("history", serve_history, 0),
- REQ_LINE("release", serve_release, 0),
- REQ_LINE("watch-on", serve_watch_on, 0),
- REQ_LINE("watch-off", serve_watch_off, 0),
- REQ_LINE("watch-add", serve_watch_add, 0),
- REQ_LINE("watch-remove", serve_watch_remove, 0),
- REQ_LINE("watchers", serve_watchers, 0),
- REQ_LINE("editors", serve_editors, 0),
- REQ_LINE("init", serve_init, RQ_ROOTLESS),
- REQ_LINE("annotate", serve_annotate, 0),
- REQ_LINE("rannotate", serve_rannotate, 0),
- REQ_LINE("noop", serve_noop, RQ_ROOTLESS),
- REQ_LINE("version", serve_version, RQ_ROOTLESS),
- REQ_LINE(NULL, NULL, 0)
-
-#undef REQ_LINE
-};
-
-#endif /* SERVER_SUPPORT or CLIENT_SUPPORT */
-#ifdef SERVER_SUPPORT
-
-static void
-serve_valid_requests (arg)
- char *arg;
-{
- struct request *rq;
- if (print_pending_error ())
- return;
- buf_output0 (buf_to_net, "Valid-requests");
- for (rq = requests; rq->name != NULL; rq++)
- {
- if (rq->func != NULL)
- {
- buf_append_char (buf_to_net, ' ');
- buf_output0 (buf_to_net, rq->name);
- }
- }
- buf_output0 (buf_to_net, "\nok\n");
-
- /* The client is waiting for the list of valid requests, so we
- must send the output now. */
- buf_flush (buf_to_net, 1);
-}
-
-#ifdef SUNOS_KLUDGE
-/*
- * Delete temporary files. SIG is the signal making this happen, or
- * 0 if not called as a result of a signal.
- */
-static int command_pid_is_dead;
-static void wait_sig (sig)
- int sig;
-{
- int status;
- pid_t r = wait (&status);
- if (r == command_pid)
- command_pid_is_dead++;
-}
-#endif /* SUNOS_KLUDGE */
-
-void
-server_cleanup (sig)
- int sig;
-{
- /* Do "rm -rf" on the temp directory. */
- int status;
- int save_noexec;
-
- if (buf_to_net != NULL)
- {
- /* Since we're done, go ahead and put BUF_TO_NET back into blocking
- * mode and send any pending output. In the usual case there won't
- * won't be any, but there might be if an error occured.
- */
-
- set_block (buf_to_net);
- buf_flush (buf_to_net, 1);
-
- /* Next we shut down BUF_FROM_NET. That will pick up the checksum
- * generated when the client shuts down its buffer. Then, after we
- * have generated any final output, we shut down BUF_TO_NET.
- */
-
- if (buf_from_net != NULL)
- {
- status = buf_shutdown (buf_from_net);
- if (status != 0)
- error (0, status, "shutting down buffer from client");
- buf_free (buf_from_net);
- buf_from_net = NULL;
- }
-
- if (dont_delete_temp)
- {
- (void) buf_flush (buf_to_net, 1);
- (void) buf_shutdown (buf_to_net);
- buf_free (buf_to_net);
- buf_to_net = NULL;
- error_use_protocol = 0;
- return;
- }
- }
- else if (dont_delete_temp)
- return;
-
- /* What a bogus kludge. This disgusting code makes all kinds of
- assumptions about SunOS, and is only for a bug in that system.
- So only enable it on Suns. */
-#ifdef SUNOS_KLUDGE
- if (command_pid > 0)
- {
- /* To avoid crashes on SunOS due to bugs in SunOS tmpfs
- triggered by the use of rename() in RCS, wait for the
- subprocess to die. Unfortunately, this means draining output
- while waiting for it to unblock the signal we sent it. Yuck! */
- int status;
- pid_t r;
-
- signal (SIGCHLD, wait_sig);
- if (sig)
- /* Perhaps SIGTERM would be more correct. But the child
- process will delay the SIGINT delivery until its own
- children have exited. */
- kill (command_pid, SIGINT);
- /* The caller may also have sent a signal to command_pid, so
- always try waiting. First, though, check and see if it's still
- there.... */
- do_waitpid:
- r = waitpid (command_pid, &status, WNOHANG);
- if (r == 0)
- ;
- else if (r == command_pid)
- command_pid_is_dead++;
- else if (r == -1)
- switch (errno)
- {
- case ECHILD:
- command_pid_is_dead++;
- break;
- case EINTR:
- goto do_waitpid;
- }
- else
- /* waitpid should always return one of the above values */
- abort ();
- while (!command_pid_is_dead)
- {
- struct timeval timeout;
- struct fd_set_wrapper readfds;
- char buf[100];
- int i;
-
- /* Use a non-zero timeout to avoid eating up CPU cycles. */
- timeout.tv_sec = 2;
- timeout.tv_usec = 0;
- readfds = command_fds_to_drain;
- switch (select (max_command_fd + 1, &readfds.fds,
- (fd_set *)0, (fd_set *)0,
- &timeout))
- {
- case -1:
- if (errno != EINTR)
- abort ();
- case 0:
- /* timeout */
- break;
- case 1:
- for (i = 0; i <= max_command_fd; i++)
- {
- if (!FD_ISSET (i, &readfds.fds))
- continue;
- /* this fd is non-blocking */
- while (read (i, buf, sizeof (buf)) >= 1)
- ;
- }
- break;
- default:
- abort ();
- }
- }
- }
-#endif /* SUNOS_KLUDGE */
-
- CVS_CHDIR (Tmpdir);
- /* Temporarily clear noexec, so that we clean up our temp directory
- regardless of it (this could more cleanly be handled by moving
- the noexec check to all the unlink_file_dir callers from
- unlink_file_dir itself). */
- save_noexec = noexec;
- noexec = 0;
- /* FIXME? Would be nice to not ignore errors. But what should we do?
- We could try to do this before we shut down the network connection,
- and try to notify the client (but the client might not be waiting
- for responses). We could try something like syslog() or our own
- log file. */
- unlink_file_dir (orig_server_temp_dir);
- noexec = save_noexec;
-
- if (buf_to_net != NULL)
- {
- (void) buf_flush (buf_to_net, 1);
- (void) buf_shutdown (buf_to_net);
- buf_free (buf_to_net);
- buf_to_net = NULL;
- error_use_protocol = 0;
- }
-}
-
-int
-server (argc, argv)
- int argc;
- char **argv;
-{
- char *error_prog_name; /* Used in error messages */
-
- if (argc == -1)
- {
- static const char *const msg[] =
- {
- "Usage: %s %s\n",
- " Normally invoked by a cvs client on a remote machine.\n",
- NULL
- };
- usage (msg);
- }
- /* Ignore argc and argv. They might be from .cvsrc. */
-
- buf_to_net = fd_buffer_initialize (STDOUT_FILENO, 0,
- outbuf_memory_error);
- buf_from_net = stdio_buffer_initialize (stdin, 0, 1, outbuf_memory_error);
-
- saved_output = buf_nonio_initialize (outbuf_memory_error);
- saved_outerr = buf_nonio_initialize (outbuf_memory_error);
-
- /* Since we're in the server parent process, error should use the
- protocol to report error messages. */
- error_use_protocol = 1;
-
- /* OK, now figure out where we stash our temporary files. */
- {
- char *p;
-
- /* The code which wants to chdir into server_temp_dir is not set
- up to deal with it being a relative path. So give an error
- for that case. */
- if (!isabsolute (Tmpdir))
- {
- if (alloc_pending (80 + strlen (Tmpdir)))
- sprintf (pending_error_text,
- "E Value of %s for TMPDIR is not absolute", Tmpdir);
-
- /* FIXME: we would like this error to be persistent, that
- is, not cleared by print_pending_error. The current client
- will exit as soon as it gets an error, but the protocol spec
- does not require a client to do so. */
- }
- else
- {
- int status;
- int i = 0;
-
- server_temp_dir = xmalloc (strlen (Tmpdir) + 80);
- if (server_temp_dir == NULL)
- {
- /*
- * Strictly speaking, we're not supposed to output anything
- * now. But we're about to exit(), give it a try.
- */
- printf ("E Fatal server error, aborting.\n\
-error ENOMEM Virtual memory exhausted.\n");
-
- error_exit ();
- }
- strcpy (server_temp_dir, Tmpdir);
-
- /* Remove a trailing slash from TMPDIR if present. */
- p = server_temp_dir + strlen (server_temp_dir) - 1;
- if (*p == '/')
- *p = '\0';
-
- /*
- * I wanted to use cvs-serv/PID, but then you have to worry about
- * the permissions on the cvs-serv directory being right. So
- * use cvs-servPID.
- */
- strcat (server_temp_dir, "/cvs-serv");
-
- p = server_temp_dir + strlen (server_temp_dir);
- sprintf (p, "%ld", (long) getpid ());
-
- orig_server_temp_dir = server_temp_dir;
-
- /* Create the temporary directory, and set the mode to
- 700, to discourage random people from tampering with
- it. */
- while ((status = mkdir_p (server_temp_dir)) == EEXIST)
- {
- static const char suffix[] = "abcdefghijklmnopqrstuvwxyz";
-
- if (i >= sizeof suffix - 1) break;
- if (i == 0) p = server_temp_dir + strlen (server_temp_dir);
- p[0] = suffix[i++];
- p[1] = '\0';
- }
- if (status != 0)
- {
- if (alloc_pending (80 + strlen (server_temp_dir)))
- sprintf (pending_error_text,
- "E can't create temporary directory %s",
- server_temp_dir);
- pending_error = status;
- }
-#ifndef CHMOD_BROKEN
- else if (chmod (server_temp_dir, S_IRWXU) < 0)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (server_temp_dir)))
- sprintf (pending_error_text,
-"E cannot change permissions on temporary directory %s",
- server_temp_dir);
- pending_error = save_errno;
- }
-#endif
- else if (CVS_CHDIR (server_temp_dir) < 0)
- {
- int save_errno = errno;
- if (alloc_pending (80 + strlen (server_temp_dir)))
- sprintf (pending_error_text,
-"E cannot change to temporary directory %s",
- server_temp_dir);
- pending_error = save_errno;
- }
- }
- }
-
- /* Now initialize our argument vector (for arguments from the client). */
-
- /* Small for testing. */
- argument_vector_size = 1;
- argument_vector = xmalloc (argument_vector_size * sizeof (char *));
- argument_count = 1;
- /* This gets printed if the client supports an option which the
- server doesn't, causing the server to print a usage message.
- FIXME: just a nit, I suppose, but the usage message the server
- prints isn't literally true--it suggests "cvs server" followed
- by options which are for a particular command. Might be nice to
- say something like "client apparently supports an option not supported
- by this server" or something like that instead of usage message. */
- error_prog_name = xmalloc (strlen (program_name) + 8);
- sprintf(error_prog_name, "%s server", program_name);
- argument_vector[0] = error_prog_name;
-
- while (1)
- {
- char *cmd, *orig_cmd;
- struct request *rq;
- int status;
-
- status = buf_read_line (buf_from_net, &cmd, NULL);
- if (status == -2)
- {
- buf_output0 (buf_to_net, "E Fatal server error, aborting.\n\
-error ENOMEM Virtual memory exhausted.\n");
- break;
- }
- if (status != 0)
- break;
-
- orig_cmd = cmd;
- for (rq = requests; rq->name != NULL; ++rq)
- if (strncmp (cmd, rq->name, strlen (rq->name)) == 0)
- {
- int len = strlen (rq->name);
- if (cmd[len] == '\0')
- cmd += len;
- else if (cmd[len] == ' ')
- cmd += len + 1;
- else
- /*
- * The first len characters match, but it's a different
- * command. e.g. the command is "cooperate" but we matched
- * "co".
- */
- continue;
-
- if (!(rq->flags & RQ_ROOTLESS)
- && current_parsed_root == NULL)
- {
- /* For commands which change the way in which data
- is sent and received, for example Gzip-stream,
- this does the wrong thing. Since the client
- assumes that everything is being compressed,
- unconditionally, there is no way to give this
- error to the client without turning on
- compression. The obvious fix would be to make
- Gzip-stream RQ_ROOTLESS (with the corresponding
- change to the spec), and that might be a good
- idea but then again I can see some settings in
- CVSROOT about what compression level to allow.
- I suppose a more baroque answer would be to
- turn on compression (say, at level 1), just
- enough to give the "Root request missing"
- error. For now we just lose. */
- if (alloc_pending (80))
- sprintf (pending_error_text,
- "E Protocol error: Root request missing");
- }
- else
- (*rq->func) (cmd);
- break;
- }
- if (rq->name == NULL)
- {
- if (!print_pending_error ())
- {
- buf_output0 (buf_to_net, "error unrecognized request `");
- buf_output0 (buf_to_net, cmd);
- buf_append_char (buf_to_net, '\'');
- buf_append_char (buf_to_net, '\n');
- }
- }
- free (orig_cmd);
- }
- free (error_prog_name);
-
- /* We expect the client is done talking to us at this point. If there is
- * any data in the buffer or on the network pipe, then something we didn't
- * prepare for is happening.
- */
- if (!buf_empty (buf_from_net))
- {
- /* Try to send the error message to the client, but also syslog it, in
- * case the client isn't listening anymore.
- */
-#ifdef HAVE_SYSLOG_H
- /* FIXME: Can the IP address of the connecting client be retrieved
- * and printed here?
- */
- syslog (LOG_DAEMON | LOG_ERR, "Dying gasps received from client.");
-#endif
- error (0, 0, "Dying gasps received from client.");
- }
-
- /* This command will actually close the network buffers. */
- server_cleanup (0);
- return 0;
-}
-
-
-
-#if defined (HAVE_KERBEROS) || defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)
-static void switch_to_user PROTO((const char *, const char *));
-
-static void
-switch_to_user (cvs_username, username)
- const char *cvs_username; /* Only used for error messages. */
- const char *username;
-{
- struct passwd *pw;
-
- pw = getpwnam (username);
- if (pw == NULL)
- {
- /* check_password contains a similar check, so this usually won't be
- reached unless the CVS user is mapped to an invalid system user. */
-
- printf ("E Fatal error, aborting.\n\
-error 0 %s: no such system user\n", username);
- /* Don't worry about server_cleanup; server_active isn't set yet. */
- error_exit ();
- }
-
- if (pw->pw_uid == 0)
- {
-#ifdef HAVE_SYSLOG_H
- /* FIXME: Can the IP address of the connecting client be retrieved
- * and printed here?
- */
- syslog (LOG_DAEMON | LOG_ALERT,
- "attempt to root from account: %s", cvs_username
- );
-#endif
- printf("error 0: root not allowed\n");
- error_exit ();
- }
-
-#if HAVE_INITGROUPS
- if (initgroups (pw->pw_name, pw->pw_gid) < 0
-# ifdef EPERM
- /* At least on the system I tried, initgroups() only works as root.
- But we do still want to report ENOMEM and whatever other
- errors initgroups() might dish up. */
- && errno != EPERM
-# endif
- )
- {
- /* This could be a warning, but I'm not sure I see the point
- in doing that instead of an error given that it would happen
- on every connection. We could log it somewhere and not tell
- the user. But at least for now make it an error. */
- printf ("error 0 initgroups failed: %s\n", strerror (errno));
- /* Don't worry about server_cleanup; server_active isn't set yet. */
- error_exit ();
- }
-#endif /* HAVE_INITGROUPS */
-
-#ifdef SETXID_SUPPORT
- /* honor the setgid bit iff set*/
- if (getgid() != getegid())
- {
- if (setgid (getegid ()) < 0)
- {
- /* See comments at setuid call below for more discussion. */
- printf ("error 0 setgid failed: %s\n", strerror (errno));
- /* Don't worry about server_cleanup;
- server_active isn't set yet. */
- error_exit ();
- }
- }
- else
-#endif
- {
- if (setgid (pw->pw_gid) < 0)
- {
- /* See comments at setuid call below for more discussion. */
- printf ("error 0 setgid failed: %s\n", strerror (errno));
-#ifdef HAVE_SYSLOG_H
- syslog (LOG_DAEMON | LOG_ERR,
- "setgid to %d failed (%m): real %d/%d, effective %d/%d ",
- pw->pw_gid, getuid(), getgid(), geteuid(), getegid());
-#endif
- /* Don't worry about server_cleanup;
- server_active isn't set yet. */
- error_exit ();
- }
- }
-
- if (setuid (pw->pw_uid) < 0)
- {
- /* Note that this means that if run as a non-root user,
- CVSROOT/passwd must contain the user we are running as
- (e.g. "joe:FsEfVcu:cvs" if run as "cvs" user). This seems
- cleaner than ignoring the error like CVS 1.10 and older but
- it does mean that some people might need to update their
- CVSROOT/passwd file. */
- printf ("error 0 setuid failed: %s\n", strerror (errno));
-#ifdef HAVE_SYSLOG_H
- syslog (LOG_DAEMON | LOG_ERR,
- "setuid to %d failed (%m): real %d/%d, effective %d/%d ",
- pw->pw_uid, getuid(), getgid(), geteuid(), getegid());
-#endif
- /* Don't worry about server_cleanup; server_active isn't set yet. */
- error_exit ();
- }
-
- /* We don't want our umask to change file modes. The modes should
- be set by the modes used in the repository, and by the umask of
- the client. */
- umask (0);
-
-#ifdef AUTH_SERVER_SUPPORT
- /* Make sure our CVS_Username has been set. */
- if (CVS_Username == NULL)
- CVS_Username = xstrdup (username);
-#endif
-
-#if HAVE_PUTENV
- /* Set LOGNAME, USER and CVS_USER in the environment, in case they
- are already set to something else. */
- {
- char *env;
-
- env = xmalloc (sizeof "LOGNAME=" + strlen (username));
- (void) sprintf (env, "LOGNAME=%s", username);
- (void) putenv (env);
-
- env = xmalloc (sizeof "USER=" + strlen (username));
- (void) sprintf (env, "USER=%s", username);
- (void) putenv (env);
-
-#ifdef AUTH_SERVER_SUPPORT
- env = xmalloc (sizeof "CVS_USER=" + strlen (CVS_Username));
- (void) sprintf (env, "CVS_USER=%s", CVS_Username);
- (void) putenv (env);
-#endif
- }
-#endif /* HAVE_PUTENV */
-}
-#endif
-
-#ifdef AUTH_SERVER_SUPPORT
-
-extern char *crypt PROTO((const char *, const char *));
-
-
-/*
- * 0 means no entry found for this user.
- * 1 means entry found and password matches (or found password is empty)
- * 2 means entry found, but password does not match.
- *
- * If 1, host_user_ptr will be set to point at the system
- * username (i.e., the "real" identity, which may or may not be the
- * CVS username) of this user; caller may free this. Global
- * CVS_Username will point at an allocated copy of cvs username (i.e.,
- * the username argument below).
- * kff todo: FIXME: last sentence is not true, it applies to caller.
- */
-static int
-check_repository_password (username, password, repository, host_user_ptr)
- char *username, *password, *repository, **host_user_ptr;
-{
- int retval = 0;
- FILE *fp;
- char *filename;
- char *linebuf = NULL;
- size_t linebuf_len;
- int found_it = 0;
- int namelen;
-
- /* We don't use current_parsed_root->directory because it hasn't been
- * set yet -- our `repository' argument came from the authentication
- * protocol, not the regular CVS protocol.
- */
-
- filename = xmalloc (strlen (repository)
- + 1
- + strlen (CVSROOTADM)
- + 1
- + strlen (CVSROOTADM_PASSWD)
- + 1);
-
- (void) sprintf (filename, "%s/%s/%s", repository,
- CVSROOTADM, CVSROOTADM_PASSWD);
-
- fp = CVS_FOPEN (filename, "r");
- if (fp == NULL)
- {
- if (!existence_error (errno))
- error (0, errno, "cannot open %s", filename);
- free (filename);
- return 0;
- }
-
- /* Look for a relevant line -- one with this user's name. */
- namelen = strlen (username);
- while (getline (&linebuf, &linebuf_len, fp) >= 0)
- {
- if ((strncmp (linebuf, username, namelen) == 0)
- && (linebuf[namelen] == ':'))
- {
- found_it = 1;
- break;
- }
- }
- if (ferror (fp))
- error (0, errno, "cannot read %s", filename);
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", filename);
-
- /* If found_it, then linebuf contains the information we need. */
- if (found_it)
- {
- char *found_password, *host_user_tmp;
- char *non_cvsuser_portion;
-
- /* We need to make sure lines such as
- *
- * "username::sysuser\n"
- * "username:\n"
- * "username: \n"
- *
- * all result in a found_password of NULL, but we also need to
- * make sure that
- *
- * "username: :sysuser\n"
- * "username: <whatever>:sysuser\n"
- *
- * continues to result in an impossible password. That way,
- * an admin would be on safe ground by going in and tacking a
- * space onto the front of a password to disable the account
- * (a technique some people use to close accounts
- * temporarily).
- */
-
- /* Make `non_cvsuser_portion' contain everything after the CVS
- username, but null out any final newline. */
- non_cvsuser_portion = linebuf + namelen;
- strtok (non_cvsuser_portion, "\n");
-
- /* If there's a colon now, we just want to inch past it. */
- if (strchr (non_cvsuser_portion, ':') == non_cvsuser_portion)
- non_cvsuser_portion++;
-
- /* Okay, after this conditional chain, found_password and
- host_user_tmp will have useful values: */
-
- if ((non_cvsuser_portion == NULL)
- || (strlen (non_cvsuser_portion) == 0)
- || ((strspn (non_cvsuser_portion, " \t"))
- == strlen (non_cvsuser_portion)))
- {
- found_password = NULL;
- host_user_tmp = NULL;
- }
- else if (strncmp (non_cvsuser_portion, ":", 1) == 0)
- {
- found_password = NULL;
- host_user_tmp = non_cvsuser_portion + 1;
- if (strlen (host_user_tmp) == 0)
- host_user_tmp = NULL;
- }
- else
- {
- found_password = strtok (non_cvsuser_portion, ":");
- host_user_tmp = strtok (NULL, ":");
- }
-
- /* Of course, maybe there was no system user portion... */
- if (host_user_tmp == NULL)
- host_user_tmp = username;
-
- /* Verify blank passwords directly, otherwise use crypt(). */
- if ((found_password == NULL)
- || ((strcmp (found_password, crypt (password, found_password))
- == 0)))
- {
- /* Give host_user_ptr permanent storage. */
- *host_user_ptr = xstrdup (host_user_tmp);
- retval = 1;
- }
- else
- {
-#ifdef LOG_AUTHPRIV
- syslog (LOG_AUTHPRIV | LOG_NOTICE,
- "password mismatch for %s in %s: %s vs. %s", username,
- repository, crypt(password, found_password), found_password);
-#endif
- *host_user_ptr = NULL;
- retval = 2;
- }
- }
- else /* Didn't find this user, so deny access. */
- {
- *host_user_ptr = NULL;
- retval = 0;
- }
-
- free (filename);
- if (linebuf)
- free (linebuf);
-
- return retval;
-}
-
-
-
-/* Return a hosting username if password matches, else NULL. */
-static char *
-check_password (username, password, repository)
- char *username, *password, *repository;
-{
- int rc;
- char *host_user = NULL;
- char *found_passwd = NULL;
- struct passwd *pw;
-
- /* First we see if this user has a password in the CVS-specific
- password file. If so, that's enough to authenticate with. If
- not, we'll check /etc/passwd. */
-
- if (require_real_user)
- rc = 0; /* "not found" */
- else
- rc = check_repository_password (username, password, repository,
- &host_user);
-
- if (rc == 2)
- return NULL;
-
- if (rc == 1)
- {
- /* host_user already set by reference, so just return. */
- goto handle_return;
- }
-
- assert (rc == 0);
-
- if (!system_auth)
- {
- /* Note that the message _does_ distinguish between the case in
- which we check for a system password and the case in which
- we do not. It is a real pain to track down why it isn't
- letting you in if it won't say why, and I am not convinced
- that the potential information disclosure to an attacker
- outweighs this. */
- printf ("error 0 no such user %s in CVSROOT/passwd\n", username);
-
- error_exit ();
- }
-
- /* No cvs password found, so try /etc/passwd. */
-
-#ifdef HAVE_GETSPNAM
- {
- struct spwd *spw;
-
- spw = getspnam (username);
- if (spw != NULL)
- {
- found_passwd = spw->sp_pwdp;
- }
- }
-#endif
-
- if (found_passwd == NULL && (pw = getpwnam (username)) != NULL)
- {
- found_passwd = pw->pw_passwd;
- }
-
- if (found_passwd == NULL)
- {
- printf ("E Fatal error, aborting.\n\
-error 0 %s: no such user\n", username);
-
- error_exit ();
- }
-
- /* Allow for dain bramaged HPUX passwd aging
- * - Basically, HPUX adds a comma and some data
- * about whether the passwd has expired or not
- * on the end of the passwd field.
- * - This code replaces the ',' with '\0'.
- *
- * FIXME - our workaround is brain damaged too. I'm
- * guessing that HPUX WANTED other systems to think the
- * password was wrong so logins would fail if the
- * system didn't handle expired passwds and the passwd
- * might be expired. I think the way to go here
- * is with PAM.
- */
- strtok (found_passwd, ",");
-
- if (*found_passwd)
- {
- /* user exists and has a password */
- if (strcmp (found_passwd, crypt (password, found_passwd)) == 0)
- {
- host_user = xstrdup (username);
- }
- else
- {
- host_user = NULL;
-#ifdef LOG_AUTHPRIV
- syslog (LOG_AUTHPRIV | LOG_NOTICE,
- "password mismatch for %s: %s vs. %s", username,
- crypt(password, found_passwd), found_passwd);
-#endif
- }
- goto handle_return;
- }
-
- if (password && *password)
- {
- /* user exists and has no system password, but we got
- one as parameter */
- host_user = xstrdup (username);
- goto handle_return;
- }
-
- /* user exists but has no password at all */
- host_user = NULL;
-#ifdef LOG_AUTHPRIV
- syslog (LOG_AUTHPRIV | LOG_NOTICE,
- "login refused for %s: user has no password", username);
-#endif
-
-handle_return:
- if (host_user)
- {
- /* Set CVS_Username here, in allocated space.
- It might or might not be the same as host_user. */
- CVS_Username = xmalloc (strlen (username) + 1);
- strcpy (CVS_Username, username);
- }
-
- return host_user;
-}
-
-#endif /* AUTH_SERVER_SUPPORT */
-
-#if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)
-
-/* Read username and password from client (i.e., stdin).
- If correct, then switch to run as that user and send an ACK to the
- client via stdout, else send NACK and die. */
-void
-pserver_authenticate_connection ()
-{
- char *tmp = NULL;
- size_t tmp_allocated = 0;
-#ifdef AUTH_SERVER_SUPPORT
- char *repository = NULL;
- size_t repository_allocated = 0;
- char *username = NULL;
- size_t username_allocated = 0;
- char *password = NULL;
- size_t password_allocated = 0;
-
- char *host_user;
- char *descrambled_password;
-#endif /* AUTH_SERVER_SUPPORT */
- int verify_and_exit = 0;
-
- /* The Authentication Protocol. Client sends:
- *
- * BEGIN AUTH REQUEST\n
- * <REPOSITORY>\n
- * <USERNAME>\n
- * <PASSWORD>\n
- * END AUTH REQUEST\n
- *
- * Server uses above information to authenticate, then sends
- *
- * I LOVE YOU\n
- *
- * if it grants access, else
- *
- * I HATE YOU\n
- *
- * if it denies access (and it exits if denying).
- *
- * When the client is "cvs login", the user does not desire actual
- * repository access, but would like to confirm the password with
- * the server. In this case, the start and stop strings are
- *
- * BEGIN VERIFICATION REQUEST\n
- *
- * and
- *
- * END VERIFICATION REQUEST\n
- *
- * On a verification request, the server's responses are the same
- * (with the obvious semantics), but it exits immediately after
- * sending the response in both cases.
- *
- * Why is the repository sent? Well, note that the actual
- * client/server protocol can't start up until authentication is
- * successful. But in order to perform authentication, the server
- * needs to look up the password in the special CVS passwd file,
- * before trying /etc/passwd. So the client transmits the
- * repository as part of the "authentication protocol". The
- * repository will be redundantly retransmitted later, but that's no
- * big deal.
- */
-
-#ifdef SO_KEEPALIVE
- /* Set SO_KEEPALIVE on the socket, so that we don't hang forever
- if the client dies while we are waiting for input. */
- {
- int on = 1;
-
- if (setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
- (char *) &on, sizeof on) < 0)
- {
-#ifdef HAVE_SYSLOG_H
- syslog (LOG_DAEMON | LOG_ERR, "error setting KEEPALIVE: %m");
-#endif
- }
- }
-#endif
-
- /* Make sure the protocol starts off on the right foot... */
- if (getline_safe (&tmp, &tmp_allocated, stdin, PATH_MAX) < 0)
- {
-#ifdef HAVE_SYSLOG_H
- syslog (LOG_DAEMON | LOG_NOTICE, "bad auth protocol start: EOF");
-#endif
- error (1, 0, "bad auth protocol start: EOF");
- }
-
- if (strcmp (tmp, "BEGIN VERIFICATION REQUEST\n") == 0)
- verify_and_exit = 1;
- else if (strcmp (tmp, "BEGIN AUTH REQUEST\n") == 0)
- ;
- else if (strcmp (tmp, "BEGIN GSSAPI REQUEST\n") == 0)
- {
-#ifdef HAVE_GSSAPI
- free (tmp);
- gserver_authenticate_connection ();
- return;
-#else
- error (1, 0, "GSSAPI authentication not supported by this server");
-#endif
- }
- else
- error (1, 0, "bad auth protocol start: %s", tmp);
-
-#ifndef AUTH_SERVER_SUPPORT
-
- error (1, 0, "Password authentication not supported by this server");
-
-#else /* AUTH_SERVER_SUPPORT */
-
- /* Get the three important pieces of information in order. */
- /* See above comment about error handling. */
- getline_safe (&repository, &repository_allocated, stdin, PATH_MAX);
- getline_safe (&username, &username_allocated, stdin, PATH_MAX);
- getline_safe (&password, &password_allocated, stdin, PATH_MAX);
-
- /* Make them pure.
- *
- * We check that none of the lines were truncated by getnline in order
- * to be sure that we don't accidentally allow a blind DOS attack to
- * authenticate, however slim the odds of that might be.
- */
- if (!strip_trailing_newlines (repository)
- || !strip_trailing_newlines (username)
- || !strip_trailing_newlines (password))
- error (1, 0, "Maximum line length exceeded during authentication.");
-
- /* ... and make sure the protocol ends on the right foot. */
- /* See above comment about error handling. */
- getline_safe (&tmp, &tmp_allocated, stdin, PATH_MAX);
- if (strcmp (tmp,
- verify_and_exit ?
- "END VERIFICATION REQUEST\n" : "END AUTH REQUEST\n")
- != 0)
- {
- error (1, 0, "bad auth protocol end: %s", tmp);
- }
- if (!root_allow_ok (repository))
- {
- printf ("error 0 %s: no such repository\n", repository);
-#ifdef HAVE_SYSLOG_H
- syslog (LOG_DAEMON | LOG_NOTICE, "login refused for %s", repository);
-#endif
- goto i_hate_you;
- }
-
- /* OK, now parse the config file, so we can use it to control how
- to check passwords. If there was an error parsing the config
- file, parse_config already printed an error. We keep going.
- Why? Because if we didn't, then there would be no way to check
- in a new CVSROOT/config file to fix the broken one! */
- parse_config (repository);
-
- /* We need the real cleartext before we hash it. */
- descrambled_password = descramble (password);
- host_user = check_password (username, descrambled_password, repository);
- if (host_user == NULL)
- {
-#ifdef HAVE_SYSLOG_H
- syslog (LOG_DAEMON | LOG_NOTICE, "login failure (for %s)", repository);
-#endif
- memset (descrambled_password, 0, strlen (descrambled_password));
- free (descrambled_password);
- i_hate_you:
- printf ("I HATE YOU\n");
- fflush (stdout);
-
- /* Don't worry about server_cleanup, server_active isn't set
- yet. */
- error_exit ();
- }
- memset (descrambled_password, 0, strlen (descrambled_password));
- free (descrambled_password);
-
- /* Don't go any farther if we're just responding to "cvs login". */
- if (verify_and_exit)
- {
- printf ("I LOVE YOU\n");
- fflush (stdout);
-
- /* It's okay to skip rcs_cleanup() and Lock_Cleanup() here. */
-
-#ifdef SYSTEM_CLEANUP
- /* Hook for OS-specific behavior, for example socket subsystems on
- NT and OS2 or dealing with windows and arguments on Mac. */
- SYSTEM_CLEANUP ();
-#endif
-
- exit (0);
- }
-
- /* Set Pserver_Repos so that we can check later that the same
- repository is sent in later client/server protocol. */
- Pserver_Repos = xmalloc (strlen (repository) + 1);
- strcpy (Pserver_Repos, repository);
-
- /* Switch to run as this user. */
- switch_to_user (username, host_user);
- free (host_user);
- free (tmp);
- free (repository);
- free (username);
- free (password);
-
- printf ("I LOVE YOU\n");
- fflush (stdout);
-#endif /* AUTH_SERVER_SUPPORT */
-}
-
-#endif /* AUTH_SERVER_SUPPORT || HAVE_GSSAPI */
-
-
-#ifdef HAVE_KERBEROS
-void
-kserver_authenticate_connection ()
-{
- int status;
- char instance[INST_SZ];
- struct sockaddr_in peer;
- struct sockaddr_in laddr;
- int len;
- KTEXT_ST ticket;
- AUTH_DAT auth;
- char version[KRB_SENDAUTH_VLEN];
- char user[ANAME_SZ];
-
- strcpy (instance, "*");
- len = sizeof peer;
- if (getpeername (STDIN_FILENO, (struct sockaddr *) &peer, &len) < 0
- || getsockname (STDIN_FILENO, (struct sockaddr *) &laddr,
- &len) < 0)
- {
- printf ("E Fatal error, aborting.\n\
-error %s getpeername or getsockname failed\n", strerror (errno));
-
- error_exit ();
- }
-
-#ifdef SO_KEEPALIVE
- /* Set SO_KEEPALIVE on the socket, so that we don't hang forever
- if the client dies while we are waiting for input. */
- {
- int on = 1;
-
- if (setsockopt (STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
- (char *) &on, sizeof on) < 0)
- {
-#ifdef HAVE_SYSLOG_H
- syslog (LOG_DAEMON | LOG_ERR, "error setting KEEPALIVE: %m");
-#endif
- }
- }
-#endif
-
- status = krb_recvauth (KOPT_DO_MUTUAL, STDIN_FILENO, &ticket, "rcmd",
- instance, &peer, &laddr, &auth, "", sched,
- version);
- if (status != KSUCCESS)
- {
- printf ("E Fatal error, aborting.\n\
-error 0 kerberos: %s\n", krb_get_err_text(status));
-
- error_exit ();
- }
-
- memcpy (kblock, auth.session, sizeof (C_Block));
-
- /* Get the local name. */
- status = krb_kntoln (&auth, user);
- if (status != KSUCCESS)
- {
- printf ("E Fatal error, aborting.\n\
-error 0 kerberos: can't get local name: %s\n", krb_get_err_text(status));
-
- error_exit ();
- }
-
- /* Switch to run as this user. */
- switch_to_user ("Kerberos 4", user);
-}
-#endif /* HAVE_KERBEROS */
-
-#ifdef HAVE_GSSAPI
-
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN (256)
-#endif
-
-/* Authenticate a GSSAPI connection. This is called from
- pserver_authenticate_connection, and it handles success and failure
- the same way. */
-
-static void
-gserver_authenticate_connection ()
-{
- char hostname[MAXHOSTNAMELEN];
- struct hostent *hp;
- gss_buffer_desc tok_in, tok_out;
- char buf[1024];
- char *credbuf;
- size_t credbuflen;
- OM_uint32 stat_min, ret;
- gss_name_t server_name, client_name;
- gss_cred_id_t server_creds;
- int nbytes;
- gss_OID mechid;
-
- gethostname (hostname, sizeof hostname);
- hp = gethostbyname (hostname);
- if (hp == NULL)
- error (1, 0, "can't get canonical hostname");
-
- sprintf (buf, "cvs@%s", hp->h_name);
- tok_in.value = buf;
- tok_in.length = strlen (buf);
-
- if (gss_import_name (&stat_min, &tok_in, GSS_C_NT_HOSTBASED_SERVICE,
- &server_name) != GSS_S_COMPLETE)
- error (1, 0, "could not import GSSAPI service name %s", buf);
-
- /* Acquire the server credential to verify the client's
- authentication. */
- if (gss_acquire_cred (&stat_min, server_name, 0, GSS_C_NULL_OID_SET,
- GSS_C_ACCEPT, &server_creds,
- NULL, NULL) != GSS_S_COMPLETE)
- error (1, 0, "could not acquire GSSAPI server credentials");
-
- gss_release_name (&stat_min, &server_name);
-
- /* The client will send us a two byte length followed by that many
- bytes. */
- if (fread (buf, 1, 2, stdin) != 2)
- error (1, errno, "read of length failed");
-
- nbytes = ((buf[0] & 0xff) << 8) | (buf[1] & 0xff);
- if (nbytes <= sizeof buf)
- {
- credbuf = buf;
- credbuflen = sizeof buf;
- }
- else
- {
- credbuflen = nbytes;
- credbuf = xmalloc (credbuflen);
- }
-
- if (fread (credbuf, 1, nbytes, stdin) != nbytes)
- error (1, errno, "read of data failed");
-
- gcontext = GSS_C_NO_CONTEXT;
- tok_in.length = nbytes;
- tok_in.value = credbuf;
-
- if (gss_accept_sec_context (&stat_min,
- &gcontext, /* context_handle */
- server_creds, /* verifier_cred_handle */
- &tok_in, /* input_token */
- NULL, /* channel bindings */
- &client_name, /* src_name */
- &mechid, /* mech_type */
- &tok_out, /* output_token */
- &ret,
- NULL, /* ignore time_rec */
- NULL) /* ignore del_cred_handle */
- != GSS_S_COMPLETE)
- {
- error (1, 0, "could not verify credentials");
- }
-
- /* FIXME: Use Kerberos v5 specific code to authenticate to a user.
- We could instead use an authentication to access mapping. */
- {
- krb5_context kc;
- krb5_principal p;
- gss_buffer_desc desc;
-
- krb5_init_context (&kc);
- if (gss_display_name (&stat_min, client_name, &desc,
- &mechid) != GSS_S_COMPLETE
- || krb5_parse_name (kc, ((gss_buffer_t) &desc)->value, &p) != 0
- || krb5_aname_to_localname (kc, p, sizeof buf, buf) != 0
- || krb5_kuserok (kc, p, buf) != TRUE)
- {
- error (1, 0, "access denied");
- }
- krb5_free_principal (kc, p);
- krb5_free_context (kc);
- }
-
- if (tok_out.length != 0)
- {
- char cbuf[2];
-
- cbuf[0] = (tok_out.length >> 8) & 0xff;
- cbuf[1] = tok_out.length & 0xff;
- if (fwrite (cbuf, 1, 2, stdout) != 2
- || (fwrite (tok_out.value, 1, tok_out.length, stdout)
- != tok_out.length))
- error (1, errno, "fwrite failed");
- }
-
- switch_to_user ("GSSAPI", buf);
-
- if (credbuf != buf)
- free (credbuf);
-
- printf ("I LOVE YOU\n");
- fflush (stdout);
-}
-
-#endif /* HAVE_GSSAPI */
-
-#endif /* SERVER_SUPPORT */
-
-#if defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT)
-
-/* This global variable is non-zero if the user requests encryption on
- the command line. */
-int cvsencrypt;
-
-/* This global variable is non-zero if the users requests stream
- authentication on the command line. */
-int cvsauthenticate;
-
-#ifdef HAVE_GSSAPI
-
-/* An buffer interface using GSSAPI. This is built on top of a
- packetizing buffer. */
-
-/* This structure is the closure field of the GSSAPI translation
- routines. */
-
-struct cvs_gssapi_wrap_data
-{
- /* The GSSAPI context. */
- gss_ctx_id_t gcontext;
-};
-
-static int cvs_gssapi_wrap_input PROTO((void *, const char *, char *, int));
-static int cvs_gssapi_wrap_output PROTO((void *, const char *, char *, int,
- int *));
-
-/* Create a GSSAPI wrapping buffer. We use a packetizing buffer with
- GSSAPI wrapping routines. */
-
-struct buffer *
-cvs_gssapi_wrap_buffer_initialize (buf, input, gcontext, memory)
- struct buffer *buf;
- int input;
- gss_ctx_id_t gcontext;
- void (*memory) PROTO((struct buffer *));
-{
- struct cvs_gssapi_wrap_data *gd;
-
- gd = (struct cvs_gssapi_wrap_data *) xmalloc (sizeof *gd);
- gd->gcontext = gcontext;
-
- return (packetizing_buffer_initialize
- (buf,
- input ? cvs_gssapi_wrap_input : NULL,
- input ? NULL : cvs_gssapi_wrap_output,
- gd,
- memory));
-}
-
-/* Unwrap data using GSSAPI. */
-
-static int
-cvs_gssapi_wrap_input (fnclosure, input, output, size)
- void *fnclosure;
- const char *input;
- char *output;
- int size;
-{
- struct cvs_gssapi_wrap_data *gd =
- (struct cvs_gssapi_wrap_data *) fnclosure;
- gss_buffer_desc inbuf, outbuf;
- OM_uint32 stat_min;
- int conf;
-
- inbuf.value = (void *) input;
- inbuf.length = size;
-
- if (gss_unwrap (&stat_min, gd->gcontext, &inbuf, &outbuf, &conf, NULL)
- != GSS_S_COMPLETE)
- {
- error (1, 0, "gss_unwrap failed");
- }
-
- if (outbuf.length > size)
- abort ();
-
- memcpy (output, outbuf.value, outbuf.length);
-
- /* The real packet size is stored in the data, so we don't need to
- remember outbuf.length. */
-
- gss_release_buffer (&stat_min, &outbuf);
-
- return 0;
-}
-
-/* Wrap data using GSSAPI. */
-
-static int
-cvs_gssapi_wrap_output (fnclosure, input, output, size, translated)
- void *fnclosure;
- const char *input;
- char *output;
- int size;
- int *translated;
-{
- struct cvs_gssapi_wrap_data *gd =
- (struct cvs_gssapi_wrap_data *) fnclosure;
- gss_buffer_desc inbuf, outbuf;
- OM_uint32 stat_min;
- int conf_req, conf;
-
- inbuf.value = (void *) input;
- inbuf.length = size;
-
-#ifdef ENCRYPTION
- conf_req = cvs_gssapi_encrypt;
-#else
- conf_req = 0;
-#endif
-
- if (gss_wrap (&stat_min, gd->gcontext, conf_req, GSS_C_QOP_DEFAULT,
- &inbuf, &conf, &outbuf) != GSS_S_COMPLETE)
- error (1, 0, "gss_wrap failed");
-
- /* The packetizing buffer only permits us to add 100 bytes.
- FIXME: I don't know what, if anything, is guaranteed by GSSAPI.
- This may need to be increased for a different GSSAPI
- implementation, or we may need a different algorithm. */
- if (outbuf.length > size + 100)
- abort ();
-
- memcpy (output, outbuf.value, outbuf.length);
-
- *translated = outbuf.length;
-
- gss_release_buffer (&stat_min, &outbuf);
-
- return 0;
-}
-
-#endif /* HAVE_GSSAPI */
-
-#ifdef ENCRYPTION
-
-#ifdef HAVE_KERBEROS
-
-/* An encryption interface using Kerberos. This is built on top of a
- packetizing buffer. */
-
-/* This structure is the closure field of the Kerberos translation
- routines. */
-
-struct krb_encrypt_data
-{
- /* The Kerberos key schedule. */
- Key_schedule sched;
- /* The Kerberos DES block. */
- C_Block block;
-};
-
-static int krb_encrypt_input PROTO((void *, const char *, char *, int));
-static int krb_encrypt_output PROTO((void *, const char *, char *, int,
- int *));
-
-/* Create a Kerberos encryption buffer. We use a packetizing buffer
- with Kerberos encryption translation routines. */
-
-struct buffer *
-krb_encrypt_buffer_initialize (buf, input, sched, block, memory)
- struct buffer *buf;
- int input;
- Key_schedule sched;
- C_Block block;
- void (*memory) PROTO((struct buffer *));
-{
- struct krb_encrypt_data *kd;
-
- kd = (struct krb_encrypt_data *) xmalloc (sizeof *kd);
- memcpy (kd->sched, sched, sizeof (Key_schedule));
- memcpy (kd->block, block, sizeof (C_Block));
-
- return packetizing_buffer_initialize (buf,
- input ? krb_encrypt_input : NULL,
- input ? NULL : krb_encrypt_output,
- kd,
- memory);
-}
-
-/* Decrypt Kerberos data. */
-
-static int
-krb_encrypt_input (fnclosure, input, output, size)
- void *fnclosure;
- const char *input;
- char *output;
- int size;
-{
- struct krb_encrypt_data *kd = (struct krb_encrypt_data *) fnclosure;
- int tcount;
-
- des_cbc_encrypt ((C_Block *) input, (C_Block *) output,
- size, kd->sched, &kd->block, 0);
-
- /* SIZE is the size of the buffer, which is set by the encryption
- routine. The packetizing buffer will arrange for the first two
- bytes in the decrypted buffer to be the real (unaligned)
- length. As a safety check, make sure that the length in the
- buffer corresponds to SIZE. Note that the length in the buffer
- is just the length of the data. We must add 2 to account for
- the buffer count itself. */
- tcount = ((output[0] & 0xff) << 8) + (output[1] & 0xff);
- if (((tcount + 2 + 7) & ~7) != size)
- error (1, 0, "Decryption failure");
-
- return 0;
-}
-
-/* Encrypt Kerberos data. */
-
-static int
-krb_encrypt_output (fnclosure, input, output, size, translated)
- void *fnclosure;
- const char *input;
- char *output;
- int size;
- int *translated;
-{
- struct krb_encrypt_data *kd = (struct krb_encrypt_data *) fnclosure;
- int aligned;
-
- /* For security against a known plaintext attack, we should
- initialize any padding bytes to random values. Instead, we
- just pick up whatever is on the stack, which is at least better
- than using zero. */
-
- /* Align SIZE to an 8 byte boundary. Note that SIZE includes the
- two byte buffer count at the start of INPUT which was added by
- the packetizing buffer. */
- aligned = (size + 7) & ~7;
-
- /* We use des_cbc_encrypt rather than krb_mk_priv because the
- latter sticks a timestamp in the block, and krb_rd_priv expects
- that timestamp to be within five minutes of the current time.
- Given the way the CVS server buffers up data, that can easily
- fail over a long network connection. We trust krb_recvauth to
- guard against a replay attack. */
-
- des_cbc_encrypt ((C_Block *) input, (C_Block *) output, aligned,
- kd->sched, &kd->block, 1);
-
- *translated = aligned;
-
- return 0;
-}
-
-#endif /* HAVE_KERBEROS */
-#endif /* ENCRYPTION */
-#endif /* defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT) */
-
-/* Output LEN bytes at STR. If LEN is zero, then output up to (not including)
- the first '\0' byte. */
-
-void
-cvs_output (str, len)
- const char *str;
- size_t len;
-{
- if (len == 0)
- len = strlen (str);
-#ifdef SERVER_SUPPORT
- if (error_use_protocol && buf_to_net != NULL)
- {
- buf_output (saved_output, str, len);
- buf_copy_lines (buf_to_net, saved_output, 'M');
- }
- else if (server_active && protocol != NULL)
- {
- buf_output (saved_output, str, len);
- buf_copy_lines (protocol, saved_output, 'M');
- buf_send_counted (protocol);
- }
- else
-#endif
- {
- size_t written;
- size_t to_write = len;
- const char *p = str;
-
- /* Local users that do 'cvs status 2>&1' on a local repository
- may see the informational messages out-of-order with the
- status messages unless we use the fflush (stderr) here. */
- fflush (stderr);
-
- while (to_write > 0)
- {
- written = fwrite (p, 1, to_write, stdout);
- if (written == 0)
- break;
- p += written;
- to_write -= written;
- }
- }
-}
-
-/* Output LEN bytes at STR in binary mode. If LEN is zero, then
- output zero bytes. */
-
-void
-cvs_output_binary (str, len)
- char *str;
- size_t len;
-{
-#ifdef SERVER_SUPPORT
- if (error_use_protocol || server_active)
- {
- struct buffer *buf;
- char size_text[40];
-
- if (error_use_protocol)
- buf = buf_to_net;
- else
- buf = protocol;
-
- if (!supported_response ("Mbinary"))
- {
- error (0, 0, "\
-this client does not support writing binary files to stdout");
- return;
- }
-
- buf_output0 (buf, "Mbinary\012");
- sprintf (size_text, "%lu\012", (unsigned long) len);
- buf_output0 (buf, size_text);
-
- /* Not sure what would be involved in using buf_append_data here
- without stepping on the toes of our caller (which is responsible
- for the memory allocation of STR). */
- buf_output (buf, str, len);
-
- if (!error_use_protocol)
- buf_send_counted (protocol);
- }
- else
-#endif
- {
- size_t written;
- size_t to_write = len;
- const char *p = str;
-#ifdef USE_SETMODE_STDOUT
- int oldmode;
-#endif
-
- /* Local users that do 'cvs status 2>&1' on a local repository
- may see the informational messages out-of-order with the
- status messages unless we use the fflush (stderr) here. */
- fflush (stderr);
-
-#ifdef USE_SETMODE_STDOUT
- /* It is possible that this should be the same ifdef as
- USE_SETMODE_BINARY but at least for the moment we keep them
- separate. Mostly this is just laziness and/or a question
- of what has been tested where. Also there might be an
- issue of setmode vs. _setmode. */
- /* The Windows doc says to call setmode only right after startup.
- I assume that what they are talking about can also be helped
- by flushing the stream before changing the mode. */
- fflush (stdout);
- oldmode = _setmode (_fileno (stdout), OPEN_BINARY);
- if (oldmode < 0)
- error (0, errno, "failed to setmode on stdout");
-#endif
-
- while (to_write > 0)
- {
- written = fwrite (p, 1, to_write, stdout);
- if (written == 0)
- break;
- p += written;
- to_write -= written;
- }
-#ifdef USE_SETMODE_STDOUT
- fflush (stdout);
- if (_setmode (_fileno (stdout), oldmode) != OPEN_BINARY)
- error (0, errno, "failed to setmode on stdout");
-#endif
- }
-}
-
-
-
-/* Like CVS_OUTPUT but output is for stderr not stdout. */
-void
-cvs_outerr (str, len)
- const char *str;
- size_t len;
-{
- if (len == 0)
- len = strlen (str);
-#ifdef SERVER_SUPPORT
- if (error_use_protocol)
- {
- buf_output (saved_outerr, str, len);
- buf_copy_lines (buf_to_net, saved_outerr, 'E');
- }
- else if (server_active)
- {
- buf_output (saved_outerr, str, len);
- buf_copy_lines (protocol, saved_outerr, 'E');
- buf_send_counted (protocol);
- }
- else
-#endif
- {
- size_t written;
- size_t to_write = len;
- const char *p = str;
-
- /* Make sure that output appears in order if stdout and stderr
- point to the same place. For the server case this is taken
- care of by the fact that saved_outerr always holds less
- than a line. */
- fflush (stdout);
-
- while (to_write > 0)
- {
- written = fwrite (p, 1, to_write, stderr);
- if (written == 0)
- break;
- p += written;
- to_write -= written;
- }
- }
-}
-
-
-
-/* Flush stderr. stderr is normally flushed automatically, of course,
- but this function is used to flush information from the server back
- to the client. */
-void
-cvs_flusherr ()
-{
-#ifdef SERVER_SUPPORT
- if (error_use_protocol)
- {
- /* skip the actual stderr flush in this case since the parent process
- * on the server should only be writing to stdout anyhow
- */
- /* Flush what we can to the network, but don't block. */
- buf_flush (buf_to_net, 0);
- }
- else if (server_active)
- {
- /* make sure stderr is flushed before we send the flush count on the
- * protocol pipe
- */
- fflush (stderr);
- /* Send a special count to tell the parent to flush. */
- buf_send_special_count (protocol, -2);
- }
- else
-#endif
- fflush (stderr);
-}
-
-
-
-/* Make it possible for the user to see what has been written to
- stdout (it is up to the implementation to decide exactly how far it
- should go to ensure this). */
-void
-cvs_flushout ()
-{
-#ifdef SERVER_SUPPORT
- if (error_use_protocol)
- {
- /* Flush what we can to the network, but don't block. */
- buf_flush (buf_to_net, 0);
- }
- else if (server_active)
- {
- /* Just do nothing. This is because the code which
- cvs_flushout replaces, setting stdout to line buffering in
- main.c, didn't get called in the server child process. But
- in the future it is quite plausible that we'll want to make
- this case work analogously to cvs_flusherr.
-
- FIXME - DRP - I tried to implement this and triggered the following
- error: "Protocol error: uncounted data discarded". I don't need
- this feature right now, so I'm not going to bother with it yet.
- */
- buf_send_special_count (protocol, -1);
- }
- else
-#endif
- fflush (stdout);
-}
-
-/* Output TEXT, tagging it according to TAG. There are lots more
- details about what TAG means in cvsclient.texi but for the simple
- case (e.g. non-client/server), TAG is just "newline" to output a
- newline (in which case TEXT must be NULL), and any other tag to
- output normal text.
-
- Note that there is no way to output either \0 or \n as part of TEXT. */
-
-void
-cvs_output_tagged (tag, text)
- const char *tag;
- const char *text;
-{
- if (text != NULL && strchr (text, '\n') != NULL)
- /* Uh oh. The protocol has no way to cope with this. For now
- we dump core, although that really isn't such a nice
- response given that this probably can be caused by newlines
- in filenames and other causes other than bugs in CVS. Note
- that we don't want to turn this into "MT newline" because
- this case is a newline within a tagged item, not a newline
- as extraneous sugar for the user. */
- assert (0);
-
- /* Start and end tags don't take any text, per cvsclient.texi. */
- if (tag[0] == '+' || tag[0] == '-')
- assert (text == NULL);
-
-#ifdef SERVER_SUPPORT
- if (server_active && supported_response ("MT"))
- {
- struct buffer *buf;
-
- if (error_use_protocol)
- buf = buf_to_net;
- else
- buf = protocol;
-
- buf_output0 (buf, "MT ");
- buf_output0 (buf, tag);
- if (text != NULL)
- {
- buf_output (buf, " ", 1);
- buf_output0 (buf, text);
- }
- buf_output (buf, "\n", 1);
-
- if (!error_use_protocol)
- buf_send_counted (protocol);
- }
- else
-#endif
- {
- if (strcmp (tag, "newline") == 0)
- cvs_output ("\n", 1);
- else if (text != NULL)
- cvs_output (text, 0);
- }
-}
diff --git a/contrib/cvs/src/server.h b/contrib/cvs/src/server.h
deleted file mode 100644
index 4c323866a5a8..000000000000
--- a/contrib/cvs/src/server.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS kit.
- *
- *
- *
- * This file contains the interface between the server and the rest of CVS.
- */
-
-/* Miscellaneous stuff which isn't actually particularly server-specific. */
-#ifndef STDIN_FILENO
-#define STDIN_FILENO 0
-#define STDOUT_FILENO 1
-#define STDERR_FILENO 2
-#endif
-
-
-/*
- * Nonzero if we are using the server. Used by various places to call
- * server-specific functions.
- */
-extern int server_active;
-
-/*
- * 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
-
-/* Server functions exported to the rest of CVS. */
-
-/* Run the server. */
-extern int server PROTO((int argc, char **argv));
-
-/* kserver user authentication. */
-# ifdef HAVE_KERBEROS
-extern void kserver_authenticate_connection PROTO ((void));
-# endif
-
-/* pserver user authentication. */
-# if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)
-extern void pserver_authenticate_connection PROTO ((void));
-# endif
-
-/* See server.c for description. */
-extern void server_pathname_check PROTO ((char *));
-
-/* We have a new Entries line for a file. TAG or DATE can be NULL. */
-extern void server_register
- PROTO((const char *name, const char *version, const char *timestamp,
- const char *options, const char *tag, const char *date,
- const char *conflict));
-
-/* Set the modification time of the next file sent. This must be
- followed by a call to server_updated on the same file. */
-extern void server_modtime PROTO ((struct file_info *finfo,
- Vers_TS *vers_ts));
-
-/*
- * We want to nuke the Entries line for a file, and (unless
- * server_scratch_entry_only is subsequently called) the file itself.
- */
-extern void server_scratch PROTO((const char *name));
-
-/*
- * The file which just had server_scratch called on it needs to have only
- * the Entries line removed, not the file itself.
- */
-extern void server_scratch_entry_only PROTO((void));
-
-/*
- * We just successfully checked in FILE (which is just the bare
- * filename, with no directory). REPOSITORY is the directory for the
- * repository.
- */
-extern void server_checked_in
- PROTO((const char *file, const char *update_dir, const char *repository));
-
-extern void server_copy_file
- PROTO((const char *file, const char *update_dir, const char *repository,
- const char *newfile));
-
-/* Send the appropriate responses for a file described by FINFO and
- VERS. This is called after server_register or server_scratch. In
- the latter case the file is to be removed (and VERS can be NULL).
- In the former case, VERS must be non-NULL, and UPDATED indicates
- whether the file is now up to date (SERVER_UPDATED, yes,
- SERVER_MERGED, no, SERVER_PATCHED, yes, but file is a diff from
- user version to repository version, SERVER_RCS_DIFF, yes, like
- SERVER_PATCHED but with an RCS style diff). MODE is the mode the
- file should get, or (mode_t) -1 if this should be obtained from the
- file itself. CHECKSUM is the MD5 checksum of the file, or NULL if
- this need not be sent. If FILEBUF is not NULL, it holds the
- contents of the file, in which case the file itself may not exist.
- If FILEBUF is not NULL, server_updated will free it. */
-enum server_updated_arg4
-{
- SERVER_UPDATED,
- SERVER_MERGED,
- SERVER_PATCHED,
- SERVER_RCS_DIFF
-};
-#ifdef __STDC__
-struct buffer;
-#endif
-
-extern void server_updated
- PROTO((struct file_info *finfo, Vers_TS *vers,
- enum server_updated_arg4 updated, mode_t mode,
- unsigned char *checksum, struct buffer *filebuf));
-
-/* Whether we should send RCS format patches. */
-extern int server_use_rcs_diff PROTO((void));
-
-/* Set the Entries.Static flag. */
-extern void server_set_entstat PROTO((const char *update_dir,
- const char *repository));
-/* Clear it. */
-extern void server_clear_entstat PROTO((const char *update_dir,
- const char *repository));
-
-/* Set or clear a per-directory sticky tag or date. */
-extern void server_set_sticky PROTO((const char *update_dir,
- const char *repository, const char *tag,
- const char *date, int nonbranch));
-/* Send Template response. */
-extern void server_template PROTO ((const char *, const char *));
-
-extern void server_update_entries
- PROTO((const char *file, const char *update_dir, const char *repository,
- enum server_updated_arg4 updated));
-
-/* Pointer to a malloc'd string which is the directory which
- the server should prepend to the pathnames which it sends
- to the client. */
-extern char *server_dir;
-
-extern void server_cleanup PROTO((int sig));
-
-#ifdef SERVER_FLOWCONTROL
-/* Pause if it's convenient to avoid memory blowout */
-extern void server_pause_check PROTO((void));
-#endif /* SERVER_FLOWCONTROL */
-
-#ifdef AUTH_SERVER_SUPPORT
-extern char *CVS_Username;
-extern int system_auth;
-#endif /* AUTH_SERVER_SUPPORT */
-
-#endif /* SERVER_SUPPORT */
-
-/* Stuff shared with the client. */
-struct request
-{
- /* Name of the request. */
- char *name;
-
-#ifdef SERVER_SUPPORT
- /*
- * Function to carry out the request. ARGS is the text of the command
- * after name and, if present, a single space, have been stripped off.
- */
- void (*func) PROTO((char *args));
-#endif
-
- /* 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 int gunzip_and_write PROTO ((int, char *, unsigned char *, size_t));
-extern int read_and_gzip PROTO ((int, const char *, unsigned char **, size_t *,
- size_t *, int));
diff --git a/contrib/cvs/src/stack.c b/contrib/cvs/src/stack.c
deleted file mode 100644
index 22a10888c350..000000000000
--- a/contrib/cvs/src/stack.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2004-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 2004-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * This module uses the hash.c module to implement a stack.
- */
-
-#include "cvs.h"
-#include <assert.h>
-
-
-
-static void
-do_push (stack, elem, isstring)
- List *stack;
- void *elem;
- int isstring;
-{
- Node *p = getnode();
-
- if (isstring)
- p->key = elem;
- else
- p->data = elem;
-
- addnode(stack, p);
-}
-
-
-
-void
-push (stack, elem)
- List *stack;
- void *elem;
-{
- do_push (stack, elem, 0);
-}
-
-
-
-void
-push_string (stack, elem)
- List *stack;
- char *elem;
-{
- do_push (stack, elem, 1);
-}
-
-
-
-static void *
-do_pop (stack, isstring)
- List *stack;
- int isstring;
-{
- void *elem;
-
- if (isempty (stack)) return NULL;
-
- if (isstring)
- {
- elem = stack->list->prev->key;
- stack->list->prev->key = NULL;
- }
- else
- {
- elem = stack->list->prev->data;
- stack->list->prev->data = NULL;
- }
-
- delnode (stack->list->prev);
- return elem;
-}
-
-
-
-void *
-pop (stack)
- List *stack;
-{
- return do_pop (stack, 0);
-}
-
-
-
-char *
-pop_string (stack)
- List *stack;
-{
- return do_pop (stack, 1);
-}
-
-
-
-static void
-do_unshift (stack, elem, isstring)
- List *stack;
- void *elem;
- int isstring;
-{
- Node *p = getnode();
-
- if (isstring)
- p->key = elem;
- else
- p->data = elem;
-
- addnode_at_front(stack, p);
-}
-
-
-
-void
-unshift (stack, elem)
- List *stack;
- void *elem;
-{
- do_unshift (stack, elem, 0);
-}
-
-
-
-void
-unshift_string (stack, elem)
- List *stack;
- char *elem;
-{
- do_unshift (stack, elem, 1);
-}
-
-
-
-static void *
-do_shift (stack, isstring)
- List *stack;
- int isstring;
-{
- void *elem;
-
- if (isempty (stack)) return NULL;
-
- if (isstring)
- {
- elem = stack->list->next->key;
- stack->list->next->key = NULL;
- }
- else
- {
- elem = stack->list->next->data;
- stack->list->next->data = NULL;
- }
- delnode (stack->list->next);
- return elem;
-}
-
-
-
-void *
-shift (stack)
- List *stack;
-{
- return do_shift (stack, 0);
-}
-
-
-
-char *
-shift_string (stack)
- List *stack;
-{
- return do_shift (stack, 1);
-}
-
-
-
-int
-isempty (stack)
- List *stack;
-{
- if (stack->list == stack->list->next)
- return 1;
- return 0;
-}
diff --git a/contrib/cvs/src/stack.h b/contrib/cvs/src/stack.h
deleted file mode 100644
index 822010bbe4a9..000000000000
--- a/contrib/cvs/src/stack.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright (c) 2004-2005 The Free Software Foundation,
- * Derek Price, and Ximbiot <http://ximbiot.com>.
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- */
-
-void push PROTO((List *_stack, void *_elem));
-void *pop PROTO((List *_stack));
-void unshift PROTO((List *_stack, void *_elem));
-void *shift PROTO((List *_stack));
-void push_string PROTO((List *_stack, char *_elem));
-char *pop_string PROTO((List *_stack));
-void unshift_string PROTO((List *_stack, char *_elem));
-char *shift_string PROTO((List *_stack));
-int isempty PROTO((List *_stack));
diff --git a/contrib/cvs/src/status.c b/contrib/cvs/src/status.c
deleted file mode 100644
index 7a828aeb7a85..000000000000
--- a/contrib/cvs/src/status.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Status Information
- */
-
-#include "cvs.h"
-
-static Dtype status_dirproc PROTO ((void *callerdat, const char *dir,
- const char *repos, const char *update_dir,
- List *entries));
-static int status_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-static int tag_list_proc PROTO((Node * p, void *closure));
-
-static int local = 0;
-static int long_format = 0;
-static RCSNode *xrcsnode;
-
-static const char *const status_usage[] =
-{
- "Usage: %s %s [-vlR] [files...]\n",
- "\t-v\tVerbose format; includes tag information for the file\n",
- "\t-l\tProcess this directory only (not recursive).\n",
- "\t-R\tProcess directories recursively.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-int
-cvsstatus (argc, argv)
- int argc;
- char **argv;
-{
- int c;
- int err = 0;
-
- if (argc == -1)
- usage (status_usage);
-
- optind = 0;
- while ((c = getopt (argc, argv, "+vlR")) != -1)
- {
- switch (c)
- {
- case 'v':
- long_format = 1;
- break;
- case 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case '?':
- default:
- usage (status_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- wrap_setup ();
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- start_server ();
-
- ign_setup ();
-
- if (long_format)
- send_arg("-v");
- if (local)
- send_arg("-l");
- send_arg ("--");
-
- /* 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_file_names (argc, argv, SEND_EXPAND_WILD);
-
- send_to_server ("status\012", 0);
- err = get_responses_and_close ();
-
- return err;
- }
-#endif
-
- /* start the recursion processor */
- err = start_recursion (status_fileproc, (FILESDONEPROC) NULL,
- status_dirproc, (DIRLEAVEPROC) NULL, NULL,
- argc, argv, local,
- W_LOCAL, 0, CVS_LOCK_READ, (char *) NULL, 1,
- (char *) NULL);
-
- return (err);
-}
-
-/*
- * display the status of a file
- */
-/* ARGSUSED */
-static int
-status_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- Ctype status;
- char *sstat;
- Vers_TS *vers;
-
- status = Classify_File (finfo, (char *) NULL, (char *) NULL, (char *) NULL,
- 1, 0, &vers, 0);
- sstat = "Classify Error";
- switch (status)
- {
- case T_UNKNOWN:
- sstat = "Unknown";
- break;
- case T_CHECKOUT:
- sstat = "Needs Checkout";
- break;
- case T_PATCH:
- sstat = "Needs Patch";
- break;
- case T_CONFLICT:
- sstat = "Unresolved Conflict";
- break;
- case T_ADDED:
- sstat = "Locally Added";
- break;
- case T_REMOVED:
- sstat = "Locally Removed";
- break;
- case T_MODIFIED:
- if (file_has_markers (finfo))
- sstat = "File had conflicts on merge";
- else
- /* Note that we do not re Register() the file when we spot
- * a resolved conflict like update_fileproc() does on the
- * premise that status should not alter the sandbox.
- */
- sstat = "Locally Modified";
- break;
- case T_REMOVE_ENTRY:
- sstat = "Entry Invalid";
- break;
- case T_UPTODATE:
- sstat = "Up-to-date";
- break;
- case T_NEEDS_MERGE:
- sstat = "Needs Merge";
- break;
- case T_TITLE:
- /* I don't think this case can occur here. Just print
- "Classify Error". */
- break;
- }
-
- cvs_output ("\
-===================================================================\n", 0);
- if (vers->ts_user == NULL)
- {
- cvs_output ("File: no file ", 0);
- cvs_output (finfo->file, 0);
- cvs_output ("\t\tStatus: ", 0);
- cvs_output (sstat, 0);
- cvs_output ("\n\n", 0);
- }
- else
- {
- char *buf;
- buf = xmalloc (strlen (finfo->file) + strlen (sstat) + 80);
- sprintf (buf, "File: %-17s\tStatus: %s\n\n", finfo->file, sstat);
- cvs_output (buf, 0);
- free (buf);
- }
-
- if (vers->vn_user == NULL)
- {
- cvs_output (" Working revision:\tNo entry for ", 0);
- cvs_output (finfo->file, 0);
- cvs_output ("\n", 0);
- }
- else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
- cvs_output (" Working revision:\tNew file!\n", 0);
- else
- {
- cvs_output (" Working revision:\t", 0);
- cvs_output (vers->vn_user, 0);
- if (!server_active)
- {
- cvs_output ("\t", 0);
- cvs_output (vers->ts_rcs, 0);
- }
- cvs_output ("\n", 0);
- }
-
- if (vers->vn_rcs == NULL)
- cvs_output (" Repository revision:\tNo revision control file\n", 0);
- else
- {
- cvs_output (" Repository revision:\t", 0);
- cvs_output (vers->vn_rcs, 0);
- cvs_output ("\t", 0);
- cvs_output (vers->srcfile->path, 0);
- cvs_output ("\n", 0);
- }
-
- if (vers->entdata)
- {
- Entnode *edata;
-
- edata = vers->entdata;
- if (edata->tag)
- {
- if (vers->vn_rcs == NULL)
- {
- cvs_output (" Sticky Tag:\t\t", 0);
- cvs_output (edata->tag, 0);
- cvs_output (" - MISSING from RCS file!\n", 0);
- }
- else
- {
- if (isdigit ((unsigned char) edata->tag[0]))
- {
- cvs_output (" Sticky Tag:\t\t", 0);
- cvs_output (edata->tag, 0);
- cvs_output ("\n", 0);
- }
- else
- {
- char *branch = NULL;
-
- if (RCS_nodeisbranch (finfo->rcs, edata->tag))
- branch = RCS_whatbranch(finfo->rcs, edata->tag);
-
- cvs_output (" Sticky Tag:\t\t", 0);
- cvs_output (edata->tag, 0);
- cvs_output (" (", 0);
- cvs_output (branch ? "branch" : "revision", 0);
- cvs_output (": ", 0);
- cvs_output (branch ? branch : vers->vn_rcs, 0);
- cvs_output (")\n", 0);
-
- if (branch)
- free (branch);
- }
- }
- }
- else if (!really_quiet)
- cvs_output (" Sticky Tag:\t\t(none)\n", 0);
-
- if (edata->date)
- {
- cvs_output (" Sticky Date:\t\t", 0);
- cvs_output (edata->date, 0);
- cvs_output ("\n", 0);
- }
- else if (!really_quiet)
- cvs_output (" Sticky Date:\t\t(none)\n", 0);
-
- if (edata->options && edata->options[0])
- {
- cvs_output (" Sticky Options:\t", 0);
- cvs_output (edata->options, 0);
- cvs_output ("\n", 0);
- }
- else if (!really_quiet)
- cvs_output (" Sticky Options:\t(none)\n", 0);
- }
-
- 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", 0);
- freevers_ts (&vers);
- return (0);
-}
-
-/*
- * Print a warm fuzzy message
- */
-/* ARGSUSED */
-static Dtype
-status_dirproc (callerdat, dir, repos, update_dir, entries)
- void *callerdat;
- const char *dir;
- const char *repos;
- const char *update_dir;
- List *entries;
-{
- if (!quiet)
- error (0, 0, "Examining %s", update_dir);
- return (R_PROCESS);
-}
-
-/*
- * Print out a tag and its type
- */
-static int
-tag_list_proc (p, closure)
- Node *p;
- void *closure;
-{
- char *branch = NULL;
- char *buf;
-
- if (RCS_nodeisbranch (xrcsnode, p->key))
- branch = RCS_whatbranch(xrcsnode, p->key) ;
-
- buf = xmalloc (80 + strlen (p->key)
- + (branch ? strlen (branch) : strlen (p->data)));
- sprintf (buf, "\t%-25s\t(%s: %s)\n", p->key,
- branch ? "branch" : "revision",
- branch ? branch : (char *)p->data);
- cvs_output (buf, 0);
- free (buf);
-
- if (branch)
- free (branch);
-
- return (0);
-}
diff --git a/contrib/cvs/src/subr.c b/contrib/cvs/src/subr.c
deleted file mode 100644
index faa988a82626..000000000000
--- a/contrib/cvs/src/subr.c
+++ /dev/null
@@ -1,968 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Various useful functions for the CVS support code.
- */
-
-#include <assert.h>
-#include "cvs.h"
-#include "getline.h"
-
-#ifdef HAVE_NANOSLEEP
-# include "xtime.h"
-#else /* HAVE_NANOSLEEP */
-# if !defined HAVE_USLEEP && defined HAVE_SELECT
- /* use select as a workaround */
-# include "xselect.h"
-# endif /* !defined HAVE_USLEEP && defined HAVE_SELECT */
-#endif /* !HAVE_NANOSLEEP */
-
-extern char *getlogin ();
-
-/*
- * malloc some data and die if it fails
- */
-void *
-xmalloc (bytes)
- size_t bytes;
-{
- char *cp;
-
- /* Parts of CVS try to xmalloc zero bytes and then free it. Some
- systems have a malloc which returns NULL for zero byte
- allocations but a free which can't handle NULL, so compensate. */
- if (bytes == 0)
- bytes = 1;
-
- cp = malloc (bytes);
- if (cp == NULL)
- {
- char buf[80];
- sprintf (buf, "out of memory; can not allocate %lu bytes",
- (unsigned long) bytes);
- error (1, 0, buf);
- }
- return (cp);
-}
-
-/*
- * realloc data and die if it fails [I've always wanted to have "realloc" do
- * a "malloc" if the argument is NULL, but you can't depend on it. Here, I
- * can *force* it.]
- */
-void *
-xrealloc (ptr, bytes)
- void *ptr;
- size_t bytes;
-{
- char *cp;
-
- if (!ptr)
- cp = malloc (bytes);
- else
- cp = realloc (ptr, bytes);
-
- if (cp == NULL)
- {
- char buf[80];
- sprintf (buf, "out of memory; can not reallocate %lu bytes",
- (unsigned long) bytes);
- error (1, 0, buf);
- }
- return (cp);
-}
-
-/* Two constants which tune expand_string. Having MIN_INCR as large
- as 1024 might waste a bit of memory, but it shouldn't be too bad
- (CVS used to allocate arrays of, say, 3000, PATH_MAX (8192, often),
- or other such sizes). Probably anything which is going to allocate
- 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.
-
- 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)
-
-/* *STRPTR is a pointer returned from malloc (or NULL), pointing to *N
- characters of space. Reallocate it so that points to at least
- NEWSIZE bytes of space. Gives a fatal error if out of memory;
- if it returns it was successful. */
-void
-expand_string (strptr, n, newsize)
- char **strptr;
- size_t *n;
- size_t newsize;
-{
- if (*n < newsize)
- {
- while (*n < newsize)
- {
- if (*n < MIN_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);
- }
-}
-
-/* *STR is a pointer to a malloc'd string. *LENP is its allocated
- length. Add SRC to the end of it, reallocating if necessary. */
-void
-xrealloc_and_strcat (str, lenp, src)
- char **str;
- size_t *lenp;
- const char *src;
-{
-
- expand_string (str, lenp, strlen (*str) + strlen (src) + 1);
- strcat (*str, src);
-}
-
-/*
- * Duplicate a string, calling xmalloc to allocate some dynamic space
- */
-char *
-xstrdup (str)
- const char *str;
-{
- char *s;
-
- if (str == NULL)
- return ((char *) NULL);
- s = xmalloc (strlen (str) + 1);
- (void) strcpy (s, str);
- return (s);
-}
-
-
-
-/* Remove trailing newlines from STRING, destructively.
- *
- * RETURNS
- *
- * True if any newlines were removed, false otherwise.
- */
-int
-strip_trailing_newlines (str)
- char *str;
-{
- size_t index, origlen;
- index = origlen = strlen (str);
-
- while (index > 0 && str[index-1] == '\n')
- str[--index] = '\0';
-
- return index != origlen;
-}
-
-
-
-/* Return the number of levels that PATH ascends above where it starts.
- * For example:
- *
- * "../../foo" -> 2
- * "foo/../../bar" -> 1
- */
-int
-pathname_levels (p)
- const char *p;
-{
- int level;
- int max_level;
-
- if (p == NULL) return 0;
-
- max_level = 0;
- level = 0;
- do
- {
- /* Now look for pathname level-ups. */
- if (p[0] == '.' && p[1] == '.' && (p[2] == '\0' || ISDIRSEP (p[2])))
- {
- --level;
- if (-level > max_level)
- max_level = -level;
- }
- else if (p[0] == '\0' || ISDIRSEP (p[0]) ||
- (p[0] == '.' && (p[1] == '\0' || ISDIRSEP (p[1]))))
- ;
- else
- ++level;
-
- /* q = strchr (p, '/'); but sub ISDIRSEP() for '/': */
- while (*p != '\0' && !ISDIRSEP (*p)) p++;
- if (*p != '\0') p++;
- } while (*p != '\0');
- return max_level;
-}
-
-
-
-/* Free a vector, where (*ARGV)[0], (*ARGV)[1], ... (*ARGV)[*PARGC - 1]
- are malloc'd and so is *ARGV itself. Such a vector is allocated by
- line2argv or expand_wild, for example. */
-void
-free_names (pargc, argv)
- int *pargc;
- char **argv;
-{
- register int i;
-
- for (i = 0; i < *pargc; i++)
- { /* only do through *pargc */
- free (argv[i]);
- }
- free (argv);
- *pargc = 0; /* and set it to zero when done */
-}
-
-/* Convert LINE into arguments separated by SEPCHARS. Set *ARGC
- to the number of arguments found, and (*ARGV)[0] to the first argument,
- (*ARGV)[1] to the second, etc. *ARGV is malloc'd and so are each of
- (*ARGV)[0], (*ARGV)[1], ... Use free_names() to return the memory
- allocated here back to the free pool. */
-void
-line2argv (pargc, argv, line, sepchars)
- int *pargc;
- char ***argv;
- char *line;
- char *sepchars;
-{
- char *cp;
- /* Could make a case for size_t or some other unsigned type, but
- we'll stick with int to avoid signed/unsigned warnings when
- comparing with *pargc. */
- int argv_allocated;
-
- /* Small for testing. */
- argv_allocated = 1;
- *argv = (char **) xmalloc (argv_allocated * sizeof (**argv));
-
- *pargc = 0;
- for (cp = strtok (line, sepchars); cp; cp = strtok ((char *) NULL, sepchars))
- {
- if (*pargc == argv_allocated)
- {
- argv_allocated *= 2;
- *argv = xrealloc (*argv, argv_allocated * sizeof (**argv));
- }
- (*argv)[*pargc] = xstrdup (cp);
- (*pargc)++;
- }
-}
-
-/*
- * Returns the number of dots ('.') found in an RCS revision number
- */
-int
-numdots (s)
- const char *s;
-{
- int dots = 0;
-
- for (; *s; s++)
- {
- if (*s == '.')
- dots++;
- }
- return (dots);
-}
-
-/* Compare revision numbers REV1 and REV2 by consecutive fields.
- Return negative, zero, or positive in the manner of strcmp. The
- two revision numbers must have the same number of fields, or else
- compare_revnums will return an inaccurate result. */
-int
-compare_revnums (rev1, rev2)
- const char *rev1;
- const char *rev2;
-{
- const char *sp, *tp;
- char *snext, *tnext;
- int result = 0;
-
- sp = rev1;
- tp = rev2;
- while (result == 0)
- {
- result = strtoul (sp, &snext, 10) - strtoul (tp, &tnext, 10);
- if (*snext == '\0' || *tnext == '\0')
- break;
- sp = snext + 1;
- tp = tnext + 1;
- }
-
- return result;
-}
-
-/* Increment a revision number. Working on the string is a bit awkward,
- but it avoid problems with integer overflow should the revision numbers
- get really big. */
-char *
-increment_revnum (rev)
- const char *rev;
-{
- char *newrev, *p;
- size_t len = strlen (rev);
-
- newrev = xmalloc (len + 2);
- memcpy (newrev, rev, len + 1);
- for (p = newrev + len; p != newrev; )
- {
- --p;
- if (!isdigit(*p))
- {
- ++p;
- break;
- }
- if (*p != '9')
- {
- ++*p;
- return newrev;
- }
- *p = '0';
- }
- /* The number was all 9s, so change the first character to 1 and add
- a 0 to the end. */
- *p = '1';
- p = newrev + len;
- *p++ = '0';
- *p = '\0';
- return newrev;
-}
-
-/* Return the username by which the caller should be identified in
- CVS, in contexts such as the author field of RCS files, various
- logs, etc. */
-char *
-getcaller ()
-{
-#ifndef SYSTEM_GETCALLER
- static char *cache;
- struct passwd *pw;
- uid_t uid;
-#endif
-
- /* If there is a CVS username, return it. */
-#ifdef AUTH_SERVER_SUPPORT
- if (CVS_Username != NULL)
- return CVS_Username;
-#endif
-
-#ifdef SYSTEM_GETCALLER
- return SYSTEM_GETCALLER ();
-#else
- /* Get the caller's login from his uid. If the real uid is "root"
- try LOGNAME USER or getlogin(). If getlogin() and getpwuid()
- both fail, return the uid as a string. */
-
- if (cache != NULL)
- return cache;
-
- uid = getuid ();
- if (uid == (uid_t) 0)
- {
- char *name;
-
- /* super-user; try getlogin() to distinguish */
- if (((name = getlogin ()) || (name = getenv("LOGNAME")) ||
- (name = getenv("USER"))) && *name)
- {
- cache = xstrdup (name);
- return cache;
- }
- }
- if ((pw = (struct passwd *) getpwuid (uid)) == NULL)
- {
- char uidname[20];
-
- (void) sprintf (uidname, "uid%lu", (unsigned long) uid);
- cache = xstrdup (uidname);
- return cache;
- }
- cache = xstrdup (pw->pw_name);
- return cache;
-#endif
-}
-
-#ifdef lint
-#ifndef __GNUC__
-/* ARGSUSED */
-time_t
-get_date (date, now)
- char *date;
- struct timeb *now;
-{
- time_t foo = 0;
-
- return (foo);
-}
-#endif
-#endif
-
-
-
-/* Given some revision, REV, return the first prior revision that exists in the
- * RCS file, RCS.
- *
- * ASSUMPTIONS
- * REV exists.
- *
- * INPUTS
- * RCS The RCS node pointer.
- * REV An existing revision in the RCS file referred to by RCS.
- *
- * RETURNS
- * The first prior revision that exists in the RCS file, or NULL if no prior
- * revision exists. The caller is responsible for disposing of this string.
- *
- * NOTES
- * This function currently neglects the case where we are on the trunk with
- * rev = X.1, where X != 1. If rev = X.Y, where X != 1 and Y > 1, then this
- * function should work fine, as revision X.1 must exist, due to RCS rules.
- */
-char *
-previous_rev (rcs, rev)
- RCSNode *rcs;
- const char *rev;
-{
- char *p;
- char *tmp = xstrdup (rev);
- long r1;
- char *retval;
-
- /* Our retval can have no more digits and dots than our input revision. */
- retval = xmalloc (strlen (rev) + 1);
- p = strrchr (tmp, '.');
- *p = '\0';
- r1 = strtol (p+1, NULL, 10);
- do {
- if (--r1 == 0)
- {
- /* If r1 == 0, then we must be on a branch and our parent must
- * exist, or we must be on the trunk with a REV like X.1.
- * We are neglecting the X.1 with X != 1 case by assuming that
- * there is no previous revision when we discover we were on
- * the trunk.
- */
- p = strrchr (tmp, '.');
- if (p == NULL)
- /* We are on the trunk. */
- retval = NULL;
- else
- {
- *p = '\0';
- sprintf (retval, "%s", tmp);
- }
- break;
- }
- sprintf (retval, "%s.%ld", tmp, r1);
- } while (!RCS_exist_rev (rcs, retval));
-
- free (tmp);
- return retval;
-}
-
-
-
-/* Given two revisions, find their greatest common ancestor. If the
- two input revisions exist, then rcs guarantees that the gca will
- exist. */
-
-char *
-gca (rev1, rev2)
- const char *rev1;
- const char *rev2;
-{
- int dots;
- char *gca, *g;
- const char *p1, *p2;
- int r1, r2;
- char *retval;
-
- if (rev1 == NULL || rev2 == NULL)
- {
- error (0, 0, "sanity failure in gca");
- abort();
- }
-
- /* The greatest common ancestor will have no more dots, and numbers
- of digits for each component no greater than the arguments. Therefore
- this string will be big enough. */
- g = gca = xmalloc (strlen (rev1) + strlen (rev2) + 100);
-
- /* walk the strings, reading the common parts. */
- p1 = rev1;
- p2 = rev2;
- do
- {
- r1 = strtol (p1, (char **) &p1, 10);
- r2 = strtol (p2, (char **) &p2, 10);
-
- /* use the lowest. */
- (void) sprintf (g, "%d.", r1 < r2 ? r1 : r2);
- g += strlen (g);
- if (*p1 == '.') ++p1;
- else break;
- if (*p2 == '.') ++p2;
- else break;
- } while (r1 == r2);
-
- /* erase that last dot. */
- *--g = '\0';
-
- /* numbers differ, or we ran out of strings. we're done with the
- common parts. */
-
- dots = numdots (gca);
- if (dots == 0)
- {
- /* revisions differ in trunk major number. */
-
- if (r2 < r1) p1 = p2;
- if (*p1 == '\0')
- {
- /* we only got one number. this is strange. */
- error (0, 0, "bad revisions %s or %s", rev1, rev2);
- abort();
- }
- else
- {
- /* we have a minor number. use it. */
- *g++ = '.';
- while (*p1 != '.' && *p1 != '\0')
- *g++ = *p1++;
- *g = '\0';
- }
- }
- else if ((dots & 1) == 0)
- {
- /* if we have an even number of dots, then we have a branch.
- remove the last number in order to make it a revision. */
-
- g = strrchr (gca, '.');
- *g = '\0';
- }
-
- retval = xstrdup (gca);
- free (gca);
- return retval;
-}
-
-/* Give fatal error if REV is numeric and ARGC,ARGV imply we are
- planning to operate on more than one file. The current directory
- should be the working directory. Note that callers assume that we
- will only be checking the first character of REV; it need not have
- '\0' at the end of the tag name and other niceties. Right now this
- is only called from admin.c, but if people like the concept it probably
- should also be called from diff -r, update -r, get -r, and log -r. */
-
-void
-check_numeric (rev, argc, argv)
- const char *rev;
- int argc;
- char **argv;
-{
- if (rev == NULL || !isdigit ((unsigned char) *rev))
- return;
-
- /* Note that the check for whether we are processing more than one
- file is (basically) syntactic; that is, we don't behave differently
- depending on whether a directory happens to contain only a single
- file or whether it contains more than one. I strongly suspect this
- is the least confusing behavior. */
- if (argc != 1
- || (!wrap_name_has (argv[0], WRAP_TOCVS) && isdir (argv[0])))
- {
- error (0, 0, "while processing more than one file:");
- error (1, 0, "attempt to specify a numeric revision");
- }
-}
-
-/*
- * Sanity checks and any required fix-up on message passed to RCS via '-m'.
- * RCS 5.7 requires that a non-total-whitespace, non-null message be provided
- * with '-m'. Returns a newly allocated, non-empty buffer with whitespace
- * stripped from end of lines and end of buffer.
- *
- * TODO: We no longer use RCS to manage repository files, so maybe this
- * nonsense about non-empty log fields can be dropped.
- */
-char *
-make_message_rcslegal (message)
- const char *message;
-{
- char *dst, *dp;
- const char *mp;
-
- if (message == NULL) message = "";
-
- /* Strip whitespace from end of lines and end of string. */
- dp = dst = (char *) xmalloc (strlen (message) + 1);
- for (mp = message; *mp != '\0'; ++mp)
- {
- if (*mp == '\n')
- {
- /* At end-of-line; backtrack to last non-space. */
- while (dp > dst && (dp[-1] == ' ' || dp[-1] == '\t'))
- --dp;
- }
- *dp++ = *mp;
- }
-
- /* Backtrack to last non-space at end of string, and truncate. */
- while (dp > dst && isspace ((unsigned char) dp[-1]))
- --dp;
- *dp = '\0';
-
- /* After all that, if there was no non-space in the string,
- substitute a non-empty message. */
- if (*dst == '\0')
- {
- free (dst);
- dst = xstrdup ("*** empty log message ***");
- }
-
- return dst;
-}
-
-
-
-/* Does the file FINFO contain conflict markers? The whole concept
- of looking at the contents of the file to figure out whether there are
- unresolved conflicts is kind of bogus (people do want to manage files
- which contain those patterns not as conflict markers), but for now it
- is what we do. */
-int
-file_has_markers (finfo)
- const struct file_info *finfo;
-{
- FILE *fp;
- char *line = NULL;
- size_t line_allocated = 0;
- int result;
-
- result = 0;
- fp = CVS_FOPEN (finfo->file, "r");
- if (fp == NULL)
- error (1, errno, "cannot open %s", finfo->fullname);
- while (getline (&line, &line_allocated, fp) > 0)
- {
- if (strncmp (line, RCS_MERGE_PAT_1, sizeof RCS_MERGE_PAT_1 - 1) == 0 ||
- strncmp (line, RCS_MERGE_PAT_2, sizeof RCS_MERGE_PAT_2 - 1) == 0 ||
- strncmp (line, RCS_MERGE_PAT_3, sizeof RCS_MERGE_PAT_3 - 1) == 0)
- {
- result = 1;
- goto out;
- }
- }
- if (ferror (fp))
- error (0, errno, "cannot read %s", finfo->fullname);
-out:
- if (fclose (fp) < 0)
- error (0, errno, "cannot close %s", finfo->fullname);
- if (line != NULL)
- free (line);
- return result;
-}
-
-/* Read the entire contents of the file NAME into *BUF.
- If NAME is NULL, read from stdin. *BUF
- is a pointer returned from malloc (or NULL), pointing to *BUFSIZE
- bytes of space. The actual size is returned in *LEN. On error,
- give a fatal error. The name of the file to use in error messages
- (typically will include a directory if we have changed directory)
- is FULLNAME. MODE is "r" for text or "rb" for binary. */
-
-void
-get_file (name, fullname, mode, buf, bufsize, len)
- const char *name;
- const char *fullname;
- const char *mode;
- char **buf;
- size_t *bufsize;
- size_t *len;
-{
- struct stat s;
- size_t nread;
- char *tobuf;
- FILE *e;
- size_t filesize;
-
- if (name == NULL)
- {
- e = stdin;
- filesize = 100; /* force allocation of minimum buffer */
- }
- else
- {
- /* 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. */
-
- if (CVS_STAT (name, &s) < 0)
- error (1, errno, "can't stat %s", fullname);
-
- /* Convert from signed to unsigned. */
- filesize = s.st_size;
-
- e = open_file (name, mode);
- }
-
- if (*buf == NULL || *bufsize <= filesize)
- {
- *bufsize = filesize + 1;
- *buf = xrealloc (*buf, *bufsize);
- }
-
- tobuf = *buf;
- nread = 0;
- while (1)
- {
- size_t got;
-
- got = fread (tobuf, 1, *bufsize - (tobuf - *buf), e);
- if (ferror (e))
- error (1, errno, "can't read %s", fullname);
- nread += got;
- tobuf += got;
-
- if (feof (e))
- break;
-
- /* Allocate more space if needed. */
- if (tobuf == *buf + *bufsize)
- {
- int c;
- long off;
-
- c = getc (e);
- if (c == EOF)
- break;
- off = tobuf - *buf;
- expand_string (buf, bufsize, *bufsize + 100);
- tobuf = *buf + off;
- *tobuf++ = c;
- ++nread;
- }
- }
-
- if (e != stdin && fclose (e) < 0)
- error (0, errno, "cannot close %s", fullname);
-
- *len = nread;
-
- /* Force *BUF to be large enough to hold a null terminator. */
- if (nread == *bufsize)
- expand_string (buf, bufsize, *bufsize + 1);
- (*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 == NULL || *filename == NULL)
- return;
-
- while (islink (*filename))
- {
-#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. */
- char *newname = xreadlink (*filename);
-
- if (isabsolute (newname))
- {
- free (*filename);
- *filename = newname;
- }
- else
- {
- const 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;
- }
-#else
- error (1, 0, "internal error: islink doesn't like readlink");
-#endif
- }
-}
-
-/*
- * Rename a file to an appropriate backup name based on BAKPREFIX.
- * If suffix non-null, then ".<suffix>" is appended to the new name.
- *
- * Returns the new name, which caller may free() if desired.
- */
-char *
-backup_file (filename, suffix)
- const char *filename;
- const char *suffix;
-{
- char *backup_name;
-
- if (suffix == NULL)
- {
- backup_name = xmalloc (sizeof (BAKPREFIX) + strlen (filename) + 1);
- sprintf (backup_name, "%s%s", BAKPREFIX, filename);
- }
- else
- {
- backup_name = xmalloc (sizeof (BAKPREFIX)
- + strlen (filename)
- + strlen (suffix)
- + 2); /* one for dot, one for trailing '\0' */
- sprintf (backup_name, "%s%s.%s", BAKPREFIX, filename, suffix);
- }
-
- if (isfile (filename))
- copy_file (filename, backup_name);
-
- return backup_name;
-}
-
-/*
- * Copy a string into a buffer escaping any shell metacharacters. The
- * buffer should be at least twice as long as the string.
- *
- * Returns a pointer to the terminating NUL byte in buffer.
- */
-
-char *
-shell_escape(buf, str)
- char *buf;
- const char *str;
-{
- static const char meta[] = "$`\\\"";
- const char *p;
-
- for (;;)
- {
- p = strpbrk(str, meta);
- if (!p) p = str + strlen(str);
- if (p > str)
- {
- memcpy(buf, str, p - str);
- buf += p - str;
- }
- if (!*p) break;
- *buf++ = '\\';
- *buf++ = *p++;
- str = p;
- }
- *buf = '\0';
- return buf;
-}
-
-
-
-/*
- * We can only travel forwards in time, not backwards. :)
- */
-void
-sleep_past (desttime)
- time_t desttime;
-{
- time_t t;
- long s;
- long us;
-
- while (time (&t) <= desttime)
- {
-#ifdef HAVE_GETTIMEOFDAY
- struct timeval tv;
- gettimeofday (&tv, NULL);
- if (tv.tv_sec > desttime)
- break;
- s = desttime - tv.tv_sec;
- if (tv.tv_usec > 0)
- us = 1000000 - tv.tv_usec;
- else
- {
- s++;
- us = 0;
- }
-#else
- /* default to 20 ms increments */
- s = desttime - t;
- us = 20000;
-#endif
-
-#if defined(HAVE_NANOSLEEP)
- {
- struct timespec ts;
- ts.tv_sec = s;
- ts.tv_nsec = us * 1000;
- (void)nanosleep (&ts, NULL);
- }
-#elif defined(HAVE_USLEEP)
- if (s > 0)
- (void)sleep (s);
- else
- (void)usleep (us);
-#elif defined(HAVE_SELECT)
- {
- /* use select instead of sleep since it is a fairly portable way of
- * sleeping for ms.
- */
- struct timeval tv;
- tv.tv_sec = s;
- tv.tv_usec = us;
- (void)select (0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL,
- &tv);
- }
-#else
- if (us > 0) s++;
- (void)sleep(s);
-#endif
- }
-}
-
-
-
-/* Return non-zero iff FILENAME is absolute.
- Trivial under Unix, but more complicated under other systems. */
-int
-isabsolute (filename)
- const char *filename;
-{
- return ISABSOLUTE (filename);
-}
diff --git a/contrib/cvs/src/tag.c b/contrib/cvs/src/tag.c
deleted file mode 100644
index 43451ce32939..000000000000
--- a/contrib/cvs/src/tag.c
+++ /dev/null
@@ -1,1465 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * Tag and Rtag
- *
- * Add or delete a symbolic name to an RCS file, or a collection of RCS files.
- * Tag uses the checked out revision in the current directory, rtag uses
- * the modules database, if necessary.
- *
- * $FreeBSD$
- */
-
-#include "cvs.h"
-#include "savecwd.h"
-
-static int rtag_proc PROTO((int argc, char **argv, char *xwhere,
- char *mwhere, char *mfile, int shorten,
- int local_specified, char *mname, char *msg));
-static int check_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-static int check_filesdoneproc PROTO ((void *callerdat, int err,
- const char *repos,
- const char *update_dir,
- List *entries));
-static int pretag_proc PROTO((const char *repository, const char *filter));
-static void masterlist_delproc PROTO((Node *p));
-static void tag_delproc PROTO((Node *p));
-static int pretag_list_proc PROTO((Node *p, void *closure));
-
-static Dtype tag_dirproc PROTO ((void *callerdat, const char *dir,
- const char *repos, const char *update_dir,
- List *entries));
-static int rtag_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-static int rtag_delete PROTO((RCSNode *rcsfile));
-static int tag_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-
-static char *numtag; /* specific revision to tag */
-static int numtag_validated = 0;
-static char *date = NULL;
-static char *symtag; /* tag to add or delete */
-static int delete_flag; /* adding a tag by default */
-static int branch_mode; /* make an automagic "branch" tag */
-static int disturb_branch_tags = 0; /* allow -F,-d to disturb branch tags */
-static int force_tag_match = 1; /* force tag to match by default */
-static int force_tag_move; /* don't force tag to move by default */
-static int check_uptodate; /* no uptodate-check by default */
-static int attic_too; /* remove tag from Attic files */
-static int is_rtag;
-
-struct tag_info
-{
- Ctype status;
- char *rev;
- char *tag;
- char *options;
-};
-
-struct master_lists
-{
- List *tlist;
-};
-
-static List *mtlist;
-static List *tlist;
-
-static const char rtag_opts[] = "+aBbdFflnQqRr:D:";
-static const char *const rtag_usage[] =
-{
- "Usage: %s %s [-abdFflnR] [-r rev|-D date] tag modules...\n",
- "\t-a\tClear tag from removed files that would not otherwise be tagged.\n",
- "\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n",
- "\t-B\tAllows -F and -d to disturb branch tags. Use with extreme care.\n",
- "\t-d\tDelete the given tag.\n",
- "\t-F\tMove tag if it already exists.\n",
- "\t-f\tForce a head revision match if tag/date not found.\n",
- "\t-l\tLocal directory only, not recursive.\n",
- "\t-n\tNo execution of 'tag program'.\n",
- "\t-R\tProcess directories recursively.\n",
- "\t-r rev\tExisting revision/tag.\n",
- "\t-D\tExisting date.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-static const char tag_opts[] = "+BbcdFflQqRr:D:";
-static const char *const tag_usage[] =
-{
- "Usage: %s %s [-bcdFflR] [-r rev|-D date] tag [files...]\n",
- "\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n",
- "\t-B\tAllows -F and -d to disturb branch tags. Use with extreme care.\n",
- "\t-c\tCheck that working files are unmodified.\n",
- "\t-d\tDelete the given tag.\n",
- "\t-F\tMove tag if it already exists.\n",
- "\t-f\tForce a head revision match if tag/date not found.\n",
- "\t-l\tLocal directory only, not recursive.\n",
- "\t-R\tProcess directories recursively.\n",
- "\t-r rev\tExisting revision/tag.\n",
- "\t-D\tExisting date.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-int
-cvstag (argc, argv)
- int argc;
- char **argv;
-{
- int local = 0; /* recursive by default */
- int c;
- int err = 0;
- int run_module_prog = 1;
-
- is_rtag = (strcmp (cvs_cmd_name, "rtag") == 0);
-
- if (argc == -1)
- usage (is_rtag ? rtag_usage : tag_usage);
-
- optind = 0;
- while ((c = getopt (argc, argv, is_rtag ? rtag_opts : tag_opts)) != -1)
- {
- switch (c)
- {
- case 'a':
- attic_too = 1;
- break;
- case 'b':
- branch_mode = 1;
- break;
- case 'B':
- disturb_branch_tags = 1;
- break;
- case 'c':
- check_uptodate = 1;
- break;
- case 'd':
- delete_flag = 1;
- break;
- case 'F':
- force_tag_move = 1;
- break;
- case 'f':
- force_tag_match = 0;
- break;
- case 'l':
- local = 1;
- break;
- case 'n':
- run_module_prog = 0;
- break;
- case 'Q':
- case 'q':
- /* The CVS 1.5 client sends these options (in addition to
- Global_option requests), so we must ignore them. */
- if (!server_active)
- error (1, 0,
- "-q or -Q must be specified before \"%s\"",
- cvs_cmd_name);
- break;
- case 'R':
- local = 0;
- break;
- case 'r':
- numtag = optarg;
- break;
- case 'D':
- if (date)
- free (date);
- date = Make_Date (optarg);
- break;
- case '?':
- default:
- usage (is_rtag ? rtag_usage : tag_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- if (argc < (is_rtag ? 2 : 1))
- usage (is_rtag ? rtag_usage : tag_usage);
- symtag = argv[0];
- argc--;
- argv++;
-
- if (date && numtag)
- error (1, 0, "-r and -D options are mutually exclusive");
- if (delete_flag && branch_mode)
- error (0, 0, "warning: -b ignored with -d options");
- RCS_check_tag (symtag);
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- /* We're the client side. Fire up the remote server. */
- start_server ();
-
- ign_setup ();
-
- if (attic_too)
- send_arg("-a");
- if (branch_mode)
- send_arg("-b");
- if (disturb_branch_tags)
- send_arg("-B");
- if (check_uptodate)
- send_arg("-c");
- if (delete_flag)
- send_arg("-d");
- if (force_tag_move)
- send_arg("-F");
- if (!force_tag_match)
- send_arg ("-f");
- if (local)
- send_arg("-l");
- if (!run_module_prog)
- send_arg("-n");
-
- if (numtag)
- option_with_arg ("-r", numtag);
- if (date)
- client_senddate (date);
-
- send_arg ("--");
-
- send_arg (symtag);
-
- if (is_rtag)
- {
- int i;
- for (i = 0; i < argc; ++i)
- send_arg (argv[i]);
- send_to_server ("rtag\012", 0);
- }
- else
- {
- send_files (argc, argv, local, 0,
-
- /* 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 ();
- }
-#endif
-
- if (is_rtag)
- {
- DBM *db;
- int i;
- db = open_module ();
- for (i = 0; i < argc; i++)
- {
- /* XXX last arg should be repository, but doesn't make sense here */
- history_write ('T', (delete_flag ? "D" : (numtag ? numtag :
- (date ? date : "A"))), symtag, argv[i], "");
- err += do_module (db, argv[i], TAG,
- delete_flag ? "Untagging" : "Tagging",
- rtag_proc, (char *) NULL, 0, local, run_module_prog,
- 0, symtag);
- }
- close_module (db);
- }
- else
- {
- err = rtag_proc (argc + 1, argv - 1, NULL, NULL, NULL, 0, local, NULL,
- NULL);
- }
-
- return (err);
-}
-
-/*
- * callback proc for doing the real work of tagging
- */
-/* ARGSUSED */
-static int
-rtag_proc (argc, argv, xwhere, mwhere, mfile, shorten, local_specified,
- mname, msg)
- int argc;
- char **argv;
- char *xwhere;
- char *mwhere;
- char *mfile;
- int shorten;
- int local_specified;
- char *mname;
- char *msg;
-{
- /* Begin section which is identical to patch_proc--should this
- be abstracted out somehow? */
- char *myargv[2];
- int err = 0;
- int which;
- char *repository;
- char *where;
-
- if (is_rtag)
- {
- repository = xmalloc (strlen (current_parsed_root->directory) + strlen (argv[0])
- + (mfile == NULL ? 0 : strlen (mfile) + 1) + 2);
- (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
- where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile) + 1)
- + 1);
- (void) strcpy (where, argv[0]);
-
- /* if mfile isn't null, we need to set up to do only part of the module */
- if (mfile != NULL)
- {
- char *cp;
- char *path;
-
- /* if the portion of the module is a path, put the dir part on repos */
- if ((cp = strrchr (mfile, '/')) != NULL)
- {
- *cp = '\0';
- (void) strcat (repository, "/");
- (void) strcat (repository, mfile);
- (void) strcat (where, "/");
- (void) strcat (where, mfile);
- mfile = cp + 1;
- }
-
- /* take care of the rest */
- path = xmalloc (strlen (repository) + strlen (mfile) + 5);
- (void) sprintf (path, "%s/%s", repository, mfile);
- if (isdir (path))
- {
- /* directory means repository gets the dir tacked on */
- (void) strcpy (repository, path);
- (void) strcat (where, "/");
- (void) strcat (where, mfile);
- }
- else
- {
- myargv[0] = argv[0];
- myargv[1] = mfile;
- argc = 2;
- argv = myargv;
- }
- free (path);
- }
-
- /* cd to the starting repository */
- if ( CVS_CHDIR (repository) < 0)
- {
- error (0, errno, "cannot chdir to %s", repository);
- free (repository);
- free (where);
- return (1);
- }
- /* End section which is identical to patch_proc. */
-
- if (delete_flag || force_tag_move || attic_too || numtag)
- which = W_REPOS | W_ATTIC;
- else
- which = W_REPOS;
- }
- else
- {
- where = NULL;
- which = W_LOCAL;
- repository = "";
- }
-
- if (numtag != NULL && !numtag_validated)
- {
- tag_check_valid (numtag, argc - 1, argv + 1, local_specified, 0, repository);
- numtag_validated = 1;
- }
-
- /* check to make sure they are authorized to tag all the
- specified files in the repository */
-
- mtlist = getlist();
- err = start_recursion (check_fileproc, check_filesdoneproc,
- (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
- argc - 1, argv + 1, local_specified, which, 0,
- CVS_LOCK_READ, where, 1, repository);
-
- if (err)
- {
- error (1, 0, "correct the above errors first!");
- }
-
- /* It would be nice to provide consistency with respect to
- commits; however CVS lacks the infrastructure to do that (see
- Concurrency in cvs.texinfo and comment in do_recursion). */
-
- /* start the recursion processor */
- err = start_recursion (is_rtag ? rtag_fileproc : tag_fileproc,
- (FILESDONEPROC) NULL, tag_dirproc,
- (DIRLEAVEPROC) NULL, NULL, argc - 1, argv + 1,
- local_specified, which, 0, CVS_LOCK_WRITE, where, 1,
- repository);
- if ( which & W_REPOS ) free ( repository );
- dellist (&mtlist);
- if (where != NULL)
- free (where);
- return (err);
-}
-
-/* check file that is to be tagged */
-/* All we do here is add it to our list */
-
-static int
-check_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- const char *xdir;
- Node *p;
- Vers_TS *vers;
-
- if (check_uptodate)
- {
- switch (Classify_File (finfo, (char *) NULL, (char *) NULL,
- (char *) NULL, 1, 0, &vers, 0))
- {
- case T_UPTODATE:
- case T_CHECKOUT:
- case T_PATCH:
- case T_REMOVE_ENTRY:
- break;
- case T_UNKNOWN:
- case T_CONFLICT:
- case T_NEEDS_MERGE:
- case T_MODIFIED:
- case T_ADDED:
- case T_REMOVED:
- default:
- error (0, 0, "%s is locally modified", finfo->fullname);
- freevers_ts (&vers);
- return (1);
- }
- }
- else
- vers = Version_TS (finfo, NULL, NULL, NULL, 0, 0);
-
- if (finfo->update_dir[0] == '\0')
- xdir = ".";
- else
- xdir = finfo->update_dir;
- if ((p = findnode (mtlist, xdir)) != NULL)
- {
- tlist = ((struct master_lists *) p->data)->tlist;
- }
- else
- {
- struct master_lists *ml;
-
- tlist = getlist ();
- p = getnode ();
- p->key = xstrdup (xdir);
- p->type = UPDATE;
- ml = (struct master_lists *)
- xmalloc (sizeof (struct master_lists));
- ml->tlist = tlist;
- p->data = ml;
- p->delproc = masterlist_delproc;
- (void) addnode (mtlist, p);
- }
- /* do tlist */
- p = getnode ();
- p->key = xstrdup (finfo->file);
- p->type = UPDATE;
- p->delproc = tag_delproc;
- if (vers->srcfile == NULL)
- {
- if (!really_quiet)
- error (0, 0, "nothing known about %s", finfo->file);
- freevers_ts (&vers);
- freenode (p);
- return (1);
- }
-
- /* Here we duplicate the calculation in tag_fileproc about which
- version we are going to tag. There probably are some subtle races
- (e.g. numtag is "foo" which gets moved between here and
- tag_fileproc). */
- if (!is_rtag && numtag == NULL && date == NULL)
- p->data = xstrdup (vers->vn_user);
- else
- p->data = RCS_getversion (vers->srcfile, numtag, date,
- force_tag_match, NULL);
-
- if (p->data != NULL)
- {
- int addit = 1;
- char *oversion;
-
- oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1,
- (int *) NULL);
- if (oversion == NULL)
- {
- 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;
- }
- else if (!force_tag_move)
- {
- addit = 0;
- }
- if (oversion != NULL)
- {
- free(oversion);
- }
- if (!addit)
- {
- free(p->data);
- p->data = NULL;
- }
- }
- freevers_ts (&vers);
- (void) addnode (tlist, p);
- return (0);
-}
-
-static int
-check_filesdoneproc (callerdat, err, repos, update_dir, entries)
- void *callerdat;
- int err;
- const char *repos;
- const char *update_dir;
- List *entries;
-{
- int n;
- Node *p;
-
- p = findnode(mtlist, update_dir);
- if (p != NULL)
- {
- tlist = ((struct master_lists *) p->data)->tlist;
- }
- else
- {
- tlist = (List *) NULL;
- }
- if ((tlist == NULL) || (tlist->list->next == tlist->list))
- {
- return (err);
- }
- if ((n = Parse_Info(CVSROOTADM_TAGINFO, repos, pretag_proc, 1)) > 0)
- {
- error (0, 0, "Pre-tag check failed");
- err += n;
- }
- return (err);
-}
-
-static int
-pretag_proc (repository, filter)
- const char *repository;
- const char *filter;
-{
- if (filter[0] == '/')
- {
- char *s, *cp;
-
- s = xstrdup(filter);
- for (cp=s; *cp; cp++)
- {
- if (isspace ((unsigned char) *cp))
- {
- *cp = '\0';
- break;
- }
- }
- if (!isfile(s))
- {
- error (0, errno, "cannot find pre-tag filter '%s'", s);
- free(s);
- return (1);
- }
- free(s);
- }
- run_setup (filter);
- run_arg (symtag);
- run_arg (delete_flag ? "del" : force_tag_move ? "mov" : "add");
- run_arg (repository);
- walklist(tlist, pretag_list_proc, NULL);
- return (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL));
-}
-
-static void
-masterlist_delproc(p)
- Node *p;
-{
- struct master_lists *ml = p->data;
-
- dellist(&ml->tlist);
- free(ml);
- return;
-}
-
-static void
-tag_delproc(p)
- Node *p;
-{
- if (p->data != NULL)
- {
- free(p->data);
- p->data = NULL;
- }
- return;
-}
-
-static int
-pretag_list_proc(p, closure)
- Node *p;
- void *closure;
-{
- if (p->data != NULL)
- {
- run_arg(p->key);
- run_arg(p->data);
- }
- return (0);
-}
-
-
-/*
- * Called to rtag a particular file, as appropriate with the options that were
- * set above.
- */
-/* ARGSUSED */
-static int
-rtag_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- RCSNode *rcsfile;
- char *version, *rev;
- int retcode = 0;
-
- /* find the parsed RCS data */
- if ((rcsfile = finfo->rcs) == NULL)
- return (1);
-
- /*
- * For tagging an RCS file which is a symbolic link, you'd best be
- * running with RCS 5.6, since it knows how to handle symbolic links
- * correctly without breaking your link!
- */
-
- if (delete_flag)
- return (rtag_delete (rcsfile));
-
- /*
- * If we get here, we are adding a tag. But, if -a was specified, we
- * need to check to see if a -r or -D option was specified. If neither
- * was specified and the file is in the Attic, remove the tag.
- */
- if (attic_too && (!numtag && !date))
- {
- if ((rcsfile->flags & VALID) && (rcsfile->flags & INATTIC))
- return (rtag_delete (rcsfile));
- }
-
- version = RCS_getversion (rcsfile, numtag, date, force_tag_match,
- (int *) NULL);
- if (version == NULL)
- {
- /* If -a specified, clean up any old tags */
- if (attic_too)
- (void) rtag_delete (rcsfile);
-
- if (!quiet && !force_tag_match)
- {
- error (0, 0, "cannot find tag `%s' in `%s'",
- numtag ? numtag : "head", rcsfile->path);
- return (1);
- }
- return (0);
- }
- if (numtag
- && isdigit ((unsigned char) *numtag)
- && strcmp (numtag, version) != 0)
- {
-
- /*
- * We didn't find a match for the numeric tag that was specified, but
- * that's OK. just pass the numeric tag on to rcs, to be tagged as
- * specified. Could get here if one tried to tag "1.1.1" and there
- * was a 1.1.1 branch with some head revision. In this case, we want
- * the tag to reference "1.1.1" and not the revision at the head of
- * the branch. Use a symbolic tag for that.
- */
- rev = branch_mode ? RCS_magicrev (rcsfile, version) : numtag;
- retcode = RCS_settag(rcsfile, symtag, numtag);
- if (retcode == 0)
- RCS_rewrite (rcsfile, NULL, NULL);
- }
- else
- {
- char *oversion;
-
- /*
- * As an enhancement for the case where a tag is being re-applied to
- * a large body of a module, make one extra call to RCS_getversion to
- * see if the tag is already set in the RCS file. If so, check to
- * see if it needs to be moved. If not, do nothing. This will
- * likely save a lot of time when simply moving the tag to the
- * "current" head revisions of a module -- which I have found to be a
- * typical tagging operation.
- */
- rev = branch_mode ? RCS_magicrev (rcsfile, version) : version;
- oversion = RCS_getversion (rcsfile, symtag, (char *) NULL, 1,
- (int *) NULL);
- if (oversion != NULL)
- {
- int isbranch = RCS_nodeisbranch (finfo->rcs, symtag);
-
- /*
- * if versions the same and neither old or new are branches don't
- * have to do anything
- */
- if (strcmp (version, oversion) == 0 && !branch_mode && !isbranch)
- {
- free (oversion);
- free (version);
- return (0);
- }
-
- if (!force_tag_move)
- {
- /* we're NOT going to move the tag */
- (void) printf ("W %s", finfo->fullname);
-
- (void) printf (" : %s already exists on %s %s",
- symtag, isbranch ? "branch" : "version",
- oversion);
- (void) printf (" : NOT MOVING tag to %s %s\n",
- branch_mode ? "branch" : "version", rev);
- free (oversion);
- free (version);
- if (branch_mode) free(rev);
- return (0);
- }
- else /* force_tag_move is set and... */
- if ((isbranch && !disturb_branch_tags) ||
- (!isbranch && disturb_branch_tags))
- {
- error(0,0, "%s: Not moving %s tag `%s' from %s to %s%s.",
- finfo->fullname,
- isbranch ? "branch" : "non-branch",
- symtag, oversion, rev,
- isbranch ? "" : " due to `-B' option");
- if (branch_mode) free(rev);
- free (oversion);
- free (version);
- return (0);
- }
- free (oversion);
- }
- retcode = RCS_settag(rcsfile, symtag, rev);
- if (retcode == 0)
- RCS_rewrite (rcsfile, NULL, NULL);
- }
-
- if (retcode != 0)
- {
- error (1, retcode == -1 ? errno : 0,
- "failed to set tag `%s' to revision `%s' in `%s'",
- symtag, rev, rcsfile->path);
- if (branch_mode)
- free (rev);
- free (version);
- return (1);
- }
- if (branch_mode)
- free (rev);
- free (version);
- return (0);
-}
-
-/*
- * If -d is specified, "force_tag_match" is set, so that this call to
- * RCS_getversion() will return a NULL version string if the symbolic
- * tag does not exist in the RCS file.
- *
- * If the -r flag was used, numtag is set, and we only delete the
- * symtag from files that have numtag.
- *
- * This is done here because it's MUCH faster than just blindly calling
- * "rcs" to remove the tag... trust me.
- */
-static int
-rtag_delete (rcsfile)
- RCSNode *rcsfile;
-{
- char *version;
- int retcode, isbranch;
-
- if (numtag)
- {
- version = RCS_getversion (rcsfile, numtag, (char *) NULL, 1,
- (int *) NULL);
- if (version == NULL)
- return (0);
- free (version);
- }
-
- version = RCS_getversion (rcsfile, symtag, (char *) NULL, 1,
- (int *) NULL);
- if (version == NULL)
- return (0);
- free (version);
-
-
- isbranch = RCS_nodeisbranch (rcsfile, symtag);
- if ((isbranch && !disturb_branch_tags) ||
- (!isbranch && disturb_branch_tags))
- {
- if (!quiet)
- error(0, 0,
- "Not removing %s tag `%s' from `%s'%s.",
- isbranch ? "branch" : "non-branch",
- symtag, rcsfile->path,
- isbranch ? "" : " due to `-B' option");
- return (1);
- }
-
- if ((retcode = RCS_deltag(rcsfile, symtag)) != 0)
- {
- if (!quiet)
- error (0, retcode == -1 ? errno : 0,
- "failed to remove tag `%s' from `%s'", symtag,
- rcsfile->path);
- return (1);
- }
- RCS_rewrite (rcsfile, NULL, NULL);
- return (0);
-}
-
-
-/*
- * Called to tag a particular file (the currently checked out version is
- * tagged with the specified tag - or the specified tag is deleted).
- */
-/* ARGSUSED */
-static int
-tag_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- char *version, *oversion;
- char *nversion = NULL;
- char *rev;
- Vers_TS *vers;
- int retcode = 0;
- int retval = 0;
-
- vers = Version_TS (finfo, NULL, NULL, NULL, 0, 0);
-
- if ((numtag != NULL) || (date != NULL))
- {
- nversion = RCS_getversion(vers->srcfile,
- numtag,
- date,
- force_tag_match,
- (int *) NULL);
- if (nversion == NULL)
- goto free_vars_and_return;
- }
- if (delete_flag)
- {
-
- int isbranch;
- /*
- * If -d is specified, "force_tag_match" is set, so that this call to
- * RCS_getversion() will return a NULL version string if the symbolic
- * tag does not exist in the RCS file.
- *
- * This is done here because it's MUCH faster than just blindly calling
- * "rcs" to remove the tag... trust me.
- */
-
- version = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1,
- (int *) NULL);
- if (version == NULL || vers->srcfile == NULL)
- goto free_vars_and_return;
-
- free (version);
-
- isbranch = RCS_nodeisbranch (finfo->rcs, symtag);
- if ((isbranch && !disturb_branch_tags) ||
- (!isbranch && disturb_branch_tags))
- {
- if (!quiet)
- error(0, 0,
- "Not removing %s tag `%s' from `%s'%s.",
- isbranch ? "branch" : "non-branch",
- symtag, vers->srcfile->path,
- isbranch ? "" : " due to `-B' option");
- retval = 1;
- goto free_vars_and_return;
- }
-
- if ((retcode = RCS_deltag(vers->srcfile, symtag)) != 0)
- {
- if (!quiet)
- error (0, retcode == -1 ? errno : 0,
- "failed to remove tag %s from %s", symtag,
- vers->srcfile->path);
- retval = 1;
- goto free_vars_and_return;
- }
- RCS_rewrite (vers->srcfile, NULL, NULL);
-
- /* warm fuzzies */
- if (!really_quiet)
- {
- cvs_output ("D ", 2);
- cvs_output (finfo->fullname, 0);
- cvs_output ("\n", 1);
- }
-
- goto free_vars_and_return;
- }
-
- /*
- * If we are adding a tag, we need to know which version we have checked
- * out and we'll tag that version.
- */
- if (nversion == NULL)
- {
- version = vers->vn_user;
- }
- else
- {
- version = nversion;
- }
- if (version == NULL)
- {
- goto free_vars_and_return;
- }
- else if (strcmp (version, "0") == 0)
- {
- if (!quiet)
- error (0, 0, "couldn't tag added but un-commited file `%s'", finfo->file);
- goto free_vars_and_return;
- }
- else if (version[0] == '-')
- {
- if (!quiet)
- error (0, 0, "skipping removed but un-commited file `%s'", finfo->file);
- goto free_vars_and_return;
- }
- else if (vers->srcfile == NULL)
- {
- if (!quiet)
- error (0, 0, "cannot find revision control file for `%s'", finfo->file);
- goto free_vars_and_return;
- }
-
- /*
- * As an enhancement for the case where a tag is being re-applied to a
- * large number of files, make one extra call to RCS_getversion to see
- * if the tag is already set in the RCS file. If so, check to see if it
- * needs to be moved. If not, do nothing. This will likely save a lot of
- * time when simply moving the tag to the "current" head revisions of a
- * module -- which I have found to be a typical tagging operation.
- */
- rev = branch_mode ? RCS_magicrev (vers->srcfile, version) : version;
- oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1,
- (int *) NULL);
- if (oversion != NULL)
- {
- int isbranch = RCS_nodeisbranch (finfo->rcs, symtag);
-
- /*
- * if versions the same and neither old or new are branches don't have
- * to do anything
- */
- if (strcmp (version, oversion) == 0 && !branch_mode && !isbranch)
- {
- free (oversion);
- if (branch_mode)
- free (rev);
- goto free_vars_and_return;
- }
-
- if (!force_tag_move)
- {
- /* we're NOT going to move the tag */
- cvs_output ("W ", 2);
- cvs_output (finfo->fullname, 0);
- cvs_output (" : ", 0);
- cvs_output (symtag, 0);
- cvs_output (" already exists on ", 0);
- cvs_output (isbranch ? "branch" : "version", 0);
- cvs_output (" ", 0);
- cvs_output (oversion, 0);
- cvs_output (" : NOT MOVING tag to ", 0);
- cvs_output (branch_mode ? "branch" : "version", 0);
- cvs_output (" ", 0);
- cvs_output (rev, 0);
- cvs_output ("\n", 1);
- free (oversion);
- if (branch_mode)
- free (rev);
- goto free_vars_and_return;
- }
- else /* force_tag_move == 1 and... */
- if ((isbranch && !disturb_branch_tags) ||
- (!isbranch && disturb_branch_tags))
- {
- error(0,0, "%s: Not moving %s tag `%s' from %s to %s%s.",
- finfo->fullname,
- isbranch ? "branch" : "non-branch",
- symtag, oversion, rev,
- isbranch ? "" : " due to `-B' option");
- free (oversion);
- if (branch_mode)
- free (rev);
- goto free_vars_and_return;
- }
- free (oversion);
- }
-
- if ((retcode = RCS_settag(vers->srcfile, symtag, rev)) != 0)
- {
- error (1, retcode == -1 ? errno : 0,
- "failed to set tag %s to revision %s in %s",
- symtag, rev, vers->srcfile->path);
- if (branch_mode)
- free (rev);
- retval = 1;
- goto free_vars_and_return;
- }
- if (branch_mode)
- free (rev);
- RCS_rewrite (vers->srcfile, NULL, NULL);
-
- /* more warm fuzzies */
- if (!really_quiet)
- {
- cvs_output ("T ", 2);
- cvs_output (finfo->fullname, 0);
- cvs_output ("\n", 1);
- }
-
- free_vars_and_return:
- if (nversion != NULL)
- free (nversion);
- freevers_ts (&vers);
- return (retval);
-}
-
-/*
- * Print a warm fuzzy message
- */
-/* ARGSUSED */
-static Dtype
-tag_dirproc (callerdat, dir, repos, update_dir, entries)
- void *callerdat;
- const char *dir;
- const char *repos;
- const char *update_dir;
- List *entries;
-{
-
- if (ignore_directory (update_dir))
- {
- /* print the warm fuzzy message */
- if (!quiet)
- error (0, 0, "Ignoring %s", update_dir);
- return R_SKIP_ALL;
- }
-
- if (!quiet)
- error (0, 0, "%s %s", delete_flag ? "Untagging" : "Tagging", update_dir);
- return (R_PROCESS);
-}
-
-/* Code relating to the val-tags file. Note that this file has no way
- of knowing when a tag has been deleted. The problem is that there
- is no way of knowing whether a tag still exists somewhere, when we
- delete it some places. Using per-directory val-tags files (in
- CVSREP) might be better, but that might slow down the process of
- verifying that a tag is correct (maybe not, for the likely cases,
- if carefully done), and/or be harder to implement correctly. */
-
-struct val_args {
- char *name;
- int found;
-};
-
-static int val_fileproc PROTO ((void *callerdat, struct file_info *finfo));
-
-static int
-val_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- RCSNode *rcsdata;
- struct val_args *args = (struct val_args *)callerdat;
- char *tag;
-
- if ((rcsdata = finfo->rcs) == NULL)
- /* Not sure this can happen, after all we passed only
- W_REPOS | W_ATTIC. */
- return 0;
-
- tag = RCS_gettag (rcsdata, args->name, 1, (int *) NULL);
- if (tag != NULL)
- {
- /* FIXME: should find out a way to stop the search at this point. */
- args->found = 1;
- free (tag);
- }
- return 0;
-}
-
-
-
-/* This routine determines whether a tag appears in CVSROOT/val-tags.
- *
- * The val-tags file will be open read-only when IDB is NULL. Since writes to
- * val-tags always append to it, the lack of locking is okay. The worst case
- * race condition might misinterpret a partially written "foobar" matched, for
- * instance, a request for "f", "foo", of "foob". Such a mismatch would be
- * caught harmlessly later.
- *
- * Before CVS adds a tag to val-tags, it will lock val-tags for write and
- * verify that the tag is still not present to avoid adding it twice.
- *
- * NOTES
- * This function expects its parent to handle any necessary locking of the
- * val-tags file.
- *
- * INPUTS
- * idb When this value is NULL, the val-tags file is opened in
- * in read-only mode. When present, the val-tags file is opened
- * in read-write mode and the DBM handle is stored in *IDB.
- * name The tag to search for.
- *
- * OUTPUTS
- * *idb The val-tags file opened for read/write, or NULL if it couldn't
- * be opened.
- *
- * ERRORS
- * Exits with an error message if the val-tags file cannot be opened for
- * read (failure to open val-tags read/write is harmless - see below).
- *
- * RETURNS
- * true 1. If NAME exists in val-tags.
- * 2. If IDB is non-NULL and val-tags cannot be opened for write.
- * This allows callers to ignore the harmless inability to
- * update the val-tags cache.
- * false If the file could be opened and the tag is not present.
- */
-static int is_in_val_tags PROTO((DBM **idb, const char *name));
-static int
-is_in_val_tags (idb, name)
- DBM **idb;
- const char *name;
-{
- DBM *db = NULL;
- char *valtags_filename;
- datum mytag;
- int status;
-
- /* Casting out const should be safe here - input datums are not
- * written to by the myndbm functions.
- */
- mytag.dptr = (char *)name;
- mytag.dsize = strlen (name);
-
- valtags_filename = xmalloc (strlen (current_parsed_root->directory)
- + sizeof CVSROOTADM
- + sizeof CVSROOTADM_VALTAGS + 3);
- sprintf (valtags_filename, "%s/%s/%s", current_parsed_root->directory,
- CVSROOTADM, CVSROOTADM_VALTAGS);
-
- if (idb)
- {
- db = dbm_open (valtags_filename, O_RDWR, 0666);
- if (!db)
- {
- mode_t omask;
-
- if (!existence_error (errno))
- {
- error (0, errno, "warning: cannot open %s read/write",
- valtags_filename);
- *idb = NULL;
- return 1;
- }
-
- omask = umask (cvsumask);
- db = dbm_open (valtags_filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
- umask (omask);
- if (!db)
- {
- error (0, errno, "warning: cannot create %s",
- valtags_filename);
- *idb = NULL;
- return 1;
- }
-
- *idb = db;
- return 0;
- }
-
- *idb = db;
- }
- else
- {
- db = dbm_open (valtags_filename, O_RDONLY, 0444);
- if (!db && !existence_error (errno))
- error (1, errno, "cannot read %s", valtags_filename);
- }
-
- /* If the file merely fails to exist, we just keep going and create
- it later if need be. */
-
- status = 0;
- if (db)
- {
- datum val;
-
- val = dbm_fetch (db, mytag);
- if (val.dptr != NULL)
- /* Found. The tag is valid. */
- status = 1;
-
- /* FIXME: should check errors somehow (add dbm_error to myndbm.c?). */
-
- if (!idb) dbm_close (db);
- }
-
- free (valtags_filename);
- return status;
-}
-
-
-
-/* Add a tag to the CVSROOT/val-tags cache. Establishes a write lock and
- * reverifies that the tag does not exist before adding it.
- */
-static void add_to_val_tags PROTO((const char *name));
-static void
-add_to_val_tags (name)
- const char *name;
-{
- DBM *db;
- datum mytag;
- datum value;
-
- if (noexec) return;
-
- val_tags_lock (current_parsed_root->directory);
-
- /* Check for presence again since we have a lock now. */
- if (is_in_val_tags (&db, name))
- {
- clear_val_tags_lock ();
- if (db)
- dbm_close (db);
- return;
- }
-
- /* Casting out const should be safe here - input datums are not
- * written to by the myndbm functions.
- */
- mytag.dptr = (char *)name;
- mytag.dsize = strlen (name);
- value.dptr = "y";
- value.dsize = 1;
-
- if (dbm_store (db, mytag, value, DBM_REPLACE) < 0)
- error (0, errno, "failed to store %s into val-tags", name);
- dbm_close (db);
-
- clear_val_tags_lock ();
-}
-
-
-
-static Dtype val_direntproc PROTO ((void *, const char *, const char *,
- const char *, List *));
-
-static Dtype
-val_direntproc (callerdat, dir, repository, update_dir, entries)
- void *callerdat;
- const char *dir;
- const char *repository;
- const char *update_dir;
- List *entries;
-{
- /* This is not quite right--it doesn't get right the case of "cvs
- update -d -r foobar" where foobar is a tag which exists only in
- files in a directory which does not exist yet, but which is
- about to be created. */
- if (isdir (dir))
- return R_PROCESS;
- return R_SKIP_ALL;
-}
-
-/* Check to see whether NAME is a valid tag. If so, return. If not
- print an error message and exit. ARGC, ARGV, LOCAL, and AFLAG specify
- which files we will be operating on.
-
- REPOSITORY is the repository if we need to cd into it, or NULL if
- we are already there, or "" if we should do a W_LOCAL recursion.
- Sorry for three cases, but the "" case is needed in case the
- working directories come from diverse parts of the repository, the
- NULL case avoids an unneccesary chdir, and the non-NULL, non-""
- case is needed for checkout, where we don't want to chdir if the
- tag is found in CVSROOTADM_VALTAGS, but there is not (yet) any
- local directory. */
-void
-tag_check_valid (name, argc, argv, local, aflag, repository)
- char *name;
- int argc;
- char **argv;
- int local;
- int aflag;
- char *repository;
-{
- struct val_args the_val_args;
- struct saved_cwd cwd;
- int which;
-
- /* Numeric tags require only a syntactic check. */
- if (isdigit ((unsigned char) name[0]))
- {
- char *p;
- for (p = name; *p != '\0'; ++p)
- {
- if (!(isdigit ((unsigned char) *p) || *p == '.'))
- error (1, 0, "\
-Numeric tag %s contains characters other than digits and '.'", name);
- }
- return;
- }
-
- /* Special tags are always valid. */
- if (strcmp (name, TAG_BASE) == 0
- || strcmp (name, TAG_HEAD) == 0)
- return;
-
- if (readonlyfs)
- return;
-
- /* Verify that the tag is valid syntactically. Some later code once made
- * assumptions about this.
- */
- RCS_check_tag (name);
-
- if (is_in_val_tags (NULL, name)) return;
-
- /* We didn't find the tag in val-tags, so look through all the RCS files
- to see whether it exists there. Yes, this is expensive, but there
- is no other way to cope with a tag which might have been created
- by an old version of CVS, from before val-tags was invented.
-
- Since we need this code anyway, we also use it to create
- entries in val-tags in general (that is, the val-tags entry
- will get created the first time the tag is used, not when the
- tag is created). */
-
- the_val_args.name = name;
- the_val_args.found = 0;
-
- which = W_REPOS | W_ATTIC;
-
- if (repository != NULL)
- {
- if (repository[0] == '\0')
- which |= W_LOCAL;
- else
- {
- if (save_cwd (&cwd))
- error_exit ();
- if (CVS_CHDIR (repository) < 0)
- error (1, errno, "cannot change to %s directory", repository);
- }
- }
-
- start_recursion (val_fileproc, (FILESDONEPROC) NULL,
- val_direntproc, (DIRLEAVEPROC) NULL,
- (void *)&the_val_args,
- argc, argv, local, which, aflag,
- CVS_LOCK_READ, NULL, 1, repository);
- if (repository != NULL && repository[0] != '\0')
- {
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- free_cwd (&cwd);
- }
-
- if (!the_val_args.found)
- error (1, 0, "no such tag %s", name);
- else
- /* The tags is valid but not mentioned in val-tags. Add it. */
- add_to_val_tags (name);
-}
-
-
-
-/*
- * Check whether a join tag is valid. This is just like
- * tag_check_valid, but we must stop before the colon if there is one.
- */
-
-void
-tag_check_valid_join (join_tag, argc, argv, local, aflag, repository)
- char *join_tag;
- int argc;
- char **argv;
- int local;
- int aflag;
- char *repository;
-{
- char *c, *s;
-
- c = xstrdup (join_tag);
- s = strchr (c, ':');
- if (s != NULL)
- {
- 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);
-
- free (c);
-}
diff --git a/contrib/cvs/src/update.c b/contrib/cvs/src/update.c
deleted file mode 100644
index f2c80874345a..000000000000
--- a/contrib/cvs/src/update.c
+++ /dev/null
@@ -1,3049 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- *
- * "update" updates the version in the present directory with respect to the RCS
- * repository. The present version must have been created by "checkout". The
- * user can keep up-to-date by calling "update" whenever he feels like it.
- *
- * The present version can be committed by "commit", but this keeps the version
- * in tact.
- *
- * Arguments following the options are taken to be file names to be updated,
- * rather than updating the entire directory.
- *
- * Modified or non-existent RCS files are checked out and reported as U
- * <user_file>
- *
- * Modified user files are reported as M <user_file>. If both the RCS file and
- * the user file have been modified, the user file is replaced by the result
- * of rcsmerge, and a backup file is written for the user in .#file.version.
- * If this throws up irreconcilable differences, the file is reported as C
- * <user_file>, and as M <user_file> otherwise.
- *
- * Files added but not yet committed are reported as A <user_file>. Files
- * removed but not yet committed are reported as R <user_file>.
- *
- * If the current directory contains subdirectories that hold concurrent
- * versions, these are updated too. If the -d option was specified, new
- * directories added to the repository are automatically created and updated
- * as well.
- *
- * $FreeBSD$
- */
-
-#include "cvs.h"
-#include <assert.h>
-#include "savecwd.h"
-#ifdef SERVER_SUPPORT
-# include "md5.h"
-#endif
-#include "watch.h"
-#include "fileattr.h"
-#include "edit.h"
-#include "getline.h"
-#include "buffer.h"
-#include "hardlink.h"
-
-static int checkout_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts,
- int adding, int merging, int update_server));
-#ifdef SERVER_SUPPORT
-static void checkout_to_buffer PROTO ((void *, const char *, size_t));
-static int patch_file PROTO ((struct file_info *finfo,
- Vers_TS *vers_ts,
- int *docheckout, struct stat *file_info,
- unsigned char *checksum));
-static void patch_file_write PROTO ((void *, const char *, size_t));
-#endif /* SERVER_SUPPORT */
-static int merge_file PROTO ((struct file_info *finfo, Vers_TS *vers));
-static int scratch_file PROTO((struct file_info *finfo, Vers_TS *vers));
-static Dtype update_dirent_proc PROTO ((void *callerdat, const char *dir,
- const char *repository,
- const char *update_dir,
- List *entries));
-static int update_dirleave_proc PROTO ((void *callerdat, const char *dir,
- int err, const char *update_dir,
- List *entries));
-static int update_fileproc PROTO ((void *callerdat, struct file_info *));
-static int update_filesdone_proc PROTO ((void *callerdat, int err,
- const char *repository,
- const char *update_dir,
- List *entries));
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
-static int get_linkinfo_proc PROTO ((void *callerdat, struct file_info *));
-#endif
-static void join_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts));
-
-static char *options = NULL;
-static char *tag = NULL;
-static char *date = NULL;
-/* This is a bit of a kludge. We call WriteTag at the beginning
- before we know whether nonbranch is set or not. And then at the
- end, once we have the right value for nonbranch, we call WriteTag
- again. I don't know whether the first call is necessary or not.
- rewrite_tag is nonzero if we are going to have to make that second
- call. */
-static int rewrite_tag;
-static int nonbranch;
-
-/* If we set the tag or date for a subdirectory, we use this to undo
- the setting. See update_dirent_proc. */
-static char *tag_update_dir;
-
-static char *join_rev1, *date_rev1;
-static char *join_rev2, *date_rev2;
-static int aflag = 0;
-static int toss_local_changes = 0;
-static int force_tag_match = 1;
-static int pull_template = 0;
-static int update_build_dirs = 0;
-static int update_prune_dirs = 0;
-static int pipeout = 0;
-#ifdef SERVER_SUPPORT
-static int patches = 0;
-static int rcs_diff_patches = 0;
-#endif
-static List *ignlist = (List *) NULL;
-static time_t last_register_time;
-static const char *const update_usage[] =
-{
- "Usage: %s %s [-APCdflRp] [-k kopt] [-r rev] [-D date] [-j rev]\n",
- " [-I ign] [-W spec] [files...]\n",
- "\t-A\tReset any sticky tags/date/kopts.\n",
- "\t-P\tPrune empty directories.\n",
- "\t-C\tOverwrite locally modified files with clean repository copies.\n",
- "\t-d\tBuild directories, like checkout does.\n",
- "\t-f\tForce a head revision match if tag/date not found.\n",
- "\t-l\tLocal directory only, no recursion.\n",
- "\t-R\tProcess directories recursively.\n",
- "\t-p\tSend updates to standard output (avoids stickiness).\n",
- "\t-k kopt\tUse RCS kopt -k option on checkout. (is sticky)\n",
- "\t-r rev\tUpdate using specified revision/tag (is sticky).\n",
- "\t-D date\tSet date to update from (is sticky).\n",
- "\t-j rev\tMerge in changes made between current revision and rev.\n",
- "\t-I ign\tMore files to ignore (! to reset).\n",
- "\t-W spec\tWrappers specification line.\n",
- "\t-T\tCreate CVS/Template.\n",
- "(Specify the --help global option for a list of other help options)\n",
- NULL
-};
-
-/*
- * update is the argv,argc based front end for arg parsing
- */
-int
-update (argc, argv)
- int argc;
- char **argv;
-{
- int c, err;
- int local = 0; /* recursive by default */
- int which; /* where to look for files and dirs */
- int xpull_template = 0;
-
- if (argc == -1)
- usage (update_usage);
-
- ign_setup ();
- wrap_setup ();
-
- /* parse the args */
- optind = 0;
- while ((c = getopt (argc, argv, "+ApCPflRQTqduk:r:D:j:I:W:")) != -1)
- {
- switch (c)
- {
- case 'A':
- aflag = 1;
- break;
- case 'C':
- toss_local_changes = 1;
- break;
- case 'I':
- ign_add (optarg, 0);
- break;
- case 'W':
- wrap_add (optarg, 0);
- break;
- case 'k':
- if (options)
- free (options);
- options = RCS_check_kflag (optarg);
- break;
- case 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case 'Q':
- case 'q':
- /* The CVS 1.5 client sends these options (in addition to
- Global_option requests), so we must ignore them. */
- if (!server_active)
- error (1, 0,
- "-q or -Q must be specified before \"%s\"",
- cvs_cmd_name);
- break;
- case 'T':
- xpull_template = 1;
- break;
- case 'd':
- update_build_dirs = 1;
- break;
- case 'f':
- force_tag_match = 0;
- break;
- case 'r':
- tag = optarg;
- break;
- case 'D':
- if (date) free (date);
- date = Make_Date (optarg);
- break;
- case 'P':
- update_prune_dirs = 1;
- break;
- case 'p':
- pipeout = 1;
- noexec = 1; /* so no locks will be created */
- break;
- case 'j':
- if (join_rev2)
- error (1, 0, "only two -j options can be specified");
- if (join_rev1)
- join_rev2 = optarg;
- else
- join_rev1 = optarg;
- break;
- case 'u':
-#ifdef SERVER_SUPPORT
- if (server_active)
- {
- patches = 1;
- rcs_diff_patches = server_use_rcs_diff ();
- }
- else
-#endif
- usage (update_usage);
- break;
- case '?':
- default:
- usage (update_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- int pass;
-
- /* The first pass does the regular update. If we receive at least
- one patch which failed, we do a second pass and just fetch
- those files whose patches failed. */
- pass = 1;
- do
- {
- int status;
-
- start_server ();
-
- if (local)
- send_arg("-l");
- if (update_build_dirs)
- send_arg("-d");
- if (pipeout)
- send_arg("-p");
- if (!force_tag_match)
- send_arg("-f");
- if (aflag)
- send_arg("-A");
- if (toss_local_changes)
- send_arg("-C");
- if (update_prune_dirs)
- send_arg("-P");
- client_prune_dirs = update_prune_dirs;
- option_with_arg ("-r", tag);
- if (options && options[0] != '\0')
- send_arg (options);
- if (date)
- client_senddate (date);
- if (join_rev1)
- option_with_arg ("-j", join_rev1);
- if (join_rev2)
- option_with_arg ("-j", join_rev2);
- wrap_send ();
-
- if (failed_patches_count == 0)
- {
- unsigned int flags = 0;
-
- /* If the server supports the command "update-patches", that
- means that it knows how to handle the -u argument to update,
- which means to send patches instead of complete files.
-
- We don't send -u if failed_patches != NULL, so that the
- server doesn't try to send patches which will just fail
- again. At least currently, the client also clobbers the
- file and tells the server it is lost, which also will get
- a full file instead of a patch, but it seems clean to omit
- -u. */
- if (supported_request ("update-patches"))
- send_arg ("-u");
-
- send_arg ("--");
-
- if (update_build_dirs)
- flags |= SEND_BUILD_DIRS;
-
- if (toss_local_changes) {
- flags |= SEND_NO_CONTENTS;
- flags |= BACKUP_MODIFIED_FILES;
- }
-
- /* If noexec, probably could be setting SEND_NO_CONTENTS.
- Same caveats as for "cvs status" apply. */
-
- send_files (argc, argv, local, aflag, flags);
- send_file_names (argc, argv, SEND_EXPAND_WILD);
- }
- else
- {
- int i;
-
- (void) printf ("%s client: refetching unpatchable files\n",
- program_name);
-
- if (toplevel_wd != NULL
- && CVS_CHDIR (toplevel_wd) < 0)
- {
- error (1, errno, "could not chdir to %s", toplevel_wd);
- }
-
- send_arg ("--");
-
- for (i = 0; i < failed_patches_count; i++)
- if (unlink_file (failed_patches[i]) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s",
- failed_patches[i]);
- send_files (failed_patches_count, failed_patches, local,
- aflag, update_build_dirs ? SEND_BUILD_DIRS : 0);
- send_file_names (failed_patches_count, failed_patches, 0);
- free_names (&failed_patches_count, failed_patches);
- }
-
- send_to_server ("update\012", 0);
-
- status = get_responses_and_close ();
-
- /* If there are any conflicts, the server will return a
- non-zero exit status. If any patches failed, we still
- want to run the update again. We use a pass count to
- avoid an endless loop. */
-
- /* Notes: (1) assuming that status != 0 implies a
- potential conflict is the best we can cleanly do given
- the current protocol. I suppose that trying to
- re-fetch in cases where there was a more serious error
- is probably more or less harmless, but it isn't really
- ideal. (2) it would be nice to have a testsuite case for the
- conflict-and-patch-failed case. */
-
- if (status != 0
- && (failed_patches_count == 0 || pass > 1))
- {
- if (failed_patches_count > 0)
- free_names (&failed_patches_count, failed_patches);
- return status;
- }
-
- ++pass;
- } while (failed_patches_count > 0);
-
- return 0;
- }
-#endif
-
- if (tag != NULL)
- tag_check_valid (tag, argc, argv, local, aflag, "");
- if (join_rev1 != NULL)
- tag_check_valid_join (join_rev1, argc, argv, local, aflag, "");
- if (join_rev2 != NULL)
- tag_check_valid_join (join_rev2, argc, argv, local, aflag, "");
-
- /*
- * If we are updating the entire directory (for real) and building dirs
- * as we go, we make sure there is no static entries file and write the
- * tag file as appropriate
- */
- if (argc <= 0 && !pipeout)
- {
- if (update_build_dirs)
- {
- if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno))
- error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
-#ifdef SERVER_SUPPORT
- if (server_active)
- {
- char *repos = Name_Repository (NULL, NULL);
- server_clear_entstat (".", repos);
- free (repos);
- }
-#endif
- }
-
- /* keep the CVS/Tag file current with the specified arguments */
- if (aflag || tag || date)
- {
- char *repos = Name_Repository (NULL, NULL);
- WriteTag ((char *) NULL, tag, date, 0, ".", repos);
- free (repos);
- rewrite_tag = 1;
- nonbranch = 0;
- }
- }
-
- /* look for files/dirs locally and in the repository */
- which = W_LOCAL | W_REPOS;
-
- /* look in the attic too if a tag or date is specified */
- if (tag != NULL || date != NULL || joining())
- which |= W_ATTIC;
-
- /* call the command line interface */
- err = do_update (argc, argv, options, tag, date, force_tag_match,
- local, update_build_dirs, aflag, update_prune_dirs,
- pipeout, which, join_rev1, join_rev2, (char *) NULL,
- xpull_template, (char *) NULL);
-
- /* free the space Make_Date allocated if necessary */
- if (date != NULL)
- free (date);
-
- return err;
-}
-
-
-
-/*
- * Command line interface to update (used by checkout)
- */
-int
-do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
- xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir,
- xpull_template, repository)
- int argc;
- char **argv;
- char *xoptions;
- char *xtag;
- char *xdate;
- int xforce;
- int local;
- int xbuild;
- int xaflag;
- int xprune;
- int xpipeout;
- int which;
- char *xjoin_rev1;
- char *xjoin_rev2;
- char *preload_update_dir;
- int xpull_template;
- char *repository;
-{
- int err = 0;
- char *cp;
-
- /* fill in the statics */
- options = xoptions;
- tag = xtag;
- date = xdate;
- force_tag_match = xforce;
- update_build_dirs = xbuild;
- aflag = xaflag;
- update_prune_dirs = xprune;
- pipeout = xpipeout;
- pull_template = xpull_template;
-
- /* setup the join support */
- join_rev1 = xjoin_rev1;
- join_rev2 = xjoin_rev2;
- if (join_rev1 && (cp = strchr (join_rev1, ':')) != NULL)
- {
- *cp++ = '\0';
- date_rev1 = Make_Date (cp);
- }
- else
- date_rev1 = (char *) NULL;
- if (join_rev2 && (cp = strchr (join_rev2, ':')) != NULL)
- {
- *cp++ = '\0';
- date_rev2 = Make_Date (cp);
- }
- else
- date_rev2 = (char *) NULL;
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- if (preserve_perms)
- {
- /* We need to do an extra recursion, bleah. It's to make sure
- that we know as much as possible about file linkage. */
- hardlist = getlist();
- working_dir = xgetwd(); /* save top-level working dir */
-
- /* FIXME-twp: the arguments to start_recursion make me dizzy. This
- function call was copied from the update_fileproc call that
- follows it; someone should make sure that I did it right. */
- err = start_recursion (get_linkinfo_proc, (FILESDONEPROC) NULL,
- (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
- argc, argv, local, which, aflag, CVS_LOCK_READ,
- preload_update_dir, 1, (char *) NULL);
- if (err)
- return err;
-
- /* FIXME-twp: at this point we should walk the hardlist
- and update the `links' field of each hardlink_info struct
- to list the files that are linked on dist. That would make
- it easier & more efficient to compare the disk linkage with
- the repository linkage (a simple strcmp). */
- }
-#endif
-
- /* call the recursion processor */
- err = start_recursion (update_fileproc, update_filesdone_proc,
- update_dirent_proc, update_dirleave_proc, NULL,
- argc, argv, local, which, aflag, CVS_LOCK_READ,
- preload_update_dir, 1, repository);
-
- /* see if we need to sleep before returning to avoid time-stamp races */
- if (!server_active && last_register_time)
- {
- sleep_past (last_register_time);
- }
-
- return err;
-}
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
-/*
- * The get_linkinfo_proc callback adds each file to the hardlist
- * (see hardlink.c).
- */
-
-static int
-get_linkinfo_proc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- char *fullpath;
- Node *linkp;
- struct hardlink_info *hlinfo;
-
- /* Get the full pathname of the current file. */
- fullpath = xmalloc (strlen(working_dir) +
- strlen(finfo->fullname) + 2);
- sprintf (fullpath, "%s/%s", working_dir, finfo->fullname);
-
- /* To permit recursing into subdirectories, files
- are keyed on the full pathname and not on the basename. */
- linkp = lookup_file_by_inode (fullpath);
- if (linkp == NULL)
- {
- /* The file isn't on disk; we are probably restoring
- a file that was removed. */
- return 0;
- }
-
- /* Create a new, empty hardlink_info node. */
- hlinfo = (struct hardlink_info *)
- xmalloc (sizeof (struct hardlink_info));
-
- hlinfo->status = (Ctype) 0; /* is this dumb? */
- hlinfo->checked_out = 0;
-
- linkp->data = hlinfo;
-
- return 0;
-}
-#endif
-
-
-
-/*
- * This is the callback proc for update. It is called for each file in each
- * directory by the recursion code. The current directory is the local
- * instantiation. file is the file name we are to operate on. update_dir is
- * set to the path relative to where we started (for pretty printing).
- * repository is the repository. entries and srcfiles are the pre-parsed
- * entries and source control files.
- *
- * This routine decides what needs to be done for each file and does the
- * appropriate magic for checkout
- */
-static int
-update_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- int retval;
- Ctype status;
- Vers_TS *vers;
-
- status = Classify_File (finfo, tag, date, options, force_tag_match,
- aflag, &vers, pipeout);
-
- /* Keep track of whether TAG is a branch tag.
- Note that if it is a branch tag in some files and a nonbranch tag
- in others, treat it as a nonbranch tag. It is possible that case
- should elicit a warning or an error. */
- if (rewrite_tag
- && tag != NULL
- && finfo->rcs != NULL)
- {
- char *rev = RCS_getversion (finfo->rcs, tag, date, 1, NULL);
- if (rev != NULL
- && !RCS_nodeisbranch (finfo->rcs, tag))
- nonbranch = 1;
- if (rev != NULL)
- free (rev);
- }
-
- if (pipeout)
- {
- /*
- * We just return success without doing anything if any of the really
- * funky cases occur
- *
- * If there is still a valid RCS file, do a regular checkout type
- * operation
- */
- switch (status)
- {
- case T_UNKNOWN: /* unknown file was explicitly asked
- * about */
- case T_REMOVE_ENTRY: /* needs to be un-registered */
- case T_ADDED: /* added but not committed */
- retval = 0;
- break;
- case T_CONFLICT: /* old punt-type errors */
- retval = 1;
- break;
- case T_UPTODATE: /* file was already up-to-date */
- case T_NEEDS_MERGE: /* needs merging */
- case T_MODIFIED: /* locally modified */
- case T_REMOVED: /* removed but not committed */
- case T_CHECKOUT: /* needs checkout */
- case T_PATCH: /* needs patch */
- retval = checkout_file (finfo, vers, 0, 0, 0);
- break;
-
- default: /* can't ever happen :-) */
- error (0, 0,
- "unknown file status %d for file %s", status, finfo->file);
- retval = 0;
- break;
- }
- }
- else
- {
- switch (status)
- {
- case T_UNKNOWN: /* unknown file was explicitly asked
- * about */
- case T_UPTODATE: /* file was already up-to-date */
- retval = 0;
- break;
- case T_CONFLICT: /* old punt-type errors */
- retval = 1;
- write_letter (finfo, 'C');
- break;
- case T_NEEDS_MERGE: /* needs merging */
- if (! toss_local_changes)
- {
- retval = merge_file (finfo, vers);
- break;
- }
- /* else FALL THROUGH */
- case T_MODIFIED: /* locally modified */
- retval = 0;
- if (toss_local_changes)
- {
- char *bakname;
- bakname = backup_file (finfo->file, vers->vn_user);
- /* This behavior is sufficiently unexpected to
- justify overinformativeness, I think. */
- if (!really_quiet && !server_active)
- (void) printf ("(Locally modified %s moved to %s)\n",
- finfo->file, bakname);
- free (bakname);
-
- /* The locally modified file is still present, but
- it will be overwritten by the repository copy
- after this. */
- status = T_CHECKOUT;
- retval = checkout_file (finfo, vers, 0, 0, 1);
- }
- else
- {
- if (vers->ts_conflict)
- {
- if (file_has_markers (finfo))
- {
- write_letter (finfo, 'C');
- retval = 1;
- }
- else
- {
- /* Reregister to clear conflict flag. */
- Register (finfo->entries, finfo->file,
- vers->vn_rcs, vers->ts_rcs,
- vers->options, vers->tag,
- vers->date, (char *)0);
- }
- }
- if (!retval)
- write_letter (finfo, 'M');
- }
- break;
- case T_PATCH: /* needs patch */
-#ifdef SERVER_SUPPORT
- if (patches)
- {
- int docheckout;
- struct stat file_info;
- unsigned char checksum[16];
-
- retval = patch_file (finfo,
- vers, &docheckout,
- &file_info, checksum);
- if (! docheckout)
- {
- if (server_active && retval == 0)
- server_updated (finfo, vers,
- (rcs_diff_patches
- ? SERVER_RCS_DIFF
- : SERVER_PATCHED),
- file_info.st_mode, checksum,
- (struct buffer *) NULL);
- break;
- }
- }
-#endif
- /* If we're not running as a server, just check the
- file out. It's simpler and faster than producing
- and applying patches. */
- /* Fall through. */
- case T_CHECKOUT: /* needs checkout */
- retval = checkout_file (finfo, vers, 0, 0, 1);
- break;
- case T_ADDED: /* added but not committed */
- write_letter (finfo, 'A');
- retval = 0;
- break;
- case T_REMOVED: /* removed but not committed */
- write_letter (finfo, 'R');
- retval = 0;
- break;
- case T_REMOVE_ENTRY: /* needs to be un-registered */
- retval = scratch_file (finfo, vers);
- break;
- default: /* can't ever happen :-) */
- error (0, 0,
- "unknown file status %d for file %s", status, finfo->file);
- retval = 0;
- break;
- }
- }
-
- /* only try to join if things have gone well thus far */
- if (retval == 0 && join_rev1)
- join_file (finfo, vers);
-
- /* if this directory has an ignore list, add this file to it */
- if (ignlist && (status != T_UNKNOWN || vers->ts_user == NULL))
- {
- Node *p;
-
- p = getnode ();
- p->type = FILES;
- p->key = xstrdup (finfo->file);
- if (addnode (ignlist, p) != 0)
- freenode (p);
- }
-
- freevers_ts (&vers);
- return retval;
-}
-
-
-
-static void update_ignproc PROTO ((const char *, const char *));
-
-static void
-update_ignproc (file, dir)
- const char *file;
- const char *dir;
-{
- struct file_info finfo;
- char *tmp;
-
- memset (&finfo, 0, sizeof (finfo));
- finfo.file = file;
- finfo.update_dir = dir;
- if (dir[0] == '\0')
- tmp = xstrdup (file);
- else
- {
- tmp = xmalloc (strlen (file) + strlen (dir) + 10);
- strcpy (tmp, dir);
- strcat (tmp, "/");
- strcat (tmp, file);
- }
-
- finfo.fullname = tmp;
- write_letter (&finfo, '?');
- free (tmp);
-}
-
-
-
-/* ARGSUSED */
-static int
-update_filesdone_proc (callerdat, err, repository, update_dir, entries)
- void *callerdat;
- int err;
- const char *repository;
- const char *update_dir;
- List *entries;
-{
- if (rewrite_tag)
- {
- WriteTag (NULL, tag, date, nonbranch, update_dir, repository);
- rewrite_tag = 0;
- }
-
- /* if this directory has an ignore list, process it then free it */
- if (ignlist)
- {
- ignore_files (ignlist, entries, update_dir, update_ignproc);
- dellist (&ignlist);
- }
-
- /* Clean up CVS admin dirs if we are export */
- if (strcmp (cvs_cmd_name, "export") == 0)
- {
- /* I'm not sure the existence_error is actually possible (except
- in cases where we really should print a message), but since
- this code used to ignore all errors, I'll play it safe. */
- if (unlink_file_dir (CVSADM) < 0 && !existence_error (errno))
- error (0, errno, "cannot remove %s directory", CVSADM);
- }
- else if (!server_active && !pipeout)
- {
- /* If there is no CVS/Root file, add one */
- if (!isfile (CVSADM_ROOT))
- Create_Root ((char *) NULL, current_parsed_root->original);
- }
-
- return err;
-}
-
-
-
-/*
- * update_dirent_proc () is called back by the recursion processor before a
- * sub-directory is processed for update. In this case, update_dirent proc
- * will probably create the directory unless -d isn't specified and this is a
- * new directory. A return code of 0 indicates the directory should be
- * processed by the recursion code. A return of non-zero indicates the
- * recursion code should skip this directory.
- */
-static Dtype
-update_dirent_proc (callerdat, dir, repository, update_dir, entries)
- void *callerdat;
- const char *dir;
- const char *repository;
- const char *update_dir;
- List *entries;
-{
- if (ignore_directory (update_dir))
- {
- /* print the warm fuzzy message */
- if (!quiet)
- error (0, 0, "Ignoring %s", update_dir);
- return R_SKIP_ALL;
- }
-
- if (!isdir (dir))
- {
- /* if we aren't building dirs, blow it off */
- if (!update_build_dirs)
- return R_SKIP_ALL;
-
- /* 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. Generally
- the behavior is to just skip over that directory (see
- dirs test in sanity.sh; the case which reaches here
- is when update -d is specified, and the working directory
- is gone but the subdirectory is still mentioned in
- CVS/Entries). */
- /* In the remote case, the client should refrain from
- sending us the directory in the first place. So we
- want to continue to give an error, so clients make
- sure to do this. */
- if (!server_active && !isdir (repository))
- return R_SKIP_ALL;
-
- if (noexec)
- {
- /* ignore the missing dir if -n is specified */
- error (0, 0, "New directory `%s' -- ignored", update_dir);
- return R_SKIP_ALL;
- }
- else
- {
- /* otherwise, create the dir and appropriate adm files */
-
- /* If no tag or date were specified on the command line,
- and we're not using -A, we want the subdirectory to use
- the tag and date, if any, of the current directory.
- That way, update -d will work correctly when working on
- a branch.
-
- We use TAG_UPDATE_DIR to undo the tag setting in
- update_dirleave_proc. If we did not do this, we would
- not correctly handle a working directory with multiple
- tags (and maybe we should prohibit such working
- directories, but they work now and we shouldn't make
- them stop working without more thought). */
- if ((tag == NULL && date == NULL) && ! aflag)
- {
- ParseTag (&tag, &date, &nonbranch);
- if (tag != NULL || date != NULL)
- tag_update_dir = xstrdup (update_dir);
- }
-
- make_directory (dir);
- Create_Admin (dir, update_dir, repository, tag, date,
- /* This is a guess. We will rewrite it later
- via WriteTag. */
- 0,
- 0,
- pull_template);
- rewrite_tag = 1;
- nonbranch = 0;
- Subdir_Register (entries, (char *) NULL, dir);
- }
- }
- /* Do we need to check noexec here? */
- else if (!pipeout)
- {
- char *cvsadmdir;
-
- /* The directory exists. Check to see if it has a CVS
- subdirectory. */
-
- cvsadmdir = xmalloc (strlen (dir) + 80);
- strcpy (cvsadmdir, dir);
- strcat (cvsadmdir, "/");
- strcat (cvsadmdir, CVSADM);
-
- if (!isdir (cvsadmdir))
- {
- /* We cannot successfully recurse into a directory without a CVS
- subdirectory. Generally we will have already printed
- "? foo". */
- free (cvsadmdir);
- return R_SKIP_ALL;
- }
- free (cvsadmdir);
- }
-
- /*
- * If we are building dirs and not going to stdout, we make sure there is
- * no static entries file and write the tag file as appropriate
- */
- if (!pipeout)
- {
- if (update_build_dirs)
- {
- char *tmp;
-
- tmp = xmalloc (strlen (dir) + sizeof (CVSADM_ENTSTAT) + 10);
- (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENTSTAT);
- if (unlink_file (tmp) < 0 && ! existence_error (errno))
- error (1, errno, "cannot remove file %s", tmp);
-#ifdef SERVER_SUPPORT
- if (server_active)
- server_clear_entstat (update_dir, repository);
-#endif
- free (tmp);
- }
-
- /* keep the CVS/Tag file current with the specified arguments */
- if (aflag || tag || date)
- {
- WriteTag (dir, tag, date, 0, update_dir, repository);
- rewrite_tag = 1;
- nonbranch = 0;
- }
-
- /* keep the CVS/Template file current */
- if (pull_template)
- {
- WriteTemplate (dir, update_dir);
- }
-
- /* initialize the ignore list for this directory */
- ignlist = getlist ();
- }
-
- /* print the warm fuzzy message */
- if (!quiet)
- error (0, 0, "Updating %s", update_dir);
-
- return R_PROCESS;
-}
-
-
-
-/*
- * update_dirleave_proc () is called back by the recursion code upon leaving
- * a directory. It will prune empty directories if needed and will execute
- * any appropriate update programs.
- */
-/* ARGSUSED */
-static int
-update_dirleave_proc (callerdat, dir, err, update_dir, entries)
- void *callerdat;
- const char *dir;
- int err;
- const char *update_dir;
- List *entries;
-{
- /* Delete the ignore list if it hasn't already been done. */
- if (ignlist)
- dellist (&ignlist);
-
- /* If we set the tag or date for a new subdirectory in
- update_dirent_proc, and we're now done with that subdirectory,
- undo the tag/date setting. Note that we know that the tag and
- date were both originally NULL in this case. */
- if (tag_update_dir != NULL && strcmp (update_dir, tag_update_dir) == 0)
- {
- if (tag != NULL)
- {
- free (tag);
- tag = NULL;
- }
- if (date != NULL)
- {
- free (date);
- date = NULL;
- }
- nonbranch = 0;
- free (tag_update_dir);
- tag_update_dir = NULL;
- }
-
- if (strchr (dir, '/') == NULL)
- {
- /* FIXME: chdir ("..") loses with symlinks. */
- /* Prune empty dirs on the way out - if necessary */
- (void) CVS_CHDIR ("..");
- if (update_prune_dirs && isemptydir (dir, 0))
- {
- /* I'm not sure the existence_error is actually possible (except
- in cases where we really should print a message), but since
- this code used to ignore all errors, I'll play it safe. */
- if (unlink_file_dir (dir) < 0 && !existence_error (errno))
- error (0, errno, "cannot remove %s directory", dir);
- Subdir_Deregister (entries, (char *) NULL, dir);
- }
- }
-
- return err;
-}
-
-
-
-static int isremoved PROTO ((Node *, void *));
-
-/* Returns 1 if the file indicated by node has been removed. */
-static int
-isremoved (node, closure)
- Node *node;
- void *closure;
-{
- Entnode *entdata = node->data;
-
- /* If the first character of the version is a '-', the file has been
- removed. */
- return (entdata->version && entdata->version[0] == '-') ? 1 : 0;
-}
-
-
-
-/* Returns 1 if the argument directory is completely empty, other than the
- existence of the CVS directory entry. Zero otherwise. If MIGHT_NOT_EXIST
- and the directory doesn't exist, then just return 0. */
-int
-isemptydir (dir, might_not_exist)
- const char *dir;
- int might_not_exist;
-{
- DIR *dirp;
- struct dirent *dp;
-
- if ((dirp = CVS_OPENDIR (dir)) == NULL)
- {
- if (might_not_exist && existence_error (errno))
- return 0;
- error (0, errno, "cannot open directory %s for empty check", dir);
- return 0;
- }
- errno = 0;
- while ((dp = CVS_READDIR (dirp)) != NULL)
- {
- if (strcmp (dp->d_name, ".") != 0
- && strcmp (dp->d_name, "..") != 0)
- {
- if (strcmp (dp->d_name, CVSADM) != 0)
- {
- /* An entry other than the CVS directory. The directory
- is certainly not empty. */
- (void) CVS_CLOSEDIR (dirp);
- return 0;
- }
- else
- {
- /* The CVS directory entry. We don't have to worry about
- this unless the Entries file indicates that files have
- been removed, but not committed, in this directory.
- (Removing the directory would prevent people from
- comitting the fact that they removed the files!) */
- List *l;
- int files_removed;
- struct saved_cwd cwd;
-
- if (save_cwd (&cwd))
- error_exit ();
-
- if (CVS_CHDIR (dir) < 0)
- error (1, errno, "cannot change directory to %s", dir);
- l = Entries_Open (0, NULL);
- files_removed = walklist (l, isremoved, 0);
- Entries_Close (l);
-
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- free_cwd (&cwd);
-
- if (files_removed != 0)
- {
- /* There are files that have been removed, but not
- committed! Do not consider the directory empty. */
- (void) CVS_CLOSEDIR (dirp);
- return 0;
- }
- }
- }
- errno = 0;
- }
- if (errno != 0)
- {
- error (0, errno, "cannot read directory %s", dir);
- (void) CVS_CLOSEDIR (dirp);
- return 0;
- }
- (void) CVS_CLOSEDIR (dirp);
- return 1;
-}
-
-
-
-/*
- * scratch the Entries file entry associated with a file
- */
-static int
-scratch_file (finfo, vers)
- struct file_info *finfo;
- Vers_TS *vers;
-{
- history_write ('W', finfo->update_dir, "", finfo->file, finfo->repository);
- Scratch_Entry (finfo->entries, finfo->file);
-#ifdef SERVER_SUPPORT
- if (server_active)
- {
- if (vers->ts_user == NULL)
- server_scratch_entry_only ();
- server_updated (finfo, vers,
- SERVER_UPDATED, (mode_t) -1,
- (unsigned char *) NULL,
- (struct buffer *) NULL);
- }
-#endif
- if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
- error (0, errno, "unable to remove %s", finfo->fullname);
- else if (!server_active)
- {
- /* skip this step when the server is running since
- * server_updated should have handled it */
- /* keep the vers structure up to date in case we do a join
- * - if there isn't a file, it can't very well have a version number, can it?
- */
- if (vers->vn_user != NULL)
- {
- free (vers->vn_user);
- vers->vn_user = NULL;
- }
- if (vers->ts_user != NULL)
- {
- free (vers->ts_user);
- vers->ts_user = NULL;
- }
- }
- return 0;
-}
-
-
-
-/*
- * Check out a file.
- */
-static int
-checkout_file (finfo, vers_ts, adding, merging, update_server)
- struct file_info *finfo;
- Vers_TS *vers_ts;
- int adding;
- int merging;
- int update_server;
-{
- char *backup;
- int set_time, retval = 0;
- int status;
- int file_is_dead;
- struct buffer *revbuf;
-
- backup = NULL;
- revbuf = NULL;
-
- /* Don't screw with backup files if we're going to stdout, or if
- we are the server. */
- if (!pipeout && !server_active)
- {
- backup = xmalloc (strlen (finfo->file)
- + sizeof (CVSADM)
- + sizeof (CVSPREFIX)
- + 10);
- (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
- if (isfile (finfo->file))
- rename_file (finfo->file, backup);
- else
- {
- /* If -f/-t wrappers are being used to wrap up a directory,
- then backup might be a directory instead of just a file. */
- if (unlink_file_dir (backup) < 0)
- {
- /* Not sure if the existence_error check is needed here. */
- if (!existence_error (errno))
- /* FIXME: should include update_dir in message. */
- error (0, errno, "error removing %s", backup);
- }
- free (backup);
- backup = NULL;
- }
- }
-
- file_is_dead = RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs);
-
- if (!file_is_dead)
- {
- /*
- * if we are checking out to stdout, print a nice message to
- * stderr, and add the -p flag to the command */
- if (pipeout)
- {
- if (!quiet)
- {
- cvs_outerr ("\
-===================================================================\n\
-Checking out ", 0);
- cvs_outerr (finfo->fullname, 0);
- cvs_outerr ("\n\
-RCS: ", 0);
- cvs_outerr (vers_ts->srcfile->path, 0);
- cvs_outerr ("\n\
-VERS: ", 0);
- cvs_outerr (vers_ts->vn_rcs, 0);
- cvs_outerr ("\n***************\n", 0);
- }
- }
-
-#ifdef SERVER_SUPPORT
- if (update_server
- && server_active
- && ! pipeout
- && ! file_gzip_level
- && ! joining ()
- && ! wrap_name_has (finfo->file, WRAP_FROMCVS))
- {
- revbuf = buf_nonio_initialize ((BUFMEMERRPROC) NULL);
- status = RCS_checkout (vers_ts->srcfile, (char *) NULL,
- vers_ts->vn_rcs, vers_ts->tag,
- vers_ts->options, RUN_TTY,
- checkout_to_buffer, revbuf);
- }
- else
-#endif
- status = RCS_checkout (vers_ts->srcfile,
- pipeout ? NULL : finfo->file,
- vers_ts->vn_rcs, vers_ts->tag,
- vers_ts->options, RUN_TTY,
- (RCSCHECKOUTPROC) NULL, (void *) NULL);
- }
- if (file_is_dead || status == 0)
- {
- mode_t mode;
-
- mode = (mode_t) -1;
-
- if (!pipeout)
- {
- Vers_TS *xvers_ts;
-
- if (revbuf != NULL && !noexec)
- {
- struct stat sb;
-
- /* FIXME: We should have RCS_checkout return the mode.
- That would also fix the kludge with noexec, above, which
- is here only because noexec doesn't write srcfile->path
- for us to stat. */
- if (stat (vers_ts->srcfile->path, &sb) < 0)
- {
-#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
- buf_free (revbuf);
-#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
- error (1, errno, "cannot stat %s",
- vers_ts->srcfile->path);
- }
- mode = sb.st_mode &~ (S_IWRITE | S_IWGRP | S_IWOTH);
- }
-
- if (cvswrite
- && !file_is_dead
- && !fileattr_get (finfo->file, "_watched"))
- {
- if (revbuf == NULL)
- xchmod (finfo->file, 1);
- else
- {
- /* We know that we are the server here, so
- although xchmod checks umask, we don't bother. */
- mode |= (((mode & S_IRUSR) ? S_IWUSR : 0)
- | ((mode & S_IRGRP) ? S_IWGRP : 0)
- | ((mode & S_IROTH) ? S_IWOTH : 0));
- }
- }
-
- {
- /* A newly checked out file is never under the spell
- of "cvs edit". If we think we were editing it
- from a previous life, clean up. Would be better to
- check for same the working directory instead of
- same user, but that is hairy. */
-
- struct addremove_args args;
-
- editor_set (finfo->file, getcaller (), NULL);
-
- memset (&args, 0, sizeof args);
- args.remove_temp = 1;
- watch_modify_watchers (finfo->file, &args);
- }
-
- /* set the time from the RCS file iff it was unknown before */
- set_time =
- (!noexec
- && (vers_ts->vn_user == NULL ||
- strncmp (vers_ts->ts_rcs, "Initial", 7) == 0)
- && !file_is_dead);
-
- wrap_fromcvs_process_file (finfo->file);
-
- xvers_ts = Version_TS (finfo, options, tag, date,
- force_tag_match, set_time);
- if (strcmp (xvers_ts->options, "-V4") == 0)
- xvers_ts->options[0] = '\0';
-
- if (revbuf != NULL)
- {
- /* If we stored the file data into a buffer, then we
- didn't create a file at all, so xvers_ts->ts_user
- is wrong. The correct value is to have it be the
- same as xvers_ts->ts_rcs, meaning that the working
- file is unchanged from the RCS file.
-
- FIXME: We should tell Version_TS not to waste time
- statting the nonexistent file.
-
- FIXME: Actually, I don't think the ts_user value
- matters at all here. The only use I know of is
- that it is printed in a trace message by
- Server_Register. */
-
- if (xvers_ts->ts_user != NULL)
- free (xvers_ts->ts_user);
- xvers_ts->ts_user = xstrdup (xvers_ts->ts_rcs);
- }
-
- (void) time (&last_register_time);
-
- if (file_is_dead)
- {
- if (xvers_ts->vn_user != NULL)
- {
- error (0, 0,
- "warning: %s is not (any longer) pertinent",
- finfo->fullname);
- }
- Scratch_Entry (finfo->entries, finfo->file);
-#ifdef SERVER_SUPPORT
- if (server_active && xvers_ts->ts_user == NULL)
- server_scratch_entry_only ();
-#endif
- /* FIXME: Rather than always unlink'ing, and ignoring the
- existence_error, we should do the unlink only if
- vers_ts->ts_user is non-NULL. Then there would be no
- need to ignore an existence_error (for example, if the
- user removes the file while we are running). */
- if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
- {
- error (0, errno, "cannot remove %s", finfo->fullname);
- }
- }
- else
- Register (finfo->entries, finfo->file,
- adding ? "0" : xvers_ts->vn_rcs,
- xvers_ts->ts_user, xvers_ts->options,
- xvers_ts->tag, xvers_ts->date,
- (char *)0); /* Clear conflict flag on fresh checkout */
-
- /* fix up the vers structure, in case it is used by join */
- if (join_rev1)
- {
- /* FIXME: It seems like we should be preserving ts_user
- * & ts_rcs here, but setting them causes problems in
- * join_file().
- */
- if (vers_ts->vn_user != NULL)
- free (vers_ts->vn_user);
- if (vers_ts->vn_rcs != NULL)
- free (vers_ts->vn_rcs);
- vers_ts->vn_user = xstrdup (xvers_ts->vn_rcs);
- vers_ts->vn_rcs = xstrdup (xvers_ts->vn_rcs);
- }
-
- /* If this is really Update and not Checkout, recode history */
- if (strcmp (cvs_cmd_name, "update") == 0)
- history_write ('U', finfo->update_dir, xvers_ts->vn_rcs, finfo->file,
- finfo->repository);
-
- freevers_ts (&xvers_ts);
-
- if (!really_quiet && !file_is_dead)
- {
- write_letter (finfo, 'U');
- }
- }
-
-#ifdef SERVER_SUPPORT
- if (update_server && server_active)
- server_updated (finfo, vers_ts,
- merging ? SERVER_MERGED : SERVER_UPDATED,
- mode, (unsigned char *) NULL, revbuf);
-#endif
- }
- else
- {
- if (backup != NULL)
- {
- rename_file (backup, finfo->file);
- free (backup);
- backup = NULL;
- }
-
- error (0, 0, "could not check out %s", finfo->fullname);
-
- retval = status;
- }
-
- if (backup != NULL)
- {
- /* If -f/-t wrappers are being used to wrap up a directory,
- then backup might be a directory instead of just a file. */
- if (unlink_file_dir (backup) < 0)
- {
- /* Not sure if the existence_error check is needed here. */
- if (!existence_error (errno))
- /* FIXME: should include update_dir in message. */
- error (0, errno, "error removing %s", backup);
- }
- free (backup);
- }
-
-#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
- if (revbuf != NULL)
- buf_free (revbuf);
-#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
- return retval;
-}
-
-
-
-#ifdef SERVER_SUPPORT
-
-/* This function is used to write data from a file being checked out
- into a buffer. */
-
-static void
-checkout_to_buffer (callerdat, data, len)
- void *callerdat;
- const char *data;
- size_t len;
-{
- struct buffer *buf = (struct buffer *) callerdat;
-
- buf_output (buf, data, len);
-}
-
-#endif /* SERVER_SUPPORT */
-
-#ifdef SERVER_SUPPORT
-
-/* This structure is used to pass information between patch_file and
- patch_file_write. */
-
-struct patch_file_data
-{
- /* File name, for error messages. */
- const char *filename;
- /* File to which to write. */
- FILE *fp;
- /* Whether to compute the MD5 checksum. */
- int compute_checksum;
- /* Data structure for computing the MD5 checksum. */
- struct cvs_MD5Context context;
- /* Set if the file has a final newline. */
- int final_nl;
-};
-
-/* Patch a file. Runs diff. This is only done when running as the
- * server. The hope is that the diff will be smaller than the file
- * itself.
- */
-static int
-patch_file (finfo, vers_ts, docheckout, file_info, checksum)
- struct file_info *finfo;
- Vers_TS *vers_ts;
- int *docheckout;
- struct stat *file_info;
- unsigned char *checksum;
-{
- char *backup;
- char *file1;
- char *file2;
- int retval = 0;
- int retcode = 0;
- int fail;
- FILE *e;
- struct patch_file_data data;
-
- *docheckout = 0;
-
- if (noexec || pipeout || joining ())
- {
- *docheckout = 1;
- return 0;
- }
-
- /* If this file has been marked as being binary, then never send a
- patch. */
- if (strcmp (vers_ts->options, "-kb") == 0)
- {
- *docheckout = 1;
- return 0;
- }
-
- /* First check that the first revision exists. If it has been nuked
- by cvs admin -o, then just fall back to checking out entire
- revisions. In some sense maybe we don't have to do this; after
- all cvs.texinfo says "Make sure that no-one has checked out a
- copy of the revision you outdate" but then again, that advice
- doesn't really make complete sense, because "cvs admin" operates
- on a working directory and so _someone_ will almost always have
- _some_ revision checked out. */
- {
- char *rev;
-
- rev = RCS_gettag (finfo->rcs, vers_ts->vn_user, 1, NULL);
- if (rev == NULL)
- {
- *docheckout = 1;
- return 0;
- }
- else
- free (rev);
- }
-
- /* If the revision is dead, let checkout_file handle it rather
- than duplicating the processing here. */
- if (RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs))
- {
- *docheckout = 1;
- return 0;
- }
-
- backup = xmalloc (strlen (finfo->file)
- + sizeof (CVSADM)
- + sizeof (CVSPREFIX)
- + 10);
- (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
- if (isfile (finfo->file))
- rename_file (finfo->file, backup);
- else
- {
- if (unlink_file (backup) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", backup);
- }
-
- file1 = xmalloc (strlen (finfo->file)
- + sizeof (CVSADM)
- + sizeof (CVSPREFIX)
- + 10);
- (void) sprintf (file1, "%s/%s%s-1", CVSADM, CVSPREFIX, finfo->file);
- file2 = xmalloc (strlen (finfo->file)
- + sizeof (CVSADM)
- + sizeof (CVSPREFIX)
- + 10);
- (void) sprintf (file2, "%s/%s%s-2", CVSADM, CVSPREFIX, finfo->file);
-
- fail = 0;
-
- /* We need to check out both revisions first, to see if either one
- has a trailing newline. Because of this, we don't use rcsdiff,
- but just use diff. */
-
- e = CVS_FOPEN (file1, "w");
- if (e == NULL)
- error (1, errno, "cannot open %s", file1);
-
- data.filename = file1;
- data.fp = e;
- data.final_nl = 0;
- data.compute_checksum = 0;
-
- /* Duplicating the client working file, so use the original sticky options.
- */
- retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL,
- vers_ts->vn_user, vers_ts->entdata->tag,
- vers_ts->entdata->options, RUN_TTY,
- patch_file_write, (void *) &data);
-
- if (fclose (e) < 0)
- error (1, errno, "cannot close %s", file1);
-
- if (retcode != 0 || ! data.final_nl)
- fail = 1;
-
- if (! fail)
- {
- e = CVS_FOPEN (file2, "w");
- if (e == NULL)
- error (1, errno, "cannot open %s", file2);
-
- data.filename = file2;
- data.fp = e;
- data.final_nl = 0;
- data.compute_checksum = 1;
- cvs_MD5Init (&data.context);
-
- retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL,
- vers_ts->vn_rcs, vers_ts->tag,
- vers_ts->options, RUN_TTY,
- patch_file_write, (void *) &data);
-
- if (fclose (e) < 0)
- error (1, errno, "cannot close %s", file2);
-
- if (retcode != 0 || ! data.final_nl)
- fail = 1;
- else
- cvs_MD5Final (checksum, &data.context);
- }
-
- retcode = 0;
- if (! fail)
- {
- int dargc = 0;
- size_t darg_allocated = 0;
- char **dargv = NULL;
-
- /* If the client does not support the Rcs-diff command, we
- send a context diff, and the client must invoke patch.
- That approach was problematical for various reasons. The
- new approach only requires running diff in the server; the
- client can handle everything without invoking an external
- program. */
- if (!rcs_diff_patches)
- /* We use -c, not -u, because that is what CVS has
- traditionally used. Kind of a moot point, now that
- Rcs-diff is preferred, so there is no point in making
- the compatibility issues worse. */
- run_add_arg_p (&dargc, &darg_allocated, &dargv, "-c");
- else
- /* Now that diff is librarified, we could be passing -a if
- we wanted to. However, it is unclear to me whether we
- would want to. Does diff -a, in any significant
- percentage of cases, produce patches which are smaller
- than the files it is patching? I guess maybe text
- files with character sets which diff regards as
- 'binary'. Conversely, do they tend to be much larger
- in the bad cases? This needs some more
- thought/investigation, I suspect. */
- run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n");
- retcode = diff_exec (file1, file2, NULL, NULL, dargc, dargv,
- finfo->file);
- run_arg_free_p (dargc, dargv);
- free (dargv);
-
- /* A retcode of 0 means no differences. 1 means some differences. */
- if (retcode != 0
- && retcode != 1)
- {
- fail = 1;
- }
- }
-
- if (! fail)
- {
- struct stat file2_info;
-
- /* Check to make sure the patch is really shorter */
- if (CVS_STAT (file2, &file2_info) < 0)
- error (1, errno, "could not stat %s", file2);
- if (CVS_STAT (finfo->file, file_info) < 0)
- error (1, errno, "could not stat %s", finfo->file);
- if (file2_info.st_size <= file_info->st_size)
- fail = 1;
- }
-
- if (! fail)
- {
-# define BINARY "Binary"
- char buf[sizeof BINARY];
- unsigned int c;
-
- /* Check the diff output to make sure patch will be handle it. */
- e = CVS_FOPEN (finfo->file, "r");
- if (e == NULL)
- error (1, errno, "could not open diff output file %s",
- finfo->fullname);
- c = fread (buf, 1, sizeof BINARY - 1, e);
- buf[c] = '\0';
- if (strcmp (buf, BINARY) == 0)
- {
- /* These are binary files. We could use diff -a, but
- patch can't handle that. */
- fail = 1;
- }
- fclose (e);
- }
-
- if (! fail)
- {
- Vers_TS *xvers_ts;
-
- /* Stat the original RCS file, and then adjust it the way
- that RCS_checkout would. FIXME: This is an abstraction
- violation. */
- if (CVS_STAT (vers_ts->srcfile->path, file_info) < 0)
- error (1, errno, "could not stat %s", vers_ts->srcfile->path);
- if (chmod (finfo->file,
- file_info->st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH))
- < 0)
- error (0, errno, "cannot change mode of file %s", finfo->file);
- if (cvswrite
- && !fileattr_get (finfo->file, "_watched"))
- xchmod (finfo->file, 1);
-
- /* This stuff is just copied blindly from checkout_file. I
- don't really know what it does. */
- xvers_ts = Version_TS (finfo, options, tag, date,
- force_tag_match, 0);
- if (strcmp (xvers_ts->options, "-V4") == 0)
- xvers_ts->options[0] = '\0';
-
- Register (finfo->entries, finfo->file, xvers_ts->vn_rcs,
- xvers_ts->ts_user, xvers_ts->options,
- xvers_ts->tag, xvers_ts->date, NULL);
-
- if (CVS_STAT (finfo->file, file_info) < 0)
- error (1, errno, "could not stat %s", finfo->file);
-
- /* If this is really Update and not Checkout, record history. */
- if (strcmp (cvs_cmd_name, "update") == 0)
- history_write ('P', finfo->update_dir, xvers_ts->vn_rcs,
- finfo->file, finfo->repository);
-
- freevers_ts (&xvers_ts);
-
- if (!really_quiet)
- {
- write_letter (finfo, 'P');
- }
- }
- else
- {
- int old_errno = errno; /* save errno value over the rename */
-
- if (isfile (backup))
- rename_file (backup, finfo->file);
-
- if (retcode != 0 && retcode != 1)
- error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0,
- "could not diff %s", finfo->fullname);
-
- *docheckout = 1;
- retval = retcode;
- }
-
- if (unlink_file (backup) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", backup);
- if (unlink_file (file1) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", file1);
- if (unlink_file (file2) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", file2);
-
- free (backup);
- free (file1);
- free (file2);
- return retval;
-}
-
-
-
-/* Write data to a file. Record whether the last byte written was a
- newline. Optionally compute a checksum. This is called by
- patch_file via RCS_checkout. */
-
-static void
-patch_file_write (callerdat, buffer, len)
- void *callerdat;
- const char *buffer;
- size_t len;
-{
- struct patch_file_data *data = (struct patch_file_data *) callerdat;
-
- if (fwrite (buffer, 1, len, data->fp) != len)
- error (1, errno, "cannot write %s", data->filename);
-
- data->final_nl = (buffer[len - 1] == '\n');
-
- if (data->compute_checksum)
- cvs_MD5Update (&data->context, (unsigned char *) buffer, len);
-}
-
-#endif /* SERVER_SUPPORT */
-
-/*
- * Several of the types we process only print a bit of information consisting
- * of a single letter and the name.
- */
-void
-write_letter (finfo, letter)
- struct file_info *finfo;
- int letter;
-{
- if (!really_quiet)
- {
- char *tag = NULL;
- /* Big enough for "+updated" or any of its ilk. */
- char buf[80];
-
- switch (letter)
- {
- case 'U':
- tag = "updated";
- break;
- default:
- /* We don't yet support tagged output except for "U". */
- break;
- }
-
- if (tag != NULL)
- {
- sprintf (buf, "+%s", tag);
- cvs_output_tagged (buf, NULL);
- }
- buf[0] = letter;
- buf[1] = ' ';
- buf[2] = '\0';
- cvs_output_tagged ("text", buf);
- cvs_output_tagged ("fname", finfo->fullname);
- cvs_output_tagged ("newline", NULL);
- if (tag != NULL)
- {
- sprintf (buf, "-%s", tag);
- cvs_output_tagged (buf, NULL);
- }
- }
- return;
-}
-
-
-
-/* Reregister a file after a merge. */
-static void
-RegisterMerge PROTO((struct file_info *finfo, Vers_TS *vers,
- const char *backup, int has_conflicts));
-static void
-RegisterMerge (finfo, vers, backup, has_conflicts)
- struct file_info *finfo;
- Vers_TS *vers;
- const char *backup;
- int has_conflicts;
-{
- /* This file is the result of a merge, which means that it has
- been modified. We use a special timestamp string which will
- not compare equal to any actual timestamp. */
- char *cp = NULL;
-
- if (has_conflicts)
- {
- time (&last_register_time);
- cp = time_stamp (finfo->file);
- }
- Register (finfo->entries, finfo->file, vers->vn_rcs ? vers->vn_rcs : "0",
- "Result of merge", vers->options, vers->tag, vers->date, cp);
- if (cp)
- free (cp);
-
-#ifdef SERVER_SUPPORT
- /* Send the new contents of the file before the message. If we
- wanted to be totally correct, we would have the client write
- the message only after the file has safely been written. */
- if (server_active)
- {
- server_copy_file (finfo->file, finfo->update_dir, finfo->repository,
- backup);
- server_updated (finfo, vers, SERVER_MERGED, (mode_t) -1, NULL, NULL);
- }
-#endif
-}
-
-
-
-/*
- * Do all the magic associated with a file which needs to be merged
- */
-static int
-merge_file (finfo, vers)
- struct file_info *finfo;
- Vers_TS *vers;
-{
- char *backup;
- int status;
- int retcode = 0;
- int retval;
-
- assert (vers->vn_user);
-
- /*
- * The users currently modified file is moved to a backup file name
- * ".#filename.version", so that it will stay around for a few days
- * before being automatically removed by some cron daemon. The "version"
- * is the version of the file that the user was most up-to-date with
- * before the merge.
- */
- backup = xmalloc (strlen (finfo->file)
- + strlen (vers->vn_user)
- + sizeof (BAKPREFIX)
- + 10);
- (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
-
- if (unlink_file (backup) && !existence_error (errno))
- error (0, errno, "unable to remove %s", backup);
- copy_file (finfo->file, backup);
- xchmod (finfo->file, 1);
-
- if (strcmp (vers->options, "-kb") == 0
- || wrap_merge_is_copy (finfo->file)
- || special_file_mismatch (finfo, NULL, vers->vn_rcs))
- {
- /* For binary files, a merge is always a conflict. Same for
- files whose permissions or linkage do not match. We give the
- user the two files, and let them resolve it. It is possible
- that we should require a "touch foo" or similar step before
- we allow a checkin. */
-
- /* TODO: it may not always be necessary to regard a permission
- mismatch as a conflict. The working file and the RCS file
- have a common ancestor `A'; if the working file's permissions
- match A's, then it's probably safe to overwrite them with the
- RCS permissions. Only if the working file, the RCS file, and
- A all disagree should this be considered a conflict. But more
- thought needs to go into this, and in the meantime it is safe
- to treat any such mismatch as an automatic conflict. -twp */
-
- retcode = RCS_checkout (finfo->rcs, finfo->file,
- vers->vn_rcs, vers->tag,
- vers->options, NULL, NULL, NULL);
- if (retcode)
- {
- error (0, 0, "failed to check out `%s' file", finfo->fullname);
- error (0, 0, "restoring `%s' from backup file `%s'",
- finfo->fullname, backup);
- rename_file (backup, finfo->file);
- retval = 1;
- goto out;
- }
- xchmod (finfo->file, 1);
-
- RegisterMerge (finfo, vers, backup, 1);
-
- /* Is there a better term than "nonmergeable file"? What we
- really mean is, not something that CVS cannot or does not
- want to merge (there might be an external manual or
- automatic merge process). */
- error (0, 0, "nonmergeable file needs merge");
- error (0, 0, "revision %s from repository is now in %s",
- vers->vn_rcs, finfo->fullname);
- error (0, 0, "file from working directory is now in %s", backup);
- write_letter (finfo, 'C');
-
- history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file,
- finfo->repository);
- retval = 0;
- goto out;
- }
-
- status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
- vers->options, vers->vn_user, vers->vn_rcs);
- if (status != 0 && status != 1)
- {
- error (0, status == -1 ? errno : 0,
- "could not merge revision %s of %s", vers->vn_user, finfo->fullname);
- error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
- finfo->fullname, backup);
- rename_file (backup, finfo->file);
- retval = 1;
- goto out;
- }
-
- if (strcmp (vers->options, "-V4") == 0)
- vers->options[0] = '\0';
-
- /* fix up the vers structure, in case it is used by join */
- if (join_rev1)
- {
- /* FIXME: Throwing away the original revision info is almost
- certainly wrong -- what if join_rev1 is "BASE"? */
- if (vers->vn_user != NULL)
- free (vers->vn_user);
- vers->vn_user = xstrdup (vers->vn_rcs);
- }
-
- RegisterMerge (finfo, vers, backup, status);
-
- /* FIXME: the noexec case is broken. RCS_merge could be doing the
- xcmp on the temporary files without much hassle, I think. */
- if (!noexec && !xcmp (backup, finfo->file))
- {
- cvs_output (finfo->fullname, 0);
- cvs_output (" already contains the differences between ", 0);
- cvs_output (vers->vn_user, 0);
- cvs_output (" and ", 0);
- cvs_output (vers->vn_rcs, 0);
- cvs_output ("\n", 1);
-
- history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file,
- finfo->repository);
- retval = 0;
- goto out;
- }
-
- if (status == 1)
- {
- error (0, 0, "conflicts found in %s", finfo->fullname);
-
- write_letter (finfo, 'C');
-
- history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file,
- finfo->repository);
-
- }
- else if (retcode == -1)
- {
- error (1, errno, "fork failed while examining update of %s",
- finfo->fullname);
- }
- else
- {
- write_letter (finfo, 'M');
- history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file,
- finfo->repository);
- }
- retval = 0;
- out:
- free (backup);
- return retval;
-}
-
-
-
-/*
- * Do all the magic associated with a file which needs to be joined
- * (reached via the -j option to checkout or update).
- *
- * INPUTS
- * finfo File information about the destination file.
- * vers The Vers_TS structure for finfo.
- *
- * GLOBALS
- * join_rev1 From the command line.
- * join_rev2 From the command line.
- * server_active Natch.
- *
- * ASSUMPTIONS
- * 1. Is not called in client mode.
- */
-static void
-join_file (finfo, vers)
- struct file_info *finfo;
- Vers_TS *vers;
-{
- char *backup;
- char *t_options;
- int status;
-
- char *rev1;
- char *rev2;
- char *jrev1;
- char *jrev2;
- char *jdate1;
- char *jdate2;
-
- if (trace)
- fprintf (stderr, "%s-> join_file(%s, %s%s%s%s, %s, %s)\n",
- CLIENT_SERVER_STR,
- finfo->file,
- vers->tag ? vers->tag : "",
- vers->tag ? " (" : "",
- vers->vn_rcs ? vers->vn_rcs : "",
- vers->tag ? ")" : "",
- join_rev1 ? join_rev1 : "",
- join_rev2 ? join_rev2 : "");
-
- jrev1 = join_rev1;
- jrev2 = join_rev2;
- jdate1 = date_rev1;
- jdate2 = date_rev2;
-
- /* Determine if we need to do anything at all. */
- if (vers->srcfile == NULL ||
- vers->srcfile->path == NULL)
- {
- return;
- }
-
- /* If only one join revision is specified, it becomes the second
- revision. */
- if (jrev2 == NULL)
- {
- jrev2 = jrev1;
- jrev1 = NULL;
- jdate2 = jdate1;
- jdate1 = NULL;
- }
-
- /* FIXME: Need to handle "BASE" for jrev1 and/or jrev2. Note caveat
- below about vn_user. */
-
- /* Convert the second revision, walking branches and dates. */
- rev2 = RCS_getversion (vers->srcfile, jrev2, jdate2, 1, (int *) NULL);
-
- /* If this is a merge of two revisions, get the first revision.
- If only one join tag was specified, then the first revision is
- the greatest common ancestor of the second revision and the
- working file. */
- if (jrev1 != NULL)
- rev1 = RCS_getversion (vers->srcfile, jrev1, jdate1, 1, (int *) NULL);
- else
- {
- /* Note that we use vn_rcs here, since vn_user may contain a
- special string such as "-nn". */
- if (vers->vn_rcs == NULL)
- rev1 = NULL;
- else if (rev2 == NULL)
- {
- /* This means that the file never existed on the branch.
- It does not mean that the file was removed on the
- branch: that case is represented by a dead rev2. If
- the file never existed on the branch, then we have
- nothing to merge, so we just return. */
- return;
- }
- else
- rev1 = gca (vers->vn_rcs, rev2);
- }
-
- /* Handle a nonexistent or dead merge target. */
- if (rev2 == NULL || RCS_isdead (vers->srcfile, rev2))
- {
- char *mrev;
- short conflict = 0;
-
- if (rev2 != NULL)
- free (rev2);
-
- /* If the first revision doesn't exist either, then there is
- no change between the two revisions, so we don't do
- anything. */
- if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
- {
- if (rev1 != NULL)
- free (rev1);
- return;
- }
-
- /* If we are merging two revisions, then the file was removed
- between the first revision and the second one. In this
- case we want to mark the file for removal.
-
- If we are merging one revision, then the file has been
- removed between the greatest common ancestor and the merge
- revision. From the perspective of the branch on to which
- we ar emerging, which may be the trunk, either 1) the file
- does not currently exist on the target, or 2) the file has
- not been modified on the target branch since the greatest
- common ancestor, or 3) the file has been modified on the
- target branch since the greatest common ancestor. In case
- 1 there is nothing to do. In case 2 we mark the file for
- removal. In case 3 we have a conflict.
-
- Note that the handling is slightly different depending upon
- whether one or two join targets were specified. If two
- join targets were specified, we don't check whether the
- file was modified since a given point. My reasoning is
- that if you ask for an explicit merge between two tags,
- then you want to merge in whatever was changed between
- those two tags. If a file was removed between the two
- tags, then you want it to be removed. However, if you ask
- for a merge of a branch, then you want to merge in all
- changes which were made on the branch. If a file was
- removed on the branch, that is a change to the file. If
- the file was also changed on the main line, then that is
- also a change. These two changes--the file removal and the
- modification--must be merged. This is a conflict. */
-
- /* If the user file is dead, or does not exist, or has been
- marked for removal, then there is nothing to do. */
- if (vers->vn_user == NULL
- || vers->vn_user[0] == '-'
- || RCS_isdead (vers->srcfile, vers->vn_user))
- {
- free (rev1);
- return;
- }
-
- /* If the user file has been marked for addition, or has been
- locally modified, then we have a conflict which we can not
- resolve. No_Difference will already have been called in
- this case, so comparing the timestamps is sufficient to
- determine whether the file is locally modified. */
- if (/* may have changed on destination branch */
- /* file added locally */
- !strcmp (vers->vn_user, "0")
- || /* destination branch modified in repository */
- strcmp (rev1, vers->vn_user)
- || /* locally modified */
- vers->ts_user && strcmp (vers->ts_user, vers->ts_rcs))
- {
- /* The removal should happen if either the file has never changed
- * on the destination or the file has changed to be identical to
- * the first join revision.
- *
- * ------R-----------D
- * |
- * \----J1---J2-----S
- *
- * So:
- *
- * J2 is dead.
- * D is destination.
- * R is source branch root/GCA.
- * if J1 == D removal should happen
- * if D == R removal should happen
- * otherwise, fail.
- *
- * (In the source, J2 = REV2, D = user file (potentially VN_USER),
- * R = GCA computed below)
- */
- char *gca_rev1 = gca (rev1, vers->vn_user);
-#ifdef SERVER_SUPPORT
- if (server_active && !isreadable (finfo->file))
- {
- int retcode;
- /* The file is up to date. Need to check out the current
- * contents.
- */
- /* FIXME - see the FIXME comment above the call to RCS_checkout
- * in the patch_file function.
- */
- retcode = RCS_checkout (vers->srcfile, finfo->file,
- vers->vn_user, vers->tag,
- NULL, RUN_TTY, NULL, NULL);
- if (retcode)
- error (1, 0,
- "failed to check out %s file", finfo->fullname);
- }
-#endif
- if (/* genuinely changed on destination branch */
- RCS_cmp_file (vers->srcfile, gca_rev1, NULL,
- NULL, vers->options, finfo->file)
- && /* genuinely different from REV1 */
- RCS_cmp_file (vers->srcfile, rev1, NULL,
- NULL, vers->options, finfo->file))
- conflict = 1;
- }
-
- free (rev1);
-
- if (conflict)
- {
- char *cp;
-
- if (jdate2)
- error (0, 0,
- "file %s has been removed in revision %s as of %s, but the destination is incompatibly modified",
- finfo->fullname, jrev2, jdate2);
- else
- error (0, 0,
- "file %s has been removed in revision %s, but the destination is incompatibly modified",
- finfo->fullname, jrev2);
-
- /* Register the conflict with the client. */
-
- /* FIXME: vers->ts_user should always be set here but sometimes
- * isn't, namely when checkout_file() has just created the file,
- * but simply setting it in checkout_file() appears to cause other
- * problems.
- */
- if (isfile (finfo->file))
- cp = time_stamp (finfo->file);
- else
- cp = xstrdup (vers->ts_user);
-
- Register (finfo->entries, finfo->file, vers->vn_user,
- "Result of merge", vers->options, vers->tag, vers->date,
- cp);
- write_letter (finfo, 'C');
- free (cp);
-
-#ifdef SERVER_SUPPORT
- /* Abuse server_checked_in() to send the updated entry without
- * needing to update the file.
- */
- if (server_active)
- server_checked_in (finfo->file, finfo->update_dir,
- finfo->repository);
-#endif
-
- return;
- }
-
- /* The user file exists and has not been modified. Mark it
- for removal. FIXME: If we are doing a checkout, this has
- the effect of first checking out the file, and then
- removing it. It would be better to just register the
- removal.
-
- The same goes for a removal then an add. e.g.
- cvs up -rbr -jbr2 could remove and readd the same file
- */
- /* save the rev since server_updated might invalidate it */
- mrev = xmalloc (strlen (vers->vn_user) + 2);
- sprintf (mrev, "-%s", vers->vn_user);
-#ifdef SERVER_SUPPORT
- if (server_active)
- {
- server_scratch (finfo->file);
- server_updated (finfo, vers, SERVER_UPDATED, (mode_t) -1,
- (unsigned char *) NULL, (struct buffer *) NULL);
- }
-#endif
- Register (finfo->entries, finfo->file, mrev, vers->ts_rcs,
- vers->options, vers->tag, vers->date, vers->ts_conflict);
- free (mrev);
- /* We need to check existence_error here because if we are
- running as the server, and the file is up to date in the
- working directory, the client will not have sent us a copy. */
- if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
- error (0, errno, "cannot remove file %s", finfo->fullname);
-#ifdef SERVER_SUPPORT
- if (server_active)
- server_checked_in (finfo->file, finfo->update_dir,
- finfo->repository);
-#endif
- if (! really_quiet)
- error (0, 0, "scheduling %s for removal", finfo->fullname);
-
- return;
- }
-
- /* If the two merge revisions are the same, then there is nothing
- * to do. This needs to be checked before the rev2 == up-to-date base
- * revision check tha comes next. Otherwise, rev1 can == rev2 and get an
- * "already contains the changes between <rev1> and <rev1>" message.
- */
- if (rev1 && strcmp (rev1, rev2) == 0)
- {
- free (rev1);
- free (rev2);
- return;
- }
-
- /* If we know that the user file is up-to-date, then it becomes an
- * optimization to skip the merge when rev2 is the same as the base
- * revision. i.e. we know that diff3(file2,file1,file2) will produce
- * file2.
- */
- if (vers->vn_user != NULL && vers->ts_user != NULL
- && strcmp (vers->ts_user, vers->ts_rcs) == 0
- && strcmp (rev2, vers->vn_user) == 0)
- {
- if (!really_quiet)
- {
- cvs_output (finfo->fullname, 0);
- cvs_output (" already contains the differences between ", 0);
- cvs_output (rev1 ? rev1 : "creation", 0);
- cvs_output (" and ", 0);
- cvs_output (rev2, 0);
- cvs_output ("\n", 1);
- }
-
- if (rev1 != NULL)
- free (rev1);
- free (rev2);
-
- return;
- }
-
- /* If rev1 is dead or does not exist, then the file was added
- between rev1 and rev2. */
- if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
- {
- if (rev1 != NULL)
- free (rev1);
- free (rev2);
-
- /* If the file does not exist in the working directory, then
- we can just check out the new revision and mark it for
- addition. */
- if (vers->vn_user == NULL)
- {
- char *saved_options = options;
- Vers_TS *xvers;
-
- xvers = Version_TS (finfo, vers->options, jrev2, jdate2, 1, 0);
-
- /* Reset any keyword expansion option. Otherwise, when a
- command like `cvs update -kk -jT1 -jT2' creates a new file
- (because a file had the T2 tag, but not T1), the subsequent
- commit of that just-added file effectively would set the
- admin `-kk' option for that file in the repository. */
- options = NULL;
-
- /* FIXME: If checkout_file fails, we should arrange to
- return a non-zero exit status. */
- status = checkout_file (finfo, xvers, 1, 0, 1);
- options = saved_options;
-
- freevers_ts (&xvers);
-
- return;
- }
-
- /* The file currently exists in the working directory, so we
- have a conflict which we can not resolve. Note that this
- is true even if the file is marked for addition or removal. */
-
- if (jdate2 != NULL)
- error (0, 0,
- "file %s exists, but has been added in revision %s as of %s",
- finfo->fullname, jrev2, jdate2);
- else
- error (0, 0,
- "file %s exists, but has been added in revision %s",
- finfo->fullname, jrev2);
-
- return;
- }
-
- /* If there is no working file, then we can't do the merge. */
- if (vers->vn_user == NULL || vers->vn_user[0] == '-')
- {
- free (rev1);
- free (rev2);
-
- if (jdate2 != NULL)
- error (0, 0,
- "file %s does not exist, but is present in revision %s as of %s",
- finfo->fullname, jrev2, jdate2);
- else
- error (0, 0,
- "file %s does not exist, but is present in revision %s",
- finfo->fullname, jrev2);
-
- /* FIXME: Should we arrange to return a non-zero exit status? */
-
- return;
- }
-
-#ifdef SERVER_SUPPORT
- if (server_active && !isreadable (finfo->file))
- {
- int retcode;
- /* The file is up to date. Need to check out the current contents. */
- /* FIXME - see the FIXME comment above the call to RCS_checkout in the
- * patch_file function.
- */
- retcode = RCS_checkout (vers->srcfile, finfo->file,
- vers->vn_user, vers->tag,
- (char *) NULL, RUN_TTY,
- (RCSCHECKOUTPROC) NULL, (void *) NULL);
- if (retcode != 0)
- error (1, 0,
- "failed to check out %s file", finfo->fullname);
- }
-#endif
-
- /*
- * The users currently modified file is moved to a backup file name
- * ".#filename.version", so that it will stay around for a few days
- * before being automatically removed by some cron daemon. The "version"
- * is the version of the file that the user was most up-to-date with
- * before the merge.
- */
- backup = xmalloc (strlen (finfo->file)
- + strlen (vers->vn_user)
- + sizeof (BAKPREFIX)
- + 10);
- (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
-
- if (unlink_file (backup) < 0
- && !existence_error (errno))
- error (0, errno, "cannot remove %s", backup);
- copy_file (finfo->file, backup);
- xchmod (finfo->file, 1);
-
- t_options = vers->options;
-#if 0
- if (*t_options == '\0')
- t_options = "-kk"; /* to ignore keyword expansions */
-#endif
-
- /* If the source of the merge is the same as the working file
- revision, then we can just RCS_checkout the target (no merging
- as such). In the text file case, this is probably quite
- similar to the RCS_merge, but in the binary file case,
- RCS_merge gives all kinds of trouble. */
- if (vers->vn_user != NULL
- && strcmp (rev1, vers->vn_user) == 0
- /* See comments above about how No_Difference has already been
- called. */
- && vers->ts_user != NULL
- && strcmp (vers->ts_user, vers->ts_rcs) == 0
-
- /* Avoid this in the text file case. See below for why.
- */
- && (strcmp (t_options, "-kb") == 0
- || wrap_merge_is_copy (finfo->file)))
- {
- /* FIXME: Verify my comment below:
- *
- * RCS_merge does nothing with keywords. It merges the changes between
- * two revisions without expanding the keywords (it might expand in
- * -kk mode before computing the diff between rev1 and rev2 - I'm not
- * sure). In other words, the keyword lines in the current work file
- * get left alone.
- *
- * Therfore, checking out the destination revision (rev2) is probably
- * incorrect in the text case since we should see the keywords that were
- * substituted into the original file at the time it was checked out
- * and not the keywords from rev2.
- *
- * Also, it is safe to pass in NULL for nametag since we know no
- * substitution is happening during the binary mode checkout.
- */
- if (RCS_checkout ( finfo->rcs, finfo->file, rev2, (char *)NULL, t_options,
- RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0 )
- status = 2;
- else
- status = 0;
-
- /* OK, this is really stupid. RCS_checkout carefully removes
- write permissions, and we carefully put them back. But
- until someone gets around to fixing it, that seems like the
- easiest way to get what would seem to be the right mode.
- I don't check CVSWRITE or _watched; I haven't thought about
- that in great detail, but it seems like a watched file should
- be checked out (writable) after a merge. */
- xchmod (finfo->file, 1);
-
- /* Traditionally, the text file case prints a whole bunch of
- scary looking and verbose output which fails to tell the user
- what is really going on (it gives them rev1 and rev2 but doesn't
- indicate in any way that rev1 == vn_user). I think just a
- simple "U foo" is good here; it seems analogous to the case in
- which the file was added on the branch in terms of what to
- print. */
- write_letter (finfo, 'U');
- }
- else if (strcmp (t_options, "-kb") == 0
- || wrap_merge_is_copy (finfo->file)
- || special_file_mismatch (finfo, rev1, rev2))
- {
- /* We are dealing with binary files, or files with a
- permission/linkage mismatch (this second case only occurs when
- PRESERVE_PERMISSIONS_SUPPORT is enabled), and real merging would
- need to take place. This is a conflict. We give the user
- the two files, and let them resolve it. It is possible
- that we should require a "touch foo" or similar step before
- we allow a checkin. */
- if (RCS_checkout ( finfo->rcs, finfo->file, rev2, (char *)NULL,
- t_options, RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0)
- status = 2;
- else
- status = 0;
-
- /* OK, this is really stupid. RCS_checkout carefully removes
- write permissions, and we carefully put them back. But
- until someone gets around to fixing it, that seems like the
- easiest way to get what would seem to be the right mode.
- I don't check CVSWRITE or _watched; I haven't thought about
- that in great detail, but it seems like a watched file should
- be checked out (writable) after a merge. */
- xchmod (finfo->file, 1);
-
- /* Hmm. We don't give them REV1 anywhere. I guess most people
- probably don't have a 3-way merge tool for the file type in
- question, and might just get confused if we tried to either
- provide them with a copy of the file from REV1, or even just
- told them what REV1 is so they can get it themself, but it
- might be worth thinking about. */
- /* See comment in merge_file about the "nonmergeable file"
- terminology. */
- error (0, 0, "nonmergeable file needs merge");
- error (0, 0, "revision %s from repository is now in %s",
- rev2, finfo->fullname);
- error (0, 0, "file from working directory is now in %s", backup);
- write_letter (finfo, 'C');
- }
- else
- status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
- t_options, rev1, rev2);
-
- if (status != 0)
- {
- if (status != 1)
- {
- error (0, status == -1 ? errno : 0,
- "could not merge revision %s of %s", rev2, finfo->fullname);
- error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
- finfo->fullname, backup);
- rename_file (backup, finfo->file);
- }
- }
- else /* status == 0 */
- {
- /* FIXME: the noexec case is broken. RCS_merge could be doing the
- xcmp on the temporary files without much hassle, I think. */
- if (!noexec && !xcmp (backup, finfo->file))
- {
- if (!really_quiet)
- {
- cvs_output (finfo->fullname, 0);
- cvs_output (" already contains the differences between ", 0);
- cvs_output (rev1, 0);
- cvs_output (" and ", 0);
- cvs_output (rev2, 0);
- cvs_output ("\n", 1);
- }
-
- /* and skip the registering and sending the new file since it
- * hasn't been updated.
- */
- goto out;
- }
- }
-
- /* The file has changed, but if we just checked it out it may
- still have the same timestamp it did when it was first
- registered above in checkout_file. We register it again with a
- dummy timestamp to make sure that later runs of CVS will
- recognize that it has changed.
-
- We don't actually need to register again if we called
- RCS_checkout above, and we aren't running as the server.
- However, that is not the normal case, and calling Register
- again won't cost much in that case. */
- RegisterMerge (finfo, vers, backup, status);
-
-out:
- free (rev1);
- free (rev2);
- free (backup);
-}
-
-
-
-/*
- * Report whether revisions REV1 and REV2 of FINFO agree on:
- * . file ownership
- * . permissions
- * . major and minor device numbers
- * . symbolic links
- * . hard links
- *
- * If either REV1 or REV2 is NULL, the working copy is used instead.
- *
- * Return 1 if the files differ on these data.
- */
-
-int
-special_file_mismatch (finfo, rev1, rev2)
- struct file_info *finfo;
- char *rev1;
- char *rev2;
-{
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- struct stat sb;
- RCSVers *vp;
- Node *n;
- uid_t rev1_uid, rev2_uid;
- gid_t rev1_gid, rev2_gid;
- mode_t rev1_mode, rev2_mode;
- unsigned long dev_long;
- dev_t rev1_dev, rev2_dev;
- char *rev1_symlink = NULL;
- char *rev2_symlink = NULL;
- List *rev1_hardlinks = NULL;
- List *rev2_hardlinks = NULL;
- int check_uids, check_gids, check_modes;
- int result;
-
- /* If we don't care about special file info, then
- don't report a mismatch in any case. */
- if (!preserve_perms)
- return 0;
-
- /* When special_file_mismatch is called from No_Difference, the
- RCS file has been only partially parsed. We must read the
- delta tree in order to compare special file info recorded in
- the delta nodes. (I think this is safe. -twp) */
- if (finfo->rcs->flags & PARTIAL)
- RCS_reparsercsfile (finfo->rcs, NULL, NULL);
-
- check_uids = check_gids = check_modes = 1;
-
- /* Obtain file information for REV1. If this is null, then stat
- finfo->file and use that info. */
- /* If a revision does not know anything about its status,
- then presumably it doesn't matter, and indicates no conflict. */
-
- if (rev1 == NULL)
- {
- if (islink (finfo->file))
- rev1_symlink = xreadlink (finfo->file);
- else
- {
-# ifdef HAVE_STRUCT_STAT_ST_RDEV
- if (CVS_LSTAT (finfo->file, &sb) < 0)
- error (1, errno, "could not get file information for %s",
- finfo->file);
- rev1_uid = sb.st_uid;
- rev1_gid = sb.st_gid;
- rev1_mode = sb.st_mode;
- if (S_ISBLK (rev1_mode) || S_ISCHR (rev1_mode))
- rev1_dev = sb.st_rdev;
-# else
- error (1, 0, "cannot handle device files on this system (%s)",
- finfo->file);
-# endif
- }
- rev1_hardlinks = list_linked_files_on_disk (finfo->file);
- }
- else
- {
- n = findnode (finfo->rcs->versions, rev1);
- vp = n->data;
-
- n = findnode (vp->other_delta, "symlink");
- if (n != NULL)
- rev1_symlink = xstrdup (n->data);
- else
- {
- n = findnode (vp->other_delta, "owner");
- if (n == NULL)
- check_uids = 0; /* don't care */
- else
- rev1_uid = strtoul (n->data, NULL, 10);
-
- n = findnode (vp->other_delta, "group");
- if (n == NULL)
- check_gids = 0; /* don't care */
- else
- rev1_gid = strtoul (n->data, NULL, 10);
-
- n = findnode (vp->other_delta, "permissions");
- if (n == NULL)
- check_modes = 0; /* don't care */
- else
- rev1_mode = strtoul (n->data, NULL, 8);
-
- n = findnode (vp->other_delta, "special");
- if (n == NULL)
- rev1_mode |= S_IFREG;
- else
- {
- /* If the size of `ftype' changes, fix the sscanf call also */
- char ftype[16];
- if (sscanf (n->data, "%15s %lu", ftype,
- &dev_long) < 2)
- error (1, 0, "%s:%s has bad `special' newphrase %s",
- finfo->file, rev1, (char *)n->data);
- rev1_dev = dev_long;
- if (strcmp (ftype, "character") == 0)
- rev1_mode |= S_IFCHR;
- else if (strcmp (ftype, "block") == 0)
- rev1_mode |= S_IFBLK;
- else
- error (0, 0, "%s:%s unknown file type `%s'",
- finfo->file, rev1, ftype);
- }
-
- rev1_hardlinks = vp->hardlinks;
- if (rev1_hardlinks == NULL)
- rev1_hardlinks = getlist();
- }
- }
-
- /* Obtain file information for REV2. */
- if (rev2 == NULL)
- {
- if (islink (finfo->file))
- rev2_symlink = xreadlink (finfo->file);
- else
- {
-# ifdef HAVE_STRUCT_STAT_ST_RDEV
- if (CVS_LSTAT (finfo->file, &sb) < 0)
- error (1, errno, "could not get file information for %s",
- finfo->file);
- rev2_uid = sb.st_uid;
- rev2_gid = sb.st_gid;
- rev2_mode = sb.st_mode;
- if (S_ISBLK (rev2_mode) || S_ISCHR (rev2_mode))
- rev2_dev = sb.st_rdev;
-# else
- error (1, 0, "cannot handle device files on this system (%s)",
- finfo->file);
-# endif
- }
- rev2_hardlinks = list_linked_files_on_disk (finfo->file);
- }
- else
- {
- n = findnode (finfo->rcs->versions, rev2);
- vp = n->data;
-
- n = findnode (vp->other_delta, "symlink");
- if (n != NULL)
- rev2_symlink = xstrdup (n->data);
- else
- {
- n = findnode (vp->other_delta, "owner");
- if (n == NULL)
- check_uids = 0; /* don't care */
- else
- rev2_uid = strtoul (n->data, NULL, 10);
-
- n = findnode (vp->other_delta, "group");
- if (n == NULL)
- check_gids = 0; /* don't care */
- else
- rev2_gid = strtoul (n->data, NULL, 10);
-
- n = findnode (vp->other_delta, "permissions");
- if (n == NULL)
- check_modes = 0; /* don't care */
- else
- rev2_mode = strtoul (n->data, NULL, 8);
-
- n = findnode (vp->other_delta, "special");
- if (n == NULL)
- rev2_mode |= S_IFREG;
- else
- {
- /* If the size of `ftype' changes, fix the sscanf call also */
- char ftype[16];
- if (sscanf (n->data, "%15s %lu", ftype,
- &dev_long) < 2)
- error (1, 0, "%s:%s has bad `special' newphrase %s",
- finfo->file, rev2, (char *)n->data);
- rev2_dev = dev_long;
- if (strcmp (ftype, "character") == 0)
- rev2_mode |= S_IFCHR;
- else if (strcmp (ftype, "block") == 0)
- rev2_mode |= S_IFBLK;
- else
- error (0, 0, "%s:%s unknown file type `%s'",
- finfo->file, rev2, ftype);
- }
-
- rev2_hardlinks = vp->hardlinks;
- if (rev2_hardlinks == NULL)
- rev2_hardlinks = getlist();
- }
- }
-
- /* Check the user/group ownerships and file permissions, printing
- an error for each mismatch found. Return 0 if all characteristics
- matched, and 1 otherwise. */
-
- result = 0;
-
- /* Compare symlinks first, since symlinks are simpler (don't have
- any other characteristics). */
- if (rev1_symlink != NULL && rev2_symlink == NULL)
- {
- error (0, 0, "%s is a symbolic link",
- (rev1 == NULL ? "working file" : rev1));
- result = 1;
- }
- else if (rev1_symlink == NULL && rev2_symlink != NULL)
- {
- error (0, 0, "%s is a symbolic link",
- (rev2 == NULL ? "working file" : rev2));
- result = 1;
- }
- else if (rev1_symlink != NULL)
- result = (strcmp (rev1_symlink, rev2_symlink) == 0);
- else
- {
- /* Compare user ownership. */
- if (check_uids && rev1_uid != rev2_uid)
- {
- error (0, 0, "%s: owner mismatch between %s and %s",
- finfo->file,
- (rev1 == NULL ? "working file" : rev1),
- (rev2 == NULL ? "working file" : rev2));
- result = 1;
- }
-
- /* Compare group ownership. */
- if (check_gids && rev1_gid != rev2_gid)
- {
- error (0, 0, "%s: group mismatch between %s and %s",
- finfo->file,
- (rev1 == NULL ? "working file" : rev1),
- (rev2 == NULL ? "working file" : rev2));
- result = 1;
- }
-
- /* Compare permissions. */
- if (check_modes &&
- (rev1_mode & 07777) != (rev2_mode & 07777))
- {
- error (0, 0, "%s: permission mismatch between %s and %s",
- finfo->file,
- (rev1 == NULL ? "working file" : rev1),
- (rev2 == NULL ? "working file" : rev2));
- result = 1;
- }
-
- /* Compare device file characteristics. */
- if ((rev1_mode & S_IFMT) != (rev2_mode & S_IFMT))
- {
- error (0, 0, "%s: %s and %s are different file types",
- finfo->file,
- (rev1 == NULL ? "working file" : rev1),
- (rev2 == NULL ? "working file" : rev2));
- result = 1;
- }
- else if (S_ISBLK (rev1_mode))
- {
- if (rev1_dev != rev2_dev)
- {
- error (0, 0, "%s: device numbers of %s and %s do not match",
- finfo->file,
- (rev1 == NULL ? "working file" : rev1),
- (rev2 == NULL ? "working file" : rev2));
- result = 1;
- }
- }
-
- /* Compare hard links. */
- if (compare_linkage_lists (rev1_hardlinks, rev2_hardlinks) == 0)
- {
- error (0, 0, "%s: hard linkage of %s and %s do not match",
- finfo->file,
- (rev1 == NULL ? "working file" : rev1),
- (rev2 == NULL ? "working file" : rev2));
- result = 1;
- }
- }
-
- if (rev1_symlink != NULL)
- free (rev1_symlink);
- if (rev2_symlink != NULL)
- free (rev2_symlink);
- if (rev1_hardlinks != NULL)
- dellist (&rev1_hardlinks);
- if (rev2_hardlinks != NULL)
- dellist (&rev2_hardlinks);
-
- return result;
-#else
- return 0;
-#endif
-}
-
-
-
-int
-joining ()
-{
- return join_rev1 != NULL;
-}
diff --git a/contrib/cvs/src/update.h b/contrib/cvs/src/update.h
deleted file mode 100644
index c886b4c8f1b7..000000000000
--- a/contrib/cvs/src/update.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Declarations for update.c.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-/*
- * $FreeBSD$
- */
-
-int do_update PROTO((int argc, char *argv[], char *xoptions, char *xtag,
- char *xdate, int xforce, int local, int xbuild,
- int xaflag, int xprune, int xpipeout, int which,
- char *xjoin_rev1, char *xjoin_rev2, char *preload_update_dir,
- int xpull_template, char *repository));
-int joining PROTO((void));
-extern int isemptydir PROTO ((const char *dir, int might_not_exist));
diff --git a/contrib/cvs/src/vers_ts.c b/contrib/cvs/src/vers_ts.c
deleted file mode 100644
index 1bf880a10056..000000000000
--- a/contrib/cvs/src/vers_ts.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with the CVS source distribution.
- */
-
-#include "cvs.h"
-
-#ifdef SERVER_SUPPORT
-static void time_stamp_server PROTO((const char *, Vers_TS *, Entnode *));
-#endif
-
-
-
-/* Fill in and return a Vers_TS structure for the file FINFO. TAG and
- DATE are from the command line. */
-
-Vers_TS *
-Version_TS (finfo, options, tag, date, force_tag_match, set_time)
- struct file_info *finfo;
-
- /* Keyword expansion options, I think generally from the command
- line. Can be either NULL or "" to indicate none are specified
- here. */
- char *options;
- char *tag;
- char *date;
- int force_tag_match;
- int set_time;
-{
- Node *p;
- RCSNode *rcsdata;
- Vers_TS *vers_ts;
- struct stickydirtag *sdtp;
- Entnode *entdata;
- char *rcsexpand = NULL;
-
-#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));
-
- /*
- * look up the entries file entry and fill in the version and timestamp
- * if entries is NULL, there is no entries file so don't bother trying to
- * look it up (used by checkout -P)
- */
- if (finfo->entries == NULL)
- {
- sdtp = NULL;
- p = NULL;
- }
- else
- {
- p = findnode_fn (finfo->entries, finfo->file);
- sdtp = finfo->entries->list->data; /* list-private */
- }
-
- entdata = NULL;
- if (p != NULL)
- {
- entdata = p->data;
-
- if (entdata->type == ENT_SUBDIR)
- {
- /* According to cvs.texinfo, the various fields in the Entries
- file for a directory (other than the name) do not have a
- defined meaning. We need to pass them along without getting
- confused based on what is in them. Therefore we make sure
- not to set vn_user and the like from Entries, add.c and
- perhaps other code will expect these fields to be NULL for
- a directory. */
- vers_ts->entdata = entdata;
- }
- else
-#ifdef SERVER_SUPPORT
- /* An entries line with "D" in the timestamp indicates that the
- client sent Is-modified without sending Entry. So we want to
- use the entries line for the sole purpose of telling
- time_stamp_server what is up; we don't want the rest of CVS
- to think there is an entries line. */
- if (strcmp (entdata->timestamp, "D") != 0)
-#endif
- {
- vers_ts->vn_user = xstrdup (entdata->version);
- vers_ts->ts_rcs = xstrdup (entdata->timestamp);
- vers_ts->ts_conflict = xstrdup (entdata->conflict);
- if (!(tag || date) && !(sdtp && sdtp->aflag))
- {
- vers_ts->tag = xstrdup (entdata->tag);
- vers_ts->date = xstrdup (entdata->date);
- }
- vers_ts->entdata = entdata;
- }
- /* Even if we don't have an "entries line" as such
- (vers_ts->entdata), we want to pick up options which could
- have been from a Kopt protocol request. */
- if (!options || *options == '\0')
- {
- if (!(sdtp && sdtp->aflag))
- vers_ts->options = xstrdup (entdata->options);
- }
- }
-
- /* Always look up the RCS keyword mode when we have an RCS archive. It
- * will either be needed as a default or to avoid allowing the -k options
- * specified on the command line from overriding binary mode (-kb).
- */
- if (finfo->rcs != NULL)
- rcsexpand = RCS_getexpand (finfo->rcs);
-
- /*
- * -k options specified on the command line override (and overwrite)
- * options stored in the entries file and default options from the RCS
- * archive, except for binary mode (-kb).
- */
- if (options && *options != '\0')
- {
- if (vers_ts->options != NULL)
- free (vers_ts->options);
- if (rcsexpand != NULL && strcmp (rcsexpand, "b") == 0)
- vers_ts->options = xstrdup ("-kb");
- else
- vers_ts->options = xstrdup (options);
- }
- else if ((!vers_ts->options || *vers_ts->options == '\0')
- && rcsexpand != NULL)
- {
- /* If no keyword expansion was specified on command line,
- use whatever was in the rcs file (if there is one). This
- is how we, if we are the server, tell the client whether
- a file is binary. */
- if (vers_ts->options != NULL)
- free (vers_ts->options);
- vers_ts->options = xmalloc (strlen (rcsexpand) + 3);
- strcpy (vers_ts->options, "-k");
- strcat (vers_ts->options, rcsexpand);
- }
- if (!vers_ts->options)
- vers_ts->options = xstrdup ("");
-
- /*
- * if tags were specified on the command line, they override what is in
- * the Entries file
- */
- if (tag || date)
- {
- vers_ts->tag = xstrdup (tag);
- vers_ts->date = xstrdup (date);
- }
- else if (!vers_ts->entdata && (sdtp && sdtp->aflag == 0))
- {
- if (!vers_ts->tag)
- {
- vers_ts->tag = xstrdup (sdtp->tag);
- vers_ts->nonbranch = sdtp->nonbranch;
- }
- if (!vers_ts->date)
- vers_ts->date = xstrdup (sdtp->date);
- }
-
- /* Now look up the info on the source controlled file */
- if (finfo->rcs != NULL)
- {
- rcsdata = finfo->rcs;
- rcsdata->refcount++;
- }
- else if (finfo->repository != NULL)
- rcsdata = RCS_parse (finfo->file, finfo->repository);
- else
- rcsdata = NULL;
-
- if (rcsdata != NULL)
- {
- /* squirrel away the rcsdata pointer for others */
- vers_ts->srcfile = rcsdata;
-
- if (vers_ts->tag && strcmp (vers_ts->tag, TAG_BASE) == 0)
- {
- vers_ts->vn_rcs = xstrdup (vers_ts->vn_user);
- vers_ts->vn_tag = xstrdup (vers_ts->vn_user);
- }
- else
- {
- int simple;
-
- vers_ts->vn_rcs = RCS_getversion (rcsdata, vers_ts->tag,
- vers_ts->date, force_tag_match,
- &simple);
- if (vers_ts->vn_rcs == NULL)
- vers_ts->vn_tag = NULL;
- else if (simple)
- vers_ts->vn_tag = xstrdup (vers_ts->tag);
- else
- vers_ts->vn_tag = xstrdup (vers_ts->vn_rcs);
- }
-
- /*
- * If the source control file exists and has the requested revision,
- * get the Date the revision was checked in. If "user" exists, set
- * its mtime.
- */
- if (set_time && vers_ts->vn_rcs != NULL)
- {
-#ifdef SERVER_SUPPORT
- if (server_active)
- server_modtime (finfo, vers_ts);
- else
-#endif
- {
- struct utimbuf t;
-
- memset (&t, 0, sizeof (t));
- t.modtime = RCS_getrevtime (rcsdata, vers_ts->vn_rcs, 0, 0);
- if (t.modtime != (time_t) -1)
- {
- (void) time (&t.actime);
-
-#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)
- {
- xchmod (finfo->file, 0);
- change_it_back = 0;
- }
-#endif /* UTIME_EXPECTS_WRITABLE */
- }
- }
- }
- }
-
- /* get user file time-stamp in ts_user */
- if (finfo->entries != (List *) NULL)
- {
-#ifdef SERVER_SUPPORT
- if (server_active)
- time_stamp_server (finfo->file, vers_ts, entdata);
- else
-#endif
- vers_ts->ts_user = time_stamp (finfo->file);
- }
-
- return (vers_ts);
-}
-
-#ifdef SERVER_SUPPORT
-
-/* Set VERS_TS->TS_USER to time stamp for FILE. */
-
-/* Separate these out to keep the logic below clearer. */
-#define mark_lost(V) ((V)->ts_user = 0)
-#define mark_unchanged(V) ((V)->ts_user = xstrdup ((V)->ts_rcs))
-
-static void
-time_stamp_server (file, vers_ts, entdata)
- const char *file;
- Vers_TS *vers_ts;
- Entnode *entdata;
-{
- struct stat sb;
- char *cp;
-
- if (CVS_LSTAT (file, &sb) < 0)
- {
- if (! existence_error (errno))
- error (1, errno, "cannot stat temp file");
-
- /* Missing file means lost or unmodified; check entries
- file to see which.
-
- XXX FIXME - If there's no entries file line, we
- wouldn't be getting the file at all, so consider it
- lost. I don't know that that's right, but it's not
- clear to me that either choice is. Besides, would we
- have an RCS string in that case anyways? */
- if (entdata == NULL)
- mark_lost (vers_ts);
- else if (entdata->timestamp
- && entdata->timestamp[0] == '=')
- mark_unchanged (vers_ts);
- else if (entdata->conflict
- && entdata->conflict[0] == '=')
- {
- /* These just need matching content. Might as well minimize it. */
- vers_ts->ts_user = xstrdup ("");
- vers_ts->ts_conflict = xstrdup ("");
- }
- else if (entdata->timestamp
- && (entdata->timestamp[0] == 'M'
- || entdata->timestamp[0] == 'D')
- && entdata->timestamp[1] == '\0')
- vers_ts->ts_user = xstrdup ("Is-modified");
- else
- mark_lost (vers_ts);
- }
- else if (sb.st_mtime == 0)
- {
- /* We shouldn't reach this case any more! */
- abort ();
- }
- else
- {
- struct tm *tm_p;
-
- vers_ts->ts_user = xmalloc (25);
- /* We want to use the same timestamp format as is stored in the
- st_mtime. For unix (and NT I think) this *must* be universal
- time (UT), so that files don't appear to be modified merely
- because the timezone has changed. For VMS, or hopefully other
- systems where gmtime returns NULL, the modification time is
- stored in local time, and therefore it is not possible to cause
- st_mtime to be out of sync by changing the timezone. */
- tm_p = gmtime (&sb.st_mtime);
- cp = tm_p ? asctime (tm_p) : ctime (&sb.st_mtime);
- cp[24] = 0;
- /* Fix non-standard format. */
- if (cp[8] == '0') cp[8] = ' ';
- (void) strcpy (vers_ts->ts_user, cp);
- }
-}
-
-#endif /* SERVER_SUPPORT */
-/*
- * Gets the time-stamp for the file "file" and returns it in space it
- * allocates
- */
-char *
-time_stamp (file)
- const char *file;
-{
- struct stat sb;
- char *cp;
- char *ts = NULL;
- time_t mtime = 0L;
-
- if (!CVS_LSTAT (file, &sb))
- {
- mtime = sb.st_mtime;
- }
- else if (! existence_error (errno))
- error (0, errno, "cannot lstat %s", file);
-
- /* If it's a symlink, return whichever is the newest mtime of
- the link and its target, for safety.
- */
- if (!CVS_STAT (file, &sb))
- {
- if (mtime < sb.st_mtime)
- mtime = sb.st_mtime;
- }
- else if (! existence_error (errno))
- error (0, errno, "cannot stat %s", file);
-
- if (mtime)
- {
- struct tm *tm_p;
- ts = xmalloc (25);
- /* We want to use the same timestamp format as is stored in the
- st_mtime. For unix (and NT I think) this *must* be universal
- time (UT), so that files don't appear to be modified merely
- because the timezone has changed. For VMS, or hopefully other
- systems where gmtime returns NULL, the modification time is
- stored in local time, and therefore it is not possible to cause
- st_mtime to be out of sync by changing the timezone. */
- tm_p = gmtime (&sb.st_mtime);
- cp = tm_p ? asctime (tm_p) : ctime (&sb.st_mtime);
- cp[24] = 0;
- /* Fix non-standard format. */
- if (cp[8] == '0') cp[8] = ' ';
- (void) strcpy (ts, cp);
- }
-
- return (ts);
-}
-
-/*
- * free up a Vers_TS struct
- */
-void
-freevers_ts (versp)
- Vers_TS **versp;
-{
- if ((*versp)->srcfile)
- freercsnode (&((*versp)->srcfile));
- if ((*versp)->vn_user)
- free ((*versp)->vn_user);
- if ((*versp)->vn_rcs)
- free ((*versp)->vn_rcs);
- if ((*versp)->vn_tag)
- free ((*versp)->vn_tag);
- if ((*versp)->ts_user)
- free ((*versp)->ts_user);
- if ((*versp)->ts_rcs)
- free ((*versp)->ts_rcs);
- if ((*versp)->options)
- free ((*versp)->options);
- if ((*versp)->tag)
- free ((*versp)->tag);
- if ((*versp)->date)
- free ((*versp)->date);
- if ((*versp)->ts_conflict)
- free ((*versp)->ts_conflict);
- free ((char *) *versp);
- *versp = (Vers_TS *) NULL;
-}
diff --git a/contrib/cvs/src/version.c b/contrib/cvs/src/version.c
deleted file mode 100644
index 09f99f4940b1..000000000000
--- a/contrib/cvs/src/version.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1994 david d `zoo' zuhn
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions Copyright (C) 1989-1992, Brian Berliner
- *
- * You may distribute under the terms of the GNU General Public License as
- * specified in the README file that comes with this CVS source distribution.
- *
- * version.c - the CVS version number
- */
-
-#include "cvs.h"
-
-#ifdef CLIENT_SUPPORT
-#ifdef SERVER_SUPPORT
-char *config_string = " (client/server)\n";
-#else
-char *config_string = " (client)\n";
-#endif
-#else
-#ifdef SERVER_SUPPORT
-char *config_string = " (server)\n";
-#else
-char *config_string = "\n";
-#endif
-#endif
-
-
-
-static const char *const version_usage[] =
-{
- "Usage: %s %s\n",
- NULL
-};
-
-
-
-/*
- * Output a version string for the client and server.
- *
- * This function will output the simple version number (for the '--version'
- * option) or the version numbers of the client and server (using the 'version'
- * command).
- */
-int
-version (argc, argv)
- int argc;
- char **argv;
-{
- int err = 0;
-
- if (argc == -1)
- usage (version_usage);
-
- if (current_parsed_root && current_parsed_root->isremote)
- (void) fputs ("Client: ", stdout);
-
- /* Having the year here is a good idea, so people have
- some idea of how long ago their version of CVS was
- released. */
- (void) fputs (PACKAGE_STRING, stdout);
- (void) fputs (config_string, stdout);
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root && current_parsed_root->isremote)
- {
- (void) fputs ("Server: ", stdout);
- start_server ();
- if (supported_request ("version"))
- send_to_server ("version\012", 0);
- else
- {
- send_to_server ("noop\012", 0);
- fputs ("(unknown)\n", stdout);
- }
- err = get_responses_and_close ();
- }
-#endif
- return err;
-}
-
diff --git a/contrib/cvs/src/watch.c b/contrib/cvs/src/watch.c
deleted file mode 100644
index 0ef987cedc5b..000000000000
--- a/contrib/cvs/src/watch.c
+++ /dev/null
@@ -1,522 +0,0 @@
-/* Implementation for "cvs watch add", "cvs watchers", and related commands
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-#include "cvs.h"
-#include "edit.h"
-#include "fileattr.h"
-#include "watch.h"
-
-const char *const watch_usage[] =
-{
- "Usage: %s %s {on|off|add|remove} [-lR] [-a <action>]... [<path>]...\n",
- "on/off: Turn on/off read-only checkouts of files.\n",
- "add/remove: Add or remove notification on actions.\n",
- "-l (on/off/add/remove): Local directory only, not recursive.\n",
- "-R (on/off/add/remove): Process directories recursively (default).\n",
- "-a (add/remove): Specify what actions, one of: `edit', `unedit',\n",
- " `commit', `all', or `none' (defaults to `all').\n",
- "(Specify the --help global option for a list of other help options.)\n",
- NULL
-};
-
-static struct addremove_args the_args;
-
-void
-watch_modify_watchers (file, what)
- const char *file;
- struct addremove_args *what;
-{
- char *curattr = fileattr_get0 (file, "_watchers");
- char *p;
- char *pend;
- char *nextp;
- char *who;
- int who_len;
- char *mycurattr;
- char *mynewattr;
- size_t mynewattr_size;
-
- int add_edit_pending;
- int add_unedit_pending;
- int add_commit_pending;
- int remove_edit_pending;
- int remove_unedit_pending;
- int remove_commit_pending;
- int add_tedit_pending;
- int add_tunedit_pending;
- int add_tcommit_pending;
-
- who = getcaller ();
- who_len = strlen (who);
-
- /* Look for current watcher types for this user. */
- mycurattr = NULL;
- if (curattr != NULL)
- {
- p = curattr;
- while (1) {
- if (strncmp (who, p, who_len) == 0
- && p[who_len] == '>')
- {
- /* Found this user. */
- mycurattr = p + who_len + 1;
- }
- p = strchr (p, ',');
- if (p == NULL)
- break;
- ++p;
- }
- }
- if (mycurattr != NULL)
- {
- mycurattr = xstrdup (mycurattr);
- p = strchr (mycurattr, ',');
- if (p != NULL)
- *p = '\0';
- }
-
- /* Now copy mycurattr to mynewattr, making the requisite modifications.
- Note that we add a dummy '+' to the start of mynewattr, to reduce
- special cases (but then we strip it off when we are done). */
-
- mynewattr_size = sizeof "+edit+unedit+commit+tedit+tunedit+tcommit";
- if (mycurattr != NULL)
- mynewattr_size += strlen (mycurattr);
- mynewattr = xmalloc (mynewattr_size);
- mynewattr[0] = '\0';
-
- add_edit_pending = what->adding && what->edit;
- add_unedit_pending = what->adding && what->unedit;
- add_commit_pending = what->adding && what->commit;
- remove_edit_pending = !what->adding && what->edit;
- remove_unedit_pending = !what->adding && what->unedit;
- remove_commit_pending = !what->adding && what->commit;
- add_tedit_pending = what->add_tedit;
- add_tunedit_pending = what->add_tunedit;
- add_tcommit_pending = what->add_tcommit;
-
- /* Copy over existing watch types, except those to be removed. */
- p = mycurattr;
- while (p != NULL)
- {
- pend = strchr (p, '+');
- if (pend == NULL)
- {
- pend = p + strlen (p);
- nextp = NULL;
- }
- else
- nextp = pend + 1;
-
- /* Process this item. */
- if (pend - p == 4 && strncmp ("edit", p, 4) == 0)
- {
- if (!remove_edit_pending)
- strcat (mynewattr, "+edit");
- add_edit_pending = 0;
- }
- else if (pend - p == 6 && strncmp ("unedit", p, 6) == 0)
- {
- if (!remove_unedit_pending)
- strcat (mynewattr, "+unedit");
- add_unedit_pending = 0;
- }
- else if (pend - p == 6 && strncmp ("commit", p, 6) == 0)
- {
- if (!remove_commit_pending)
- strcat (mynewattr, "+commit");
- add_commit_pending = 0;
- }
- else if (pend - p == 5 && strncmp ("tedit", p, 5) == 0)
- {
- if (!what->remove_temp)
- strcat (mynewattr, "+tedit");
- add_tedit_pending = 0;
- }
- else if (pend - p == 7 && strncmp ("tunedit", p, 7) == 0)
- {
- if (!what->remove_temp)
- strcat (mynewattr, "+tunedit");
- add_tunedit_pending = 0;
- }
- else if (pend - p == 7 && strncmp ("tcommit", p, 7) == 0)
- {
- if (!what->remove_temp)
- strcat (mynewattr, "+tcommit");
- add_tcommit_pending = 0;
- }
- else
- {
- char *mp;
-
- /* Copy over any unrecognized watch types, for future
- expansion. */
- mp = mynewattr + strlen (mynewattr);
- *mp++ = '+';
- strncpy (mp, p, pend - p);
- *(mp + (pend - p)) = '\0';
- }
-
- /* Set up for next item. */
- p = nextp;
- }
-
- /* Add in new watch types. */
- if (add_edit_pending)
- strcat (mynewattr, "+edit");
- if (add_unedit_pending)
- strcat (mynewattr, "+unedit");
- if (add_commit_pending)
- strcat (mynewattr, "+commit");
- if (add_tedit_pending)
- strcat (mynewattr, "+tedit");
- if (add_tunedit_pending)
- strcat (mynewattr, "+tunedit");
- if (add_tcommit_pending)
- strcat (mynewattr, "+tcommit");
-
- {
- char *curattr_new;
-
- curattr_new =
- fileattr_modify (curattr,
- who,
- mynewattr[0] == '\0' ? NULL : mynewattr + 1,
- '>',
- ',');
- /* If the attribute is unchanged, don't rewrite the attribute file. */
- if (!((curattr_new == NULL && curattr == NULL)
- || (curattr_new != NULL
- && curattr != NULL
- && strcmp (curattr_new, curattr) == 0)))
- fileattr_set (file,
- "_watchers",
- curattr_new);
- if (curattr_new != NULL)
- free (curattr_new);
- }
-
- if (curattr != NULL)
- free (curattr);
- if (mycurattr != NULL)
- free (mycurattr);
- if (mynewattr != NULL)
- free (mynewattr);
-}
-
-static int addremove_fileproc PROTO ((void *callerdat,
- struct file_info *finfo));
-
-static int
-addremove_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- watch_modify_watchers (finfo->file, &the_args);
- return 0;
-}
-
-
-
-static int addremove_filesdoneproc PROTO ((void *, int, const char *,
- const char *, List *));
-
-static int
-addremove_filesdoneproc (callerdat, err, repository, update_dir, entries)
- void *callerdat;
- int err;
- const char *repository;
- const char *update_dir;
- List *entries;
-{
- if (the_args.setting_default)
- watch_modify_watchers (NULL, &the_args);
- return err;
-}
-
-static int watch_addremove PROTO ((int argc, char **argv));
-
-static int
-watch_addremove (argc, argv)
- int argc;
- char **argv;
-{
- int c;
- int local = 0;
- int err;
- int a_omitted;
-
- a_omitted = 1;
- the_args.commit = 0;
- the_args.edit = 0;
- the_args.unedit = 0;
- optind = 0;
- while ((c = getopt (argc, argv, "+lRa:")) != -1)
- {
- switch (c)
- {
- case 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case 'a':
- a_omitted = 0;
- if (strcmp (optarg, "edit") == 0)
- the_args.edit = 1;
- else if (strcmp (optarg, "unedit") == 0)
- the_args.unedit = 1;
- else if (strcmp (optarg, "commit") == 0)
- the_args.commit = 1;
- else if (strcmp (optarg, "all") == 0)
- {
- the_args.edit = 1;
- the_args.unedit = 1;
- the_args.commit = 1;
- }
- else if (strcmp (optarg, "none") == 0)
- {
- the_args.edit = 0;
- the_args.unedit = 0;
- the_args.commit = 0;
- }
- else
- usage (watch_usage);
- break;
- case '?':
- default:
- usage (watch_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- if (a_omitted)
- {
- the_args.edit = 1;
- the_args.unedit = 1;
- the_args.commit = 1;
- }
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- start_server ();
- ign_setup ();
-
- if (local)
- send_arg ("-l");
- /* FIXME: copes poorly with "all" if server is extended to have
- new watch types and client is still running an old version. */
- if (the_args.edit)
- option_with_arg ("-a", "edit");
- if (the_args.unedit)
- option_with_arg ("-a", "unedit");
- if (the_args.commit)
- option_with_arg ("-a", "commit");
- if (!the_args.edit && !the_args.unedit && !the_args.commit)
- option_with_arg ("-a", "none");
- send_arg ("--");
- 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);
- return get_responses_and_close ();
- }
-#endif /* CLIENT_SUPPORT */
-
- the_args.setting_default = (argc <= 0);
-
- lock_tree_for_write (argc, argv, local, W_LOCAL, 0);
-
- err = start_recursion (addremove_fileproc, addremove_filesdoneproc,
- (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
- argc, argv, local, W_LOCAL, 0, CVS_LOCK_NONE,
- (char *) NULL, 1, (char *) NULL);
-
- Lock_Cleanup ();
- return err;
-}
-
-int
-watch_add (argc, argv)
- int argc;
- char **argv;
-{
- the_args.adding = 1;
- return watch_addremove (argc, argv);
-}
-
-int
-watch_remove (argc, argv)
- int argc;
- char **argv;
-{
- the_args.adding = 0;
- return watch_addremove (argc, argv);
-}
-
-int
-watch (argc, argv)
- int argc;
- char **argv;
-{
- if (argc <= 1)
- usage (watch_usage);
- if (strcmp (argv[1], "on") == 0)
- {
- --argc;
- ++argv;
- return watch_on (argc, argv);
- }
- else if (strcmp (argv[1], "off") == 0)
- {
- --argc;
- ++argv;
- return watch_off (argc, argv);
- }
- else if (strcmp (argv[1], "add") == 0)
- {
- --argc;
- ++argv;
- return watch_add (argc, argv);
- }
- else if (strcmp (argv[1], "remove") == 0)
- {
- --argc;
- ++argv;
- return watch_remove (argc, argv);
- }
- else
- usage (watch_usage);
- return 0;
-}
-
-static const char *const watchers_usage[] =
-{
- "Usage: %s %s [-lR] [<file>]...\n",
- "-l\tProcess this directory only (not recursive).\n",
- "-R\tProcess directories recursively (default).\n",
- "(Specify the --help global option for a list of other help options.)\n",
- NULL
-};
-
-static int watchers_fileproc PROTO ((void *callerdat,
- struct file_info *finfo));
-
-static int
-watchers_fileproc (callerdat, finfo)
- void *callerdat;
- struct file_info *finfo;
-{
- char *them;
- char *p;
-
- them = fileattr_get0 (finfo->file, "_watchers");
- if (them == NULL)
- return 0;
-
- cvs_output (finfo->fullname, 0);
-
- p = them;
- while (1)
- {
- cvs_output ("\t", 1);
- while (*p != '>' && *p != '\0')
- cvs_output (p++, 1);
- if (*p == '\0')
- {
- /* Only happens if attribute is misformed. */
- cvs_output ("\n", 1);
- break;
- }
- ++p;
- cvs_output ("\t", 1);
- while (1)
- {
- while (*p != '+' && *p != ',' && *p != '\0')
- cvs_output (p++, 1);
- if (*p == '\0')
- {
- cvs_output ("\n", 1);
- goto out;
- }
- if (*p == ',')
- {
- ++p;
- break;
- }
- ++p;
- cvs_output ("\t", 1);
- }
- cvs_output ("\n", 1);
- }
- out:;
- free (them);
- return 0;
-}
-
-int
-watchers (argc, argv)
- int argc;
- char **argv;
-{
- int local = 0;
- int c;
-
- if (argc == -1)
- usage (watchers_usage);
-
- optind = 0;
- while ((c = getopt (argc, argv, "+lR")) != -1)
- {
- switch (c)
- {
- case 'l':
- local = 1;
- break;
- case 'R':
- local = 0;
- break;
- case '?':
- default:
- usage (watchers_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- start_server ();
- ign_setup ();
-
- if (local)
- send_arg ("-l");
- send_arg ("--");
- 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 ();
- }
-#endif /* CLIENT_SUPPORT */
-
- return start_recursion (watchers_fileproc, (FILESDONEPROC) NULL,
- (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
- argc, argv, local, W_LOCAL, 0, CVS_LOCK_READ,
- (char *) NULL, 1, (char *) NULL);
-}
diff --git a/contrib/cvs/src/watch.h b/contrib/cvs/src/watch.h
deleted file mode 100644
index 0394635bcc6a..000000000000
--- a/contrib/cvs/src/watch.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Interface to "cvs watch add", "cvs watchers", and related features
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-extern const char *const watch_usage[];
-
-/* Flags to pass between the various functions making up the
- add/remove code. All in a single structure in case there is some
- need to make the code reentrant some day. */
-
-struct addremove_args {
- /* A flag for each watcher type. */
- int edit;
- int unedit;
- int commit;
-
- /* Are we adding or removing (non-temporary) edit,unedit,and/or commit
- watches? */
- int adding;
-
- /* Should we add a temporary edit watch? */
- int add_tedit;
- /* Should we add a temporary unedit watch? */
- int add_tunedit;
- /* Should we add a temporary commit watch? */
- int add_tcommit;
-
- /* Should we remove all temporary watches? */
- int remove_temp;
-
- /* Should we set the default? This is here for passing among various
- routines in watch.c (a good place for it if there is ever any reason
- to make the stuff reentrant), not for watch_modify_watchers. */
- int setting_default;
-};
-
-/* Modify the watchers for FILE. *WHAT tells what to do to them.
- If FILE is NULL, modify default args (WHAT->SETTING_DEFAULT is
- not used). */
-extern void watch_modify_watchers PROTO ((const char *file,
- struct addremove_args *what));
-
-extern int watch_add PROTO ((int argc, char **argv));
-extern int watch_remove PROTO ((int argc, char **argv));
diff --git a/contrib/cvs/src/wrapper.c b/contrib/cvs/src/wrapper.c
deleted file mode 100644
index 512e96c6771d..000000000000
--- a/contrib/cvs/src/wrapper.c
+++ /dev/null
@@ -1,623 +0,0 @@
-/* This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-#include "cvs.h"
-#include "getline.h"
-
-/*
- Original Author: athan@morgan.com <Andrew C. Athan> 2/1/94
- Modified By: vdemarco@bou.shl.com
-
- This package was written to support the NEXTSTEP concept of
- "wrappers." These are essentially directories that are to be
- treated as "files." This package allows such wrappers to be
- "processed" on the way in and out of CVS. The intended use is to
- wrap up a wrapper into a single tar, such that that tar can be
- treated as a single binary file in CVS. To solve the problem
- effectively, it was also necessary to be able to prevent rcsmerge
- application at appropriate times.
-
- ------------------
- Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
-
- wildcard [option value][option value]...
-
- where option is one of
- -m update methodology value: MERGE or COPY
- -k default -k rcs option to use on import or add
-
- and value is a single-quote delimited value.
-
- E.g:
- *.nib -f 'gunzipuntar' -t 'targzip' -m 'COPY'
-*/
-
-
-typedef struct {
- char *wildCard;
- char *tocvsFilter;
- char *fromcvsFilter;
- char *rcsOption;
- WrapMergeMethod mergeMethod;
-} WrapperEntry;
-
-static WrapperEntry **wrap_list=NULL;
-static WrapperEntry **wrap_saved_list=NULL;
-
-static int wrap_size=0;
-static int wrap_count=0;
-static int wrap_tempcount=0;
-
-/* FIXME: the relationship between wrap_count, wrap_tempcount,
- * wrap_saved_count, and wrap_saved_tempcount is not entirely clear;
- * it is certainly suspicious that wrap_saved_count is never set to a
- * value other than zero! If the variable isn't being used, it should
- * be removed. And in general, we should describe how temporary
- * vs. permanent wrappers are implemented, and then make sure the
- * implementation is actually doing that.
- *
- * Right now things seem to be working, but that's no guarantee there
- * isn't a bug lurking somewhere in the murk.
- */
-
-static int wrap_saved_count=0;
-
-static int wrap_saved_tempcount=0;
-
-#define WRAPPER_GROW 8
-
-void wrap_add_entry PROTO((WrapperEntry *e,int temp));
-void wrap_kill PROTO((void));
-void wrap_kill_temp PROTO((void));
-void wrap_free_entry PROTO((WrapperEntry *e));
-void wrap_free_entry_internal PROTO((WrapperEntry *e));
-void wrap_restore_saved PROTO((void));
-
-void wrap_setup()
-{
- /* FIXME-reentrancy: if we do a multithreaded server, will need to
- move this to a per-connection data structure, or better yet
- think about a cleaner solution. */
- static int wrap_setup_already_done = 0;
- char *homedir;
-
- if (wrap_setup_already_done != 0)
- return;
- else
- wrap_setup_already_done = 1;
-
- if (!current_parsed_root->isremote)
- {
- char *file;
-
- file = xmalloc (strlen (current_parsed_root->directory)
- + sizeof (CVSROOTADM)
- + sizeof (CVSROOTADM_WRAPPER)
- + 3);
- /* Then add entries found in repository, if it exists. */
- (void) sprintf (file, "%s/%s/%s", current_parsed_root->directory, CVSROOTADM,
- CVSROOTADM_WRAPPER);
- if (isfile (file))
- {
- wrap_add_file(file,0);
- }
- free (file);
- }
-
- /* 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 = strcat_filename_onto_homedir (homedir, CVSDOTWRAPPER);
- if (isfile (file))
- {
- wrap_add_file (file, 0);
- }
- free (file);
- }
-
- /* FIXME: calling wrap_add() below implies that the CVSWRAPPERS
- * environment variable contains exactly one "wrapper" -- a line
- * of the form
- *
- * FILENAME_PATTERN FLAG OPTS [ FLAG OPTS ...]
- *
- * This may disagree with the documentation, which states:
- *
- * `$CVSWRAPPERS'
- * A whitespace-separated list of file name patterns that CVS
- * should treat as wrappers. *Note Wrappers::.
- *
- * Does this mean the environment variable can hold multiple
- * wrappers lines? If so, a single call to wrap_add() is
- * insufficient.
- */
-
- /* Then add entries found in CVSWRAPPERS environment variable. */
- wrap_add (getenv (WRAPPER_ENV), 0);
-}
-
-#ifdef CLIENT_SUPPORT
-/* Send -W arguments for the wrappers to the server. The command must
- be one that accepts them (e.g. update, import). */
-void
-wrap_send ()
-{
- int i;
-
- for (i = 0; i < wrap_count + wrap_tempcount; ++i)
- {
- if (wrap_list[i]->tocvsFilter != NULL
- || wrap_list[i]->fromcvsFilter != NULL)
- /* For greater studliness we would print the offending option
- and (more importantly) where we found it. */
- error (0, 0, "\
--t and -f wrapper options are not supported remotely; ignored");
- if (wrap_list[i]->mergeMethod == WRAP_COPY)
- /* For greater studliness we would print the offending option
- and (more importantly) where we found it. */
- error (0, 0, "\
--m wrapper option is not supported remotely; ignored");
- send_to_server ("Argument -W\012Argument ", 0);
- send_to_server (wrap_list[i]->wildCard, 0);
- send_to_server (" -k '", 0);
- if (wrap_list[i]->rcsOption != NULL)
- send_to_server (wrap_list[i]->rcsOption, 0);
- else
- send_to_server ("kv", 0);
- send_to_server ("'\012", 0);
- }
-}
-#endif /* CLIENT_SUPPORT */
-
-#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
-/* Output wrapper entries in the format of cvswrappers lines.
- *
- * This is useful when one side of a client/server connection wants to
- * send its wrappers to the other; since the receiving side would like
- * to use wrap_add() to incorporate the wrapper, it's best if the
- * entry arrives in this format.
- *
- * The entries are stored in `line', which is allocated here. Caller
- * can free() it.
- *
- * If first_call_p is nonzero, then start afresh. */
-void
-wrap_unparse_rcs_options (line, first_call_p)
- char **line;
- int first_call_p;
-{
- /* FIXME-reentrancy: we should design a reentrant interface, like
- a callback which gets handed each wrapper (a multithreaded
- server being the most concrete reason for this, but the
- non-reentrant interface is fairly unnecessary/ugly). */
- static int i;
-
- if (first_call_p)
- i = 0;
-
- if (i >= wrap_count + wrap_tempcount) {
- *line = NULL;
- return;
- }
-
- *line = xmalloc (strlen (wrap_list[i]->wildCard)
- + strlen ("\t")
- + strlen (" -k '")
- + (wrap_list[i]->rcsOption != NULL ?
- strlen (wrap_list[i]->rcsOption) : 2)
- + strlen ("'")
- + 1); /* leave room for '\0' */
-
- strcpy (*line, wrap_list[i]->wildCard);
- strcat (*line, " -k '");
- if (wrap_list[i]->rcsOption != NULL)
- strcat (*line, wrap_list[i]->rcsOption);
- else
- strcat (*line, "kv");
- strcat (*line, "'");
-
- ++i;
-}
-#endif /* SERVER_SUPPORT || CLIENT_SUPPORT */
-
-/*
- * Remove fmt str specifier other than %% or %s. And allow
- * only max_s %s specifiers
- */
-void
-wrap_clean_fmt_str(char *fmt, int max_s)
-{
- while (*fmt) {
- if (fmt[0] == '%' && fmt[1])
- {
- if (fmt[1] == '%')
- fmt++;
- else
- if (fmt[1] == 's' && max_s > 0)
- {
- max_s--;
- fmt++;
- } else
- *fmt = ' ';
- }
- fmt++;
- }
-}
-
-/*
- * Open a file and read lines, feeding each line to a line parser. Arrange
- * for keeping a temporary list of wrappers at the end, if the "temp"
- * argument is set.
- */
-void
-wrap_add_file (file, temp)
- const char *file;
- int temp;
-{
- FILE *fp;
- char *line = NULL;
- size_t line_allocated = 0;
-
- wrap_restore_saved ();
- wrap_kill_temp ();
-
- /* Load the file. */
- fp = CVS_FOPEN (file, "r");
- if (fp == NULL)
- {
- if (!existence_error (errno))
- error (0, errno, "cannot open %s", file);
- return;
- }
- while (getline (&line, &line_allocated, fp) >= 0)
- wrap_add (line, temp);
- if (line)
- free (line);
- if (ferror (fp))
- error (0, errno, "cannot read %s", file);
- if (fclose (fp) == EOF)
- error (0, errno, "cannot close %s", file);
-}
-
-void
-wrap_kill()
-{
- wrap_kill_temp();
- while(wrap_count)
- wrap_free_entry(wrap_list[--wrap_count]);
-}
-
-void
-wrap_kill_temp()
-{
- WrapperEntry **temps=wrap_list+wrap_count;
-
- while(wrap_tempcount)
- wrap_free_entry(temps[--wrap_tempcount]);
-}
-
-void
-wrap_free_entry(e)
- WrapperEntry *e;
-{
- wrap_free_entry_internal(e);
- free(e);
-}
-
-void
-wrap_free_entry_internal(e)
- WrapperEntry *e;
-{
- free (e->wildCard);
- if (e->tocvsFilter)
- free (e->tocvsFilter);
- if (e->fromcvsFilter)
- free (e->fromcvsFilter);
- if (e->rcsOption)
- free (e->rcsOption);
-}
-
-void
-wrap_restore_saved()
-{
- if(!wrap_saved_list)
- return;
-
- wrap_kill();
-
- free(wrap_list);
-
- wrap_list=wrap_saved_list;
- wrap_count=wrap_saved_count;
- wrap_tempcount=wrap_saved_tempcount;
-
- wrap_saved_list=NULL;
- wrap_saved_count=0;
- wrap_saved_tempcount=0;
-}
-
-void
-wrap_add (line, isTemp)
- char *line;
- int isTemp;
-{
- char *temp;
- char ctemp;
- WrapperEntry e;
- char opt;
-
- if (!line || line[0] == '#')
- return;
-
- memset (&e, 0, sizeof(e));
-
- /* Search for the wild card */
- while (*line && isspace ((unsigned char) *line))
- ++line;
- for (temp = line;
- *line && !isspace ((unsigned char) *line);
- ++line)
- ;
- if(temp==line)
- return;
-
- ctemp=*line;
- *line='\0';
-
- e.wildCard=xstrdup(temp);
- *line=ctemp;
-
- while(*line){
- /* Search for the option */
- while(*line && *line!='-')
- ++line;
- if(!*line)
- break;
- ++line;
- if(!*line)
- break;
- opt=*line;
-
- /* Search for the filter commandline */
- for(++line;*line && *line!='\'';++line);
- if(!*line)
- break;
-
- for(temp=++line;*line && (*line!='\'' || line[-1]=='\\');++line)
- ;
-
- /* This used to "break;" (ignore the option) if there was a
- single character between the single quotes (I'm guessing
- that was accidental). Now it "break;"s if there are no
- characters. I'm not sure either behavior is particularly
- necessary--the current options might not require ''
- arguments, but surely some future option legitimately
- might. Also I'm not sure that ignoring the option is a
- swift way to handle syntax errors in general. */
- if (line==temp)
- break;
-
- ctemp=*line;
- *line='\0';
- switch(opt){
- case 'f':
- /* Before this is reenabled, need to address the problem in
- commit.c (see
- http://ximbiot.com/cvs/cvshome/docs/infowrapper.html). */
- error (1, 0,
- "-t/-f wrappers not supported by this version of CVS");
-
- if(e.fromcvsFilter)
- free(e.fromcvsFilter);
- /* FIXME: error message should say where the bad value
- came from. */
- e.fromcvsFilter=expand_path (temp, "<wrapper>", 0);
- if (!e.fromcvsFilter)
- error (1, 0, "Correct above errors first");
- break;
- case 't':
- /* Before this is reenabled, need to address the problem in
- commit.c (see
- http://ximbiot.com/cvs/cvshome/docs/infowrapper.html). */
- error (1, 0,
- "-t/-f wrappers not supported by this version of CVS");
-
- if(e.tocvsFilter)
- free(e.tocvsFilter);
- /* FIXME: error message should say where the bad value
- came from. */
- e.tocvsFilter=expand_path (temp, "<wrapper>", 0);
- if (!e.tocvsFilter)
- error (1, 0, "Correct above errors first");
- break;
- case 'm':
- if(*temp=='C' || *temp=='c')
- e.mergeMethod=WRAP_COPY;
- else
- e.mergeMethod=WRAP_MERGE;
- break;
- case 'k':
- if (e.rcsOption)
- free (e.rcsOption);
- e.rcsOption = strcmp (temp, "kv") ? xstrdup (temp) : NULL;
- break;
- default:
- break;
- }
- *line=ctemp;
- if(!*line)break;
- ++line;
- }
-
- wrap_add_entry(&e, isTemp);
-}
-
-void
-wrap_add_entry(e, temp)
- WrapperEntry *e;
- int temp;
-{
- int x;
- if(wrap_count+wrap_tempcount>=wrap_size){
- wrap_size += WRAPPER_GROW;
- wrap_list = (WrapperEntry **) xrealloc ((char *) wrap_list,
- wrap_size *
- sizeof (WrapperEntry *));
- }
-
- if(!temp && wrap_tempcount){
- for(x=wrap_count+wrap_tempcount-1;x>=wrap_count;--x)
- wrap_list[x+1]=wrap_list[x];
- }
-
- x=(temp ? wrap_count+(wrap_tempcount++):(wrap_count++));
- wrap_list[x]=(WrapperEntry *)xmalloc(sizeof(WrapperEntry));
- *wrap_list[x]=*e;
-}
-
-/* Return 1 if the given filename is a wrapper filename */
-int
-wrap_name_has (name,has)
- const char *name;
- WrapMergeHas has;
-{
- int x,count=wrap_count+wrap_tempcount;
- char *temp;
-
- for(x=0;x<count;++x)
- if (CVS_FNMATCH (wrap_list[x]->wildCard, name, 0) == 0){
- switch(has){
- case WRAP_TOCVS:
- temp=wrap_list[x]->tocvsFilter;
- break;
- case WRAP_FROMCVS:
- temp=wrap_list[x]->fromcvsFilter;
- break;
- case WRAP_RCSOPTION:
- temp = wrap_list[x]->rcsOption;
- break;
- default:
- abort ();
- }
- if(temp==NULL)
- return (0);
- else
- return (1);
- }
- return (0);
-}
-
-static WrapperEntry *wrap_matching_entry PROTO ((const char *));
-
-static WrapperEntry *
-wrap_matching_entry (name)
- const char *name;
-{
- int x,count=wrap_count+wrap_tempcount;
-
- for(x=0;x<count;++x)
- if (CVS_FNMATCH (wrap_list[x]->wildCard, name, 0) == 0)
- return wrap_list[x];
- return (WrapperEntry *)NULL;
-}
-
-/* Return the RCS options for FILENAME in a newly malloc'd string. If
- ASFLAG, then include "-k" at the beginning (e.g. "-kb"), otherwise
- just give the option itself (e.g. "b"). */
-char *
-wrap_rcsoption (filename, asflag)
- const char *filename;
- int asflag;
-{
- WrapperEntry *e = wrap_matching_entry (filename);
- char *buf;
-
- if (e == NULL || e->rcsOption == NULL || (*e->rcsOption == '\0'))
- return NULL;
-
- buf = xmalloc (strlen (e->rcsOption) + 3);
- if (asflag)
- {
- strcpy (buf, "-k");
- strcat (buf, e->rcsOption);
- }
- else
- {
- strcpy (buf, e->rcsOption);
- }
- return buf;
-}
-
-char *
-wrap_tocvs_process_file(fileName)
- const char *fileName;
-{
- WrapperEntry *e=wrap_matching_entry(fileName);
- static char *buf = NULL;
- char *args;
-
- if(e==NULL || e->tocvsFilter==NULL)
- return NULL;
-
- if (buf != NULL)
- free (buf);
- buf = cvs_temp_name ();
-
- args = xmalloc (strlen (e->tocvsFilter)
- + strlen (fileName)
- + strlen (buf));
-
- wrap_clean_fmt_str(e->tocvsFilter, 2);
- sprintf (args, e->tocvsFilter, fileName, buf);
- run_setup (args);
- run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY );
- free (args);
-
- return buf;
-}
-
-int
-wrap_merge_is_copy (fileName)
- const char *fileName;
-{
- WrapperEntry *e=wrap_matching_entry(fileName);
- if(e==NULL || e->mergeMethod==WRAP_MERGE)
- return 0;
-
- return 1;
-}
-
-void
-wrap_fromcvs_process_file(fileName)
- const char *fileName;
-{
- char *args;
- WrapperEntry *e=wrap_matching_entry(fileName);
-
- if(e==NULL || e->fromcvsFilter==NULL)
- return;
-
- args = xmalloc (strlen (e->fromcvsFilter)
- + strlen (fileName));
-
- wrap_clean_fmt_str(e->fromcvsFilter, 1);
- sprintf (args, e->fromcvsFilter, fileName);
- run_setup (args);
- run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL );
- free (args);
- return;
-}
diff --git a/contrib/cvs/src/zlib.c b/contrib/cvs/src/zlib.c
deleted file mode 100644
index 46ed0e6b6325..000000000000
--- a/contrib/cvs/src/zlib.c
+++ /dev/null
@@ -1,760 +0,0 @@
-/* zlib.c --- interface to the zlib compression library
- Ian Lance Taylor <ian@cygnus.com>
-
- This file is part of GNU CVS.
-
- GNU CVS is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details. */
-
-/* The routines in this file are the interface between the CVS
- client/server support and the zlib compression library. */
-
-#include <assert.h>
-#include "cvs.h"
-#include "buffer.h"
-
-#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
-
-#include "zlib.h"
-
-/* OS/2 doesn't have EIO. FIXME: this whole notion of turning
- a different error into EIO strikes me as pretty dubious. */
-#if !defined (EIO)
-#define EIO EBADPOS
-#endif
-
-/* The compression interface is built upon the buffer data structure.
- We provide a buffer type which compresses or decompresses the data
- which passes through it. An input buffer decompresses the data
- read from an underlying buffer, and an output buffer compresses the
- data before writing it to an underlying buffer. */
-
-/* This structure is the closure field of the buffer. */
-
-struct compress_buffer
-{
- /* The underlying buffer. */
- struct buffer *buf;
- /* The compression information. */
- z_stream zstr;
-};
-
-static void compress_error PROTO((int, int, z_stream *, const char *));
-static int compress_buffer_input PROTO((void *, char *, int, int, int *));
-static int compress_buffer_output PROTO((void *, const char *, int, int *));
-static int compress_buffer_flush PROTO((void *));
-static int compress_buffer_block PROTO((void *, int));
-static int compress_buffer_shutdown_input PROTO((struct buffer *));
-static int compress_buffer_shutdown_output PROTO((struct buffer *));
-
-/* Report an error from one of the zlib functions. */
-
-static void
-compress_error (status, zstatus, zstr, msg)
- int status;
- int zstatus;
- z_stream *zstr;
- const char *msg;
-{
- int hold_errno;
- const char *zmsg;
- char buf[100];
-
- hold_errno = errno;
-
- zmsg = zstr->msg;
- if (zmsg == NULL)
- {
- sprintf (buf, "error %d", zstatus);
- zmsg = buf;
- }
-
- error (status,
- zstatus == Z_ERRNO ? hold_errno : 0,
- "%s: %s", msg, zmsg);
-}
-
-/* Create a compression buffer. */
-
-struct buffer *
-compress_buffer_initialize (buf, input, level, memory)
- struct buffer *buf;
- int input;
- int level;
- void (*memory) PROTO((struct buffer *));
-{
- struct compress_buffer *n;
- int zstatus;
-
- n = (struct compress_buffer *) xmalloc (sizeof *n);
- memset (n, 0, sizeof *n);
-
- n->buf = buf;
-
- if (input)
- zstatus = inflateInit (&n->zstr);
- else
- zstatus = deflateInit (&n->zstr, level);
- if (zstatus != Z_OK)
- compress_error (1, zstatus, &n->zstr, "compression initialization");
-
- /* There may already be data buffered on BUF. For an output
- buffer, this is OK, because these routines will just use the
- buffer routines to append data to the (uncompressed) data
- already on BUF. An input buffer expects to handle a single
- buffer_data of buffered input to be uncompressed, so that is OK
- provided there is only one buffer. At present that is all
- there ever will be; if this changes, compress_buffer_input must
- be modified to handle multiple input buffers. */
- assert (! input || buf->data == NULL || buf->data->next == NULL);
-
- return buf_initialize (input ? compress_buffer_input : NULL,
- input ? NULL : compress_buffer_output,
- input ? NULL : compress_buffer_flush,
- compress_buffer_block,
- (input
- ? compress_buffer_shutdown_input
- : compress_buffer_shutdown_output),
- memory,
- n);
-}
-
-/* Input data from a compression buffer. */
-
-static int
-compress_buffer_input (closure, data, need, size, got)
- void *closure;
- char *data;
- int need;
- int size;
- int *got;
-{
- struct compress_buffer *cb = (struct compress_buffer *) closure;
- struct buffer_data *bd;
-
- if (cb->buf->input == NULL)
- abort ();
-
- /* We use a single buffer_data structure to buffer up data which
- the z_stream structure won't use yet. We can safely store this
- on cb->buf->data, because we never call the buffer routines on
- cb->buf; we only call the buffer input routine, since that
- gives us the semantics we want. As noted in
- compress_buffer_initialize, the buffer_data structure may
- already exist, and hold data which was already read and
- buffered before the decompression began. */
- bd = cb->buf->data;
- if (bd == NULL)
- {
- bd = ((struct buffer_data *) xmalloc (sizeof (struct buffer_data)));
- if (bd == NULL)
- return -2;
- bd->text = (char *) xmalloc (BUFFER_DATA_SIZE);
- if (bd->text == NULL)
- {
- free (bd);
- return -2;
- }
- bd->bufp = bd->text;
- bd->size = 0;
- cb->buf->data = bd;
- }
-
- cb->zstr.avail_out = size;
- cb->zstr.next_out = (Bytef *) data;
-
- while (1)
- {
- int zstatus, sofar, status, nread;
-
- /* First try to inflate any data we already have buffered up.
- This is useful even if we don't have any buffered data,
- because there may be data buffered inside the z_stream
- structure. */
-
- cb->zstr.avail_in = bd->size;
- cb->zstr.next_in = (Bytef *) bd->bufp;
-
- do
- {
- zstatus = inflate (&cb->zstr, Z_NO_FLUSH);
- if (zstatus == Z_STREAM_END)
- break;
- if (zstatus != Z_OK && zstatus != Z_BUF_ERROR)
- {
- compress_error (0, zstatus, &cb->zstr, "inflate");
- return EIO;
- }
- } while (cb->zstr.avail_in > 0
- && cb->zstr.avail_out > 0);
-
- bd->size = cb->zstr.avail_in;
- bd->bufp = (char *) cb->zstr.next_in;
-
- if (zstatus == Z_STREAM_END)
- return -1;
-
- /* If we have obtained NEED bytes, then return, unless NEED is
- zero and we haven't obtained anything at all. If NEED is
- zero, we will keep reading from the underlying buffer until
- we either can't read anything, or we have managed to
- inflate at least one byte. */
- sofar = size - cb->zstr.avail_out;
- if (sofar > 0 && sofar >= need)
- break;
-
- /* All our buffered data should have been processed at this
- point. */
- assert (bd->size == 0);
-
- /* This will work well in the server, because this call will
- do an unblocked read and fetch all the available data. In
- the client, this will read a single byte from the stdio
- stream, which will cause us to call inflate once per byte.
- It would be more efficient if we could make a call which
- would fetch all the available bytes, and at least one byte. */
-
- status = (*cb->buf->input) (cb->buf->closure, bd->text,
- need > 0 ? 1 : 0,
- BUFFER_DATA_SIZE, &nread);
- if (status != 0)
- return status;
-
- /* If we didn't read anything, then presumably the buffer is
- in nonblocking mode, and we should just get out now with
- whatever we've inflated. */
- if (nread == 0)
- {
- assert (need == 0);
- break;
- }
-
- bd->bufp = bd->text;
- bd->size = nread;
- }
-
- *got = size - cb->zstr.avail_out;
-
- return 0;
-}
-
-/* Output data to a compression buffer. */
-
-static int
-compress_buffer_output (closure, data, have, wrote)
- void *closure;
- const char *data;
- int have;
- int *wrote;
-{
- struct compress_buffer *cb = (struct compress_buffer *) closure;
-
- cb->zstr.avail_in = have;
- cb->zstr.next_in = (unsigned char *) data;
-
- while (cb->zstr.avail_in > 0)
- {
- char buffer[BUFFER_DATA_SIZE];
- int zstatus;
-
- cb->zstr.avail_out = BUFFER_DATA_SIZE;
- cb->zstr.next_out = (unsigned char *) buffer;
-
- zstatus = deflate (&cb->zstr, Z_NO_FLUSH);
- if (zstatus != Z_OK)
- {
- compress_error (0, zstatus, &cb->zstr, "deflate");
- return EIO;
- }
-
- if (cb->zstr.avail_out != BUFFER_DATA_SIZE)
- buf_output (cb->buf, buffer,
- BUFFER_DATA_SIZE - cb->zstr.avail_out);
- }
-
- *wrote = have;
-
- /* We will only be here because buf_send_output was called on the
- compression buffer. That means that we should now call
- buf_send_output on the underlying buffer. */
- return buf_send_output (cb->buf);
-}
-
-/* Flush a compression buffer. */
-
-static int
-compress_buffer_flush (closure)
- void *closure;
-{
- struct compress_buffer *cb = (struct compress_buffer *) closure;
-
- cb->zstr.avail_in = 0;
- cb->zstr.next_in = NULL;
-
- while (1)
- {
- char buffer[BUFFER_DATA_SIZE];
- int zstatus;
-
- cb->zstr.avail_out = BUFFER_DATA_SIZE;
- cb->zstr.next_out = (unsigned char *) buffer;
-
- zstatus = deflate (&cb->zstr, Z_SYNC_FLUSH);
-
- /* The deflate function will return Z_BUF_ERROR if it can't do
- anything, which in this case means that all data has been
- flushed. */
- if (zstatus == Z_BUF_ERROR)
- break;
-
- if (zstatus != Z_OK)
- {
- compress_error (0, zstatus, &cb->zstr, "deflate flush");
- return EIO;
- }
-
- if (cb->zstr.avail_out != BUFFER_DATA_SIZE)
- buf_output (cb->buf, buffer,
- BUFFER_DATA_SIZE - cb->zstr.avail_out);
-
- /* If the deflate function did not fill the output buffer,
- then all data has been flushed. */
- if (cb->zstr.avail_out > 0)
- break;
- }
-
- /* Now flush the underlying buffer. Note that if the original
- call to buf_flush passed 1 for the BLOCK argument, then the
- buffer will already have been set into blocking mode, so we
- should always pass 0 here. */
- return buf_flush (cb->buf, 0);
-}
-
-/* The block routine for a compression buffer. */
-
-static int
-compress_buffer_block (closure, block)
- void *closure;
- int block;
-{
- struct compress_buffer *cb = (struct compress_buffer *) closure;
-
- if (block)
- return set_block (cb->buf);
- else
- return set_nonblock (cb->buf);
-}
-
-/* Shut down an input buffer. */
-
-static int
-compress_buffer_shutdown_input (buf)
- struct buffer *buf;
-{
- struct compress_buffer *cb = (struct compress_buffer *) buf->closure;
- int zstatus;
-
- /* Don't make any attempt to pick up trailing data since we are shutting
- * down. If the client doesn't know we are shutting down, we might not
- * see the EOF we are expecting.
- */
-
- zstatus = inflateEnd (&cb->zstr);
- if (zstatus != Z_OK)
- {
- compress_error (0, zstatus, &cb->zstr, "inflateEnd");
- return EIO;
- }
-
- return buf_shutdown (cb->buf);
-}
-
-/* Shut down an output buffer. */
-
-static int
-compress_buffer_shutdown_output (buf)
- struct buffer *buf;
-{
- struct compress_buffer *cb = (struct compress_buffer *) buf->closure;
- int zstatus, status;
-
- do
- {
- char buffer[BUFFER_DATA_SIZE];
-
- cb->zstr.avail_out = BUFFER_DATA_SIZE;
- cb->zstr.next_out = (unsigned char *) buffer;
-
- zstatus = deflate (&cb->zstr, Z_FINISH);
- if (zstatus != Z_OK && zstatus != Z_STREAM_END)
- {
- compress_error (0, zstatus, &cb->zstr, "deflate finish");
- return EIO;
- }
-
- if (cb->zstr.avail_out != BUFFER_DATA_SIZE)
- buf_output (cb->buf, buffer,
- BUFFER_DATA_SIZE - cb->zstr.avail_out);
- } while (zstatus != Z_STREAM_END);
-
- zstatus = deflateEnd (&cb->zstr);
- if (zstatus != Z_OK)
- {
- compress_error (0, zstatus, &cb->zstr, "deflateEnd");
- return EIO;
- }
-
- status = buf_flush (cb->buf, 1);
- if (status != 0)
- return status;
-
- return buf_shutdown (cb->buf);
-}
-
-
-
-/* Here is our librarified gzip implementation. It is very minimal
- but attempts to be RFC1952 compliant. */
-
-/* GZIP ID byte values */
-#define GZIP_ID1 31
-#define GZIP_ID2 139
-
-/* Compression methods */
-#define GZIP_CDEFLATE 8
-
-/* Flags */
-#define GZIP_FTEXT 1
-#define GZIP_FHCRC 2
-#define GZIP_FEXTRA 4
-#define GZIP_FNAME 8
-#define GZIP_FCOMMENT 16
-
-/* 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 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. */
-
-int
-gunzip_and_write (fd, fullname, buf, size)
- int fd;
- char *fullname;
- unsigned char *buf;
- size_t size;
-{
- size_t pos;
- z_stream zstr;
- int zstatus;
- unsigned char outbuf[32768];
- unsigned long crc;
-
- if (size < 10)
- {
- error (0, 0, "gzipped data too small - lacks complete header");
- return 1;
- }
- if (buf[0] != GZIP_ID1 || buf[1] != GZIP_ID2)
- {
- error (0, 0, "gzipped data does not start with gzip identification");
- return 1;
- }
- if (buf[2] != GZIP_CDEFLATE)
- {
- 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. As we skip each field, we keep pos <= size. The checks
- on positions and lengths are really checks for malformed or
- incomplete gzip data. */
- pos = 10;
- if (buf[3] & GZIP_FEXTRA)
- {
- if (pos + 2 >= size)
- {
- error (0, 0, "%s lacks proper gzip XLEN field", fullname);
- return 1;
- }
- pos += buf[pos] + (buf[pos + 1] << 8) + 2;
- if (pos > size)
- {
- error (0, 0, "%s lacks proper gzip \"extra field\"", fullname);
- return 1;
- }
-
- }
- if (buf[3] & GZIP_FNAME)
- {
- unsigned char *p = memchr(buf + pos, '\0', size - pos);
- if (p == NULL)
- {
- error (0, 0, "%s has bad gzip filename field", fullname);
- return 1;
- }
- pos = p - buf + 1;
- }
- if (buf[3] & GZIP_FCOMMENT)
- {
- unsigned char *p = memchr(buf + pos, '\0', size - pos);
- if (p == NULL)
- {
- error (0, 0, "%s has bad gzip comment field", fullname);
- return 1;
- }
- pos = p - buf + 1;
- }
- if (buf[3] & GZIP_FHCRC)
- {
- pos += 2;
- if (pos > size)
- {
- error (0, 0, "%s has bad gzip CRC16 field", fullname);
- return 1;
- }
- }
-
- /* There could be no data to decompress - check and short circuit. */
- if (pos >= size)
- {
- error (0, 0, "gzip data incomplete for %s (no data)", fullname);
- return 1;
- }
-
- memset (&zstr, 0, sizeof zstr);
- /* Passing a negative argument tells zlib not to look for a zlib
- (RFC1950) header. This is an undocumented feature; I suppose if
- we wanted to be anal we could synthesize a header instead,
- but why bother? */
- zstatus = inflateInit2 (&zstr, -15);
-
- if (zstatus != Z_OK)
- compress_error (1, zstatus, &zstr, fullname);
-
- /* I don't see why we should have to include the 8 byte trailer in
- avail_in. But I see that zlib/gzio.c does, and it seemed to fix
- a fairly rare bug in which we'd get a Z_BUF_ERROR for no obvious
- reason. */
- zstr.avail_in = size - pos;
- zstr.next_in = buf + pos;
-
- crc = crc32 (0, NULL, 0);
-
- do
- {
- zstr.avail_out = sizeof (outbuf);
- zstr.next_out = outbuf;
- zstatus = inflate (&zstr, Z_NO_FLUSH);
- if (zstatus != Z_STREAM_END && zstatus != Z_OK)
- {
- compress_error (0, zstatus, &zstr, fullname);
- return 1;
- }
- if (write (fd, outbuf, sizeof (outbuf) - zstr.avail_out) < 0)
- {
- 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);
- if (zstatus != Z_OK)
- compress_error (0, zstatus, &zstr, fullname);
-
- /* Check that there is still 8 trailer bytes remaining (CRC32
- and ISIZE). Check total decomp. data, plus header len (pos)
- against input buffer total size. */
- pos += zstr.total_in;
- if (size - pos != 8)
- {
- error (0, 0, "gzip data incomplete for %s (no trailer)", fullname);
- return 1;
- }
-
- if (crc != ((unsigned long)buf[pos]
- + ((unsigned long)buf[pos + 1] << 8)
- + ((unsigned long)buf[pos + 2] << 16)
- + ((unsigned long)buf[pos + 3] << 24)))
- {
- error (0, 0, "CRC error uncompressing %s", fullname);
- return 1;
- }
-
- if (zstr.total_out != ((unsigned long)buf[pos + 4]
- + ((unsigned long)buf[pos + 5] << 8)
- + ((unsigned long)buf[pos + 6] << 16)
- + ((unsigned long)buf[pos + 7] << 24)))
- {
- 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 xmalloc'd and *SIZE is
- its allocated size. Put the actual number of bytes of data in
- *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). */
-
-int
-read_and_gzip (fd, fullname, buf, size, len, level)
- int fd;
- const char *fullname;
- unsigned char **buf;
- size_t *size;
- size_t *len;
- int level;
-{
- z_stream zstr;
- int zstatus;
- unsigned char inbuf[8192];
- int nread;
- unsigned long crc;
-
- if (*size < 1024)
- {
- unsigned char *newbuf;
-
- *size = 1024;
- newbuf = xrealloc (*buf, *size);
- if (newbuf == NULL)
- {
- error (0, 0, "out of memory");
- return 1;
- }
- *buf = newbuf;
- }
- (*buf)[0] = GZIP_ID1;
- (*buf)[1] = GZIP_ID2;
- (*buf)[2] = GZIP_CDEFLATE;
- (*buf)[3] = 0;
- (*buf)[4] = (*buf)[5] = (*buf)[6] = (*buf)[7] = 0;
- /* Could set this based on level, but why bother? */
- (*buf)[8] = 0;
- (*buf)[9] = 255;
-
- memset (&zstr, 0, sizeof zstr);
- zstatus = deflateInit2 (&zstr, level, Z_DEFLATED, -15, 8,
- Z_DEFAULT_STRATEGY);
- crc = crc32 (0, NULL, 0);
- if (zstatus != Z_OK)
- {
- compress_error (0, zstatus, &zstr, fullname);
- return 1;
- }
-
- /* Adjust for 10-byte output header (filled in above) */
- zstr.total_out = 10;
- zstr.avail_out = *size - 10;
- zstr.next_out = *buf + 10;
-
- while (1)
- {
- int finish = 0;
-
- nread = read (fd, inbuf, sizeof inbuf);
- if (nread < 0)
- {
- error (0, errno, "cannot read %s", fullname);
- return 1;
- }
- else if (nread == 0)
- /* End of file. */
- finish = 1;
- crc = crc32 (crc, inbuf, nread);
- zstr.next_in = inbuf;
- zstr.avail_in = nread;
-
- do
- {
- /* I don't see this documented anywhere, but deflate seems
- to tend to dump core sometimes if we pass it Z_FINISH and
- a small (e.g. 2147 byte) avail_out. So we insist on at
- least 4096 bytes (that is what zlib/gzio.c uses). */
-
- if (zstr.avail_out < 4096)
- {
- unsigned char *newbuf;
-
- assert(zstr.avail_out + zstr.total_out == *size);
- assert(zstr.next_out == *buf + zstr.total_out);
- *size *= 2;
- newbuf = xrealloc (*buf, *size);
- if (newbuf == NULL)
- {
- error (0, 0, "out of memory");
- return 1;
- }
- *buf = newbuf;
- zstr.next_out = *buf + zstr.total_out;
- zstr.avail_out = *size - zstr.total_out;
- assert(zstr.avail_out + zstr.total_out == *size);
- assert(zstr.next_out == *buf + zstr.total_out);
- }
-
- zstatus = deflate (&zstr, finish ? Z_FINISH : 0);
- if (zstatus == Z_STREAM_END)
- goto done;
- else if (zstatus != Z_OK)
- compress_error (0, zstatus, &zstr, fullname);
- } while (zstr.avail_out == 0);
- }
- done:
- /* Need to add the CRC information (8 bytes)
- to the end of the gzip'd output.
- Ensure there is enough space in the output buffer
- to do so. */
- if (zstr.avail_out < 8)
- {
- unsigned char *newbuf;
-
- assert(zstr.avail_out + zstr.total_out == *size);
- assert(zstr.next_out == *buf + zstr.total_out);
- *size += 8 - zstr.avail_out;
- newbuf = realloc (*buf, *size);
- if (newbuf == NULL)
- {
- error (0, 0, "out of memory");
- return 1;
- }
- *buf = newbuf;
- zstr.next_out = *buf + zstr.total_out;
- zstr.avail_out = *size - zstr.total_out;
- assert(zstr.avail_out + zstr.total_out == *size);
- assert(zstr.next_out == *buf + zstr.total_out);
- }
- *zstr.next_out++ = (unsigned char)(crc & 0xff);
- *zstr.next_out++ = (unsigned char)((crc >> 8) & 0xff);
- *zstr.next_out++ = (unsigned char)((crc >> 16) & 0xff);
- *zstr.next_out++ = (unsigned char)((crc >> 24) & 0xff);
-
- *zstr.next_out++ = (unsigned char)(zstr.total_in & 0xff);
- *zstr.next_out++ = (unsigned char)((zstr.total_in >> 8) & 0xff);
- *zstr.next_out++ = (unsigned char)((zstr.total_in >> 16) & 0xff);
- *zstr.next_out++ = (unsigned char)((zstr.total_in >> 24) & 0xff);
-
- zstr.total_out += 8;
- zstr.avail_out -= 8;
- assert(zstr.avail_out + zstr.total_out == *size);
- assert(zstr.next_out == *buf + zstr.total_out);
-
- *len = zstr.total_out;
-
- zstatus = deflateEnd (&zstr);
- if (zstatus != Z_OK)
- compress_error (0, zstatus, &zstr, fullname);
-
- return 0;
-}
-#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */