aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>1999-03-18 09:21:42 +0000
committerPeter Wemm <peter@FreeBSD.org>1999-03-18 09:21:42 +0000
commit0008866e589b5dd29f5332c9bc0e208ba10a7772 (patch)
tree1b2cd3bad90a2dd8ccb449f73ddfb9e295c0737d
parent4b06c8929116f104d337c272761ff7d11f8e48e6 (diff)
downloadsrc-0008866e589b5dd29f5332c9bc0e208ba10a7772.tar.gz
src-0008866e589b5dd29f5332c9bc0e208ba10a7772.zip
Import cvs-1.10 onto vendor branch. Merge to follow shortly.
Obtained from: cyclic.com
Notes
Notes: svn path=/vendor/cvs/dist/; revision=44852
-rw-r--r--contrib/cvs/BUGS14
-rw-r--r--contrib/cvs/ChangeLog83
-rw-r--r--contrib/cvs/INSTALL14
-rw-r--r--contrib/cvs/Makefile.in2
-rw-r--r--contrib/cvs/NEWS19
-rw-r--r--contrib/cvs/TESTS11
-rw-r--r--contrib/cvs/acconfig.h4
-rw-r--r--contrib/cvs/config.h.in13
-rwxr-xr-xcontrib/cvs/configure189
-rw-r--r--contrib/cvs/configure.in54
-rw-r--r--contrib/cvs/contrib/ChangeLog4
-rw-r--r--contrib/cvs/contrib/log.pl11
-rw-r--r--contrib/cvs/diff/ChangeLog53
-rw-r--r--contrib/cvs/diff/Makefile.in7
-rw-r--r--contrib/cvs/diff/context.c54
-rw-r--r--contrib/cvs/diff/diff.c97
-rw-r--r--contrib/cvs/diff/diff.h13
-rw-r--r--contrib/cvs/diff/diff3.c344
-rw-r--r--contrib/cvs/diff/diffrun.h69
-rw-r--r--contrib/cvs/diff/ed.c40
-rw-r--r--contrib/cvs/diff/ifdef.c70
-rw-r--r--contrib/cvs/diff/normal.c8
-rw-r--r--contrib/cvs/diff/side.c44
-rw-r--r--contrib/cvs/diff/util.c145
-rw-r--r--contrib/cvs/doc/ChangeLog135
-rw-r--r--contrib/cvs/doc/RCSFILES65
-rw-r--r--contrib/cvs/doc/cvs.texinfo977
-rw-r--r--contrib/cvs/doc/cvsclient.texi47
-rw-r--r--contrib/cvs/lib/ChangeLog4
-rw-r--r--contrib/cvs/lib/Makefile.in2
-rw-r--r--contrib/cvs/man/ChangeLog5
-rw-r--r--contrib/cvs/man/cvs.1111
-rw-r--r--contrib/cvs/src/ChangeLog712
-rw-r--r--contrib/cvs/src/Makefile.in5
-rw-r--r--contrib/cvs/src/add.c33
-rw-r--r--contrib/cvs/src/admin.c20
-rw-r--r--contrib/cvs/src/checkout.c103
-rw-r--r--contrib/cvs/src/classify.c10
-rw-r--r--contrib/cvs/src/client.c60
-rw-r--r--contrib/cvs/src/commit.c184
-rw-r--r--contrib/cvs/src/cvs.h7
-rw-r--r--contrib/cvs/src/diff.c18
-rw-r--r--contrib/cvs/src/edit.c20
-rw-r--r--contrib/cvs/src/error.c14
-rw-r--r--contrib/cvs/src/fileattr.c8
-rw-r--r--contrib/cvs/src/filesubr.c42
-rw-r--r--contrib/cvs/src/hardlink.c220
-rw-r--r--contrib/cvs/src/hardlink.h6
-rw-r--r--contrib/cvs/src/history.c43
-rw-r--r--contrib/cvs/src/import.c32
-rw-r--r--contrib/cvs/src/main.c41
-rw-r--r--contrib/cvs/src/mkmodules.c5
-rw-r--r--contrib/cvs/src/options.h.in13
-rw-r--r--contrib/cvs/src/parseinfo.c12
-rw-r--r--contrib/cvs/src/rcs.c1063
-rw-r--r--contrib/cvs/src/rcs.h9
-rw-r--r--contrib/cvs/src/rcscmds.c108
-rw-r--r--contrib/cvs/src/recurse.c47
-rw-r--r--contrib/cvs/src/rtag.c2
-rwxr-xr-xcontrib/cvs/src/sanity.sh1768
-rw-r--r--contrib/cvs/src/server.c96
-rw-r--r--contrib/cvs/src/status.c2
-rw-r--r--contrib/cvs/src/tag.c15
-rw-r--r--contrib/cvs/src/update.c82
-rw-r--r--contrib/cvs/src/version.c3
-rw-r--r--contrib/cvs/src/wrapper.c10
66 files changed, 5632 insertions, 1889 deletions
diff --git a/contrib/cvs/BUGS b/contrib/cvs/BUGS
index 58be27c8c6aa..713d4c058820 100644
--- a/contrib/cvs/BUGS
+++ b/contrib/cvs/BUGS
@@ -15,20 +15,6 @@ similar file for the unix-like operating systems (not yet, at least).
This file also might contain some platform-specific bugs.
-* One cannot specify some files as binary in a "cvs import" using
-CVSROOT/cvswrappers (for why, note that client_process_import_file has
-no way of knowing about CVSROOT/cvswrappers which is off on the
-server).
-
-
-* I don't think that "cvs add" honors any of the -k wrappers, at least
-not in client/server mode. I would think it should. Getting
-CVSROOT/cvswrappers to work would presumably best be done by keeping a
-copy of it in the CVS directory on the client, as has also been
-discussed for CVS/Template, &c. Getting a client-side .cvswrappers to
-work is a separate issue.
-
-
* Need more work on the procedure for fixing it if a binary file is
accidentally added in text mode (sanity.sh test cases, better
documentation, probably update and/or admin -kb should update
diff --git a/contrib/cvs/ChangeLog b/contrib/cvs/ChangeLog
index 82ea5ac486ee..cb4801be4234 100644
--- a/contrib/cvs/ChangeLog
+++ b/contrib/cvs/ChangeLog
@@ -1,3 +1,86 @@
+1998-08-06 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * INSTALL: Update for SCO OpenServer 5 (reported by Jeffery
+ Cann).
+
+1998-08-01 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * INSTALL: Add Unixware 7 (reported by Phillip Porch).
+
+1998-07-29 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvsnt.mak: For rcscmds.c, also include files from the diff
+ directory. Plus of course the usual voluminous "because Visual
+ C++ 4.0 feels like it" changes.
+
+Tue Jul 28 22:16:48 1998 Noel Cragg <noel@swish.red-bean.com>
+
+ * Makefile.in (dist): unset the GZIP shell variable before calling
+ gzip to avoid invocation problems.
+
+Sun Jul 26 16:22:21 1998 Noel Cragg <noel@swish.red-bean.com>
+
+ * NEWS: add info about TopLevelAdmin.
+
+1998-07-20 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * INSTALL: Update entries for HPUX and AIX (based on a submission
+ from Andreas Ley).
+
+1998-06-25 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * README.VMS: We generally don't need GNU patch any more.
+
+1998-06-03 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * TESTS: Don't mention the version of Solaris; Mark Borges says
+ that it applies to Solaris 2.5 as well as 2.6.
+
+1998-06-02 Assar Westerlund <assar@sics.se>
+
+ * configure.in: Test for GSS_C_NT_HOSTBASED_SERVICE in gssapi.h.
+ * acconfig.h: Add undef for HAVE_GSS_C_NT_HOSTBASED_SERVICE.
+ * configure, config.h.in: Rebuild.
+
+1998-06-01 Assar Westerlund <assar@sics.se>
+ and Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Check for GSSAPI headers individually. Use a
+ different set of GSSPI libraries if gssapi.h rather than
+ gssapi/gssapi.h is found. Adds Heimdal support.
+ * configure, config.h.in: Rebuild.
+
+1998-05-25 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvs.spec (%description): Rewrite to be slightly more verbose
+ about the basic features. Don't try to mention what CVS lacks.
+
+1998-05-23 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * BUGS: Remove items about binary file bugs which were fixed
+ approximately 6 months ago.
+
+1998-04-28 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * TESTS: Add note about Solaris sort program (reported by Mark
+ D. Baushke).
+
+1998-03-16 Larry Jones <larry.jones@sdrc.com>
+
+ * configure.in: Simplify test for shadow password support since
+ the code now handles the case where shadow passwords are supported
+ but are not in use.
+ * configure: Regenerated.
+
+1998-03-07 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * TESTS: Remove note about SGI's XFS. Someone reports that it
+ works (I would assume due to the 13 Feb 1998, and earlier, changes
+ to sanity.sh).
+
+ * NEWS: Add item about PreservePermissions. Fix unclear wording
+ in gserver item.
+
1998-03-04 Jim Kingdon <kingdon@harvey.cyclic.com>
* acconfig.h, configure.in: Add PRESERVE_PERMISSIONS_SUPPORT and
diff --git a/contrib/cvs/INSTALL b/contrib/cvs/INSTALL
index 576f9a6f62cc..252849077f9f 100644
--- a/contrib/cvs/INSTALL
+++ b/contrib/cvs/INSTALL
@@ -118,14 +118,15 @@ HPPA:
HPPA running HP-UX 9 (1.8)
HPPA 1.1 running HP-UX A.09.03 (1.5.95) (footnote 8)
HPPA 1.1 running HP-UX A.09.04 (1.7.1)
- HPPA 9000/735 running HP-UX A.09.05 (1.8.87)
+ HPPA running HP-UX 9.05 (1.9)
HPPA running HP-UX 10.01 (1.7)
- HPPA running HP-UX 10.20 using gcc 2.7.2.2 (1.9.14)
+ HPPA running HP-UX 10.20 (1.9, 1.9.14)
NextSTEP 3.3 (1.7)
i386 family:
Solaris 2.4 using gcc (about 1.4A2)
UnixWare v1.1.1 using gcc (about 1.4A2)
Unixware 2.1 (1.8.86)
+ Unixware 7 (1.9.29)
ISC 4.0.1 (1.8.87)
Linux (kernel 1.2.x) (1.8.86)
Linux (kernel 2.0.x, RedHat 4.2) (1.9)
@@ -133,7 +134,7 @@ i386 family:
FreeBSD 2.1.5-stable (1.8.87)
NextSTEP 3.3 (1.7)
SCO Unix 3.2.4.2, gcc 2.7.2 (1.8.87) (footnote 4)
- SCO OpenServer 5 (1.8.86)
+ SCO OpenServer 5 (1.9.29)
Sequent Dynix/PTX 4.1.4 (1.9.20 or so + patches)
Lynx 2.3.0 080695 (1.6.86) (footnote 9)
Windows NT 3.51 (1.8.86 client; 1.8.3 local)
@@ -164,7 +165,7 @@ MIPS:
PowerPC or RS/6000:
IBM RS/6000 running AIX 3.1 using gcc and cc (1.6.86)
IBM RS/6000 running AIX 3.2.5 (1.8)
- IBM RS/6000 running AIX 4.1 using gcc and cc (about 1.4A2) (footnote 1)
+ IBM RS/6000 running AIX 4.1 (1.9)
Lynx 2.3.1 120495 (1.6.86) (footnote 9)
Lynx 2.5 (1.9) (footnote 10)
SPARC:
@@ -179,11 +180,6 @@ VAX:
VAX running VMS 6.2 (1.9+patches, client-only)
(see README.VMS for information on necessary hacks).
-(footnote 1)
- AIX 4.1 systems fail to run "configure" due to bugs in their
- "/bin/sh" implementation. You might want to try feeding the
- configure script to "bash" ported to AIX 4.1. (about 1.4A2).
-
(footnote 2)
Some Irix 4.0 systems may core dump in malloc while running
CVS. We believe this is a bug in the Irix malloc. You can
diff --git a/contrib/cvs/Makefile.in b/contrib/cvs/Makefile.in
index ff75cfba5b46..a7c69f16164e 100644
--- a/contrib/cvs/Makefile.in
+++ b/contrib/cvs/Makefile.in
@@ -222,7 +222,7 @@ dist: spec
${MAKE} dist-dir DISTDIR="$${DISTDIR}" \
); \
done
- tar chf${TAR_VERBOSE} - `cat .fname` | ${GZIP} > "`cat .fname`.tar${GZIP_EXT}"
+ (unset GZIP; tar chf${TAR_VERBOSE} - `cat .fname` | ${GZIP} > "`cat .fname`.tar${GZIP_EXT}")
rm -rf `cat .fname` .fname .version
.PHONY: dist-dir
diff --git a/contrib/cvs/NEWS b/contrib/cvs/NEWS
index 5e746fe6fe12..309c5105a610 100644
--- a/contrib/cvs/NEWS
+++ b/contrib/cvs/NEWS
@@ -1,8 +1,19 @@
Changes since 1.9:
+* There is a new feature, enabled by TopLevelAdmin in CVSROOT/config,
+which tells CVS to modify the behavior of the "checkout" command. The
+command now creates a CVS directory at the top level of the new
+working directory, in addition to CVS directories created within
+checked-out directories. See the Cederqvist for details.
+
+* There is an optional set of features, enabled by PreservePermissions
+in CVSROOT/config, which allow CVS to store unix-specific file
+information such as permissions, file ownership, and links. See the
+Cederqvist for details.
+
* One can now authenticate and encrypt using the GSSAPI network
-security interface. For details see the description of :gserver: in
-CVSROOT, and the -a global option.
+security interface. For details see the Cederqvist's description of
+specifying :gserver: in CVSROOT, and the -a global option.
* All access to RCS files is now implemented internally rather than by
calling RCS programs. The main user-visible consequence of this is
@@ -50,10 +61,6 @@ cvs.texinfo for details, including a discussion of security issues.
Note that the requirement that read-only users be able to create locks
and write the history file still applies.
-* The "checkout" command now creates a CVS directory at the top level
-of the new working directory, in addition to CVS directories created
-within checked-out directories.
-
* There is a new administrative file verifymsg which is like editinfo
but merely validates the message, rather than also getting it from the
user. It therefore works with client/server CVS or if one uses the -m
diff --git a/contrib/cvs/TESTS b/contrib/cvs/TESTS
index fa9697f43ad6..7281ac1a9286 100644
--- a/contrib/cvs/TESTS
+++ b/contrib/cvs/TESTS
@@ -14,13 +14,14 @@ disks are slow or over-loaded.
The tests work in /tmp/cvs-sanity (which the tests create) by default.
If for some reason you want them to work in a different directory, you
can set the TESTDIR environment variable to the desired location
-before running them. In particular, using SGI's Irix 6, the tests
-will fail if TESTDIR is an XFS filesystem (which /tmp often is);
-you'll want to set TESTDIR to a non-XFS filesystem.
+before running them.
You will probably need GNU expr, which is part of the GNU sh-utils
-package (this is just for running the tests; CVS itself doesn't use
-expr).
+package. You may also need sort from the GNU textutils; Solaris
+in particular has been reported to have a sort program which does not
+behave the way that the testsuite expects (with Solaris, lines
+starting with tabs sort before blank lines). These programs are just
+for running the tests; CVS itself doesn't require expr or sort.
If there is some unexpected output, that is a failure which can be
somewhat hard to track down. Finding out which test is producing the
diff --git a/contrib/cvs/acconfig.h b/contrib/cvs/acconfig.h
index 8ccbf8f90217..7748e28f19ab 100644
--- a/contrib/cvs/acconfig.h
+++ b/contrib/cvs/acconfig.h
@@ -4,6 +4,10 @@
/* Define if you have GSSAPI with MIT Kerberos version 5 available. */
#undef HAVE_GSSAPI
+/* Define if GSS_C_NT_HOSTBASED_SERVICE is defined in the gssapi.h
+ header file. Only relevant when using GSSAPI. */
+#undef HAVE_GSS_C_NT_HOSTBASED_SERVICE
+
/* Define if you want CVS to be able to be a remote repository client. */
#undef CLIENT_SUPPORT
diff --git a/contrib/cvs/config.h.in b/contrib/cvs/config.h.in
index af42df6b3f32..1280d2e54bd4 100644
--- a/contrib/cvs/config.h.in
+++ b/contrib/cvs/config.h.in
@@ -74,6 +74,10 @@
/* Define if you have GSSAPI with MIT Kerberos version 5 available. */
#undef HAVE_GSSAPI
+/* Define if GSS_C_NT_HOSTBASED_SERVICE is defined in the gssapi.h
+ header file. Only relevant when using GSSAPI. */
+#undef HAVE_GSS_C_NT_HOSTBASED_SERVICE
+
/* Define if you want CVS to be able to be a remote repository client. */
#undef CLIENT_SUPPORT
@@ -191,6 +195,15 @@
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
+/* Define if you have the <gssapi.h> header file. */
+#undef HAVE_GSSAPI_H
+
+/* Define if you have the <gssapi/gssapi.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_H
+
+/* Define if you have the <gssapi/gssapi_generic.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_GENERIC_H
+
/* Define if you have the <io.h> header file. */
#undef HAVE_IO_H
diff --git a/contrib/cvs/configure b/contrib/cvs/configure
index 01c0ace6d150..4fd7b5e3da06 100755
--- a/contrib/cvs/configure
+++ b/contrib/cvs/configure
@@ -2126,11 +2126,7 @@ EOF
fi
-echo $ac_n "checking for evidence of shadow passwords""... $ac_c" 1>&6
-if test -f /etc/shadow \
- || test -f /etc/security/passwd.adjunct ; then
- found="yes"
- echo $ac_n "checking for -lsec""... $ac_c" 1>&6
+echo $ac_n "checking for -lsec""... $ac_c" 1>&6
ac_lib_var=`echo sec'_'getspnam | tr './+\055' '__p_'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -2138,7 +2134,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lsec $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 2142 "configure"
+#line 2138 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -2150,7 +2146,7 @@ int t() {
getspnam()
; return 0; }
EOF
-if { (eval echo configure:2154: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2150: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -2174,14 +2170,14 @@ else
echo "$ac_t""no" 1>&6
fi
- for ac_func in getspnam
+for ac_func in getspnam
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2185 "configure"
+#line 2181 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2205,7 +2201,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2209: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2205: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2227,10 +2223,6 @@ else
fi
done
-else
- found="no"
-fi
-echo "$ac_t""$found" 1>&6
echo $ac_n "checking whether utime accepts a null argument""... $ac_c" 1>&6
if eval "test \"`echo '$''{'ac_cv_func_utime_null'+set}'`\" = set"; then
@@ -2242,7 +2234,7 @@ if test "$cross_compiling" = yes; then
ac_cv_func_utime_null=no
else
cat > conftest.$ac_ext <<EOF
-#line 2246 "configure"
+#line 2238 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -2253,7 +2245,7 @@ exit(!(stat ("conftestdata", &s) == 0 && utime("conftestdata", (long *)0) == 0
&& t.st_mtime - s.st_mtime < 120));
}
EOF
-{ (eval echo configure:2257: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+{ (eval echo configure:2249: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
ac_cv_func_utime_null=yes
else
@@ -2317,7 +2309,7 @@ else
ccvs_cv_sys_working_fnmatch=no
else
cat > conftest.$ac_ext <<EOF
-#line 2321 "configure"
+#line 2313 "configure"
#include "confdefs.h"
#include <fnmatch.h>
@@ -2329,7 +2321,7 @@ main ()
? 0 : 1);
}
EOF
-{ (eval echo configure:2333: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+{ (eval echo configure:2325: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
if test -s conftest && (./conftest; exit) 2>/dev/null; then
ccvs_cv_sys_working_fnmatch=yes
else
@@ -2354,7 +2346,7 @@ if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2358 "configure"
+#line 2350 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char connect(); below. */
@@ -2378,7 +2370,7 @@ connect();
; return 0; }
EOF
-if { (eval echo configure:2382: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2374: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_func_connect=yes"
else
@@ -2403,7 +2395,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lnsl_s $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 2407 "configure"
+#line 2399 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -2415,7 +2407,7 @@ int t() {
printf()
; return 0; }
EOF
-if { (eval echo configure:2419: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2411: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -2450,7 +2442,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lnsl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 2454 "configure"
+#line 2446 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -2462,7 +2454,7 @@ int t() {
printf()
; return 0; }
EOF
-if { (eval echo configure:2466: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2458: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -2497,7 +2489,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lsocket $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 2501 "configure"
+#line 2493 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -2509,7 +2501,7 @@ int t() {
connect()
; return 0; }
EOF
-if { (eval echo configure:2513: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2505: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -2544,7 +2536,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-linet $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 2548 "configure"
+#line 2540 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -2556,7 +2548,7 @@ int t() {
connect()
; return 0; }
EOF
-if { (eval echo configure:2560: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2552: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -2607,7 +2599,7 @@ if test "$cross_compiling" != yes && test -r $KRB4/include/krb.h; then
hold_cflags=$CFLAGS
CFLAGS="$CFLAGS -I$KRB4/include"
cat > conftest.$ac_ext <<EOF
-#line 2611 "configure"
+#line 2603 "configure"
#include "confdefs.h"
#include <krb.h>
int main() { return 0; }
@@ -2615,14 +2607,14 @@ int t() {
int i;
; return 0; }
EOF
-if { (eval echo configure:2619: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2611: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
krb_h=yes krb_incdir=$KRB4/include
else
rm -rf conftest*
CFLAGS=$hold_cflags
cat > conftest.$ac_ext <<EOF
-#line 2626 "configure"
+#line 2618 "configure"
#include "confdefs.h"
#include <krb.h>
int main() { return 0; }
@@ -2630,7 +2622,7 @@ int t() {
int i;
; return 0; }
EOF
-if { (eval echo configure:2634: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2626: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
krb_h=yes krb_incdir=
fi
@@ -2642,7 +2634,7 @@ rm -f conftest*
CFLAGS=$hold_cflags
else
cat > conftest.$ac_ext <<EOF
-#line 2646 "configure"
+#line 2638 "configure"
#include "confdefs.h"
#include <krb.h>
int main() { return 0; }
@@ -2650,7 +2642,7 @@ int t() {
int i;
; return 0; }
EOF
-if { (eval echo configure:2654: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2646: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
krb_h=yes krb_incdir=
fi
@@ -2659,7 +2651,7 @@ rm -f conftest*
fi
if test -z "$krb_h"; then
cat > conftest.$ac_ext <<EOF
-#line 2663 "configure"
+#line 2655 "configure"
#include "confdefs.h"
#include <krb.h>
int main() { return 0; }
@@ -2667,7 +2659,7 @@ int t() {
int i;
; return 0; }
EOF
-if { (eval echo configure:2671: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2663: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
krb_h=yes krb_incdir=
else
@@ -2676,7 +2668,7 @@ else
hold_cflags=$CFLAGS
CFLAGS="$CFLAGS -I$KRB4/include/kerberosIV"
cat > conftest.$ac_ext <<EOF
-#line 2680 "configure"
+#line 2672 "configure"
#include "confdefs.h"
#include <krb.h>
int main() { return 0; }
@@ -2684,7 +2676,7 @@ int t() {
int i;
; return 0; }
EOF
-if { (eval echo configure:2688: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2680: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
krb_h=yes krb_incdir=$KRB4/include/kerberosIV
fi
@@ -2713,7 +2705,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lkrb $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 2717 "configure"
+#line 2709 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -2725,7 +2717,7 @@ int t() {
printf()
; return 0; }
EOF
-if { (eval echo configure:2729: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2721: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -2752,7 +2744,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lkrb $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 2756 "configure"
+#line 2748 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -2764,7 +2756,7 @@ int t() {
open()
; return 0; }
EOF
-if { (eval echo configure:2768: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2760: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -2794,7 +2786,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lkrb $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 2798 "configure"
+#line 2790 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -2806,7 +2798,7 @@ int t() {
printf()
; return 0; }
EOF
-if { (eval echo configure:2810: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2802: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -2845,7 +2837,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ldes $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 2849 "configure"
+#line 2841 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -2857,7 +2849,7 @@ int t() {
printf()
; return 0; }
EOF
-if { (eval echo configure:2861: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2853: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -2888,7 +2880,7 @@ if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2892 "configure"
+#line 2884 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2912,7 +2904,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2916: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2908: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2945,21 +2937,22 @@ fi
echo "default place for GSSAPI is $GSSAPI"
-echo $ac_n "checking for gssapi.h""... $ac_c" 1>&6
hold_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS -I$GSSAPI/include "
-ac_safe=`echo "gssapi/gssapi.h" | tr './\055' '___'`
-echo $ac_n "checking for gssapi/gssapi.h""... $ac_c" 1>&6
+for ac_hdr in gssapi.h gssapi/gssapi.h gssapi/gssapi_generic.h
+do
+ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 2958 "configure"
+#line 2951 "configure"
#include "confdefs.h"
-#include <gssapi/gssapi.h>
+#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2963: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2956: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -2973,15 +2966,69 @@ rm -f conftest*
fi
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdefghijklmnopqrstuvwxyz./\055' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ___'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+CPPFLAGS=$hold_cppflags
+
+if test "$ac_cv_header_gssapi_h" = "yes" || test "$ac_cv_header_gssapi_gssapi_h" = "yes"; then
cat >> confdefs.h <<\EOF
#define HAVE_GSSAPI 1
EOF
- LIBS="$LIBS -L$GSSAPI/lib -lgssapi_krb5 -lkrb5 -lcrypto -lcom_err"
- includeopt="${includeopt} -I$GSSAPI/include"
- # This is necessary on Irix 5.3, in order to link against libkrb5 --
- # there, an_to_ln.o refers to things defined only in -lgen.
- echo $ac_n "checking for -lgen""... $ac_c" 1>&6
+ includeopt="${includeopt} -I$GSSAPI/include"
+ # FIXME: This is ugly, but these things don't seem to be standardized.
+ if test "$ac_cv_header_gssapi_h" = "yes"; then
+ LIBS="$LIBS -L$GSSAPI/lib -lgssapi -lkrb5 -lasn1 -ldes -lroken"
+ else
+ LIBS="$LIBS -L$GSSAPI/lib -lgssapi_krb5 -lkrb5 -lcrypto -lcom_err"
+ fi
+ save_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="-I$GSSAPI/include $CPPFLAGS"
+ if test "$ac_cv_header_gssapi_h" = "yes"; then
+ cat > conftest.$ac_ext <<EOF
+#line 2998 "configure"
+#include "confdefs.h"
+#include <gssapi.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "GSS_C_NT_HOSTBASED_SERVICE" >/dev/null 2>&1; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_GSS_C_NT_HOSTBASED_SERVICE 1
+EOF
+
+fi
+rm -f conftest*
+
+ else
+ cat > conftest.$ac_ext <<EOF
+#line 3014 "configure"
+#include "confdefs.h"
+#include <gssapi/gssapi.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "GSS_C_NT_HOSTBASED_SERVICE" >/dev/null 2>&1; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_GSS_C_NT_HOSTBASED_SERVICE 1
+EOF
+
+fi
+rm -f conftest*
+
+ fi
+ CPPFLAGS=$save_CPPFLAGS
+ # This is necessary on Irix 5.3, in order to link against libkrb5 --
+ # there, an_to_ln.o refers to things defined only in -lgen.
+ echo $ac_n "checking for -lgen""... $ac_c" 1>&6
ac_lib_var=`echo gen'_'compile | tr './+\055' '__p_'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -2989,7 +3036,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lgen $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 2993 "configure"
+#line 3040 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -3001,7 +3048,7 @@ int t() {
compile()
; return 0; }
EOF
-if { (eval echo configure:3005: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:3052: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -3025,12 +3072,8 @@ else
echo "$ac_t""no" 1>&6
fi
-else
- echo "$ac_t""no" 1>&6
fi
-CPPFLAGS=$hold_cppflags
-
# Check whether --enable-encryption or --disable-encryption was given.
if test "${enable_encryption+set}" = set; then
enableval="$enable_encryption"
@@ -3055,7 +3098,7 @@ if eval "test \"`echo '$''{'ac_cv_func_gethostname'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3059 "configure"
+#line 3102 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char gethostname(); below. */
@@ -3079,7 +3122,7 @@ gethostname();
; return 0; }
EOF
-if { (eval echo configure:3083: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:3126: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_func_gethostname=yes"
else
@@ -3156,7 +3199,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lcrypt $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 3160 "configure"
+#line 3203 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -3168,7 +3211,7 @@ int t() {
crypt()
; return 0; }
EOF
-if { (eval echo configure:3172: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:3215: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -3199,7 +3242,7 @@ if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3203 "configure"
+#line 3246 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -3223,7 +3266,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:3227: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:3270: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -3264,7 +3307,7 @@ if eval "test \"`echo '$''{'ccvs_cv_sys_cygwin32'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 3268 "configure"
+#line 3311 "configure"
#include "confdefs.h"
int main() { return 0; }
@@ -3272,7 +3315,7 @@ int t() {
return __CYGWIN32__;
; return 0; }
EOF
-if { (eval echo configure:3276: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3319: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ccvs_cv_sys_cygwin32=yes
else
diff --git a/contrib/cvs/configure.in b/contrib/cvs/configure.in
index b848ab6f1dde..29070257b743 100644
--- a/contrib/cvs/configure.in
+++ b/contrib/cvs/configure.in
@@ -91,24 +91,13 @@ AC_FUNC_VFORK
AC_FUNC_CLOSEDIR_VOID
dnl
-dnl Look for shadow password files before we go ahead and set getspnam.
-dnl On some systems (Linux), the C library has getspnam but shadow
-dnl passwords might not be in use.
+dnl Check for shadow password support.
dnl
-dnl We used to check for the existence of the /etc/security directory
-dnl here, but that's incorrect, since it's possible to have PAM installed
-dnl without using shadow passwords.
-dnl
-AC_MSG_CHECKING([for evidence of shadow passwords])
-if test -f /etc/shadow \
- || test -f /etc/security/passwd.adjunct ; then
- found="yes"
- AC_CHECK_LIB(sec, getspnam)
- AC_CHECK_FUNCS(getspnam)
-else
- found="no"
-fi
-AC_MSG_RESULT([$found])
+dnl We used to try to determine whether shadow passwords were actually in
+dnl use or not, but the code has been changed to work right reguardless,
+dnl so we can go back to a simple check.
+AC_CHECK_LIB(sec, getspnam)
+AC_CHECK_FUNCS(getspnam)
dnl We always use CVS's regular expression matcher.
dnl This is because:
@@ -271,18 +260,33 @@ echo "default place for GSSAPI is $GSSAPI"
AC_SUBST(GSSAPI)])dnl
WITH_GSSAPI
-AC_MSG_CHECKING([for gssapi.h])
hold_cppflags=$CPPFLAGS
CPPFLAGS="$CPPFLAGS -I$GSSAPI/include "
-AC_CHECK_HEADER(gssapi/gssapi.h,
- [AC_DEFINE(HAVE_GSSAPI)
- LIBS="$LIBS -L$GSSAPI/lib -lgssapi_krb5 -lkrb5 -lcrypto -lcom_err"
- includeopt="${includeopt} -I$GSSAPI/include"
- # This is necessary on Irix 5.3, in order to link against libkrb5 --
- # there, an_to_ln.o refers to things defined only in -lgen.
- AC_CHECK_LIB(gen, compile)])
+AC_CHECK_HEADERS(gssapi.h gssapi/gssapi.h gssapi/gssapi_generic.h)
CPPFLAGS=$hold_cppflags
+if test "$ac_cv_header_gssapi_h" = "yes" || test "$ac_cv_header_gssapi_gssapi_h" = "yes"; then
+ AC_DEFINE(HAVE_GSSAPI)
+ includeopt="${includeopt} -I$GSSAPI/include"
+ # FIXME: This is ugly, but these things don't seem to be standardized.
+ if test "$ac_cv_header_gssapi_h" = "yes"; then
+ LIBS="$LIBS -L$GSSAPI/lib -lgssapi -lkrb5 -lasn1 -ldes -lroken"
+ else
+ LIBS="$LIBS -L$GSSAPI/lib -lgssapi_krb5 -lkrb5 -lcrypto -lcom_err"
+ fi
+ save_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="-I$GSSAPI/include $CPPFLAGS"
+ if test "$ac_cv_header_gssapi_h" = "yes"; then
+ AC_EGREP_HEADER(GSS_C_NT_HOSTBASED_SERVICE, gssapi.h, AC_DEFINE(HAVE_GSS_C_NT_HOSTBASED_SERVICE))
+ else
+ AC_EGREP_HEADER(GSS_C_NT_HOSTBASED_SERVICE, gssapi/gssapi.h, AC_DEFINE(HAVE_GSS_C_NT_HOSTBASED_SERVICE))
+ fi
+ CPPFLAGS=$save_CPPFLAGS
+ # This is necessary on Irix 5.3, in order to link against libkrb5 --
+ # there, an_to_ln.o refers to things defined only in -lgen.
+ AC_CHECK_LIB(gen, compile)
+fi
+
dnl
dnl Use --with-encryption to turn on encryption support
dnl
diff --git a/contrib/cvs/contrib/ChangeLog b/contrib/cvs/contrib/ChangeLog
index e0d87e14a103..8bf96a16b541 100644
--- a/contrib/cvs/contrib/ChangeLog
+++ b/contrib/cvs/contrib/ChangeLog
@@ -1,3 +1,7 @@
+1998-05-11 W. Bradley Rubenstein
+
+ * log.pl: Check for errors from open and exec.
+
Sat Feb 21 21:59:45 1998 Ian Lance Taylor <ian@cygnus.com>
* Makefile.in (clean): Change "/bin/rm" to "rm".
diff --git a/contrib/cvs/contrib/log.pl b/contrib/cvs/contrib/log.pl
index e4fb9b1d3fbc..f1d66e3db02a 100644
--- a/contrib/cvs/contrib/log.pl
+++ b/contrib/cvs/contrib/log.pl
@@ -145,7 +145,16 @@ if ($dostatus != 0) {
}
last;
}
- open(RCS, "-|") || exec 'cvs', '-nQq', 'status', '-v', $file;
+ $pid = open(RCS, "-|");
+ if ( !defined $pid )
+ {
+ die "fork failed: $!";
+ }
+ if ($pid == 0)
+ {
+ exec 'cvs', '-nQq', 'status', '-v', $file;
+ die "cvs exec failed: $!";
+ }
while (<RCS>) {
print OUT;
if (MAIL) {
diff --git a/contrib/cvs/diff/ChangeLog b/contrib/cvs/diff/ChangeLog
index 34aa7077b8c4..3ebde5df9d07 100644
--- a/contrib/cvs/diff/ChangeLog
+++ b/contrib/cvs/diff/ChangeLog
@@ -1,3 +1,56 @@
+1998-08-06 David Masterson of kla-tencor.com
+
+ * util.c (flush_output): Don't prototype.
+
+Thu Jul 2 16:34:38 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ Simplify the callback interface:
+ * diffrun.h: Don't include <stdarg.h> or <varargs.h>.
+ (struct diff_callbacks): Remove printf_output field.
+ * util.c: Include <stdarg.h> or <varargs.h>.
+ (printf_output): Use vasprintf and write_output callback rather
+ than printf_output callback.
+ * diff3.c (read_diff): Don't set my_callbacks.printf_output.
+
+Thu Jun 18 12:43:53 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * diffrun.h: New file.
+ * diff.h: Include diffrun.h.
+ (callbacks): New EXTERN variable.
+ (write_output, printf_output, flush_output): Declare.
+ * diff.c (diff_run): Add parameter callbacks_arg. Use callback
+ functions rather than writing to stdout. Don't open a file if
+ there is a write_output callback. Call perror_with_name rather
+ than perror.
+ (usage): Use callbacks if defined rather than writing to stdout.
+ (compare_files): Call flush_output rather than fflush (outfile).
+ * diff3.c: Include diffrun.h. Change several functions to use
+ output functions from util.c rather than direct printing. Use
+ diff_error and friends rather than printing to stderr. Set global
+ variable outfile.
+ (outfile, callbacks): Declare.
+ (write_output, printf_output, flush_output): Declare.
+ (diff3_run): Add parameter callbacks_arg. Use callback functions
+ rather than writing to stdout.
+ (usage): Use callbacks if defined rather than writing to stdout.
+ (read_diff): Preserve callbacks and outfile around call to
+ diff_run.
+ * util.c (perror_with_name): Use error callback if defined.
+ (pfatal_with_name, diff_error): Likewise.
+ (message5): Use printf_output and write_output.
+ (print_message_queue, print_1_line, output_1_line): Likewise.
+ (begin_output): Reject paginate_flag if there are output
+ callbacks.
+ (write_output, printf_output, flush_output): New functions.
+ * context.c: Change all output to outfile to use printf_output and
+ write_output.
+ * ed.c: Likewise.
+ * ifdef.c: Likewise.
+ * normal.c: Likewise.
+ * side.c: Likewise.
+ * Makefile.in (SOURCES): Add diffrun.h.
+ ($(OBJECTS)): Depend upon diffrun.h.
+
Fri Jan 16 14:58:19 1998 Larry Jones <larry.jones@sdrc.com>
* diff.c, diff3.c: Plug memory leaks.
diff --git a/contrib/cvs/diff/Makefile.in b/contrib/cvs/diff/Makefile.in
index 333d4d9251d0..b47d4c1ed15d 100644
--- a/contrib/cvs/diff/Makefile.in
+++ b/contrib/cvs/diff/Makefile.in
@@ -1,5 +1,5 @@
# Makefile for GNU DIFF
-# Copyright (C) 1988,1989,1991,1992,1993,1994,1997 Free Software Foundation, Inc.
+# Copyright (C) 1988,1989,1991,1992,1993,1994,1997,1998 Free Software Foundation, Inc.
#
# This file is part of GNU DIFF.
#
@@ -43,7 +43,8 @@ SHELL = /bin/sh
# The source files for all of the programs.
SOURCES = diff.c diff3.c analyze.c cmpbuf.c cmpbuf.h io.c context.c ed.c \
- normal.c ifdef.c util.c dir.c version.c diff.h side.c system.h
+ normal.c ifdef.c util.c dir.c version.c diff.h side.c system.h \
+ diffrun.h
OBJECTS = diff.o diff3.o analyze.o cmpbuf.o dir.o io.o util.o \
context.o ed.o ifdef.o normal.o side.o version.o
DISTFILES = $(SOURCES) ChangeLog build_diff.com Makefile.in
@@ -66,7 +67,7 @@ libdiff libdiff.a: $(OBJECTS)
$(AR) cr libdiff.a $(OBJECTS)
-$(RANLIB) libdiff.a
-$(OBJECTS): diff.h system.h
+$(OBJECTS): diff.h diffrun.h system.h
analyze.o cmpbuf.o: cmpbuf.h
util.o: util.c
diff --git a/contrib/cvs/diff/context.c b/contrib/cvs/diff/context.c
index 14f950c52699..e843734f45cf 100644
--- a/contrib/cvs/diff/context.c
+++ b/contrib/cvs/diff/context.c
@@ -1,5 +1,5 @@
/* Context-format output routines for GNU DIFF.
- Copyright (C) 1988,1989,1991,1992,1993,1994 Free Software Foundation, Inc.
+ Copyright (C) 1988,1989,1991,1992,1993,1994,1998 Free Software Foundation, Inc.
This file is part of GNU DIFF.
@@ -43,14 +43,14 @@ print_context_label (mark, inf, label)
char const *label;
{
if (label)
- fprintf (outfile, "%s %s\n", mark, label);
+ printf_output ("%s %s\n", mark, label);
else
{
char const *ct = ctime (&inf->stat.st_mtime);
if (!ct)
ct = "?\n";
/* See Posix.2 section 4.17.6.1.4 for this format. */
- fprintf (outfile, "%s %s\t%s", mark, inf->name, ct);
+ printf_output ("%s %s\t%s", mark, inf->name, ct);
}
}
@@ -116,9 +116,9 @@ print_context_number_range (file, a, b)
In this case, we should print the line number before the range,
which is B. */
if (trans_b > trans_a)
- fprintf (outfile, "%d,%d", trans_a, trans_b);
+ printf_output ("%d,%d", trans_a, trans_b);
else
- fprintf (outfile, "%d", trans_b);
+ printf_output ("%d", trans_b);
}
/* Print a portion of an edit script in context format.
@@ -137,7 +137,6 @@ pr_context_hunk (hunk)
char const *prefix;
char const *function;
size_t function_length;
- FILE *out;
/* Determine range of line numbers involved in each file. */
@@ -160,21 +159,20 @@ pr_context_hunk (hunk)
find_function (&files[0], first0, &function, &function_length);
begin_output ();
- out = outfile;
/* If we looked for and found a function this is part of,
include its name in the header of the diff section. */
- fprintf (out, "***************");
+ printf_output ("***************");
if (function)
{
- fprintf (out, " ");
- fwrite (function, 1, min (function_length - 1, 40), out);
+ printf_output (" ");
+ write_output (function, min (function_length - 1, 40));
}
- fprintf (out, "\n*** ");
+ printf_output ("\n*** ");
print_context_number_range (&files[0], first0, last0);
- fprintf (out, " ****\n");
+ printf_output (" ****\n");
if (show_from)
{
@@ -201,9 +199,9 @@ pr_context_hunk (hunk)
}
}
- fprintf (out, "--- ");
+ printf_output ("--- ");
print_context_number_range (&files[1], first1, last1);
- fprintf (out, " ----\n");
+ printf_output (" ----\n");
if (show_to)
{
@@ -250,9 +248,9 @@ print_unidiff_number_range (file, a, b)
In this case, we should print the line number before the range,
which is B. */
if (trans_b <= trans_a)
- fprintf (outfile, trans_b == trans_a ? "%d" : "%d,0", trans_b);
+ printf_output (trans_b == trans_a ? "%d" : "%d,0", trans_b);
else
- fprintf (outfile, "%d,%d", trans_a, trans_b - trans_a + 1);
+ printf_output ("%d,%d", trans_a, trans_b - trans_a + 1);
}
/* Print a portion of an edit script in unidiff format.
@@ -270,7 +268,6 @@ pr_unidiff_hunk (hunk)
struct change *next;
char const *function;
size_t function_length;
- FILE *out;
/* Determine range of line numbers involved in each file. */
@@ -293,23 +290,22 @@ pr_unidiff_hunk (hunk)
find_function (&files[0], first0, &function, &function_length);
begin_output ();
- out = outfile;
- fprintf (out, "@@ -");
+ printf_output ("@@ -");
print_unidiff_number_range (&files[0], first0, last0);
- fprintf (out, " +");
+ printf_output (" +");
print_unidiff_number_range (&files[1], first1, last1);
- fprintf (out, " @@");
+ printf_output (" @@");
/* If we looked for and found a function this is part of,
include its name in the header of the diff section. */
if (function)
{
- putc (' ', out);
- fwrite (function, 1, min (function_length - 1, 40), out);
+ write_output (" ", 1);
+ write_output (function, min (function_length - 1, 40));
}
- putc ('\n', out);
+ write_output ("\n", 1);
next = hunk;
i = first0;
@@ -322,7 +318,7 @@ pr_unidiff_hunk (hunk)
if (!next || i < next->line0)
{
- putc (tab_align_flag ? '\t' : ' ', out);
+ write_output (tab_align_flag ? "\t" : " ", 1);
print_1_line (0, &files[0].linbuf[i++]);
j++;
}
@@ -333,9 +329,9 @@ pr_unidiff_hunk (hunk)
k = next->deleted;
while (k--)
{
- putc ('-', out);
+ write_output ("-", 1);
if (tab_align_flag)
- putc ('\t', out);
+ write_output ("\t", 1);
print_1_line (0, &files[0].linbuf[i++]);
}
@@ -344,9 +340,9 @@ pr_unidiff_hunk (hunk)
k = next->inserted;
while (k--)
{
- putc ('+', out);
+ write_output ("+", 1);
if (tab_align_flag)
- putc ('\t', out);
+ write_output ("\t", 1);
print_1_line (0, &files[1].linbuf[j++]);
}
diff --git a/contrib/cvs/diff/diff.c b/contrib/cvs/diff/diff.c
index c0e37d7d4212..3467b537aeca 100644
--- a/contrib/cvs/diff/diff.c
+++ b/contrib/cvs/diff/diff.c
@@ -1,5 +1,5 @@
/* GNU DIFF entry routine.
- Copyright (C) 1988, 1989, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1992, 1993, 1994, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU DIFF.
@@ -231,10 +231,11 @@ static struct option const longopts[] =
};
int
-diff_run (argc, argv, out)
+diff_run (argc, argv, out, callbacks_arg)
int argc;
char *argv[];
char *out;
+ const struct diff_callbacks *callbacks_arg;
{
int val;
int c;
@@ -242,6 +243,9 @@ diff_run (argc, argv, out)
int width = DEFAULT_WIDTH;
int show_c_function = 0;
int optind_old;
+ int opened_file = 0;
+
+ callbacks = callbacks_arg;
/* Do our initializations. */
initialize_main (&argc, &argv);
@@ -476,7 +480,14 @@ diff_run (argc, argv, out)
break;
case 'v':
- printf ("diff - GNU diffutils version %s\n", diff_version_string);
+ if (callbacks && callbacks->write_stdout)
+ {
+ (*callbacks->write_stdout) ("diff - GNU diffutils version ");
+ (*callbacks->write_stdout) (diff_version_string);
+ (*callbacks->write_stdout) ("\n");
+ }
+ else
+ printf ("diff - GNU diffutils version %s\n", diff_version_string);
return 0;
case 'w':
@@ -555,7 +566,8 @@ diff_run (argc, argv, out)
case 141:
usage ();
- check_output (stdout);
+ if (! callbacks || ! callbacks->write_stdout)
+ check_output (stdout);
return 0;
case 142:
@@ -645,23 +657,35 @@ diff_run (argc, argv, out)
switch_string = option_list (argv + 1, optind - 1);
- if (out == NULL)
- outfile = stdout;
+ if (callbacks && callbacks->write_output)
+ {
+ if (out != NULL)
+ {
+ diff_error ("write callback with output file", 0, 0);
+ return 2;
+ }
+ }
else
{
-#if HAVE_SETMODE
- /* A diff which is full of ^Z and such isn't going to work
- very well in text mode. */
- if (binary_I_O)
- outfile = fopen (out, "wb");
+ if (out == NULL)
+ outfile = stdout;
else
+ {
+#if HAVE_SETMODE
+ /* A diff which is full of ^Z and such isn't going to work
+ very well in text mode. */
+ if (binary_I_O)
+ outfile = fopen (out, "wb");
+ else
#endif
- outfile = fopen (out, "w");
- if (outfile == NULL)
- {
- perror_with_name ("could not open output file");
- return 2;
- }
+ outfile = fopen (out, "w");
+ if (outfile == NULL)
+ {
+ perror_with_name ("could not open output file");
+ return 2;
+ }
+ opened_file = 1;
+ }
}
/* Set the jump buffer, so that diff may abort execution without
@@ -669,7 +693,7 @@ diff_run (argc, argv, out)
if ((val = setjmp (diff_abort_buf)) != 0)
{
optind = optind_old;
- if (outfile != stdout)
+ if (opened_file)
fclose (outfile);
return val;
}
@@ -682,10 +706,14 @@ diff_run (argc, argv, out)
free (switch_string);
optind = optind_old;
- check_output (outfile);
- if (outfile != stdout)
+
+ if (! callbacks || ! callbacks->write_output)
+ check_output (outfile);
+
+ if (opened_file)
if (fclose (outfile) != 0)
- perror ("close error on output file");
+ perror_with_name ("close error on output file");
+
return val;
}
@@ -799,10 +827,27 @@ usage ()
{
char const * const *p;
- printf ("Usage: %s [OPTION]... FILE1 FILE2\n\n", diff_program_name);
- for (p = option_help; *p; p++)
- printf (" %s\n", *p);
- printf ("\nIf FILE1 or FILE2 is `-', read standard input.\n");
+ if (callbacks && callbacks->write_stdout)
+ {
+ (*callbacks->write_stdout) ("Usage: ");
+ (*callbacks->write_stdout) (diff_program_name);
+ (*callbacks->write_stdout) (" [OPTION]... FILE1 FILE2\n\n");
+ for (p = option_help; *p; p++)
+ {
+ (*callbacks->write_stdout) (" ");
+ (*callbacks->write_stdout) (*p);
+ (*callbacks->write_stdout) ("\n");
+ }
+ (*callbacks->write_stdout)
+ ("\nIf FILE1 or FILE2 is `-', read standard input.\n");
+ }
+ else
+ {
+ printf ("Usage: %s [OPTION]... FILE1 FILE2\n\n", diff_program_name);
+ for (p = option_help; *p; p++)
+ printf (" %s\n", *p);
+ printf ("\nIf FILE1 or FILE2 is `-', read standard input.\n");
+ }
}
static int
@@ -1147,7 +1192,7 @@ compare_files (dir0, name0, dir1, name1, depth)
inf[0].name, inf[1].name);
}
else
- fflush (outfile);
+ flush_output ();
if (free0)
free (free0);
diff --git a/contrib/cvs/diff/diff.h b/contrib/cvs/diff/diff.h
index fba26a7bf076..6107e6221fb1 100644
--- a/contrib/cvs/diff/diff.h
+++ b/contrib/cvs/diff/diff.h
@@ -1,5 +1,5 @@
/* Shared definitions for GNU DIFF
- Copyright (C) 1988, 89, 91, 92, 93, 97 Free Software Foundation, Inc.
+ Copyright (C) 1988, 89, 91, 92, 93, 97, 1998 Free Software Foundation, Inc.
This file is part of GNU DIFF.
@@ -21,6 +21,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <setjmp.h>
#include "regex.h"
+#include "diffrun.h"
#define TAB_WIDTH 8
@@ -32,6 +33,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define EXTERN
#endif
+/* The callbacks to use for output. */
+EXTERN const struct diff_callbacks *callbacks;
+
enum output_style {
/* Default output style. */
OUTPUT_NORMAL,
@@ -329,6 +333,13 @@ void debug_script PARAMS((struct change *));
void diff_error PARAMS((char const *, char const *, char const *));
void fatal PARAMS((char const *));
void finish_output PARAMS((void));
+void write_output PARAMS((char const *, size_t));
+void printf_output PARAMS((char const *, ...))
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 6)
+ __attribute__ ((__format__ (__printf__, 1, 2)))
+#endif
+ ;
+void flush_output PARAMS((void));
void message PARAMS((char const *, char const *, char const *));
void message5 PARAMS((char const *, char const *, char const *, char const *, char const *));
void output_1_line PARAMS((char const *, char const *, char const *, char const *));
diff --git a/contrib/cvs/diff/diff3.c b/contrib/cvs/diff/diff3.c
index 533214c436b1..64867f48f230 100644
--- a/contrib/cvs/diff/diff3.c
+++ b/contrib/cvs/diff/diff3.c
@@ -1,5 +1,5 @@
/* Three way file comparison program (diff3) for Project GNU.
- Copyright (C) 1988, 1989, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1992, 1993, 1994, 1997, 1998 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
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <setjmp.h>
#include "getopt.h"
+#include "diffrun.h"
/* diff3.c has a real initialize_main function. */
#ifdef initialize_main
@@ -30,6 +31,18 @@
extern char const diff_version_string[];
+extern FILE *outfile;
+
+extern const struct diff_callbacks *callbacks;
+
+void write_output PARAMS((char const *, size_t));
+void printf_output PARAMS((char const *, ...))
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 6)
+ __attribute__ ((__format__ (__printf__, 1, 2)))
+#endif
+ ;
+void flush_output PARAMS((void));
+
/*
* Internal data structures and macros for the diff3 program; includes
* data structures for both diff3 diffs and normal diffs.
@@ -186,9 +199,9 @@ static char *scan_diff_line PARAMS((char *, char **, size_t *, char *, int));
static enum diff_type process_diff_control PARAMS((char **, struct diff_block *));
static int compare_line_list PARAMS((char * const[], size_t const[], char * const[], size_t const[], int));
static int copy_stringlist PARAMS((char * const[], size_t const[], char *[], size_t[], int));
-static int dotlines PARAMS((FILE *, struct diff3_block *, int));
-static int output_diff3_edscript PARAMS((FILE *, struct diff3_block *, int const[3], int const[3], char const *, char const *, char const *));
-static int output_diff3_merge PARAMS((FILE *, FILE *, struct diff3_block *, int const[3], int const[3], char const *, char const *, char const *));
+static int dotlines PARAMS((struct diff3_block *, int));
+static int output_diff3_edscript PARAMS((struct diff3_block *, int const[3], int const[3], char const *, char const *, char const *));
+static int output_diff3_merge PARAMS((FILE *, struct diff3_block *, int const[3], int const[3], char const *, char const *, char const *));
static size_t myread PARAMS((int, char *, size_t));
static struct diff3_block *create_diff3_block PARAMS((int, int, int, int, int, int));
static struct diff3_block *make_3way_diff PARAMS((struct diff_block *, struct diff_block *));
@@ -197,17 +210,16 @@ static struct diff3_block *using_to_diff3_block PARAMS((struct diff_block *[2],
static struct diff_block *process_diff PARAMS((char const *, char const *, struct diff_block **, char **));
static void check_output PARAMS((FILE *));
static void diff3_fatal PARAMS((char const *));
-static void output_diff3 PARAMS((FILE *, struct diff3_block *, int const[3], int const[3]));
+static void output_diff3 PARAMS((struct diff3_block *, int const[3], int const[3]));
static void diff3_perror_with_exit PARAMS((char const *));
static int try_help PARAMS((char const *));
-static void undotlines PARAMS((FILE *, int, int, int));
+static void undotlines PARAMS((int, int, int));
static void usage PARAMS((void));
static void initialize_main PARAMS((int *, char ***));
static void free_diff_blocks PARAMS((struct diff_block *));
static void free_diff3_blocks PARAMS((struct diff3_block *));
/* Functions provided in libdiff.a or other external sources. */
-int diff_run PARAMS((int, char **, char *));
VOID *xmalloc PARAMS((size_t));
VOID *xrealloc PARAMS((VOID *, size_t));
void perror_with_name PARAMS((char const *));
@@ -238,10 +250,11 @@ static struct option const longopts[] =
* combines the two diffs, and outputs them.
*/
int
-diff3_run (argc, argv, outfile)
+diff3_run (argc, argv, out, callbacks_arg)
int argc;
char **argv;
- char *outfile;
+ char *out;
+ const struct diff_callbacks *callbacks_arg;
{
int c, i;
int mapping[3];
@@ -258,7 +271,9 @@ diff3_run (argc, argv, outfile)
char **file;
struct stat statb;
int optind_old;
- FILE *outstream;
+ int opened_file = 0;
+
+ callbacks = callbacks_arg;
initialize_main (&argc, &argv);
@@ -303,11 +318,19 @@ diff3_run (argc, argv, outfile)
tab_align_flag = 1;
break;
case 'v':
- printf ("diff3 - GNU diffutils version %s\n", diff_version_string);
+ if (callbacks && callbacks->write_stdout)
+ {
+ (*callbacks->write_stdout) ("diff3 - GNU diffutils version ");
+ (*callbacks->write_stdout) (diff_version_string);
+ (*callbacks->write_stdout) ("\n");
+ }
+ else
+ printf ("diff3 - GNU diffutils version %s\n", diff_version_string);
return 0;
case 129:
usage ();
- check_output (stdout);
+ if (! callbacks || ! callbacks->write_stdout)
+ check_output (stdout);
return 0;
case 'L':
/* Handle up to three -L options. */
@@ -383,22 +406,33 @@ diff3_run (argc, argv, outfile)
}
else if (S_ISDIR(statb.st_mode))
{
- fprintf (stderr, "%s: %s: Is a directory\n",
- diff_program_name, file[i]);
+ diff_error ("%s: Is a directory", file[i], 0);
return 2;
}
}
- if (outfile == NULL)
- outstream = stdout;
- else
+ if (callbacks && callbacks->write_output)
{
- outstream = fopen (outfile, "w");
- if (outstream == NULL)
- {
- perror_with_name ("could not open output file");
+ if (out != NULL)
+ {
+ diff_error ("write callback with output file", 0, 0);
return 2;
- }
+ }
+ }
+ else
+ {
+ if (out == NULL)
+ outfile = stdout;
+ else
+ {
+ outfile = fopen (out, "w");
+ if (outfile == NULL)
+ {
+ perror_with_name ("could not open output file");
+ return 2;
+ }
+ opened_file = 1;
+ }
}
/* Set the jump buffer, so that diff may abort execution without
@@ -421,21 +455,21 @@ diff3_run (argc, argv, outfile)
diff3 = make_3way_diff (thread0, thread1);
if (edscript)
conflicts_found
- = output_diff3_edscript (outstream, diff3, mapping, rev_mapping,
+ = output_diff3_edscript (diff3, mapping, rev_mapping,
tag_strings[0], tag_strings[1], tag_strings[2]);
else if (merge)
{
if (! freopen (file[rev_mapping[FILE0]], "r", stdin))
diff3_perror_with_exit (file[rev_mapping[FILE0]]);
conflicts_found
- = output_diff3_merge (stdin, outstream, diff3, mapping, rev_mapping,
+ = output_diff3_merge (stdin, diff3, mapping, rev_mapping,
tag_strings[0], tag_strings[1], tag_strings[2]);
if (ferror (stdin))
diff3_fatal ("read error");
}
else
{
- output_diff3 (outstream, diff3, mapping, rev_mapping);
+ output_diff3 (diff3, mapping, rev_mapping);
conflicts_found = 0;
}
@@ -445,10 +479,13 @@ diff3_run (argc, argv, outfile)
free_diff_blocks(thread1);
free_diff3_blocks(diff3);
- check_output (outstream);
- if (outstream != stdout)
- if (fclose (outstream) != 0)
- perror ("close error on output file");
+ if (! callbacks || ! callbacks->write_output)
+ check_output (outfile);
+
+ if (opened_file)
+ if (fclose (outfile) != 0)
+ perror_with_name ("close error on output file");
+
return conflicts_found;
}
@@ -457,9 +494,8 @@ try_help (reason)
char const *reason;
{
if (reason)
- fprintf (stderr, "%s: %s\n", diff_program_name, reason);
- fprintf (stderr, "%s: Try `%s --help' for more information.\n",
- diff_program_name, diff_program_name);
+ diff_error ("%s", reason, 0);
+ diff_error ("Try `%s --help' for more information.", diff_program_name, 0);
return 2;
}
@@ -477,25 +513,52 @@ check_output (stream)
static void
usage ()
{
- printf ("Usage: %s [OPTION]... MYFILE OLDFILE YOURFILE\n\n", diff_program_name);
+ if (callbacks && callbacks->write_stdout)
+ {
+ (*callbacks->write_stdout) ("Usage: ");
+ (*callbacks->write_stdout) (diff_program_name);
+ (*callbacks->write_stdout) (" [OPTION]... MYFILE OLDFILE YOURFILE\n\n");
- printf ("%s", "\
+ (*callbacks->write_stdout) ("\
-e --ed Output unmerged changes from OLDFILE to YOURFILE into MYFILE.\n\
-E --show-overlap Output unmerged changes, bracketing conflicts.\n\
-A --show-all Output all changes, bracketing conflicts.\n\
-x --overlap-only Output overlapping changes.\n\
-X Output overlapping changes, bracketing them.\n\
-3 --easy-only Output unmerged nonoverlapping changes.\n\n");
- printf ("%s", "\
+ (*callbacks->write_stdout) ("\
-m --merge Output merged file instead of ed script (default -A).\n\
-L LABEL --label=LABEL Use LABEL instead of file name.\n\
-i Append `w' and `q' commands to ed scripts.\n\
-a --text Treat all files as text.\n\
-T --initial-tab Make tabs line up by prepending a tab.\n\n");
- printf ("%s", "\
+ (*callbacks->write_stdout) ("\
-v --version Output version info.\n\
--help Output this help.\n\n");
- printf ("If a FILE is `-', read standard input.\n");
+ (*callbacks->write_stdout) ("If a FILE is `-', read standard input.\n");
+ }
+ else
+ {
+ printf ("Usage: %s [OPTION]... MYFILE OLDFILE YOURFILE\n\n", diff_program_name);
+
+ printf ("%s", "\
+ -e --ed Output unmerged changes from OLDFILE to YOURFILE into MYFILE.\n\
+ -E --show-overlap Output unmerged changes, bracketing conflicts.\n\
+ -A --show-all Output all changes, bracketing conflicts.\n\
+ -x --overlap-only Output overlapping changes.\n\
+ -X Output overlapping changes, bracketing them.\n\
+ -3 --easy-only Output unmerged nonoverlapping changes.\n\n");
+ printf ("%s", "\
+ -m --merge Output merged file instead of ed script (default -A).\n\
+ -L LABEL --label=LABEL Use LABEL instead of file name.\n\
+ -i Append `w' and `q' commands to ed scripts.\n\
+ -a --text Treat all files as text.\n\
+ -T --initial-tab Make tabs line up by prepending a tab.\n\n");
+ printf ("%s", "\
+ -v --version Output version info.\n\
+ --help Output this help.\n\n");
+ printf ("If a FILE is `-', read standard input.\n");
+ }
}
/*
@@ -1011,12 +1074,13 @@ process_diff (filea, fileb, last_block, diff_contents)
dt = process_diff_control (&scan_diff, bptr);
if (dt == ERROR || *scan_diff != '\n')
{
- fprintf (stderr, "%s: diff error: ", diff_program_name);
- do
- {
- putc (*scan_diff, stderr);
- }
- while (*scan_diff++ != '\n');
+ char *serr;
+
+ for (serr = scan_diff; *serr != '\n'; serr++)
+ ;
+ *serr = '\0';
+ diff_error ("diff error: %s", scan_diff, 0);
+ *serr = '\n';
DIFF3_ABORT (2);
}
scan_diff++;
@@ -1185,6 +1249,10 @@ read_diff (filea, fileb, output_placement)
size_t bytes, current_chunk_size, total;
int fd, wstatus;
struct stat pipestat;
+ FILE *outfile_hold;
+ const struct diff_callbacks *callbacks_hold;
+ struct diff_callbacks my_callbacks;
+ struct diff_callbacks *my_callbacks_arg;
/* 302 / 1000 is log10(2.0) rounded up. Subtract 1 for the sign bit;
add 1 for integer division truncation; add 1 more for a minus sign. */
@@ -1207,7 +1275,30 @@ read_diff (filea, fileb, output_placement)
*ap = 0;
diffout = tmpnam(NULL);
- wstatus = diff_run (ap - argv, (char **) argv, diffout);
+
+ outfile_hold = outfile;
+ callbacks_hold = callbacks;
+
+ /* We want to call diff_run preserving any stdout and stderr
+ callbacks, but discarding any callbacks to handle file output,
+ since we want the file output to go to our temporary file.
+ FIXME: We should use callbacks to just read it into a memory
+ buffer; that's we do with the temporary file just below anyhow. */
+ if (callbacks == NULL)
+ my_callbacks_arg = NULL;
+ else
+ {
+ my_callbacks = *callbacks;
+ my_callbacks.write_output = NULL;
+ my_callbacks.flush_output = NULL;
+ my_callbacks_arg = &my_callbacks;
+ }
+
+ wstatus = diff_run (ap - argv, (char **) argv, diffout, my_callbacks_arg);
+
+ outfile = outfile_hold;
+ callbacks = callbacks_hold;
+
if (wstatus == 2)
diff3_fatal ("subsidiary diff failed");
@@ -1282,17 +1373,25 @@ scan_diff_line (scan_ptr, set_start, set_length, limit, leadingchar)
*set_length = line_ptr - *set_start;
if (line_ptr < limit && *line_ptr == '\\')
{
- if (edscript)
- fprintf (stderr, "%s:", diff_program_name);
+ if (! edscript)
+ {
+ --*set_length;
+ line_ptr++;
+ while (*line_ptr++ != '\n')
+ ;
+ }
else
- --*set_length;
- line_ptr++;
- do
{
- if (edscript)
- putc (*line_ptr, stderr);
+ char *serr;
+
+ line_ptr++;
+ serr = line_ptr;
+ while (*line_ptr++ != '\n')
+ ;
+ line_ptr[-1] = '\0';
+ diff_error ("%s", serr, 0);
+ line_ptr[-1] = '\n';
}
- while (*line_ptr++ != '\n');
}
return line_ptr;
@@ -1310,8 +1409,7 @@ scan_diff_line (scan_ptr, set_start, set_length, limit, leadingchar)
* REV_MAPPING is the inverse of MAPPING.
*/
static void
-output_diff3 (outputfile, diff, mapping, rev_mapping)
- FILE *outputfile;
+output_diff3 (diff, mapping, rev_mapping)
struct diff3_block *diff;
int const mapping[3], rev_mapping[3];
{
@@ -1348,7 +1446,7 @@ output_diff3 (outputfile, diff, mapping, rev_mapping)
default:
diff3_fatal ("internal error: invalid diff type passed to output");
}
- fprintf (outputfile, "====%s\n", x);
+ printf_output ("====%s\n", x);
/* Go 0, 2, 1 if the first and third outputs are equivalent. */
for (i = 0; i < 3;
@@ -1359,17 +1457,17 @@ output_diff3 (outputfile, diff, mapping, rev_mapping)
lowt = D_LOWLINE (ptr, realfile),
hight = D_HIGHLINE (ptr, realfile);
- fprintf (outputfile, "%d:", i + 1);
+ printf_output ("%d:", i + 1);
switch (lowt - hight)
{
case 1:
- fprintf (outputfile, "%da\n", lowt - 1);
+ printf_output ("%da\n", lowt - 1);
break;
case 0:
- fprintf (outputfile, "%dc\n", lowt);
+ printf_output ("%dc\n", lowt);
break;
default:
- fprintf (outputfile, "%d,%dc\n", lowt, hight);
+ printf_output ("%d,%dc\n", lowt, hight);
break;
}
@@ -1380,14 +1478,14 @@ output_diff3 (outputfile, diff, mapping, rev_mapping)
line = 0;
do
{
- fprintf (outputfile, line_prefix);
+ printf_output (line_prefix);
cp = D_RELNUM (ptr, realfile, line);
length = D_RELLEN (ptr, realfile, line);
- fwrite (cp, sizeof (char), length, outputfile);
+ write_output (cp, length);
}
while (++line < hight - lowt + 1);
if (cp[length - 1] != '\n')
- fprintf (outputfile, "\n\\ No newline at end of file\n");
+ printf_output ("\n\\ No newline at end of file\n");
}
}
}
@@ -1395,12 +1493,11 @@ output_diff3 (outputfile, diff, mapping, rev_mapping)
/*
- * Output to OUTPUTFILE the lines of B taken from FILENUM.
+ * Output the lines of B taken from FILENUM.
* Double any initial '.'s; yield nonzero if any initial '.'s were doubled.
*/
static int
-dotlines (outputfile, b, filenum)
- FILE *outputfile;
+dotlines (b, filenum)
struct diff3_block *b;
int filenum;
{
@@ -1415,10 +1512,9 @@ dotlines (outputfile, b, filenum)
if (line[0] == '.')
{
leading_dot = 1;
- fprintf (outputfile, ".");
+ write_output (".", 1);
}
- fwrite (line, sizeof (char),
- D_RELLEN (b, filenum, i), outputfile);
+ write_output (line, D_RELLEN (b, filenum, i));
}
return leading_dot;
@@ -1430,16 +1526,15 @@ dotlines (outputfile, b, filenum)
* starting with line START and continuing for NUM lines.
*/
static void
-undotlines (outputfile, leading_dot, start, num)
- FILE *outputfile;
+undotlines (leading_dot, start, num)
int leading_dot, start, num;
{
- fprintf (outputfile, ".\n");
+ write_output (".\n", 2);
if (leading_dot)
if (num == 1)
- fprintf (outputfile, "%ds/^\\.//\n", start);
+ printf_output ("%ds/^\\.//\n", start);
else
- fprintf (outputfile, "%d,%ds/^\\.//\n", start, start + num - 1);
+ printf_output ("%d,%ds/^\\.//\n", start, start + num - 1);
}
/*
@@ -1465,9 +1560,7 @@ undotlines (outputfile, leading_dot, start, num)
*/
static int
-output_diff3_edscript (outputfile, diff, mapping, rev_mapping,
- file0, file1, file2)
- FILE *outputfile;
+output_diff3_edscript (diff, mapping, rev_mapping, file0, file1, file2)
struct diff3_block *diff;
int const mapping[3], rev_mapping[3];
char const *file0, *file1, *file2;
@@ -1502,22 +1595,22 @@ output_diff3_edscript (outputfile, diff, mapping, rev_mapping,
/* Mark end of conflict. */
- fprintf (outputfile, "%da\n", D_HIGHLINE (b, mapping[FILE0]));
+ printf_output ("%da\n", D_HIGHLINE (b, mapping[FILE0]));
leading_dot = 0;
if (type == DIFF_ALL)
{
if (show_2nd)
{
/* Append lines from FILE1. */
- fprintf (outputfile, "||||||| %s\n", file1);
- leading_dot = dotlines (outputfile, b, mapping[FILE1]);
+ printf_output ("||||||| %s\n", file1);
+ leading_dot = dotlines (b, mapping[FILE1]);
}
/* Append lines from FILE2. */
- fprintf (outputfile, "=======\n");
- leading_dot |= dotlines (outputfile, b, mapping[FILE2]);
+ printf_output ("=======\n");
+ leading_dot |= dotlines (b, mapping[FILE2]);
}
- fprintf (outputfile, ">>>>>>> %s\n", file2);
- undotlines (outputfile, leading_dot,
+ printf_output (">>>>>>> %s\n", file2);
+ undotlines (leading_dot,
D_HIGHLINE (b, mapping[FILE0]) + 2,
(D_NUMLINES (b, mapping[FILE1])
+ D_NUMLINES (b, mapping[FILE2]) + 1));
@@ -1525,17 +1618,17 @@ output_diff3_edscript (outputfile, diff, mapping, rev_mapping,
/* Mark start of conflict. */
- fprintf (outputfile, "%da\n<<<<<<< %s\n",
- D_LOWLINE (b, mapping[FILE0]) - 1,
- type == DIFF_ALL ? file0 : file1);
+ printf_output ("%da\n<<<<<<< %s\n",
+ D_LOWLINE (b, mapping[FILE0]) - 1,
+ type == DIFF_ALL ? file0 : file1);
leading_dot = 0;
if (type == DIFF_2ND)
{
/* Prepend lines from FILE1. */
- leading_dot = dotlines (outputfile, b, mapping[FILE1]);
- fprintf (outputfile, "=======\n");
+ leading_dot = dotlines (b, mapping[FILE1]);
+ printf_output ("=======\n");
}
- undotlines (outputfile, leading_dot,
+ undotlines (leading_dot,
D_LOWLINE (b, mapping[FILE0]) + 1,
D_NUMLINES (b, mapping[FILE1]));
}
@@ -1543,12 +1636,11 @@ output_diff3_edscript (outputfile, diff, mapping, rev_mapping,
/* Write out a delete */
{
if (D_NUMLINES (b, mapping[FILE0]) == 1)
- fprintf (outputfile, "%dd\n",
- D_LOWLINE (b, mapping[FILE0]));
+ printf_output ("%dd\n", D_LOWLINE (b, mapping[FILE0]));
else
- fprintf (outputfile, "%d,%dd\n",
- D_LOWLINE (b, mapping[FILE0]),
- D_HIGHLINE (b, mapping[FILE0]));
+ printf_output ("%d,%dd\n",
+ D_LOWLINE (b, mapping[FILE0]),
+ D_HIGHLINE (b, mapping[FILE0]));
}
else
/* Write out an add or change */
@@ -1556,33 +1648,32 @@ output_diff3_edscript (outputfile, diff, mapping, rev_mapping,
switch (D_NUMLINES (b, mapping[FILE0]))
{
case 0:
- fprintf (outputfile, "%da\n",
- D_HIGHLINE (b, mapping[FILE0]));
+ printf_output ("%da\n", D_HIGHLINE (b, mapping[FILE0]));
break;
case 1:
- fprintf (outputfile, "%dc\n",
- D_HIGHLINE (b, mapping[FILE0]));
+ printf_output ("%dc\n", D_HIGHLINE (b, mapping[FILE0]));
break;
default:
- fprintf (outputfile, "%d,%dc\n",
- D_LOWLINE (b, mapping[FILE0]),
- D_HIGHLINE (b, mapping[FILE0]));
+ printf_output ("%d,%dc\n",
+ D_LOWLINE (b, mapping[FILE0]),
+ D_HIGHLINE (b, mapping[FILE0]));
break;
}
- undotlines (outputfile, dotlines (outputfile, b, mapping[FILE2]),
+ undotlines (dotlines (b, mapping[FILE2]),
D_LOWLINE (b, mapping[FILE0]),
D_NUMLINES (b, mapping[FILE2]));
}
}
- if (finalwrite) fprintf (outputfile, "w\nq\n");
+ if (finalwrite) printf_output ("w\nq\n");
return conflicts_found;
}
/*
- * Read from INFILE and output to OUTPUTFILE a set of diff3_ blocks DIFF
- * as a merged file. This acts like 'ed file0 <[output_diff3_edscript]',
- * except that it works even for binary data or incomplete lines.
+ * Read from INFILE and output to the standard output file a set of
+ * diff3_ blocks DIFF as a merged file. This acts like 'ed file0
+ * <[output_diff3_edscript]', except that it works even for binary
+ * data or incomplete lines.
*
* As before, MAPPING maps from arg list file number to diff file number,
* REV_MAPPING is its inverse,
@@ -1592,14 +1683,15 @@ output_diff3_edscript (outputfile, diff, mapping, rev_mapping,
*/
static int
-output_diff3_merge (infile, outputfile, diff, mapping, rev_mapping,
+output_diff3_merge (infile, diff, mapping, rev_mapping,
file0, file1, file2)
- FILE *infile, *outputfile;
+ FILE *infile;
struct diff3_block *diff;
int const mapping[3], rev_mapping[3];
char const *file0, *file1, *file2;
{
int c, i;
+ char cc;
int conflicts_found = 0, conflict;
struct diff3_block *b;
int linesread = 0;
@@ -1638,7 +1730,8 @@ output_diff3_merge (infile, outputfile, diff, mapping, rev_mapping,
diff3_perror_with_exit ("input file");
else if (feof (infile))
diff3_fatal ("input file shrank");
- putc (c, outputfile);
+ cc = c;
+ write_output (&cc, 1);
}
while (c != '\n');
@@ -1649,37 +1742,37 @@ output_diff3_merge (infile, outputfile, diff, mapping, rev_mapping,
if (type == DIFF_ALL)
{
/* Put in lines from FILE0 with bracket. */
- fprintf (outputfile, "<<<<<<< %s\n", file0);
+ printf_output ("<<<<<<< %s\n", file0);
for (i = 0;
i < D_NUMLINES (b, mapping[FILE0]);
i++)
- fwrite (D_RELNUM (b, mapping[FILE0], i), sizeof (char),
- D_RELLEN (b, mapping[FILE0], i), outputfile);
+ write_output (D_RELNUM (b, mapping[FILE0], i),
+ D_RELLEN (b, mapping[FILE0], i));
}
if (show_2nd)
{
/* Put in lines from FILE1 with bracket. */
- fprintf (outputfile, format_2nd, file1);
+ printf_output (format_2nd, file1);
for (i = 0;
i < D_NUMLINES (b, mapping[FILE1]);
i++)
- fwrite (D_RELNUM (b, mapping[FILE1], i), sizeof (char),
- D_RELLEN (b, mapping[FILE1], i), outputfile);
+ write_output (D_RELNUM (b, mapping[FILE1], i),
+ D_RELLEN (b, mapping[FILE1], i));
}
- fprintf (outputfile, "=======\n");
+ printf_output ("=======\n");
}
/* Put in lines from FILE2. */
for (i = 0;
i < D_NUMLINES (b, mapping[FILE2]);
i++)
- fwrite (D_RELNUM (b, mapping[FILE2], i), sizeof (char),
- D_RELLEN (b, mapping[FILE2], i), outputfile);
+ write_output (D_RELNUM (b, mapping[FILE2], i),
+ D_RELLEN (b, mapping[FILE2], i));
if (conflict)
- fprintf (outputfile, ">>>>>>> %s\n", file2);
+ printf_output (">>>>>>> %s\n", file2);
/* Skip I lines in file 0. */
i = D_NUMLINES (b, FILE0);
@@ -1698,7 +1791,10 @@ output_diff3_merge (infile, outputfile, diff, mapping, rev_mapping,
}
/* Copy rest of common file. */
while ((c = getc (infile)) != EOF || !(ferror (infile) | feof (infile)))
- putc (c, outputfile);
+ {
+ cc = c;
+ write_output (&cc, 1);
+ }
return conflicts_found;
}
@@ -1737,7 +1833,7 @@ static void
diff3_fatal (string)
char const *string;
{
- fprintf (stderr, "%s: %s\n", diff_program_name, string);
+ diff_error ("%s", string, 0);
DIFF3_ABORT (2);
}
@@ -1745,10 +1841,7 @@ static void
diff3_perror_with_exit (string)
char const *string;
{
- int e = errno;
- fprintf (stderr, "%s: ", diff_program_name);
- errno = e;
- perror (string);
+ perror_with_name (string);
DIFF3_ABORT (2);
}
@@ -1768,6 +1861,7 @@ initialize_main (argcp, argvp)
finalwrite = 0;
merge = 0;
diff_program_name = (*argvp)[0];
+ outfile = NULL;
}
static void
diff --git a/contrib/cvs/diff/diffrun.h b/contrib/cvs/diff/diffrun.h
new file mode 100644
index 000000000000..28c1f45e5fd3
--- /dev/null
+++ b/contrib/cvs/diff/diffrun.h
@@ -0,0 +1,69 @@
+/* Interface header file for GNU DIFF library.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+
+This file is part of GNU DIFF.
+
+GNU DIFF 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 DIFF is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU DIFF; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef DIFFRUN_H
+#define DIFFRUN_H
+
+/* This header file defines the interfaces used by the diff library.
+ It should be included by programs which use the diff library. */
+
+#include <sys/types.h>
+
+#if defined __STDC__ && __STDC__
+#define DIFFPARAMS(args) args
+#else
+#define DIFFPARAMS(args) ()
+#endif
+
+/* The diff_callbacks structure is used to handle callbacks from the
+ diff library. All output goes through these callbacks. When a
+ pointer to this structure is passed in, it may be NULL. Also, any
+ of the individual callbacks may be NULL. This means that the
+ default action should be taken. */
+
+struct diff_callbacks
+{
+ /* Write output. This function just writes a string of a given
+ length to the output file. The default is to fwrite to OUTFILE.
+ If this callback is defined, flush_output must also be defined. */
+ void (*write_output) DIFFPARAMS((char const *, size_t));
+ /* Flush output. The default is to fflush OUTFILE. If this
+ callback is defined, write_output must also be defined. */
+ void (*flush_output) DIFFPARAMS((void));
+ /* Write to stdout. This is called for version and help messages. */
+ void (*write_stdout) DIFFPARAMS((char const *));
+ /* Print an error message. The first argument is a printf format,
+ and the next two are parameters. The default is to print a
+ message on stderr. */
+ void (*error) DIFFPARAMS((char const *, char const *, char const *));
+};
+
+/* Run a diff. */
+
+extern int diff_run DIFFPARAMS((int, char **, char *,
+ const struct diff_callbacks *));
+
+/* Run a diff3. */
+
+extern int diff3_run DIFFPARAMS((int, char **, char *,
+ const struct diff_callbacks *));
+
+#undef DIFFPARAMS
+
+#endif /* DIFFRUN_H */
diff --git a/contrib/cvs/diff/ed.c b/contrib/cvs/diff/ed.c
index 717ef358d0ee..6b00d133e4d0 100644
--- a/contrib/cvs/diff/ed.c
+++ b/contrib/cvs/diff/ed.c
@@ -1,5 +1,5 @@
/* Output routines for ed-script format.
- Copyright (C) 1988, 89, 91, 92, 93 Free Software Foundation, Inc.
+ Copyright (C) 1988, 89, 91, 92, 93, 1998 Free Software Foundation, Inc.
This file is part of GNU DIFF.
@@ -57,7 +57,7 @@ print_ed_hunk (hunk)
/* Print out the line number header for this hunk */
print_number_range (',', &files[0], f0, l0);
- fprintf (outfile, "%c\n", change_letter (inserts, deletes));
+ printf_output ("%c\n", change_letter (inserts, deletes));
/* Print new/changed lines from second file, if needed */
if (inserts)
@@ -68,8 +68,8 @@ print_ed_hunk (hunk)
{
/* Resume the insert, if we stopped. */
if (! inserting)
- fprintf (outfile, "%da\n",
- i - f1 + translate_line_number (&files[0], f0) - 1);
+ printf_output ("%da\n",
+ i - f1 + translate_line_number (&files[0], f0) - 1);
inserting = 1;
/* If the file's line is just a dot, it would confuse `ed'.
@@ -80,11 +80,11 @@ print_ed_hunk (hunk)
if (files[1].linbuf[i][0] == '.'
&& files[1].linbuf[i][1] == '\n')
{
- fprintf (outfile, "..\n");
- fprintf (outfile, ".\n");
+ printf_output ("..\n");
+ printf_output (".\n");
/* Now change that double dot to the desired single dot. */
- fprintf (outfile, "%ds/^\\.\\././\n",
- i - f1 + translate_line_number (&files[0], f0));
+ printf_output ("%ds/^\\.\\././\n",
+ i - f1 + translate_line_number (&files[0], f0));
inserting = 0;
}
else
@@ -94,7 +94,7 @@ print_ed_hunk (hunk)
/* End insert mode, if we are still in it. */
if (inserting)
- fprintf (outfile, ".\n");
+ printf_output (".\n");
}
}
@@ -124,9 +124,9 @@ pr_forward_ed_hunk (hunk)
begin_output ();
- fprintf (outfile, "%c", change_letter (inserts, deletes));
+ printf_output ("%c", change_letter (inserts, deletes));
print_number_range (' ', files, f0, l0);
- fprintf (outfile, "\n");
+ printf_output ("\n");
/* If deletion only, print just the number range. */
@@ -139,7 +139,7 @@ pr_forward_ed_hunk (hunk)
for (i = f1; i <= l1; i++)
print_1_line ("", &files[1].linbuf[i]);
- fprintf (outfile, ".\n");
+ printf_output (".\n");
}
/* Print in a format somewhat like ed commands
@@ -175,23 +175,23 @@ print_rcs_hunk (hunk)
if (deletes)
{
- fprintf (outfile, "d");
+ printf_output ("d");
/* For deletion, print just the starting line number from file 0
and the number of lines deleted. */
- fprintf (outfile, "%d %d\n",
- tf0,
- (tl0 >= tf0 ? tl0 - tf0 + 1 : 1));
+ printf_output ("%d %d\n",
+ tf0,
+ (tl0 >= tf0 ? tl0 - tf0 + 1 : 1));
}
if (inserts)
{
- fprintf (outfile, "a");
+ printf_output ("a");
/* Take last-line-number from file 0 and # lines from file 1. */
translate_range (&files[1], f1, l1, &tf1, &tl1);
- fprintf (outfile, "%d %d\n",
- tl0,
- (tl1 >= tf1 ? tl1 - tf1 + 1 : 1));
+ printf_output ("%d %d\n",
+ tl0,
+ (tl1 >= tf1 ? tl1 - tf1 + 1 : 1));
/* Print the inserted lines. */
for (i = f1; i <= l1; i++)
diff --git a/contrib/cvs/diff/ifdef.c b/contrib/cvs/diff/ifdef.c
index 2834cbdfa236..94fcfb567787 100644
--- a/contrib/cvs/diff/ifdef.c
+++ b/contrib/cvs/diff/ifdef.c
@@ -1,5 +1,5 @@
/* #ifdef-format output routines for GNU DIFF.
- Copyright (C) 1989, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1991, 1992, 1993, 1994, 1998 Free Software Foundation, Inc.
This file is part of GNU DIFF.
@@ -27,13 +27,13 @@ struct group
int from, upto; /* start and limit lines for this group of lines */
};
-static char *format_group PARAMS((FILE *, char *, int, struct group const *));
+static char *format_group PARAMS((int, char *, int, struct group const *));
static char *scan_char_literal PARAMS((char *, int *));
static char *scan_printf_spec PARAMS((char *));
static int groups_letter_value PARAMS((struct group const *, int));
static void format_ifdef PARAMS((char *, int, int, int, int));
static void print_ifdef_hunk PARAMS((struct change *));
-static void print_ifdef_lines PARAMS((FILE *, char *, struct group const *));
+static void print_ifdef_lines PARAMS((int, char *, struct group const *));
static int next_line;
@@ -103,18 +103,18 @@ format_ifdef (format, beg0, end0, beg1, end1)
groups[1].file = &files[1];
groups[1].from = beg1;
groups[1].upto = end1;
- format_group (outfile, format, '\0', groups);
+ format_group (1, format, '\0', groups);
}
-/* Print to file OUT a set of lines according to FORMAT.
+/* If DOIT is non-zero, output a set of lines according to FORMAT.
The format ends at the first free instance of ENDCHAR.
Yield the address of the terminating character.
GROUPS specifies which lines to print.
If OUT is zero, do not actually print anything; just scan the format. */
static char *
-format_group (out, format, endchar, groups)
- register FILE *out;
+format_group (doit, format, endchar, groups)
+ int doit;
char *format;
int endchar;
struct group const *groups;
@@ -137,7 +137,7 @@ format_group (out, format, endchar, groups)
/* Print if-then-else format e.g. `%(n=1?thenpart:elsepart)'. */
{
int i, value[2];
- FILE *thenout, *elseout;
+ int thendoit, elsedoit;
for (i = 0; i < 2; i++)
{
@@ -159,13 +159,13 @@ format_group (out, format, endchar, groups)
goto bad_format;
}
if (value[0] == value[1])
- thenout = out, elseout = 0;
+ thendoit = doit, elsedoit = 0;
else
- thenout = 0, elseout = out;
- f = format_group (thenout, f, ':', groups);
+ thendoit = 0, elsedoit = doit;
+ f = format_group (thendoit, f, ':', groups);
if (*f)
{
- f = format_group (elseout, f + 1, ')', groups);
+ f = format_group (elsedoit, f + 1, ')', groups);
if (*f)
f++;
}
@@ -174,17 +174,17 @@ format_group (out, format, endchar, groups)
case '<':
/* Print lines deleted from first file. */
- print_ifdef_lines (out, line_format[OLD], &groups[0]);
+ print_ifdef_lines (doit, line_format[OLD], &groups[0]);
continue;
case '=':
/* Print common lines. */
- print_ifdef_lines (out, line_format[UNCHANGED], &groups[0]);
+ print_ifdef_lines (doit, line_format[UNCHANGED], &groups[0]);
continue;
case '>':
/* Print lines inserted from second file. */
- print_ifdef_lines (out, line_format[NEW], &groups[1]);
+ print_ifdef_lines (doit, line_format[NEW], &groups[1]);
continue;
default:
@@ -211,11 +211,11 @@ format_group (out, format, endchar, groups)
goto bad_format;
break;
}
- if (out)
+ if (doit)
{
/* Temporarily replace e.g. "%3dnx" with "%3d\0x". */
*speclim = 0;
- fprintf (out, spec - 1, value);
+ printf_output (spec - 1, value);
/* Undo the temporary replacement. */
*speclim = c;
}
@@ -228,8 +228,12 @@ format_group (out, format, endchar, groups)
break;
}
}
- if (out)
- putc (c, out);
+ if (doit)
+ {
+ /* Don't take the address of a register variable. */
+ char cc = c;
+ write_output (&cc, 1);
+ }
}
return f;
}
@@ -257,11 +261,11 @@ groups_letter_value (g, letter)
}
}
-/* Print to file OUT, using FORMAT to print the line group GROUP.
- But do nothing if OUT is zero. */
+/* Output using FORMAT to print the line group GROUP.
+ But do nothing if DOIT is zero. */
static void
-print_ifdef_lines (out, format, group)
- register FILE *out;
+print_ifdef_lines (doit, format, group)
+ int doit;
char *format;
struct group const *group;
{
@@ -269,7 +273,7 @@ print_ifdef_lines (out, format, group)
char const * const *linbuf = file->linbuf;
int from = group->from, upto = group->upto;
- if (!out)
+ if (!doit)
return;
/* If possible, use a single fwrite; it's faster. */
@@ -277,15 +281,15 @@ print_ifdef_lines (out, format, group)
{
if (format[1] == 'l' && format[2] == '\n' && !format[3])
{
- fwrite (linbuf[from], sizeof (char),
- linbuf[upto] + (linbuf[upto][-1] != '\n') - linbuf[from],
- out);
+ write_output (linbuf[from],
+ (linbuf[upto] + (linbuf[upto][-1] != '\n')
+ - linbuf[from]));
return;
}
if (format[1] == 'L' && !format[2])
{
- fwrite (linbuf[from], sizeof (char),
- linbuf[upto] - linbuf[from], out);
+ write_output (linbuf[from],
+ linbuf[upto] - linbuf[from]);
return;
}
}
@@ -294,6 +298,7 @@ print_ifdef_lines (out, format, group)
{
register char c;
register char *f = format;
+ char cc;
while ((c = *f++) != 0)
{
@@ -342,7 +347,7 @@ print_ifdef_lines (out, format, group)
}
/* Temporarily replace e.g. "%3dnx" with "%3d\0x". */
*speclim = 0;
- fprintf (out, spec - 1, value);
+ printf_output (spec - 1, value);
/* Undo the temporary replacement. */
*speclim = c;
}
@@ -354,7 +359,10 @@ print_ifdef_lines (out, format, group)
break;
}
}
- putc (c, out);
+
+ /* Don't take the address of a register variable. */
+ cc = c;
+ write_output (&cc, 1);
}
}
}
diff --git a/contrib/cvs/diff/normal.c b/contrib/cvs/diff/normal.c
index 4d9e23cb72a0..75dae8899309 100644
--- a/contrib/cvs/diff/normal.c
+++ b/contrib/cvs/diff/normal.c
@@ -1,5 +1,5 @@
/* Normal-format output routines for GNU DIFF.
- Copyright (C) 1988, 1989, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1993, 1998 Free Software Foundation, Inc.
This file is part of GNU DIFF.
@@ -52,9 +52,9 @@ print_normal_hunk (hunk)
/* Print out the line number header for this hunk */
print_number_range (',', &files[0], first0, last0);
- fprintf (outfile, "%c", change_letter (inserts, deletes));
+ printf_output ("%c", change_letter (inserts, deletes));
print_number_range (',', &files[1], first1, last1);
- fprintf (outfile, "\n");
+ printf_output ("\n");
/* Print the lines that the first file has. */
if (deletes)
@@ -62,7 +62,7 @@ print_normal_hunk (hunk)
print_1_line ("<", &files[0].linbuf[i]);
if (inserts && deletes)
- fprintf (outfile, "---\n");
+ printf_output ("---\n");
/* Print the lines that the second file has. */
if (inserts)
diff --git a/contrib/cvs/diff/side.c b/contrib/cvs/diff/side.c
index a150b5e705fc..d776e77eab3d 100644
--- a/contrib/cvs/diff/side.c
+++ b/contrib/cvs/diff/side.c
@@ -1,5 +1,5 @@
/* sdiff-format output routines for GNU DIFF.
- Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1992, 1993, 1998 Free Software Foundation, Inc.
This file is part of GNU DIFF.
@@ -50,17 +50,16 @@ static unsigned
tab_from_to (from, to)
unsigned from, to;
{
- FILE *out = outfile;
unsigned tab;
if (! tab_expand_flag)
for (tab = from + TAB_WIDTH - from % TAB_WIDTH; tab <= to; tab += TAB_WIDTH)
{
- putc ('\t', out);
+ write_output ("\t", 1);
from = tab;
}
while (from++ < to)
- putc (' ', out);
+ write_output (" ", 1);
return to;
}
@@ -74,7 +73,6 @@ print_half_line (line, indent, out_bound)
char const * const *line;
unsigned indent, out_bound;
{
- FILE *out = outfile;
register unsigned in_position = 0, out_position = 0;
register char const
*text_pointer = line[0],
@@ -83,6 +81,9 @@ print_half_line (line, indent, out_bound)
while (text_pointer < text_limit)
{
register unsigned char c = *text_pointer++;
+ /* We use CC to avoid taking the address of the register
+ variable C. */
+ char cc;
switch (c)
{
@@ -97,13 +98,14 @@ print_half_line (line, indent, out_bound)
if (out_bound < tabstop)
tabstop = out_bound;
for (; out_position < tabstop; out_position++)
- putc (' ', out);
+ write_output (" ", 1);
}
else
if (tabstop < out_bound)
{
out_position = tabstop;
- putc (c, out);
+ cc = c;
+ write_output (&cc, 1);
}
}
in_position += spaces;
@@ -112,7 +114,8 @@ print_half_line (line, indent, out_bound)
case '\r':
{
- putc (c, out);
+ cc = c;
+ write_output (&cc, 1);
tab_from_to (0, indent);
in_position = out_position = 0;
}
@@ -123,11 +126,12 @@ print_half_line (line, indent, out_bound)
if (out_position <= in_position)
/* Add spaces to make up for suppressed tab past out_bound. */
for (; out_position < in_position; out_position++)
- putc (' ', out);
+ write_output (" ", 1);
else
{
out_position = in_position;
- putc (c, out);
+ cc = c;
+ write_output (&cc, 1);
}
break;
@@ -135,7 +139,10 @@ print_half_line (line, indent, out_bound)
case '\v':
control_char:
if (in_position < out_bound)
- putc (c, out);
+ {
+ cc = c;
+ write_output (&cc, 1);
+ }
break;
default:
@@ -146,7 +153,8 @@ print_half_line (line, indent, out_bound)
if (in_position++ < out_bound)
{
out_position = in_position;
- putc (c, out);
+ cc = c;
+ write_output (&cc, 1);
}
break;
@@ -170,7 +178,6 @@ print_1sdiff_line (left, sep, right)
int sep;
char const * const *right;
{
- FILE *out = outfile;
unsigned hw = sdiff_half_width, c2o = sdiff_column2_offset;
unsigned col = 0;
int put_newline = 0;
@@ -184,10 +191,13 @@ print_1sdiff_line (left, sep, right)
if (sep != ' ')
{
+ char cc;
+
col = tab_from_to (col, (hw + c2o - 1) / 2) + 1;
if (sep == '|' && put_newline != (right[1][-1] == '\n'))
sep = put_newline ? '/' : '\\';
- putc (sep, out);
+ cc = sep;
+ write_output (&cc, 1);
}
if (right)
@@ -202,7 +212,7 @@ print_1sdiff_line (left, sep, right)
}
if (put_newline)
- putc ('\n', out);
+ write_output ("\n", 1);
}
/* Print lines common to both files in side-by-side format. */
@@ -215,7 +225,7 @@ print_sdiff_common_lines (limit0, limit1)
if (! sdiff_skip_common_lines && (i0 != limit0 || i1 != limit1))
{
if (sdiff_help_sdiff)
- fprintf (outfile, "i%d,%d\n", limit0 - i0, limit1 - i1);
+ printf_output ("i%d,%d\n", limit0 - i0, limit1 - i1);
if (! sdiff_left_only)
{
@@ -252,7 +262,7 @@ print_sdiff_hunk (hunk)
print_sdiff_common_lines (first0, first1);
if (sdiff_help_sdiff)
- fprintf (outfile, "c%d,%d\n", last0 - first0 + 1, last1 - first1 + 1);
+ printf_output ("c%d,%d\n", last0 - first0 + 1, last1 - first1 + 1);
/* Print ``xxx | xxx '' lines */
if (inserts && deletes)
diff --git a/contrib/cvs/diff/util.c b/contrib/cvs/diff/util.c
index 89cc27417860..1b281700a5d5 100644
--- a/contrib/cvs/diff/util.c
+++ b/contrib/cvs/diff/util.c
@@ -1,5 +1,5 @@
/* Support routines for GNU DIFF.
- Copyright (C) 1988, 1989, 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1992, 1993, 1994, 1997, 1998 Free Software Foundation, Inc.
This file is part of GNU DIFF.
@@ -19,6 +19,16 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "diff.h"
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifndef strerror
+extern char *strerror ();
+#endif
+
/* Queue up one-line messages to be printed at the end,
when -l is specified. Each message is recorded with a `struct msg'. */
@@ -48,9 +58,15 @@ perror_with_name (text)
char const *text;
{
int e = errno;
- fprintf (stderr, "%s: ", diff_program_name);
- errno = e;
- perror (text);
+
+ if (callbacks && callbacks->error)
+ (*callbacks->error) ("%s: %s", text, strerror (e));
+ else
+ {
+ fprintf (stderr, "%s: ", diff_program_name);
+ errno = e;
+ perror (text);
+ }
}
/* Use when a system call returns non-zero status and that is fatal. */
@@ -61,9 +77,14 @@ pfatal_with_name (text)
{
int e = errno;
print_message_queue ();
- fprintf (stderr, "%s: ", diff_program_name);
- errno = e;
- perror (text);
+ if (callbacks && callbacks->error)
+ (*callbacks->error) ("%s: %s", text, strerror (e));
+ else
+ {
+ fprintf (stderr, "%s: ", diff_program_name);
+ errno = e;
+ perror (text);
+ }
DIFF_ABORT (2);
}
@@ -74,9 +95,14 @@ void
diff_error (format, arg, arg1)
char const *format, *arg, *arg1;
{
- fprintf (stderr, "%s: ", diff_program_name);
- fprintf (stderr, format, arg, arg1);
- fprintf (stderr, "\n");
+ if (callbacks && callbacks->error)
+ (*callbacks->error) (format, arg, arg1);
+ else
+ {
+ fprintf (stderr, "%s: ", diff_program_name);
+ fprintf (stderr, format, arg, arg1);
+ fprintf (stderr, "\n");
+ }
}
/* Print an error message containing the string TEXT, then exit. */
@@ -119,8 +145,8 @@ message5 (format, arg1, arg2, arg3, arg4)
else
{
if (sdiff_help_sdiff)
- putc (' ', outfile);
- fprintf (outfile, format, arg1, arg2, arg3, arg4);
+ write_output (" ", 1);
+ printf_output (format, arg1, arg2, arg3, arg4);
}
}
@@ -132,7 +158,7 @@ print_message_queue ()
struct msg *m;
for (m = msg_chain; m; m = m->next)
- fprintf (outfile, m->format, m->arg1, m->arg2, m->arg3, m->arg4);
+ printf_output (m->format, m->arg1, m->arg2, m->arg3, m->arg4);
}
/* Call before outputting the results of comparing files NAME0 and NAME1
@@ -180,6 +206,9 @@ begin_output ()
This requirement is silly and does not match historical practice. */
sprintf (name, "diff%s %s %s", switch_string, current_name0, current_name1);
+ if (paginate_flag && callbacks && callbacks->write_output)
+ fatal ("can't paginate when using library callbacks");
+
if (paginate_flag)
{
/* Make OUTFILE a pipe to a subsidiary `pr'. */
@@ -243,7 +272,7 @@ begin_output ()
/* If handling multiple files (because scanning a directory),
print which files the following output is about. */
if (current_depth > 0)
- fprintf (outfile, "%s\n", name);
+ printf_output ("%s\n", name);
}
free (name);
@@ -293,6 +322,68 @@ finish_output ()
output_in_progress = 0;
}
+
+/* Write something to the output file. */
+
+void
+write_output (text, len)
+ char const *text;
+ size_t len;
+{
+ if (callbacks && callbacks->write_output)
+ (*callbacks->write_output) (text, len);
+ else if (len == 1)
+ putc (*text, outfile);
+ else
+ fwrite (text, sizeof (char), len, outfile);
+}
+
+/* Printf something to the output file. */
+
+#ifdef __STDC__
+#define VA_START(args, lastarg) va_start(args, lastarg)
+#else /* ! __STDC__ */
+#define VA_START(args, lastarg) va_start(args)
+#endif /* __STDC__ */
+
+void
+#if defined (__STDC__)
+printf_output (const char *format, ...)
+#else
+printf_output (format, va_alist)
+ char const *format;
+ va_dcl
+#endif
+{
+ va_list args;
+
+ VA_START (args, format);
+ if (callbacks && callbacks->write_output)
+ {
+ char *p;
+
+ p = NULL;
+ vasprintf (&p, format, args);
+ if (p == NULL)
+ fatal ("out of memory");
+ (*callbacks->write_output) (p, strlen (p));
+ free (p);
+ }
+ else
+ vfprintf (outfile, format, args);
+ va_end (args);
+}
+
+/* Flush the output file. */
+
+void
+flush_output ()
+{
+ if (callbacks && callbacks->flush_output)
+ (*callbacks->flush_output) ();
+ else
+ fflush (outfile);
+}
/* Compare two lines (typically one from each input file)
according to the command line options.
@@ -469,7 +560,6 @@ print_1_line (line_flag, line)
char const * const *line;
{
char const *text = line[0], *limit = line[1]; /* Help the compiler. */
- FILE *out = outfile; /* Help the compiler some more. */
char const *flag_format = 0;
/* If -T was specified, use a Tab between the line-flag and the text.
@@ -479,13 +569,13 @@ print_1_line (line_flag, line)
if (line_flag && *line_flag)
{
flag_format = tab_align_flag ? "%s\t" : "%s ";
- fprintf (out, flag_format, line_flag);
+ printf_output (flag_format, line_flag);
}
output_1_line (text, limit, flag_format, line_flag);
if ((!line_flag || line_flag[0]) && limit[-1] != '\n')
- fprintf (out, "\n\\ No newline at end of file\n");
+ printf_output ("\n\\ No newline at end of file\n");
}
/* Output a line from TEXT up to LIMIT. Without -t, output verbatim.
@@ -498,13 +588,15 @@ output_1_line (text, limit, flag_format, line_flag)
char const *text, *limit, *flag_format, *line_flag;
{
if (!tab_expand_flag)
- fwrite (text, sizeof (char), limit - text, outfile);
+ write_output (text, limit - text);
else
{
- register FILE *out = outfile;
register unsigned char c;
register char const *t = text;
register unsigned column = 0;
+ /* CC is used to avoid taking the address of the register
+ variable C. */
+ char cc;
while (t < limit)
switch ((c = *t++))
@@ -514,15 +606,15 @@ output_1_line (text, limit, flag_format, line_flag)
unsigned spaces = TAB_WIDTH - column % TAB_WIDTH;
column += spaces;
do
- putc (' ', out);
+ write_output (" ", 1);
while (--spaces);
}
break;
case '\r':
- putc (c, out);
+ write_output ("\r", 1);
if (flag_format && t < limit && *t != '\n')
- fprintf (out, flag_format, line_flag);
+ printf_output (flag_format, line_flag);
column = 0;
break;
@@ -530,13 +622,14 @@ output_1_line (text, limit, flag_format, line_flag)
if (column == 0)
continue;
column--;
- putc (c, out);
+ write_output ("\b", 1);
break;
default:
if (ISPRINT (c))
column++;
- putc (c, out);
+ cc = c;
+ write_output (&cc, 1);
break;
}
}
@@ -598,9 +691,9 @@ print_number_range (sepchar, file, a, b)
In this case, we should print the line number before the range,
which is B. */
if (trans_b > trans_a)
- fprintf (outfile, "%d%c%d", trans_a, sepchar, trans_b);
+ printf_output ("%d%c%d", trans_a, sepchar, trans_b);
else
- fprintf (outfile, "%d", trans_b);
+ printf_output ("%d", trans_b);
}
/* Look at a hunk of edit script and report the range of lines in each file
diff --git a/contrib/cvs/doc/ChangeLog b/contrib/cvs/doc/ChangeLog
index 9a01d1b6a79e..e9e4925939ee 100644
--- a/contrib/cvs/doc/ChangeLog
+++ b/contrib/cvs/doc/ChangeLog
@@ -1,3 +1,122 @@
+Sun Jul 26 02:42:20 1998 Noel Cragg <noel@swish.red-bean.com>
+
+ * cvs.texinfo (config): TopLevelAdmin variable.
+
+ * cvsclient.texi (Requests): fix typo.
+
+1998-07-14 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvsclient.texi (Requests): "remove" is like "add" in the sense
+ that it is the "ci" request which does most of the work.
+
+1998-06-23 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvs.texinfo (Excluding directories): Fix order of
+ "!first-dir/sdir" and "first-dir" to match what CVS actually
+ accepts. Reported by Tim McIntosh of sterling.com.
+
+1998-06-09 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvs.texinfo (Using keywords): Rewrite to be less specific to
+ source code in C. The old text was worse than that; it was
+ specific to certain versions of GCC (not even current GCC's, I
+ don't think) (reported most recently by Mitchell Perilstein;
+ if memory serves by others before that).
+
+1998-06-08 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvs.texinfo (Concurrency): Also mention #cvs.lock. Don't
+ mention #cvs.tfl; it is quite old (before CVS 1.5).
+ (Locks, Backing up, Concurrency): Add more index entries.
+
+1998-06-03 Ian Lance Taylor <ian@cygnus.com>
+
+ * cvs.texinfo (Tracking sources): Clarify that the vendor branch
+ is only made the head revision when you import a new file, not any
+ time you import a file.
+
+1998-05-23 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvs.texinfo (What is CVS?): info-cvs-request is now at gnu.org
+ and is no longer handled by a human (hallelujah).
+
+1998-05-12 Jim Meyering <meyering@ascend.com>
+
+ * cvs.texinfo: Add an info dir entry.
+ Remove trailing white space.
+
+1998-05-05 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvs.texinfo (Wrappers): Be more explicit that -m 'COPY' has no
+ effect on binary files.
+
+1998-05-02 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * RCSFILES: Add more discussion of the order of the revisions.
+
+1998-04-27 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvs.texinfo (loginfo example): Also give example of sending
+ mail. Use internal variable $USER rather than expecting CVS to
+ set the environment variable $USER. Change unnecessary 'sed'
+ invocation to 'cat' (it suffered from the same problem in terms of
+ internal variables versus environment variables).
+
+ * cvs.texinfo (Error messages): Add "conflict: removed FILE was
+ modified by second party".
+
+1998-04-20 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvs.texinfo (Common options): Update comment about meaning of
+ HEAD in cvs diff.
+
+1998-04-12 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvsclient.texi (Dates): Also mention log -d.
+
+ * cvs.texinfo (Invoking CVS): No space is allowed between -r or -w
+ and its argument, for the log command.
+
+1998-04-11 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvsclient.texi (Dates): New section, explaining the deal with
+ date formats.
+
+1998-04-09 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvs.texinfo (Global options, Invoking CVS): Fix typo
+ ("files files" -> "files").
+ (Invoking CVS): Make -q and -Q more concise.
+ (Invoking CVS): Use @var for metavariables in "diff -r".
+
+1998-03-17 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvs.texinfo (~/.cvsrc): In example, put "checkout" rather than
+ "co" into .cvsrc; we just finished explaining that only the former
+ works! Thanks to Lenny Foner for reporting this.
+
+ * cvs.texinfo (Copying): Remove this node. This basically
+ restores the status quo prior to 18 Oct 1996 (before then the node
+ existed but was empty).
+ (before Top): Adjust copyright notice accordingly.
+
+1998-03-12 Tim Pierce <twp@skepsis.com>
+
+ * RCSFILES: Updated description of `hardlinks' newphrases.
+
+1998-03-07 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvs.texinfo (Tags, Sticky tags, Creating a branch, Accessing
+ branches): Rename release-0-1 tag to rel-0-1 and likewise for
+ release-0-1-patches and release-0-4. This fixes an overfull hbox.
+ (diff options): Reformat table to fix underfull hboxes and such.
+
+1998-03-07 Tim Pierce <twp@skepsis.com>
+
+ * cvs.texinfo (Editing files, Special Files): Document hardlinks.
+ Various cleanups to PreservePermissions text.
+ * RCSFILES: Document PreservePermissions newphrases.
+
1998-03-04 Jim Kingdon <kingdon@harvey.cyclic.com>
* cvs.texinfo (Special Files): Add notes about client/server CVS
@@ -213,13 +332,13 @@ Sun Nov 30 20:38:17 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
* cvs.texinfo (Wrappers): Add comment: we don't document %s.
-Mon Nov 24 23:00:09 1997 Karl Fogel <kfogel@floss.red-bean.com>
+Mon Nov 24 23:00:09 1997 Karl Fogel <kfogel@floss.red-bean.com>
and Jim Kingdon <kingdon@harvey.cyclic.com>
* cvsclient.texi: Move Protocol Notes node to the end.
* cvsclient.texi (Request intro): new node/section.
- (Protocol): added some introductory material.
+ (Protocol): added some introductory material.
Rearranged menu into General Conventions, Protocol specification,
and Example etc sections.
(File Modes): replaces Modes, for consistency.
@@ -418,7 +537,7 @@ Sat Sep 6 11:29:15 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
Fri Sep 5 14:42:39 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
* cvs.texinfo (BUGS): Remove mention of unsupported resources page
- on http://www.cyclic.com, as it might go away in a future
+ on http://www.cyclic.com, as it might go away in a future
reorganization.
* DIFFUTILS-2.7-BUG: Further info from Eggert.
@@ -1229,7 +1348,7 @@ Tue Mar 18 15:50:47 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
(A sample session): Add comment about how we need an introduction
and what might go into one. Also bring in the paragraph from
Basic concepts introducing modules, but comment it out.
- (Viewing differences): Add comment about
+ (Viewing differences): Add comment about
(Basic concepts): Removed; its content has been farmed out as
described above, and as the comment said, it was fundamentally
flawed.
@@ -1544,7 +1663,7 @@ Thu Nov 14 10:22:58 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
chunks, and about atomicity to be focused more on the protocol
than the current implementation.
(Notes): Remove this node. The attempt to describe the basic
- model has pretty much been replaced by the Introduction.
+ model has pretty much been replaced by the Introduction.
The material about how to start the client is incomplete and
better left to cvs.texinfo. And the item about the lack of
SERVER_FLOWCONTROL is obsolete now that SERVER_FLOWCONTROL is the
@@ -1700,7 +1819,7 @@ Mon Sep 30 18:17:34 1996 Greg A. Woods <woods@most.weird.com>
GREPBIN.
(export examples): add one.
(import options): describe the effect of '-b 1'.
-
+
Mon Sep 30 08:09:53 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
* cvs.texinfo: Adjust comments concerning A4 vs. US letter,
@@ -2404,14 +2523,14 @@ Sun Dec 31 10:53:47 1995 Jim Kingdon <kingdon@harvey.cyclic.com>
Sun Dec 24 02:37:51 1995 Karl Fogel <kfogel@floss.cyclic.com>
- * cvs.texinfo (Using the client with password authentication):
+ * cvs.texinfo (Using the client with password authentication):
tixed fypos.
Sun Dec 24 00:00:16 1995 Karl Fogel <kfogel@floss.cyclic.com>
* cvs.texinfo (Remote repositories): use @code{rsh} most places,
because it is the name of a program, and because I am a pedant.
- Refer to new node "Password authenticated".
+ Refer to new node "Password authenticated".
(Password authenticated): new node.
(Setting up the server for password authentication): new node.
(Using the client with password authentication): new node.
diff --git a/contrib/cvs/doc/RCSFILES b/contrib/cvs/doc/RCSFILES
index 6d600b8028ba..13c4f93c7969 100644
--- a/contrib/cvs/doc/RCSFILES
+++ b/contrib/cvs/doc/RCSFILES
@@ -24,12 +24,33 @@ several other output formats. If you just want some source code to
look at, the part of CVS which applies these is RCS_deltas in
src/rcs.c.
-The first time I read rcsfile.5 I didn't really notice the part about
-the order of the revisions. This order _is_ important and CVS relies
-on it. It is documented but it would be clearer if the example in
-rcsfile.5 also showed the order of the revisions (and the "next" and
-"branch" fields and anything else where it would be useful to have an
-example of how a revision tree is represented in an RCS file).
+The rcsfile.5 documentation only _very_ briefly touches on the order
+of the revisions. The order _is_ important and CVS relies on it.
+Here is an example of what I was able to find, based on the join3
+sanity.sh testcase (and the behavior I am documenting here seems to be
+the same for RCS 5.7 and CVS 1.9.27):
+
+ 1.1 -----------------> 1.2
+ \---> 1.1.2.1 \---> 1.2.2.1
+
+Here is how this shows up in the RCS file (omitting irrelevant parts):
+
+ admin: head 1.2;
+ deltas:
+ 1.2 branches 1.2.2.1; next 1.1;
+ 1.1 branches 1.1.2.1; next;
+ 1.1.2.1 branches; next;
+ 1.2.2.1 branches; next;
+ deltatexts:
+ 1.2
+ 1.2.2.1
+ 1.1
+ 1.1.2.1
+
+Yes, the order seems to differ between the deltas and the deltatexts.
+I have no idea how much of this should actually be considered part of
+the RCS file format, and how much programs reading it should expect to
+encounter any order.
The rcsfile.5 grammar shows the {num} after "next" as optional; if it
is omitted then there is no next delta node (for example 1.1 or the
@@ -62,6 +83,38 @@ rules.
the current CVS death support, which uses a state "dead"
rather than a "dead" newphrase.
+CVS does use newphrases to implement the `PreservePermissions'
+extension introduced in CVS 1.9.26. The following new keywords are
+defined when PreservePermissions=yes:
+
+ owner
+ group
+ permissions
+ special
+ symlink
+ hardlinks
+
+The contents of the `owner' and `group' field should be a numeric uid
+and a numeric gid, respectively, representing the user and group who
+own the file. The `permissions' field contains an octal integer,
+representing the permissions that should be applied to the file. The
+`special' field contains two words; the first must be either `block'
+or `character', and the second is the file's device number. The
+`symlink' field should be present only in files which are symbolic
+links to other files, and absent on all regular files. The
+`hardlinks' field contains a list of filenames to which the current
+file is linked, in alphabetical order. Because files often contain
+characters special to RCS, like `.' and sometimes even contain spaces
+or eight-bit characters, the filenames in the hardlinks field will
+usually be enclosed in RCS strings. For example:
+
+ hardlinks README @install.txt@ @Installation Notes@;
+
+The hardlinks field should always include the name of the current
+file. That is, in the repository file README,v, any hardlinks fields
+in the delta nodes should include `README'; CVS will not operate
+properly if this is not done.
+
The rules regarding keyword expansion are not documented along with
the rest of the RCS file format; they are documented in the co(1)
manpage in the RCS 5.7 distribution. See also the "Keyword
diff --git a/contrib/cvs/doc/cvs.texinfo b/contrib/cvs/doc/cvs.texinfo
index 55585386264a..5dd2f77b327e 100644
--- a/contrib/cvs/doc/cvs.texinfo
+++ b/contrib/cvs/doc/cvs.texinfo
@@ -22,7 +22,7 @@
@c If one prints US letter on A4, reportedly there is
@c some extra space at the top and/or bottom, and the side
@c margins are a bit narrow, but no text is lost.
-@c
+@c
@c See
@c http://www.ft.uni-erlangen.de/~mskuhn/iso-paper.html
@c for more on paper sizes. Insuring that margins are
@@ -49,6 +49,14 @@
@c problems (as opposed to FIXCVS for CVS problems).
@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* CVS: (cvs). Concurrent Versions System
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@ifinfo
Copyright @copyright{} 1992, 1993 Signum Support AB
Copyright @copyright{} 1993, 1994 Free Software Foundation, Inc.
@@ -65,15 +73,13 @@ notice identical to this one except for the removal of this paragraph
@end ignore
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided also that the
-section entitled ``GNU General Public License'' is included exactly as
-in the original, and provided that the entire resulting derived work is
-distributed under the terms of a permission notice identical to this one.
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions,
-except that the section entitled ``GNU General Public License'' and
-this permission notice may be included in translations approved by the
-Free Software Foundation instead of in the original English.
+except that this permission notice may be stated in a translation
+approved by the Free Software Foundation.
@end ifinfo
@comment The titlepage section does not appear in the Info file.
@@ -103,15 +109,13 @@ are preserved on all copies.
Permission is granted to copy and distribute modified versions of this
manual under the conditions for verbatim copying, provided also that the
-section entitled ``GNU General Public License'' is included exactly as
-in the original, and provided that the entire resulting derived work is
-distributed under the terms of a permission notice identical to this one.
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual
into another language, under the above conditions for modified versions,
-except that the section entitled ``GNU General Public License'' and
-this permission notice may be included in translations approved by the
-Free Software Foundation instead of in the original English.
+except that this permission notice may be stated in a translation
+approved by the Free Software Foundation.
@end titlepage
@comment ================================================================
@@ -121,7 +125,7 @@ Free Software Foundation instead of in the original English.
@ifinfo
@c ---------------------------------------------------------------------
@node Top
-@top
+@top
@c Note: there is a space after that @top command.
@c The texinfo-format-buffer Emacs function and
@c the makeinfo shell command disagree on what arguments
@@ -164,7 +168,6 @@ References.
* Troubleshooting:: Some tips when nothing works
* Credits:: Some of the contributors to this manual
* BUGS:: Dealing with bugs in CVS or this manual
-* Copying:: GNU GENERAL PUBLIC LICENSE
* Index:: Index
@end menu
@@ -257,20 +260,12 @@ http://www.loria.fr/~molli/cvs-index.html
@cindex Mailing list
@cindex List, mailing list
@cindex Newsgroups
-@c Be careful in editing this--it is worded so that
-@c the long -request address is in the middle of a
-@c line, thus avoiding overfull hboxes.
There is a mailing list, known as @w{@code{info-cvs}},
devoted to @sc{cvs}. To subscribe or
-unsubscribe
-@c could add "to the mailing list,"
-send a message to
-@c or "write to"
-@w{@code{info-cvs-request@@prep.ai.mit.edu}}. Please
-be specific about your email address. As of May 1996,
-subscription requests are handled by a busy human
-being, so you cannot expect to be added or removed
-immediately. If you prefer a usenet group, the right
+unsubscribe
+write to
+@w{@code{info-cvs-request@@gnu.org}}.
+If you prefer a usenet group, the right
group is @code{comp.software.config-mgmt} which is for
@sc{cvs} discussions (along with other configuration
management systems). In the future, it might be
@@ -456,10 +451,10 @@ only once they have been proven.
@c people who read in order get dumped right into all
@c manner of hair regarding remote repositories,
@c creating a repository, etc.
-@c
+@c
@c The following was in the old Basic concepts node. I don't
@c know how good a job it does at introducing modules,
-@c or whether they need to be introduced so soon, but
+@c or whether they need to be introduced so soon, but
@c something of this sort might go into some
@c introductory material somewhere.
@ignore
@@ -818,7 +813,7 @@ override the @code{$CVSROOT} environment variable.
Once you've checked a working copy out from the
repository, it will remember where its repository is
(the information is recorded in the
-@file{CVS/Root} file in the working copy).
+@file{CVS/Root} file in the working copy).
The @code{-d} option and the @file{CVS/Root} file both
override the @code{$CVSROOT} environment variable. If
@@ -862,7 +857,7 @@ the file permissions appropriate for the repository.
@c @cindex filenames, legal
@c @cindex legal filenames
@c Somewhere we need to say something about legitimate
-@c characters in filenames in working directory and
+@c characters in filenames in working directory and
@c repository. Not "/" (not even on non-unix). And
@c here is a specific set of issues:
@c Files starting with a - are handled inconsistently. They can not
@@ -894,31 +889,31 @@ directories):
+--@t{local}
| |
| +--@t{cvsroot}
- | | |
+ | | |
| | +--@t{CVSROOT}
- | (administrative files)
- |
+ | (administrative files)
+ |
+--@t{gnu}
- | |
+ | |
| +--@t{diff}
- | | (source code to @sc{gnu} diff)
- | |
+ | | (source code to @sc{gnu} diff)
+ | |
| +--@t{rcs}
| | (source code to @sc{rcs})
- | |
+ | |
| +--@t{cvs}
- | (source code to @sc{cvs})
- |
+ | (source code to @sc{cvs})
+ |
+--@t{yoyodyne}
- |
+ |
+--@t{tc}
| |
| +--@t{man}
| |
| +--@t{testing}
- |
+ |
+--(other Yoyodyne software)
-@end example
+@end example
With the directories are @dfn{history files} for each file
under version control. The name of the history file is
@@ -943,7 +938,7 @@ the @file{yoyodyne/tc} directory might look like:
+--@t{man}
| |
| +--@t{tc.1,v}
- |
+ |
+--@t{testing}
|
+--@t{testpgm.t,v}
@@ -1068,18 +1063,18 @@ of @sc{cvs}; do not rely on the setting of
@code{CVSUMASK} on the client having no effect.
@c FIXME: need to explain what a umask is or cite
@c someplace which does.
-@c
+@c
@c There is also a larger (largely separate) issue
@c about the meaning of CVSUMASK in a non-unix context.
@c For example, whether there is
@c an equivalent which fits better into other
@c protection schemes like POSIX.6, VMS, &c.
-@c
+@c
@c FIXME: Need one place which discusses this
@c read-only files thing. Why would one use -r or
@c CVSREAD? Why would one use watches? How do they
@c interact?
-@c
+@c
@c FIXME: We need to state
@c whether using CVSUMASK removes the need for manually
@c fixing permissions (in fact, if we are going to mention
@@ -1194,6 +1189,10 @@ later; for details see @ref{Watches Compatibility}.
@node Locks
@subsection CVS locks in the repository
+@cindex #cvs.rfl, technical details
+@cindex #cvs.wfl, technical details
+@cindex #cvs.lock, technical details
+@cindex locks, cvs, technical details
For an introduction to CVS locks focusing on
user-visible behavior, see @ref{Concurrency}. The
following section is aimed at people who are writing
@@ -1204,6 +1203,7 @@ described here, like @dfn{read lock}, @dfn{write lock},
and @dfn{deadlock}, you might consult the literature on
operating systems or databases.
+@cindex #cvs.tfl
Any file in the repository with a name starting
with @file{#cvs.rfl} is a read lock. Any file in
the repository with a name starting with
@@ -1277,10 +1277,10 @@ differences.
For each administrative file, in addition to the
@sc{rcs} file, there is also a checked out copy of the
file. For example, there is an @sc{rcs} file
-@file{loginfo,v} and a file @file{loginfo} which
+@file{loginfo,v} and a file @file{loginfo} which
contains the latest revision contained in
@file{loginfo,v}. When you check in an administrative
-file, @sc{cvs} should print
+file, @sc{cvs} should print
@example
cvs commit: Rebuilding administrative file database
@@ -1678,7 +1678,7 @@ It is possible to commit an erroneous administrative
file. You can often fix the error and check in a new
revision, but sometimes a particularly bad error in the
administrative file makes it impossible to commit new
-revisions.
+revisions.
@c @xref{Bad administrative files} for a hint
@c about how to solve such situations.
@c -- administrative file checking--
@@ -1793,6 +1793,8 @@ in the repository; for the most part it is possible to
back them up just like any other files. However, there
are a few issues to consider.
+@cindex locks, cvs, and backups
+@cindex #cvs.rfl, and backups
The first is that to be paranoid, one should either not
use @sc{cvs} during the backup, or have the backup
program lock @sc{cvs} while doing the backup. To not
@@ -1958,7 +1960,7 @@ directory, or two megabytes, whichever is larger.
@c documenting the default configuration of CVS. If it
@c is a "standard" thing to change that value, it
@c should be some kind of run-time configuration.
-@c
+@c
@c See cvsclient.texi for more on the design decision
@c to not have locks in place while waiting for the
@c client, which is what results in memory consumption
@@ -2185,8 +2187,8 @@ to reread its initialization files.
@c this. One strange situation I ran into recently
@c was that if inetd.conf specifies a non-existent
@c cvs (e.g. /usr/local/bin/cvs doesn't exist in
-@c the above example), the client says
-@c cvs-1.8 [login aborted]: unrecognized auth response from harvey:
+@c the above example), the client says
+@c cvs-1.8 [login aborted]: unrecognized auth response from harvey:
@c which is a very unhelpful response (can it be
@c improved? does inetd log somewhere?)
@@ -2299,8 +2301,8 @@ argument or the @code{CVSROOT} environment variable.
password:
@example
-cvs -d :pserver:bach@@chainsaw.yard.com:/usr/local/cvsroot login
-CVS password:
+cvs -d :pserver:bach@@chainsaw.yard.com:/usr/local/cvsroot login
+CVS password:
@end example
The password is checked with the server; if it is
@@ -2531,7 +2533,7 @@ other access methods do not have explicit support for
read-only users because those methods all assume login
access to the repository machine anyway, and therefore
the user can do whatever local file permissions allow
-her to do.)
+her to do.)
A user who has read-only access can do only
those @sc{cvs} operations which do not modify the
@@ -2613,7 +2615,7 @@ read-only access.
@cindex server, temporary directories
While running, the @sc{cvs} server creates temporary
-directories. They are named
+directories. They are named
@example
cvs-serv@var{pid}
@@ -2848,7 +2850,7 @@ vary). See the comments in the script for details.
@node From scratch
@subsection Creating a directory tree from scratch
-@c Also/instead should be documenting
+@c Also/instead should be documenting
@c $ cvs co -l .
@c $ mkdir tc
@c $ cvs add tc
@@ -3106,7 +3108,7 @@ is expected that future names which are special to
starting with @samp{.}, rather than being named analogously to
@code{BASE} and @code{HEAD}, to avoid conflicts with
actual tag names.
-@c Including a character such as % or = has also been
+@c Including a character such as % or = has also been
@c suggested as the naming convention for future
@c special tag names. Starting with . is nice because
@c that is not a legal tag name as far as RCS is concerned.
@@ -3147,7 +3149,7 @@ command in the directory where @file{backend.c}
resides.
@example
-$ cvs tag release-0-4 backend.c
+$ cvs tag rel-0-4 backend.c
T backend.c
$ cvs status -v backend.c
===================================================================
@@ -3160,7 +3162,7 @@ File: backend.c Status: Up-to-date
Sticky Options: (none)
Existing Tags:
- release-0-4 (revision: 1.4)
+ rel-0-4 (revision: 1.4)
@end example
@@ -3170,7 +3172,7 @@ strategic points in the development life-cycle, such as when a release
is made.
@example
-$ cvs tag release-1-0 .
+$ cvs tag rel-1-0 .
cvs tag: Tagging .
T Makefile
T backend.c
@@ -3191,7 +3193,7 @@ retrieve the sources that make up release 1.0 of the module @samp{tc} at
any time in the future:
@example
-$ cvs checkout -r release-1-0 tc
+$ cvs checkout -r rel-1-0 tc
@end example
@noindent
@@ -3278,7 +3280,7 @@ File: driver.c Status: Up-to-date
Version: 1.7.2.1 Sat Dec 5 19:35:03 1992
RCS Version: 1.7.2.1 /u/cvsroot/yoyodyne/tc/driver.c,v
- Sticky Tag: release-1-0-patches (branch: 1.7.2)
+ Sticky Tag: rel-1-0-patches (branch: 1.7.2)
Sticky Date: (none)
Sticky Options: (none)
@@ -3340,7 +3342,7 @@ Checking in file1;
/tmp/cvs-sanity/cvsroot/first-dir/file1,v <-- file1
new revision: 1.3; previous revision: 1.2
done
-$
+$
@end example
@c ---------------------------------------------------------------------
@@ -3422,20 +3424,20 @@ You can create a branch with @code{tag -b}; for
example, assuming you're in a working copy:
@example
-$ cvs tag -b release-1-0-patches
+$ cvs tag -b rel-1-0-patches
@end example
@c FIXME: we should be more explicit about the value of
@c having a tag on the branchpoint. For example
-@c "cvs tag release-1-0-patches-branchpoint" before
+@c "cvs tag rel-1-0-patches-branchpoint" before
@c the "cvs tag -b". This points out that
-@c release-1-0-patches is a pretty awkward name for
+@c rel-1-0-patches is a pretty awkward name for
@c this example (more so than for the rtag example
@c below).
This splits off a branch based on the current revisions
in the working copy, assigning that branch the name
-@samp{release-1-0-patches}.
+@samp{rel-1-0-patches}.
It is important to understand that branches get created
in the repository, not in the working copy. Creating a
@@ -3448,12 +3450,12 @@ You can also create a branch without reference to any
working copy, by using @code{rtag}:
@example
-$ cvs rtag -b -r release-1-0 release-1-0-patches tc
+$ cvs rtag -b -r rel-1-0 rel-1-0-patches tc
@end example
-@samp{-r release-1-0} says that this branch should be
+@samp{-r rel-1-0} says that this branch should be
rooted at the revision that
-corresponds to the tag @samp{release-1-0}. It need not
+corresponds to the tag @samp{rel-1-0}. It need not
be the most recent revision -- it's often useful to
split a branch off an old revision (for example, when
fixing a bug in a past release otherwise known to be
@@ -3462,13 +3464,13 @@ stable).
As with @samp{tag}, the @samp{-b} flag tells
@code{rtag} to create a branch (rather than just a
symbolic revision name). Note that the numeric
-revision number that matches @samp{release-1-0} will
+revision number that matches @samp{rel-1-0} will
probably be different from file to file.
So, the full effect of the command is to create a new
-branch -- named @samp{release-1-0-patches} -- in module
+branch -- named @samp{rel-1-0-patches} -- in module
@samp{tc}, rooted in the revision tree at the point tagged
-by @samp{release-1-0}.
+by @samp{rel-1-0}.
@c - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@node Accessing branches
@@ -3491,21 +3493,21 @@ To check out a branch from the repository, invoke
the tag name of the branch (@pxref{Creating a branch}):
@example
-$ cvs checkout -r release-1-0-patches tc
+$ cvs checkout -r rel-1-0-patches tc
@end example
Or, if you already have a working copy, you can switch
it to a given branch with @samp{update -r}:
@example
-$ cvs update -r release-1-0-patches tc
+$ cvs update -r rel-1-0-patches tc
@end example
or equivalently:
@example
$ cd tc
-$ cvs update -r release-1-0-patches
+$ cvs update -r rel-1-0-patches
@end example
It does not matter if the working copy was originally
@@ -3535,34 +3537,34 @@ File: driver.c Status: Up-to-date
Version: 1.7 Sat Dec 5 18:25:54 1992
RCS Version: 1.7 /u/cvsroot/yoyodyne/tc/driver.c,v
- Sticky Tag: release-1-0-patches (branch: 1.7.2)
+ Sticky Tag: rel-1-0-patches (branch: 1.7.2)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
- release-1-0-patches (branch: 1.7.2)
- release-1-0 (revision: 1.7)
+ rel-1-0-patches (branch: 1.7.2)
+ rel-1-0 (revision: 1.7)
===================================================================
File: backend.c Status: Up-to-date
Version: 1.4 Tue Dec 1 14:39:01 1992
RCS Version: 1.4 /u/cvsroot/yoyodyne/tc/backend.c,v
- Sticky Tag: release-1-0-patches (branch: 1.4.2)
+ Sticky Tag: rel-1-0-patches (branch: 1.4.2)
Sticky Date: (none)
Sticky Options: (none)
Existing Tags:
- release-1-0-patches (branch: 1.4.2)
- release-1-0 (revision: 1.4)
- release-0-4 (revision: 1.4)
+ rel-1-0-patches (branch: 1.4.2)
+ rel-1-0 (revision: 1.4)
+ rel-0-4 (revision: 1.4)
@end example
Don't be confused by the fact that the branch numbers
for each file are different (@samp{1.7.2} and
@samp{1.4.2} respectively). The branch tag is the
-same, @samp{release-1-0-patches}, and the files are
+same, @samp{rel-1-0-patches}, and the files are
indeed on the same branch. The numbers simply reflect
the point in each file's revision history at which the
branch was made. In the above example, one can deduce
@@ -3592,7 +3594,7 @@ However, @sc{cvs} is not limited to linear development. The
@dfn{revision tree} can be split into @dfn{branches},
where each branch is a self-maintained line of
development. Changes made on one branch can easily be
-moved back to the main trunk.
+moved back to the main trunk.
Each branch has a @dfn{branch number}, consisting of an
odd number of period-separated decimal integers. The
@@ -3933,7 +3935,7 @@ structure:
| +--@t{CVS}
| | (internal @sc{cvs} files)
| +--@t{tc.1}
- |
+ |
+--@t{testing}
|
+--@t{CVS}
@@ -3956,7 +3958,7 @@ cvs update testing/testpgm.t testing/test2.t
@item
@samp{cvs update testing man} updates all files in the
-subdirectories
+subdirectories
@item
@samp{cvs update .} or just @samp{cvs update} updates
@@ -4038,7 +4040,7 @@ not recursive. You cannot even type @samp{cvs add
foo/bar}! Instead, you have to
@c FIXCVS: This is, of course, not a feature. It is
@c just that no one has gotten around to fixing "cvs add
-@c foo/bar".
+@c foo/bar".
@example
$ cd foo
@@ -4084,7 +4086,7 @@ For example, the following commands add the file
@file{backend.c} to the repository:
@c This example used to specify
-@c -m "Optimizer and code generation passes."
+@c -m "Optimizer and code generation passes."
@c to the cvs add command, but that doesn't work
@c client/server (see log2 in sanity.sh). Should fix CVS,
@c but also seems strange to document things which
@@ -4347,7 +4349,7 @@ to remove @var{old} from the repository, and add
@example
$ mv @var{old} @var{new}
$ cvs remove @var{old}
-$ cvs add @var{new}
+$ cvs add @var{new}
$ cvs commit -m "Renamed @var{old} to @var{new}" @var{old} @var{new}
@end example
@@ -4552,7 +4554,7 @@ source. You are not affected by modifications made by
others until you decide to incorporate those changes
(via the @code{update} command---@pxref{update}).
-@item
+@item
Traceability---When something has changed, you can
always see @emph{exactly} what changed.
@end itemize
@@ -4917,7 +4919,7 @@ check it in as a binary file. The @code{cvs
admin -kb} command sets the default keyword
substitution method for this file, but it does not
alter the working copy of the file that you have. If you need to
-cope with line endings (that is, you are using
+cope with line endings (that is, you are using
@sc{cvs} on a non-unix system), then you need to
check in a new copy of the file, as shown by the
@code{cvs commit} command above.
@@ -4961,7 +4963,7 @@ considerably with the operating system.
@c
@c Another, probably better, way to tell is to read the
@c file in text mode, write it to a temp file in text
-@c mode, and then do a binary mode compare of the two
+@c mode, and then do a binary mode compare of the two
@c files. If they differ, it is a binary file. This
@c might have problems on VMS (or some other system
@c with several different text modes), but in general
@@ -5210,7 +5212,7 @@ resolve the conflict as described in @ref{Conflicts example}.
@sc{Cvs} doesn't know anything about this file. For
example, you have created a new file and have not run
@code{add}.
-@c
+@c
@c "Entry Invalid" and "Classify Error" are also in the
@c status.c. The latter definitely indicates a CVS bug
@c (should it be worded more like "internal error" so
@@ -5496,7 +5498,7 @@ check in the file.
@c The old behavior was really icky; the only way out
@c was to start hacking on
@c the @code{CVS/Entries} file or other such workarounds.
-@c
+@c
@c If the timestamp thing isn't considered nice enough,
@c maybe there should be a "cvs resolved" command
@c which clears the conflict indication. For a nice user
@@ -5531,7 +5533,7 @@ newsgroup.
@node Concurrency
@section Several developers simultaneously attempting to run CVS
-@cindex locks, cvs
+@cindex locks, cvs, introduction
@c For a discussion of *why* CVS creates locks, see
@c the comment at the start of src/lock.c
If several developers try to run @sc{cvs} at the same
@@ -5541,6 +5543,9 @@ time, one may get the following message:
[11:43:23] waiting for bach's lock in /usr/local/cvsroot/foo
@end example
+@cindex #cvs.rfl, removing
+@cindex #cvs.wfl, removing
+@cindex #cvs.lock, removing
@sc{cvs} will try again every 30 seconds, and either
continue with the operation or print the message again,
if it still needs to wait. If a lock seems to stick
@@ -5549,8 +5554,8 @@ holding the lock and ask them about the cvs command
they are running. If they aren't running a cvs
command, look in the repository directory mentioned in
the message and remove files which they own whose names
-start with @file{#cvs.tfl}, @file{#cvs.rfl}, or
-@file{#cvs.wfl}.
+start with @file{#cvs.rfl},
+@file{#cvs.wfl}, or @file{#cvs.lock}.
Note that these locks are to protect @sc{cvs}'s
internal data structures and have no relationship to
@@ -5857,7 +5862,7 @@ receive notifications, she should specify @code{-a none}.
The @var{files} and options are processed as for the @code{cvs
watch} commands.
-@strong{Caution:} If the @var{PreservePermissions}
+@strong{Caution:} If the @code{PreservePermissions}
option is enabled in the repository (@pxref{config}),
CVS will not change the permissions on any of the
@var{files}. The reason for this change is to ensure
@@ -6110,7 +6115,7 @@ a new revision of the file.
@section Keyword List
@cindex Keyword List
-@c FIXME: need some kind of example here I think,
+@c FIXME: need some kind of example here I think,
@c perhaps in a
@c "Keyword intro" node. The intro in the "Keyword
@c substitution" node itself seems OK, but to launch
@@ -6170,7 +6175,7 @@ file contains
* $@asis{}Log: frob.c,v $
* Revision 1.1 1997/01/03 14:23:51 joe
* Add the superfrobnicate option
- *
+ *
*/
@end example
@@ -6212,36 +6217,21 @@ relevant text string, such as @code{$@asis{Id}$}, inside the
file, and commit the file. @sc{cvs} will automatically
expand the string as part of the commit operation.
-@need 800
-It is common to embed @code{$@asis{}Id$} string in the
-C source code. This example shows the first few lines
-of a typical file, after keyword substitution has been
-performed:
-
-@c Hmm. Someone says that
-@c "static const char rcsid[] = "foo"
-@c is a simpler way to shut up GCC. But I really
-@c suspect that we should be avoiding specifics in general
-@c (what about Java, Ada, and who knows how many other
-@c languages? What about #pragma ident and #ident and
-@c other non-GCC C compilers? What about the VMS help
-@c system and other systems which take text and convert
-@c them to a generated file?
-@example
-static char *rcsid="$@asis{}Id: samp.c,v 1.5 1993/10/19 14:57:32 ceder Exp $";
-/* @r{The following lines will prevent @code{gcc} version 2.@var{x}}
- @r{from issuing an "unused variable" warning}. */
-#if __GNUC__ == 2
-#define USE(var) static void * use_##var = (&use_##var, (void *) &var)
-USE (rcsid);
-#endif
-@end example
-
-Even though a clever optimizing compiler could remove
-the unused variable @code{rcsid}, most compilers tend
-to include the string in the binary. Some compilers
-have a @code{#pragma} directive to include literal text
-in the binary.
+It is common to embed the @code{$@asis{}Id$} string in
+the source files so that it gets passed through to
+generated files. For example, if you are managing
+computer program source code, you might include a
+variable which is initialized to contain that string.
+Or some C compilers may provide a @code{#pragma ident}
+directive. Or a document management system might
+provide a way to pass a string through to generated
+files.
+
+@c Would be nice to give an example, but doing this in
+@c portable C is not possible and the problem with
+@c picking any one language (VMS HELP files, Ada,
+@c troff, whatever) is that people use CVS for all
+@c kinds of files.
@cindex Ident (shell command)
The @code{ident} command (which is part of the @sc{rcs}
@@ -6282,7 +6272,7 @@ Keyword substitution has its disadvantages. Sometimes
you might want the literal text string
@samp{$@asis{}Author$} to appear inside a file without
@sc{cvs} interpreting it as a keyword and expanding it
-into something like @samp{$@asis{}Author: ceder $}.
+into something like @samp{$@asis{}Author: ceder $}.
There is unfortunately no way to selectively turn off
keyword substitution. You can use @samp{-ko}
@@ -6453,7 +6443,7 @@ made by the vendor, you commit it on the vendor branch
and copy the modifications onto the main trunk.
Use the @code{import} command to create and update
-the vendor branch. After a successful @code{import}
+the vendor branch. When you import a new file,
the vendor branch is made the `head' revision, so
anyone that checks out a copy of the file gets that
revision. When a local modification is committed it is
@@ -6767,6 +6757,13 @@ is Odin (see
@node Special Files
@chapter Special Files
+@cindex special files
+@cindex device nodes
+@cindex ownership, saving in CVS
+@cindex permissions, saving in CVS
+@cindex hard links
+@cindex symbolic links
+
In normal circumstances, CVS works only with regular
files. Every file in a project is assumed to be
persistent; it must be possible to open, read and close
@@ -6778,34 +6775,67 @@ if the device file cannot be opened, CVS will refuse to
handle it. Files also lose their ownerships and
permissions during repository transactions.
-If the configuration variable @var{PreservePermissions}
+If the configuration variable @code{PreservePermissions}
(@pxref{config}) is set in the repository, CVS will
-preserve file permissions and ownership across
-repository transactions, and will permit checkin and
-checkout of special files and symbolic links.
-
-Using this option affects the behavior of CVS in
-several ways. First, some of the new operations
-supported by CVS are not accessible to all users. In
-particular, file ownership and special file
-characteristics may only be changed by the superuser.
-When the @var{PreservePermissions} configuration
-variable is set, therefore, users will have to be
-`root' in order to perform CVS operations.
+save the following file characteristics in the
+repository:
+
+@itemize @bullet
+@item user and group ownership
+@item permissions
+@item major and minor device numbers
+@item symbolic links
+@item hard link structure
+@end itemize
+
+Using the @code{PreservePermissions} option affects the
+behavior of CVS in several ways. First, some of the
+new operations supported by CVS are not accessible to
+all users. In particular, file ownership and special
+file characteristics may only be changed by the
+superuser. When the @code{PreservePermissions}
+configuration variable is set, therefore, users will
+have to be `root' in order to perform CVS operations.
+
+When @code{PreservePermissions} is in use, some CVS
+operations (such as @samp{cvs status}) will not
+recognize a file's hard link structure, and so will
+emit spurious warnings about mismatching hard links.
+The reason is that CVS's internal structure does not
+make it easy for these operations to collect all the
+necessary data about hard links, so they check for file
+conflicts with inaccurate data.
A more subtle difference is that CVS considers a file
to have changed only if its contents have changed
(specifically, if the modification time of the working
file does not match that of the repository's file).
-Therefore, if only the permissions or ownership have
-changed, or if a device's major or minor numbers have
-changed, CVS will not notice. In order to commit such
-a change to the repository, you must force the commit
-with @samp{cvs commit -f}. This also means that if a
-file's permissions have changed and the repository file
-is newer than the working copy, performing @samp{cvs
-update} will silently change the permissions on the
-working copy.
+Therefore, if only the permissions, ownership or hard
+linkage have changed, or if a device's major or minor
+numbers have changed, CVS will not notice. In order to
+commit such a change to the repository, you must force
+the commit with @samp{cvs commit -f}. This also means
+that if a file's permissions have changed and the
+repository file is newer than the working copy,
+performing @samp{cvs update} will silently change the
+permissions on the working copy.
+
+Changing hard links in a CVS repository is particularly
+delicate. Suppose that file @file{foo} is linked to
+file @file{old}, but is later relinked to file
+@file{new}. You can wind up in the unusual situation
+where, although @file{foo}, @file{old} and @file{new}
+have all had their underlying link patterns changed,
+only @file{foo} and @file{new} have been modified, so
+@file{old} is not considered a candidate for checking
+in. It can be very easy to produce inconsistent
+results this way. Therefore, we recommend that when it
+is important to save hard links in a repository, the
+prudent course of action is to @code{touch} any file
+whose linkage or status has changed since the last
+checkin. Indeed, it may be wise to @code{touch *}
+before each commit in a directory with complex hard
+link structures.
It is worth noting that only regular files may
be merged, for reasons that hopefully are obvious. If
@@ -6818,9 +6848,9 @@ differences between these files, since no meaningful
textual comparisons can be made on files which contain
no text.
-The PreservePermissions features do not work with
-client/server @sc{cvs}. Another limitation is that
-hard links must be to other files within the same
+The @code{PreservePermissions} features do not work
+with client/server @sc{cvs}. Another limitation is
+that hard links must be to other files within the same
directory; hard links across directories are not
supported.
@@ -6976,7 +7006,7 @@ the file. So if this is the contents of the user's
log -N
diff -u
update -P
-co -P
+checkout -P
@end example
@noindent
@@ -7108,7 +7138,7 @@ suppressed.
@cindex read-only files, and -r
@item -r
-Make new working files files read-only. Same effect
+Make new working files read-only. Same effect
as if the @code{$CVSREAD} environment variable is set
(@pxref{Environment variables}). The default is to
make working files writable, unless watches are on
@@ -7200,7 +7230,7 @@ further updates in the same directory will use the same date
@code{diff}, @code{export}, @code{history},
@code{rdiff}, @code{rtag}, and @code{update} commands.
(The @code{history} command uses this option in a
-slightly different way; @pxref{history options}).
+slightly different way; @pxref{history options}).
@c What other formats should we accept? I don't want
@c to start accepting a whole mess of non-standard
@@ -7218,19 +7248,19 @@ slightly different way; @pxref{history options}).
@c VMS to support this format (and if we're going to do
@c that, better to make CVS support it on all
@c platforms. Maybe).
-@c
+@c
@c NOTE: The tar manual has some documentation for
@c getdate.y (just for our info; we don't want to
@c attempt to document all the formats accepted by
@c getdate.y).
-@c
+@c
@c One more note: In output, CVS should consistently
@c use one date format, and that format should be one that
@c it accepts in input as well. The former isn't
@c really true (see survey below), and I'm not
@c sure that either of those formats is accepted in
-@c input.
-@c
+@c input.
+@c
@c cvs log
@c current 1996/01/02 13:45:31
@c Internet 02 Jan 1996 13:45:31 UT
@@ -7279,7 +7309,7 @@ RFC1123).
@c So I don't know....
@c A few specific issues: (1) Maybe should reassure
@c people that years after 2000
-@c work (they are in the testsuite, so they do indeed
+@c work (they are in the testsuite, so they do indeed
@c work). (2) What do two digit years
@c mean? Where do we accept them? (3) Local times can
@c be ambiguous or nonexistent if they fall during the
@@ -7337,7 +7367,7 @@ accept all of them.
@c message from "cvs import" suggesting a merge
@c command). What else? Probably some/all of the "3
@c weeks ago" family.
-@c
+@c
@c Maybe at
@c some point have CVS start give warnings on "unofficial"
@c formats (many of which might be typos or user
@@ -7366,7 +7396,7 @@ normally ignore files that do not contain the tag (or did not
exist prior to the date) that you specified. Use the @samp{-f} option
if you want files retrieved even when there is no match for the
tag or date. (The most recent revision of the file
-will be used).
+will be used).
@need 800
@samp{-f} is available with these commands:
@@ -7396,7 +7426,7 @@ The @samp{-k} option is available with the @code{add},
@item -l
Local; run only in current working directory, rather than
-recursing through subdirectories.
+recursing through subdirectories.
@strong{Warning:} this is not the same
as the overall @samp{cvs -l} option, which you can specify to the
@@ -7420,7 +7450,7 @@ Available with the following commands: @code{add},
@item -n
Do not run any checkout/commit/tag program. (A program can be
specified to run on each of these activities, in the modules
-database (@pxref{modules}); this option bypasses it).
+database (@pxref{modules}); this option bypasses it).
@strong{Warning:} this is not the same as the overall @samp{cvs -n}
option, which you can specify to the left of a cvs command!
@@ -7460,11 +7490,8 @@ revision you last checked out into the current working directory.
@c for all cvs commands except diff. For diff, it
@c seems to be (a) the head of the trunk (or the default
@c branch?) if there is no sticky tag, (b) the head of the
-@c branch if there is a branch sticky tag, and (c) the
-@c same as BASE if there is a non-branch sticky tag. (c)
-@c would appear to be strange, maybe accidental, and so there would
-@c presumably be
-@c little problem changing it. (b) is ugly as it differs
+@c branch for the sticky tag, if there is a sticky tag.
+@c (b) is ugly as it differs
@c from what HEAD means for other commands, but people
@c and/or scripts are quite possibly used to it.
@c See "head" tests in sanity.sh.
@@ -8400,37 +8427,56 @@ One or both @samp{-r} options can be replaced by a
The following options specify the format of the
output. They have the same meaning as in GNU diff.
-@code{-a} @code{-b} @code{-B} @code{-c} @w{@code{-C}
-@var{nlines}} @code{-d} @code{-e} @code{-f} @code{-h}
-@code{-H} @code{-i} @code{-n} @code{-N} @code{-p}
-@code{-s} @code{-t} @code{-u} @code{-U} @var{nlines}
-@w{@code{-F} @var{regexp}} @w{@code{-I} @var{regexp}}
-@w{@code{-L} @var{label}} @code{-T} @w{@code{-V}
-@var{arg}} @w{@code{-W} @var{columns}} @code{-w}
-@code{-y} @code{-0} @code{-1} @code{-2} @code{-3}
-@code{-4} @code{-5} @code{-6} @code{-7} @code{-8}
-@code{-9} @code{--binary} @code{--brief}
-@code{--changed-group-format=@var{arg}}
-@code{--context[=@var{lines}]} @code{--ed}
-@code{--expand-tabs} @code{--forward-ed}
-@code{--horizon-lines=@var{arg}}
-@code{--ifdef=@var{arg}}
-@code{--ignore-all-space} @code{--ignore-blank-lines}
-@code{--ignore-case}
-@code{--ignore-matching-lines=@var{regexp}}
-@code{--ignore-space-change} @code{--initial-tab}
-@code{--label=@var{label}} @code{--left-column}
-@code{--minimal} @code{--new-file}
-@code{--new-line-format=@var{arg}}
-@code{--old-line-format=@var{arg}} @code{--paginate}
-@code{--rcs} @code{--report-identical-files}
-@code{--code-c-function} @code{--side-by-side}
-@code{--show-function-line=@var{regexp}}
-@code{--speed-large-files}
-@code{--suppress-common-lines} @code{--text}
-@code{--unchanged-group-format=@var{arg}}
-@code{--unified[=@var{lines}]}
-@code{--width=@var{columns}}
+@example
+-0 -1 -2 -3 -4 -5 -6 -7 -8 -9
+--binary
+--brief
+--changed-group-format=@var{arg}
+-c
+ -C @var{nlines}
+ --context[=@var{lines}]
+-e --ed
+-t --expand-tabs
+-f --forward-ed
+--horizon-lines=@var{arg}
+--ifdef=@var{arg}
+-w --ignore-all-space
+-B --ignore-blank-lines
+-i --ignore-case
+-I @var{regexp}
+ --ignore-matching-lines=@var{regexp}
+-h
+-b --ignore-space-change
+-T --initial-tab
+-L @var{label}
+ --label=@var{label}
+--left-column
+-d --minimal
+-N --new-file
+--new-line-format=@var{arg}
+--old-line-format=@var{arg}
+--paginate
+-n --rcs
+-s --report-identical-files
+-p
+--show-c-function
+-y --side-by-side
+-F @var{regexp}
+--show-function-line=@var{regexp}
+-H --speed-large-files
+--suppress-common-lines
+-a --text
+--unchanged-group-format=@var{arg}
+-u
+ -U @var{nlines}
+ --unified[=@var{lines}]
+@c FIXCVS: This option is accepted by src/diff.c but
+@c not diff/diff.c; it would appear that any attempt to
+@c use it would get an error.
+-V @var{arg}
+-W @var{columns}
+ --width=@var{columns}
+@end example
@c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
@node diff examples
@@ -8608,7 +8654,7 @@ kind of report is generated:
Report on each time commit was used (i.e., each time
the repository was modified).
-@item -e
+@item -e
Everything (all record types). Equivalent to
specifying @samp{-x} with all record types. Of course,
@samp{-e} will also include record types which are
@@ -8629,9 +8675,9 @@ Report on all tags.
@item -x @var{type}
Extract a particular set of record types @var{type} from the @sc{cvs}
history. The types are indicated by single letters,
-which you may specify in combination.
+which you may specify in combination.
-Certain commands have a single record type:
+Certain commands have a single record type:
@table @code
@item F
@@ -8650,7 +8696,7 @@ One of four record types may result from an update:
@table @code
@item C
A merge was necessary but collisions were
-detected (requiring manual merging).
+detected (requiring manual merging).
@item G
A merge was necessary and it succeeded.
@item U
@@ -8894,7 +8940,7 @@ be changed, but if there is a consensus on what it
should be changed to, it doesn't seem to be apparent.
(Various options in the @file{modules} file can be used
to recreate symbolic links on checkout, update, etc.;
-@pxref{modules}.)
+@pxref{modules}.)
@end table
@c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
@@ -9018,7 +9064,7 @@ Do not print the list of tags for this file. This
option can be very useful when your site uses a lot of
tags, so rather than "more"'ing over 3 pages of tag
information, the log information is presented without
-tags at all.
+tags at all.
@item -R
Print only the name of the @sc{rcs} file.
@@ -9027,7 +9073,7 @@ Print only the name of the @sc{rcs} file.
@c being explicitly documented here) is potentially
@c confusing; it shows the log message to get from the
@c previous revision to that revision. "-r1.3 -r1.6"
-@c (equivalent to "-r1.3,1.6") is even worse; it
+@c (equivalent to "-r1.3,1.6") is even worse; it
@c prints the messages to get from 1.2 to 1.3 and 1.5
@c to 1.6. By analogy with "cvs diff", users might
@c expect that it is more like specifying a range.
@@ -9056,7 +9102,7 @@ the same branch).
Revisions from the beginning of the branch up to
and including @var{rev}.
-@item @var{rev}:
+@item @var{rev}:
Revisions starting with @var{rev} to the end of the
branch containing @var{rev}.
@@ -9303,7 +9349,7 @@ if it is non-empty!
Before @code{release} releases your sources it will
print a one-line message for any file that is not
-up-to-date.
+up-to-date.
@strong{Warning:} Any new directories that you have
created, but not added to the @sc{cvs} directory hierarchy
@@ -9409,7 +9455,7 @@ Only useful with the @samp{-D @var{date}} or @samp{-r @var{tag}}
flags. If no matching revision is found, use the most
recent revision (instead of ignoring the file).
-@item -F
+@item -F
Overwrite an existing tag of the same name on a
different revision.
@c FIXME: Needs an example, and/or more explanation.
@@ -9550,7 +9596,7 @@ them):
@c "How do I move or rename a magic branch tag?"
@c in the FAQ (I think the issues it talks about still
@c apply, but this could use some sanity.sh work).
-@item -F
+@item -F
Overwrite an existing tag of the same name on a
different revision.
@c FIXME: See "rtag -F" for comments on this.
@@ -9684,7 +9730,7 @@ See @ref{Sticky tags}, for more information on sticky tags/dates.
Create any directories that exist in the repository if
they're missing from the working directory. Normally,
@code{update} acts only on directories and files that
-were already enrolled in your working directory.
+were already enrolled in your working directory.
This is useful for updating directories that were
created in the repository since the initial checkout;
@@ -9876,13 +9922,13 @@ options}.
Do not change any files. See @ref{Global options}.
@item -Q
-Cause the command to be really quiet. See @ref{Global options}.
+Be really quiet. See @ref{Global options}.
@item -q
-Cause the command to be somewhat quiet. See @ref{Global options}.
+Be somewhat quiet. See @ref{Global options}.
@item -r
-Make new working files files read-only. See @ref{Global options}.
+Make new working files read-only. See @ref{Global options}.
@item -s @var{variable}=@var{value}
Set a user variable. See @ref{Variables}.
@@ -9947,7 +9993,7 @@ Initial revision
@c The idea behind this table is that we want each item
@c to be a sentence or two at most. Preferably a
@c single line.
-@c
+@c
@c In some cases refs to "foo options" are just to get
@c this thing written quickly, not because the "foo
@c options" node is really the best place to point.
@@ -10161,7 +10207,7 @@ Diff revision for @var{rev1} against working file. See
@ref{diff options}.
@item -r @var{rev2}
-Diff rev1/date1 against rev2. See @ref{diff options}.
+Diff @var{rev1}/@var{date1} against @var{rev2}. See @ref{diff options}.
@end table
@item edit [@var{options}] [@var{files}@dots{}]
@@ -10351,7 +10397,7 @@ Do not list tags. See @ref{log options}.
@item -R
Only print name of RCS file. See @ref{log options}.
-@item -r @var{revs}
+@item -r@var{revs}
Only list revisions @var{revs}. See @ref{log options}.
@item -s @var{states}
@@ -10361,7 +10407,7 @@ Only list revisions with specified states. See @ref{log options}.
Only print header and descriptive text. See @ref{log
options}.
-@item -w @var{logins}
+@item -w@var{logins}
Only list revisions checked in by specified logins. See @ref{log options}.
@end table
@@ -10668,7 +10714,7 @@ file, which defines the modules inside the repository.
* commit files:: The commit support files
* commitinfo:: Pre-commit checking
* verifymsg:: How are log messages evaluated?
-* editinfo:: Specifying how log messages are created
+* editinfo:: Specifying how log messages are created
(obsolete)
* loginfo:: Where should log messages be sent?
* rcsinfo:: Templates for the log messages
@@ -10897,12 +10943,16 @@ before the name of each directory to be excluded.
For example, if the modules file contains:
@example
-exmodule -a first-dir !first-dir/sdir
+exmodule -a !first-dir/sdir first-dir
@end example
then checking out the module @samp{exmodule} will check
out everything in @samp{first-dir} except any files in
the subdirectory @samp{first-dir/sdir}.
+@c Note that the "!first-dir/sdir" sometimes must be listed
+@c before "first-dir". That seems like a probable bug, in which
+@c case perhaps it should be fixed (to allow either
+@c order) rather than documented. See modules4 in testsuite.
@node Module options
@appendixsubsec Module options
@@ -11024,11 +11074,13 @@ not work with client/server @sc{cvs}.
The @file{cvswrappers} also has a @samp{-m} option to
specify the merge methodology that should be used when
-the file is updated. @code{MERGE} means the usual
+a non-binary file is updated. @code{MERGE} means the usual
@sc{cvs} behavior: try to merge the files. @code{COPY}
means that @code{cvs update} will refuse to merge
files, as it also does for files specified as binary
-with @samp{-kb}. CVS will provide the user with the
+with @samp{-kb} (but if the file is specified as
+binary, there is no need to specify @samp{-m 'COPY'}).
+CVS will provide the user with the
two versions of the files, and require the user using
mechanisms outside @sc{cvs}, to insert any necessary
changes. @strong{WARNING}: do not use @code{COPY} with
@@ -11135,7 +11187,7 @@ cvs import -I ! -W "*.exe -k 'b'" first-dir vendortag reltag
@c ::::::::::::::::::
@c *.t12 -m 'COPY'
@c *.t[0-9][0-9] -f 'gunzipcp %s' -t 'gzipcp %s %s' -m 'COPY'
-@c
+@c
@c ::::::::::::::::::
@c gunzipcp
@c ::::::::::::::::::
@@ -11335,8 +11387,8 @@ repositories}).
@cindex verifymsg (admin file)
@cindex log message, verifying
-Once you have entered a log message, you can evaluate
-that message to check for specific content, such as
+Once you have entered a log message, you can evaluate
+that message to check for specific content, such as
a bug ID. Use the @file{verifymsg} file to
specify a program that is used to verify the log message.
This program could be a simple script that checks
@@ -11385,7 +11437,7 @@ free text. The following template is found in the file
@file{/usr/cvssupport/tc.template}.
@example
-BugId:
+BugId:
@end example
The script @file{/usr/cvssupport/bugid.verify} is used to
@@ -11396,7 +11448,7 @@ evaluate the log message.
#
# bugid.verify filename
#
-# Verify that the log message contains a valid bugid
+# Verify that the log message contains a valid bugid
# on the first line.
#
if head -1 < $1 | grep '^BugId:[ ]*[0-9][0-9]*$' > /dev/null; then
@@ -11500,7 +11552,7 @@ free text. The following template is found in the file
@file{/usr/cvssupport/tc.template}.
@example
-BugId:
+BugId:
@end example
The script @file{/usr/cvssupport/bugid.edit} is used to
@@ -11570,7 +11622,7 @@ matching regular expression or @samp{DEFAULT}.
The first matching regular expression is used.
@xref{commit files}, for a description of the syntax of
-the @file{loginfo} file.
+the @file{loginfo} file.
The user may specify a format string as
part of the filter. The string is composed of a
@@ -11627,22 +11679,23 @@ repositories}).
@appendixsubsec Loginfo example
The following @file{loginfo} file, together with the
-tiny shell-script below, appends all log messages
+tiny shell-script below, appends all log messages
to the file @file{$CVSROOT/CVSROOT/commitlog},
and any commits to the administrative files (inside
the @file{CVSROOT} directory) are also logged in
@file{/usr/adm/cvsroot-log}.
-@c and mailed to @t{ceder}.
+Commits to the @file{prog1} directory are mailed to @t{ceder}.
@c FIXME: is it a CVS feature or bug that only the
@c first matching line is used? It is documented
-@c above, but is it useful? This example (with the
-@c mail to ceder put back in) is awkward to write if
+@c above, but is it useful? For example, if we wanted
+@c to run both "cvs-log" and "Mail" for the CVSROOT
+@c directory, it is kind of awkward if
@c only the first matching line is used.
@example
-ALL /usr/local/bin/cvs-log $CVSROOT/CVSROOT/commitlog
-@c ^CVSROOT Mail -s %s ceder
+ALL /usr/local/bin/cvs-log $CVSROOT/CVSROOT/commitlog $USER
^CVSROOT /usr/local/bin/cvs-log /usr/adm/cvsroot-log
+^prog1 Mail -s %s ceder
@end example
The shell-script @file{/usr/local/bin/cvs-log} looks
@@ -11651,10 +11704,10 @@ like this:
@example
#!/bin/sh
(echo "------------------------------------------------------";
- echo -n $USER" ";
+ echo -n $2" ";
date;
echo;
- sed '1s+'$@{CVSROOT@}'++') >> $1
+ cat) >> $1
@end example
@node Keeping a checked out copy
@@ -11808,7 +11861,7 @@ patterns is:
*~ #* .#* ,* _$* *$
*.old *.bak *.BAK *.orig *.rej .del-*
*.a *.olb *.o *.obj *.so *.exe
- *.Z *.elc *.ln
+ *.Z *.elc *.ln
core
@end example
@@ -12018,6 +12071,24 @@ symbolic links, file permissions and ownerships in the
repository. The default value is @samp{no}.
@xref{Special Files} for the full implications of using
this keyword.
+
+@cindex TopLevelAdmin, in CVSROOT/config
+@item TopLevelAdmin=@var{value}
+Modify the @samp{checkout} command to create a
+@samp{CVS} directory at the top level of the new
+working directory, in addition to @samp{CVS}
+directories created within checked-out directories.
+The default value is @samp{no}.
+
+This option is useful if you find yourself performing
+many commands at the top level of your working
+directory, rather than in one of the checked out
+subdirectories. The @samp{CVS} directory created there
+will mean you don't have to specify @samp{CVSROOT} for
+each command. It also provides a place for the
+@samp{CVS/Template} file (@pxref{Working directory
+storage}).
+
@end table
@c ---------------------------------------------------------------------
@@ -12062,7 +12133,7 @@ can supply it on the command line: @samp{cvs -d cvsroot
cvs_command@dots{}} Once you have checked out a working
directory, @sc{cvs} stores the appropriate root (in
the file @file{CVS/Root}), so normally you only need to
-worry about this when initially checking out a working
+worry about this when initially checking out a working
directory.
@item $EDITOR
@@ -12204,7 +12275,7 @@ to use the optional developer communication features.
@c state.
@c Note: this is tricky to document without confusing
@c people--need to carefully say what CVS version we
-@c are talking about and keep in mind the distinction
+@c are talking about and keep in mind the distinction
@c between a
@c repository created with 1.3 and on which one now
@c uses 1.5+, and a repository on which one wants to
@@ -12215,7 +12286,7 @@ to use the optional developer communication features.
@c Not sure whether this should produce a warning or
@c something, and probably needs further thought, but
@c it would appear that the situation can be detected.
-@c
+@c
@c We might want to separate out the 1.3 compatibility
@c section (for repository & working directory) from the
@c rest--that might help avoid confusing people who
@@ -12320,6 +12391,17 @@ The exact format of this message may vary depending on
your system. It indicates a bug in @sc{cvs}, which can
be handled as described in @ref{BUGS}.
+@item cvs @var{command}: conflict: removed @var{file} was modified by second party
+This message indicates that you removed a file, and
+someone else modified it. To resolve the conflict,
+first run @samp{cvs add @var{file}}. If desired, look
+at the other party's modification to decide whether you
+still want to remove it. If you don't want to remove
+it, stop here. If you do want to remove it, proceed
+with @samp{cvs remove @var{file}} and commit your
+removal.
+@c Tests conflicts2-142b* in sanity.sh test for this.
+
@item cannot change permissions on temporary directory
@example
Operation not permitted
@@ -12839,401 +12921,6 @@ be comprehensive. Perhaps there will never be a
comprehensive, detailed list of known bugs.
@c ---------------------------------------------------------------------
-@node Copying
-@appendix GNU GENERAL PUBLIC LICENSE
-@center Version 2, June 1991
-
-@display
-Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-
-Everyone is permitted to copy and distribute verbatim copies
-of this license document, but changing it is not allowed.
-@end display
-
-@unnumberedsec Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software---to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
-@iftex
-@heading TERMS AND CONDITIONS FOR COPYING,
-@heading DISTRIBUTION AND MODIFICATION
-@end iftex
-@ifinfo
-@center TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-@end ifinfo
-
-@enumerate 0
-@item
-This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The ``Program'', below,
-refers to any such program or work, and a ``work based on the Program''
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term ``modification''.) Each licensee is addressed as ``you''.
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-@item
-You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-@item
-You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-@enumerate a
-@item
-You must cause the modified files to carry prominent notices
-stating that you changed the files and the date of any change.
-
-@item
-You must cause any work that you distribute or publish, that in
-whole or in part contains or is derived from the Program or any
-part thereof, to be licensed as a whole at no charge to all third
-parties under the terms of this License.
-
-@item
-If the modified program normally reads commands interactively
-when run, you must cause it, when started running for such
-interactive use in the most ordinary way, to print or display an
-announcement including an appropriate copyright notice and a
-notice that there is no warranty (or else, saying that you provide
-a warranty) and that users may redistribute the program under
-these conditions, and telling the user how to view a copy of this
-License. (Exception: if the Program itself is interactive but
-does not normally print such an announcement, your work based on
-the Program is not required to print an announcement.)
-@end enumerate
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-@item
-You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-@enumerate a
-@item
-Accompany it with the complete corresponding machine-readable
-source code, which must be distributed under the terms of Sections
-1 and 2 above on a medium customarily used for software interchange; or,
-
-@item
-Accompany it with a written offer, valid for at least three
-years, to give any third party, for a charge no more than your
-cost of physically performing source distribution, a complete
-machine-readable copy of the corresponding source code, to be
-distributed under the terms of Sections 1 and 2 above on a medium
-customarily used for software interchange; or,
-
-@item
-Accompany it with the information you received as to the offer
-to distribute corresponding source code. (This alternative is
-allowed only for noncommercial distribution and only if you
-received the program in object code or executable form with such
-an offer, in accord with Subsection b above.)
-@end enumerate
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-@item
-You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-@item
-You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-@item
-Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-@item
-If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-@item
-If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-@item
-The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and ``any
-later version'', you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-@item
-If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-@iftex
-@heading NO WARRANTY
-@end iftex
-@ifinfo
-@center NO WARRANTY
-@end ifinfo
-
-@item
-BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-@item
-IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-@end enumerate
-
-@iftex
-@heading END OF TERMS AND CONDITIONS
-@end iftex
-@ifinfo
-@center END OF TERMS AND CONDITIONS
-@end ifinfo
-
-@page
-@unnumberedsec How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the ``copyright'' line and a pointer to where the full notice is found.
-
-@smallexample
-@var{one line to give the program's name and a brief idea of what it does.}
-Copyright (C) 19@var{yy} @var{name of author}
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-@end smallexample
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-@smallexample
-Gnomovision version 69, Copyright (C) 19@var{yy} @var{name of author}
-Gnomovision comes with ABSOLUTELY NO WARRANTY; for details
-type `show w'.
-This is free software, and you are welcome to redistribute it
-under certain conditions; type `show c' for details.
-@end smallexample
-
-The hypothetical commands @samp{show w} and @samp{show c} should show
-the appropriate parts of the General Public License. Of course, the
-commands you use may be called something other than @samp{show w} and
-@samp{show c}; they could even be mouse-clicks or menu items---whatever
-suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a ``copyright disclaimer'' for the program, if
-necessary. Here is a sample; alter the names:
-
-@smallexample
-Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-`Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-@var{signature of Ty Coon}, 1 April 1989
-Ty Coon, President of Vice
-@end smallexample
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
-
-@c ---------------------------------------------------------------------
@node Index
@unnumbered Index
@cindex Index
diff --git a/contrib/cvs/doc/cvsclient.texi b/contrib/cvs/doc/cvsclient.texi
index 56577c29e2bd..6f0139976b72 100644
--- a/contrib/cvs/doc/cvsclient.texi
+++ b/contrib/cvs/doc/cvsclient.texi
@@ -320,6 +320,7 @@ General protocol conventions:
* Filenames:: Conventions regarding filenames
* File transmissions:: How file contents are transmitted
* Strings:: Strings in various requests and responses
+* Dates:: Times and dates
The protocol itself:
@@ -468,6 +469,32 @@ existing practice is probably to just transmit whatever the user
specifies, and hope that everyone involved agrees which character set is
in use, or sticks to a common subset.
+@node Dates
+@section Dates
+
+The protocol contains times and dates in various places.
+
+For the @samp{-D} option to the @code{annotate}, @code{co}, @code{diff},
+@code{export}, @code{history}, @code{rdiff}, @code{rtag}, @code{tag},
+and @code{update} requests, the server should support two formats:
+
+@example
+26 May 1997 13:01:40 GMT ; @r{RFC 822 as modified by RFC 1123}
+5/26/1997 13:01:40 GMT ; @r{traditional}
+@end example
+
+The former format is preferred; the latter however is sent by the CVS
+command line client (versions 1.5 through at least 1.9).
+
+For the @samp{-d} option to the @code{log} request, servers should at
+least support RFC 822/1123 format. Clients are encouraged to use this
+format too (traditionally the command line CVS client has just passed
+along the date format specified by the user, however).
+
+For @code{Mod-time}, see the description of that response.
+
+For @code{Notify}, see the description of that request.
+
@node Request intro
@section Request intro
@@ -517,7 +544,7 @@ for the original directory, then the command.
The @var{local-directory} is relative to
the top level at which the command is occurring (i.e. the last
@code{Directory} which is sent before the command);
-to indicate that top level, @samp{.} should be send for
+to indicate that top level, @samp{.} should be sent for
@var{local-directory}.
Here is an example of where a client gets @var{repository} and
@@ -892,7 +919,6 @@ directory.
@itemx tag \n
@itemx status \n
@itemx log \n
-@itemx remove \n
@itemx admin \n
@itemx history \n
@itemx watchers \n
@@ -1034,6 +1060,23 @@ directories, as described above), use @samp{.} for
@var{local-directory} may not get an error, but it will get you strange
@code{Checked-in} responses from the buggy servers.
+@item remove \n
+Response expected: yes. Remove a file. This uses any
+previous @code{Argument}, @code{Directory}, @code{Entry}, or
+@code{Modified} requests, if they have been sent. The
+last @code{Directory} sent specifies the working directory at the time
+of the operation.
+
+Note that this request does not actually do anything to the repository;
+the only effect of a successful @code{remove} request is to supply the
+client with a new entries line containing @samp{-} to indicate a removed
+file. In fact, the client probably could perform this operation without
+contacting the server, although using @code{remove} may cause the server
+to perform a few more checks.
+
+The client sends a subsequent @code{ci} request to actually record the
+removal in the repository.
+
@item watch-on \n
@itemx watch-off \n
@itemx watch-add \n
diff --git a/contrib/cvs/lib/ChangeLog b/contrib/cvs/lib/ChangeLog
index 623c292aca24..264b7ac52f39 100644
--- a/contrib/cvs/lib/ChangeLog
+++ b/contrib/cvs/lib/ChangeLog
@@ -1,3 +1,7 @@
+Tue Mar 24 16:08:00 1998 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (CFLAGS): Set to @CFLAGS@, not -g.
+
1998-02-20 Jim Kingdon <kingdon@harvey.cyclic.com>
* regex.c: Partial merge with version from emacs 20.2. Brings
diff --git a/contrib/cvs/lib/Makefile.in b/contrib/cvs/lib/Makefile.in
index 92122c7a09ae..99d816b7c483 100644
--- a/contrib/cvs/lib/Makefile.in
+++ b/contrib/cvs/lib/Makefile.in
@@ -77,7 +77,7 @@ DEFS = @DEFS@
RANLIB = @RANLIB@
CC = @CC@
-CFLAGS = -g
+CFLAGS = @CFLAGS@
CPPFLAGS=
YACC = @YACC@
diff --git a/contrib/cvs/man/ChangeLog b/contrib/cvs/man/ChangeLog
index c873cb27c392..f131d3e855b8 100644
--- a/contrib/cvs/man/ChangeLog
+++ b/contrib/cvs/man/ChangeLog
@@ -1,3 +1,8 @@
+1998-06-28 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * cvs.1: Update various items which were out of date. Mostly
+ these related to CVS no longer calling external RCS programs.
+
Mon Jan 12 11:10:21 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
* cvs.1: Refer to Cederqvist as Cederqvist not as cvs.texinfo.
diff --git a/contrib/cvs/man/cvs.1 b/contrib/cvs/man/cvs.1
index a0efd4bfee26..8cbe2beb9d06 100644
--- a/contrib/cvs/man/cvs.1
+++ b/contrib/cvs/man/cvs.1
@@ -35,19 +35,15 @@ described in the SEE ALSO section of this manpage).
.IX "release control system" "cvs command" "" "\fLcvs\fP \- concurrent versions system"
.IX "source control system" "cvs command" "" "\fLcvs\fP \- concurrent versions system"
.IX revisions "cvs command" "" "\fLcvs\fP \- source control"
-.B cvs
-is a front end to the
-.BR rcs ( 1 )
-revision control system which extends
-the notion of revision control from a collection of files in a single
-directory to a hierarchical collection of directories consisting of
-revision controlled files.
-These directories and files can be combined together to form a software
-release.
-.B cvs
-provides the functions necessary to manage these software releases and to
-control the concurrent editing of source files among multiple software
-developers.
+CVS is a version control system, which allows you to keep old versions
+of files (usually source code), keep a log of who, when, and why
+changes occurred, etc., like RCS or SCCS. Unlike the simpler systems,
+CVS does not just operate on one file at a time or one directory at a
+time, but operates on hierarchical collections of directories
+consisting of version controlled files. CVS helps to manage releases
+and to control the concurrent editing of source files among multiple
+authors. CVS allows triggers to enable/log/control various
+operations and works well over a wide area network.
.SP
.B cvs
keeps a single copy of the master sources.
@@ -175,7 +171,7 @@ Use
.I bindir
as the directory where
.SM RCS
-programs are located.
+programs are located (CVS 1.9 and older).
Overrides the setting of the
.SM RCSBIN
environment variable.
@@ -185,7 +181,6 @@ This value should be specified as an absolute pathname.
Use
.I CVS_root_directory
as the root directory pathname of the master
-.SM RCS
source repository.
Overrides the setting of the
.SM CVSROOT
@@ -318,7 +313,6 @@ working directory.)
.TP
.B admin
Execute
-.SM RCS
control functions on the source repository. (Changes
repository directly; uses working directory without changing it.)
.TP
@@ -366,7 +360,6 @@ as a ``vendor branch''. (Changes repository.)
.TP
.B log
Display
-.SM RCS
log information.
(Does not change repository or working directory.)
.TP
@@ -435,11 +428,8 @@ even with these standard options.
\fB\-D\fP \fIdate_spec\fP
Use the most recent revision no later than \fIdate_spec\fP (a single
argument, date description specifying a date in the
-past). A wide variety of date formats are supported by the underlying
-.SM RCS
-facilities, similar to those described in
-.BR co ( 1 ),
-but not exactly the same.
+past). A wide variety of date formats are supported, in particular
+ISO ("1972-09-24 20:05") or Internet ("24 Sep 1972 20:05").
The \fIdate_spec\fP is interpreted as being in the local timezone, unless a
specific timezone is specified.
The specification is ``sticky'' when you use it to make a
@@ -492,12 +482,8 @@ commands.
.TP
\fB\-k\fP \fIkflag\fP
Alter the default
-.SM RCS
-processing of keywords; all the
-.B \-k
-options described in
-.BR co ( 1 )
-are available. The \fB\-k\fP option is available with the
+processing of keywords.
+The \fB\-k\fP option is available with the
.BR add ", " checkout ", " diff ", " export ", "
.BR rdiff ", and " update
commands. Your \fIkflag\fP specification is ``sticky'' when you use
@@ -507,10 +493,8 @@ this option with the \fBcheckout\fP or \fBupdate\fP commands,
continues to use it with future \fBupdate\fP commands on the same file
until you specify otherwise.
.SP
-Some of the more useful \fIkflag\fPs are \-ko and \-kb (for binary files,
-only compatible with
-.SM RCS
-version 5.7 or later), and \-kv which is useful for an
+Some of the more useful \fIkflag\fPs are \-ko and \-kb (for binary files),
+and \-kv which is useful for an
.B export
where you wish to retain keyword information after an
.B import
@@ -600,9 +584,7 @@ make your own copy of a file: \fBcvs\fP remembers the \fItag\fP and
continues to use it on future \fBupdate\fP commands, until you specify
otherwise.
.I tag
-can be either a symbolic or numeric tag, in
-.SM RCS
-fashion.
+can be either a symbolic or numeric tag.
Specifying the
.B \-q
global option along with the
@@ -659,7 +641,6 @@ working directory.
Use the
.B add
command to create a new file or directory in the
-.SM RCS
source repository.
The files or directories specified with
.B add
@@ -676,7 +657,6 @@ If the argument to
.` "cvs add"
refers to an immediate sub-directory, the directory is
created at the correct place in the
-.SM RCS
source repository, and the necessary
.B cvs
administration files are created in your working directory.
@@ -719,7 +699,6 @@ or
.` "cvs update -d".)
.SP
The added files are not placed in the
-.SM RCS
source repository until you use
.` "cvs commit"
to make the change permanent.
@@ -757,9 +736,8 @@ file and can be changed with
Specifying
.` "-ko"
is useful for checking in binaries that
-shouldn't have the
-.SM RCS
-id strings expanded.
+shouldn't have
+keywords expanded.
.TP
\fBadmin\fP [\fIrcs-options\fP] \fIfiles.\|.\|.\fP
.I Requires:
@@ -774,14 +752,9 @@ repository.
This is the
.B cvs
interface to assorted administrative
-.SM RCS
-facilities, documented in
+facilities, similar to
.BR rcs ( 1 ).
-.` "cvs admin"
-simply passes all its options and arguments to the
-.B rcs
-command; it does no filtering or other processing.
-This command does work recursively, however, so extreme care should be
+This command works recursively, so extreme care should be
used.
.TP
\fBcheckout\fP [\fBoptions\fP] \fImodules\fP.\|.\|.
@@ -820,7 +793,6 @@ You can then edit these source files at any time (regardless of whether
other software developers are editing their own copies of the sources);
update them to include new changes applied by others to the source
repository; or commit your work as a permanent change to the
-.SM RCS
repository.
.SP
Note that
@@ -987,7 +959,6 @@ the time is right.
.SP
When all is well, an editor is invoked to allow you to enter a log
message that will be written to one or more logging programs and placed in the
-.SM RCS
source repository file.
You can instead specify the log message on the command line with the
.B \-m
@@ -997,12 +968,8 @@ option to specify that the argument \fIfile\fP contains the log message.
.SP
The
.B \-r
-option can be used to commit to a particular symbolic or numeric revision
-within the
-.SM RCS
-file.
+option can be used to commit to a particular symbolic or numeric revision.
For example, to bring all your files up to the
-.SM RCS
revision ``3.0'' (including those that haven't changed), you might do:
.SP
.in +1i
@@ -1154,7 +1121,6 @@ option is useful when
.B export
is used.
This causes any
-.SM RCS
keywords to be expanded such that an
.B import
done at some other site will not lose the keyword revision information.
@@ -1330,7 +1296,6 @@ For an up to date list of ignored file names, see the Cederqvist manual (as
described in the SEE ALSO section of this manpage).
.SP
The outside source is saved in a first-level
-.SM RCS
branch, by default
.` "1.1.1".
Updates are leaves of this
@@ -1390,13 +1355,7 @@ nothing.
.B rlog
.br
Display log information for \fIfiles\fP.
-.` "cvs log"
-calls
-the
-.SM RCS
-utility \fBrlog\fP; all the options described in
-.BR rlog ( 1 )
-are available. Among the more useful \fBrlog\fP options are \fB\-h\fP
+Among the more useful options are \fB\-h\fP
to display only the header (including tag definitions, but omitting
most of the full log); \fB\-r\fP to select logs on particular
revisions or ranges of revisions; and \fB\-d\fP to select particular
@@ -1444,14 +1403,6 @@ command when patching the old sources, so that
.B patch
is able to find the files that are located in other directories.
.SP
-If you use the option \fB\-V\fP \fIvn\fP,
-.SM RCS
-keywords are expanded according to the rules current in
-.SM RCS
-version \fIvn\fP (the expansion format changed with
-.SM RCS
-version 5).
-.SP
The standard option \fIflags\fP \fB\-f\fP, and \fB\-l\fP
are available with this command. There are also several
special options flags:
@@ -1769,7 +1720,6 @@ recent versions available in the repository.
\fBA\fP \fIfile\fP
The file has been \fIadded\fP to your private copy of the sources, and
will be added to the
-.SM RCS
source repository when you run
.` "cvs commit"
on the file.
@@ -1778,7 +1728,6 @@ This is a reminder to you that the file needs to be committed.
\fBR\fP \fIfile\fP
The file has been \fIremoved\fP from your private copy of the sources, and
will be removed from the
-.SM RCS
source repository when you run
.` "cvs commit"
on the file.
@@ -1797,14 +1746,12 @@ directory.
\fBC\fP \fIfile\fP
A \fIconflict\fP was detected while trying to merge your changes to
\fIfile\fP with changes from the source repository. \fIfile\fP (the
-copy in your working directory) is now the output of the
-.BR rcsmerge ( 1 )
-command on the two versions; an unmodified copy of your file is also
+copy in your working directory) is now the result of merging
+the two versions; an unmodified copy of your file is also
in your working directory, with the name `\fB.#\fP\fIfile\fP\fB.\fP\fIversion\fP',
where
.I version
is the
-.SM RCS
revision that your modified file started from.
(Note that some systems automatically purge files that begin with
\&
@@ -2037,7 +1984,6 @@ Directory for removed source files.
A lock directory created by
.B cvs
when doing sensitive changes to the
-.SM RCS
source repository.
.TP
#cvs.tfl.\fIpid\fP
@@ -2082,9 +2028,8 @@ Specifies the full pathname where to find
programs, such as
.BR co ( 1 )
and
-.BR ci ( 1 ).
-If not set, a compiled-in value is used; see the display from
-.` "cvs \-v".
+.BR ci ( 1 )
+(CVS 1.9 and older).
.TP
.SM CVSEDITOR
Specifies the program to use for recording log messages during
@@ -2150,6 +2095,8 @@ module and vendor branch support and author of the
.BR checkin ( 1 )
shell script (the ancestor of
.` "cvs import").
+.TP
+And many others too numerous to mention here.
.SH "SEE ALSO"
The most comprehensive manual for CVS is
Version Management with CVS by Per Cederqvist et al. Depending on
diff --git a/contrib/cvs/src/ChangeLog b/contrib/cvs/src/ChangeLog
index 96e170123292..8077ce8c027e 100644
--- a/contrib/cvs/src/ChangeLog
+++ b/contrib/cvs/src/ChangeLog
@@ -1,5 +1,709 @@
+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,
@@ -30,7 +734,7 @@
* update.c (special_file_mismatch): Compare the hard links of the
two revisions.
- * rcs.c (RCS_checkout):
+ * rcs.c (RCS_checkout):
* hardlink.c, hardlink.h: New files.
(hardlink_info): New struct.
@@ -235,7 +939,7 @@ 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
@@ -255,7 +959,7 @@ Tue Feb 17 02:32:21 1998 Noel Cragg <noel@swish.red-bean.com>
* 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
@@ -294,7 +998,7 @@ Tue Feb 17 02:32:21 1998 Noel Cragg <noel@swish.red-bean.com>
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.
diff --git a/contrib/cvs/src/Makefile.in b/contrib/cvs/src/Makefile.in
index 61b4fe26d30a..2c93ec2d8eb0 100644
--- a/contrib/cvs/src/Makefile.in
+++ b/contrib/cvs/src/Makefile.in
@@ -177,7 +177,10 @@ cvsbug: cvsbug.sh $(srcdir)/version.c
$(OBJECTS): $(HEADERS) options.h
-zlib.o: zlib.c
+rcscmds.o: rcscmds.c $(top_srcdir)/diff/diffrun.h
+ $(CC) $(CPPFLAGS) $(INCLUDES) -I$(top_srcdir)/diff $(DEFS) $(CFLAGS) -c $(srcdir)/rcscmds.c
+
+zlib.o: zlib.c $(top_srcdir)/zlib/zlib.h
$(CC) $(CPPFLAGS) $(INCLUDES) -I$(top_srcdir)/zlib $(DEFS) $(CFLAGS) -c $(srcdir)/zlib.c
subdir = src
diff --git a/contrib/cvs/src/add.c b/contrib/cvs/src/add.c
index d44435a3d592..a4eed40d90c6 100644
--- a/contrib/cvs/src/add.c
+++ b/contrib/cvs/src/add.c
@@ -56,6 +56,9 @@ add (argc, argv)
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;
if (argc == 1 || argc == -1)
usage (add_usage);
@@ -108,6 +111,20 @@ add (argc, argv)
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)
{
@@ -143,9 +160,16 @@ add (argc, argv)
if (options) send_arg(options);
option_with_arg ("-m", message);
- repository = Name_Repository (NULL, NULL);
- send_a_repository ("", repository, "");
- free (repository);
+ /* 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 (i = 0; i < argc; ++i)
/* FIXME: Does this erroneously call Create_Admin in error
@@ -194,7 +218,8 @@ add (argc, argv)
Create_Admin (p, argv[i], rcsdir, tag, date,
nonbranch, 0);
- send_a_repository ("", repository, update_dir);
+ if (found_slash)
+ send_a_repository ("", repository, update_dir);
if (restore_cwd (&cwd, NULL))
error_exit ();
diff --git a/contrib/cvs/src/admin.c b/contrib/cvs/src/admin.c
index 3c50f4a57ac2..72cddac616f1 100644
--- a/contrib/cvs/src/admin.c
+++ b/contrib/cvs/src/admin.c
@@ -701,15 +701,27 @@ admin_fileproc (callerdat, finfo)
rcs->path,
tag, n->data);
status = 1;
+ free (tag);
continue;
}
}
- /* Expand rev if necessary. */
- rev = RCS_gettag (rcs, p, 0, NULL);
- RCS_settag (rcs, tag, rev);
- if (rev != NULL)
+ /* 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
+ {
+ error (0, 0,
+ "%s: Symbolic name or revision %s is undefined",
+ rcs->path, p);
+ status = 1;
+ }
free (tag);
break;
case 's':
diff --git a/contrib/cvs/src/checkout.c b/contrib/cvs/src/checkout.c
index 46151eb99694..c6a81221d9d8 100644
--- a/contrib/cvs/src/checkout.c
+++ b/contrib/cvs/src/checkout.c
@@ -242,6 +242,13 @@ checkout (argc, argv)
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 (!safe_location()) {
error(1, 0, "Cannot check out files into the repository itself");
}
@@ -428,11 +435,15 @@ struct dir_to_build
/* 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, int check_existing_dirs));
+ int sticky));
static void build_one_dir PROTO ((char *, char *, int));
@@ -723,6 +734,7 @@ internal error: %s doesn't start with %s in checkout_proc",
head->repository = NULL;
head->dirpath = xstrdup (where);
head->next = NULL;
+ head->just_chdir = 0;
/* Make a copy of the repository name to play with. */
@@ -760,7 +772,26 @@ internal error: %s doesn't start with %s in checkout_proc",
assert (strlen (where));
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:
@@ -771,12 +802,13 @@ internal error: %s doesn't start with %s in checkout_proc",
cvs co -d what/ever -N foo
The results in the CVS/Repository files should be:
- . -> . (this is where we executed the cmd)
- what -> Emptydir (generated dir -- not in repos)
+ . -> (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, CVSroot_directory) == 0)
{
/* We can't walk up past CVSROOT. Instead, the
@@ -835,9 +867,6 @@ internal error: %s doesn't start with %s in checkout_proc",
}
}
}
-
- new->next = head;
- head = new;
}
/* clean up */
@@ -852,12 +881,29 @@ internal error: %s doesn't start with %s in checkout_proc",
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. */
-
- if (! where_is_absolute)
+ /* FIXME: checking where_is_absolute 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 (! where_is_absolute && top_level_admin)
{
/* It may be argued that we shouldn't set any sticky
bits for the top-level repository. FIXME? */
build_one_dir (CVSroot_directory, ".", *pargc <= 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 (".", CVSroot_directory);
+#endif
}
@@ -866,8 +912,7 @@ internal error: %s doesn't start with %s in checkout_proc",
contain a CVS subdir yet, but all the others contain
CVS and Entries.Static files */
- if (build_dirs_and_chdir (head, *pargc <= 1,
- where_is_absolute) != 0)
+ if (build_dirs_and_chdir (head, *pargc <= 1) != 0)
{
error (0, 0, "ignoring module %s", omodule);
err = 1;
@@ -1101,22 +1146,13 @@ emptydir_name ()
return repository;
}
-
-/* Build all the dirs along the path to DIRS with CVS subdirs with
- appropriate repositories. If ->repository is NULL, do not create a
- CVSADM directory for that subdirectory; just CVS_CHDIR into it. If
- check_existing_dirs is nonzero, don't create directories if they
- already exist, and don't try to write adm files in directories
- where we don't have write permission. We use this last option
- primarily when a user has specified an absolute path for checkout
- -- we will often not have permission to top-level directories, so
- we shouldn't complain. */
-
+/* Build all the dirs along the path to DIRS with CVS subdirs with appropriate
+ repositories. If ->repository is NULL, do not create a CVSADM directory
+ for that subdirectory; just CVS_CHDIR into it. */
static int
-build_dirs_and_chdir (dirs, sticky, check_existing_dirs)
+build_dirs_and_chdir (dirs, sticky)
struct dir_to_build *dirs;
int sticky;
- int check_existing_dirs;
{
int retval = 0;
struct dir_to_build *nextdir;
@@ -1124,16 +1160,12 @@ build_dirs_and_chdir (dirs, sticky, check_existing_dirs)
while (dirs != NULL)
{
char *dir = last_component (dirs->dirpath);
- int dir_is_writeable;
- if ((! check_existing_dirs) || (! isdir (dir)))
+ if (!dirs->just_chdir)
+ {
mkdir_if_needed (dir);
-
- Subdir_Register (NULL, NULL, dir);
-
- /* This is an expensive call -- only make it if necessary. */
- if (check_existing_dirs)
- dir_is_writeable = iswritable (dir);
+ Subdir_Register (NULL, NULL, dir);
+ }
if (CVS_CHDIR (dir) < 0)
{
@@ -1141,14 +1173,11 @@ build_dirs_and_chdir (dirs, sticky, check_existing_dirs)
retval = 1;
goto out;
}
-
- if ((dirs->repository != NULL)
- && ((! check_existing_dirs) || dir_is_writeable))
+ if (dirs->repository != NULL)
{
build_one_dir (dirs->repository, dirs->dirpath, sticky);
free (dirs->repository);
}
-
nextdir = dirs->next;
free (dirs->dirpath);
free (dirs);
diff --git a/contrib/cvs/src/classify.c b/contrib/cvs/src/classify.c
index b33c94537780..b0084a3d0fab 100644
--- a/contrib/cvs/src/classify.c
+++ b/contrib/cvs/src/classify.c
@@ -288,6 +288,14 @@ conflict: %s created independently by second party",
* There is no user file, so note that it was lost and
* extract a new version
*/
+ /* Comparing the command_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 (command_name, "update") == 0)
if (!really_quiet)
error (0, 0, "warning: %s was lost", finfo->fullname);
@@ -367,6 +375,8 @@ conflict: %s created independently by second party",
{
/* There is no user file, so just get it */
+ /* See comment at other "update" compare, for more
+ thoughts on this comparison. */
if (strcmp (command_name, "update") == 0)
if (!really_quiet)
error (0, 0, "warning: %s was lost", finfo->fullname);
diff --git a/contrib/cvs/src/client.c b/contrib/cvs/src/client.c
index aa897d5c7196..222e7f265342 100644
--- a/contrib/cvs/src/client.c
+++ b/contrib/cvs/src/client.c
@@ -78,8 +78,19 @@ static Key_schedule sched;
#ifdef HAVE_GSSAPI
+#ifdef HAVE_GSSAPI_H
+#include <gssapi.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_H
#include <gssapi/gssapi.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
#include <gssapi/gssapi_generic.h>
+#endif
+
+#ifndef HAVE_GSS_C_NT_HOSTBASED_SERVICE
+#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
+#endif
/* This is needed for GSSAPI encryption. */
static gss_ctx_id_t gcontext;
@@ -949,17 +960,24 @@ call_in_directory (pathname, func, data)
error (1, errno, "could not chdir to %s", toplevel_wd);
newdir = 0;
- /* Create the CVS directory at the top level if needed.
- The isdir seems like an unneeded system call, but it *does*
- need to be called both if the CVS_CHDIR below succeeds (e.g.
- "cvs co .") or if it fails (e.g. basicb-1a in testsuite). */
+ /* Create the CVS directory at the top level if needed. The
+ isdir seems like an unneeded system call, but it *does*
+ need to be called both if the CVS_CHDIR below succeeds
+ (e.g. "cvs co .") or if it fails (e.g. basicb-1a in
+ testsuite). We only need to do this for the "." case,
+ since the server takes care of forcing this directory to be
+ created in all other cases. If we don't create CVSADM
+ here, the call to Entries_Open below will fail. FIXME:
+ perhaps this means that we should change our algorithm
+ below that calls Create_Admin instead of having this code
+ here? */
if (/* I think the reposdirname_absolute case has to do with
things like "cvs update /foo/bar". In any event, the
code below which tries to put toplevel_repos into
CVS/Repository is almost surely unsuited to
the reposdirname_absolute case. */
!reposdirname_absolute
-
+ && (strcmp (dir_name, ".") == 0)
&& ! isdir (CVSADM))
{
char *repo;
@@ -2909,19 +2927,19 @@ handle_wrapper_rcs_option (args, len)
as free-form as it looks. */
p = strchr (args, ' ');
if (p == NULL)
- goto error;
+ goto handle_error;
if (*++p != '-'
|| *++p != 'k'
|| *++p != ' '
|| *++p != '\'')
- goto error;
+ goto handle_error;
if (strchr (p, '\'') == NULL)
- goto error;
+ goto handle_error;
/* Add server-side cvswrappers line to our wrapper list. */
wrap_add (args, 0);
return;
- error:
+ handle_error:
error (0, errno, "protocol error: ignoring invalid wrappers %s", args);
}
@@ -3861,7 +3879,8 @@ connect_to_gserver (sock, hostinfo)
sprintf (buf, "cvs@%s", hostinfo->h_name);
tok_in.length = strlen (buf);
tok_in.value = buf;
- gss_import_name (&stat_min, &tok_in, gss_nt_service_name, &server_name);
+ 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;
@@ -5442,13 +5461,16 @@ option_with_arg (option, arg)
send_arg (arg);
}
-/*
- * Send a date to the server. This will passed a string which is the
- * result of Make_Date, and looks like YY.MM.DD.HH.MM.SS, where all
- * the letters are single digits. The time will be GMT. getdate on
- * the server can't parse that, so we turn it back into something
- * which it can parse.
- */
+/* 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, but for now we
+ use the format that we always have, for
+ conservatism/laziness/paranoia. As far as I know all servers
+ support the RFC 822/1123 format, so probably there would be no
+ particular danger in switching. */
void
client_senddate (date)
@@ -5457,10 +5479,10 @@ client_senddate (date)
int year, month, day, hour, minute, second;
char buf[100];
- if (sscanf (date, DATEFORM, &year, &month, &day, &hour, &minute, &second)
+ if (sscanf (date, SDATEFORM, &year, &month, &day, &hour, &minute, &second)
!= 6)
{
- error (1, 0, "diff_client_senddate: sscanf failed on date");
+ error (1, 0, "client_senddate: sscanf failed on date");
}
sprintf (buf, "%d/%d/%d %d:%d:%d GMT", month, day, year,
diff --git a/contrib/cvs/src/commit.c b/contrib/cvs/src/commit.c
index 4aa243868a91..75d2e5ae7b68 100644
--- a/contrib/cvs/src/commit.c
+++ b/contrib/cvs/src/commit.c
@@ -1,17 +1,17 @@
/*
* Copyright (c) 1992, Brian Berliner and Jeff Polk
* 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...
- *
+ *
*/
#include <assert.h>
@@ -29,7 +29,7 @@ static int check_filesdoneproc PROTO ((void *callerdat, int err,
char *repos, char *update_dir,
List *entries));
static int checkaddfile PROTO((char *file, char *repository, char *tag,
- char *options, RCSNode **rcsnode));
+ char *options, RCSNode **rcsnode));
static Dtype commit_direntproc PROTO ((void *callerdat, char *dir,
char *repos, char *update_dir,
List *entries));
@@ -74,12 +74,13 @@ static int force_ci = 0;
static int got_message;
static int run_module_prog = 1;
static int aflag;
-static char *tag;
+static char *saved_tag;
static char *write_dirtag;
static int write_dirnonbranch;
static char *logfile;
static List *mulist;
-static char *message;
+static List *saved_ulist;
+static char *saved_message;
static time_t last_register_time;
static const char *const commit_usage[] =
@@ -247,7 +248,7 @@ find_fileproc (callerdat, finfo)
xfinfo.repository = NULL;
xfinfo.rcs = NULL;
- vers = Version_TS (&xfinfo, NULL, tag, NULL, 0, 0);
+ vers = Version_TS (&xfinfo, NULL, saved_tag, NULL, 0, 0);
if (vers->ts_user == NULL
&& vers->vn_user != NULL
&& vers->vn_user[0] == '-')
@@ -364,18 +365,18 @@ commit (argc, argv)
#else
use_editor = 0;
#endif
- if (message)
+ if (saved_message)
{
- free (message);
- message = NULL;
+ free (saved_message);
+ saved_message = NULL;
}
- message = xstrdup(optarg);
+ saved_message = xstrdup(optarg);
break;
case 'r':
- if (tag)
- free (tag);
- tag = xstrdup (optarg);
+ if (saved_tag)
+ free (saved_tag);
+ saved_tag = xstrdup (optarg);
break;
case 'l':
local = 1;
@@ -405,12 +406,12 @@ commit (argc, argv)
argv += optind;
/* numeric specified revision means we ignore sticky tags... */
- if (tag && isdigit (*tag))
+ if (saved_tag && isdigit (*saved_tag))
{
aflag = 1;
/* strip trailing dots */
- while (tag[strlen (tag) - 1] == '.')
- tag[strlen (tag) - 1] = '\0';
+ while (saved_tag[strlen (saved_tag) - 1] == '.')
+ saved_tag[strlen (saved_tag) - 1] = '\0';
}
/* some checks related to the "-F logfile" option */
@@ -419,7 +420,7 @@ commit (argc, argv)
int n, logfd;
struct stat statbuf;
- if (message)
+ if (saved_message)
error (1, 0, "cannot specify both a message and a log file");
/* FIXME: Why is this binary? Needs more investigation. */
@@ -429,21 +430,20 @@ commit (argc, argv)
if (fstat(logfd, &statbuf) < 0)
error (1, errno, "cannot find size of log file %s", logfile);
- message = xmalloc (statbuf.st_size + 1);
+ saved_message = xmalloc (statbuf.st_size + 1);
/* FIXME: Should keep reading until EOF, rather than assuming the
first read gets the whole thing. */
- if ((n = read (logfd, message, statbuf.st_size + 1)) < 0)
+ if ((n = read (logfd, saved_message, statbuf.st_size + 1)) < 0)
error (1, errno, "cannot read log message from %s", logfile);
(void) close (logfd);
- message[n] = '\0';
+ saved_message[n] = '\0';
}
#ifdef CLIENT_SUPPORT
- if (client_active)
+ if (client_active)
{
- int err;
struct find_data find_args;
ign_setup ();
@@ -458,7 +458,7 @@ commit (argc, argv)
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 || tag != NULL;
+ find_args.force = force_ci || saved_tag != NULL;
err = start_recursion (find_fileproc, find_filesdoneproc,
find_dirent_proc, (DIRLEAVEPROC) NULL,
@@ -500,17 +500,17 @@ commit (argc, argv)
* The protocol is designed this way. This is a feature.
*/
if (use_editor)
- do_editor (".", &message, (char *)NULL, find_args.ulist);
+ do_editor (".", &saved_message, (char *)NULL, find_args.ulist);
/* Run the user-defined script to verify/check information in
*the log message
*/
- do_verify (message, (char *)NULL);
+ do_verify (saved_message, (char *)NULL);
/* We always send some sort of message, even if empty. */
/* FIXME: is that true? There seems to be some code in do_editor
which can leave the message NULL. */
- option_with_arg ("-m", message);
+ option_with_arg ("-m", saved_message);
/* OK, now process all the questionable files we have been saving
up. */
@@ -559,7 +559,7 @@ commit (argc, argv)
send_arg("-f");
if (!run_module_prog)
send_arg("-n");
- option_with_arg ("-r", tag);
+ option_with_arg ("-r", saved_tag);
/* Sending only the names of the files which were modified, added,
or removed means that the server will only do an up-to-date
@@ -582,7 +582,7 @@ commit (argc, argv)
send_to_server ("ci\012", 0);
err = get_responses_and_close ();
- if (err != 0 && use_editor && message != NULL)
+ 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
@@ -600,7 +600,8 @@ commit (argc, argv)
fp = CVS_FOPEN (fname, "w+");
if (fp == NULL)
error (1, 0, "cannot create temporary file %s", fname);
- if (fwrite (message, 1, strlen (message), fp) != strlen (message))
+ 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);
@@ -610,12 +611,12 @@ commit (argc, argv)
}
#endif
- if (tag != NULL)
- tag_check_valid (tag, argc, argv, local, aflag, "");
+ 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 = tag;
+ write_dirtag = saved_tag;
wrap_setup ();
@@ -651,17 +652,6 @@ commit (argc, argv)
error (1, 0, "correct above errors first!");
}
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- if (preserve_perms)
- {
- /* hardlist now includes a complete index of the files
- to be committed, indexed by inode. For each inode,
- compile a list of the files that are linked to it,
- and save this list in each file's hardlink_info node. */
- (void) walklist (hardlist, cache_hardlinks_proc, NULL);
- }
-#endif
-
/*
* Run the recursion processor to commit the files
*/
@@ -683,7 +673,7 @@ commit (argc, argv)
time_t now;
(void) time (&now);
- if (now == last_register_time)
+ if (now == last_register_time)
{
sleep (1); /* to avoid time-stamp races */
}
@@ -713,10 +703,10 @@ classify_file_internal (finfo, vers)
noexec = quiet = really_quiet = 1;
/* handle specified numeric revision specially */
- if (tag && isdigit (*tag))
+ if (saved_tag && isdigit (*saved_tag))
{
/* If the tag is for the trunk, make sure we're at the head */
- if (numdots (tag) < 2)
+ if (numdots (saved_tag) < 2)
{
status = Classify_File (finfo, (char *) NULL, (char *) NULL,
(char *) NULL, 1, aflag, vers, 0);
@@ -726,7 +716,7 @@ classify_file_internal (finfo, vers)
Ctype xstatus;
freevers_ts (vers);
- xstatus = Classify_File (finfo, tag, (char *) NULL,
+ xstatus = Classify_File (finfo, saved_tag, (char *) NULL,
(char *) NULL, 1, aflag, vers, 0);
if (xstatus == T_REMOVE_ENTRY)
status = T_MODIFIED;
@@ -744,7 +734,7 @@ classify_file_internal (finfo, vers)
* The revision is off the main trunk; make sure we're
* up-to-date with the head of the specified branch.
*/
- xtag = xstrdup (tag);
+ xtag = xstrdup (saved_tag);
if ((numdots (xtag) & 1) != 0)
{
cp = strrchr (xtag, '.');
@@ -765,12 +755,12 @@ classify_file_internal (finfo, vers)
}
/* now, muck with vers to make the tag correct */
free ((*vers)->tag);
- (*vers)->tag = xstrdup (tag);
+ (*vers)->tag = xstrdup (saved_tag);
free (xtag);
}
}
else
- status = Classify_File (finfo, tag, (char *) NULL, (char *) NULL,
+ status = Classify_File (finfo, saved_tag, (char *) NULL, (char *) NULL,
1, 0, vers, 0);
noexec = save_noexec;
quiet = save_quiet;
@@ -796,7 +786,7 @@ check_fileproc (callerdat, finfo)
Vers_TS *vers;
struct commit_info *ci;
struct logfile_info *li;
-
+
status = classify_file_internal (finfo, &vers);
/*
@@ -835,7 +825,7 @@ check_fileproc (callerdat, finfo)
* allow the commit if timestamp is identical or if we find
* an RCS_MERGE_PAT in the file.
*/
- if (!tag || !isdigit (*tag))
+ if (!saved_tag || !isdigit (*saved_tag))
{
if (vers->date)
{
@@ -1047,7 +1037,6 @@ warning: file `%s' seems to still contain conflict indicators",
hlinfo = (struct hardlink_info *)
xmalloc (sizeof (struct hardlink_info));
hlinfo->status = status;
- hlinfo->links = NULL;
linkp->data = (char *) hlinfo;
}
}
@@ -1114,7 +1103,6 @@ precommit_list_proc (p, closure)
/*
* Callback proc for pre-commit checking
*/
-static List *ulist;
static int
precommit_proc (repository, filter)
char *repository;
@@ -1124,7 +1112,7 @@ precommit_proc (repository, filter)
if (isabsolute (filter))
{
char *s, *cp;
-
+
s = xstrdup (filter);
for (cp = s; *cp; cp++)
if (isspace (*cp))
@@ -1143,7 +1131,7 @@ precommit_proc (repository, filter)
run_setup (filter);
run_arg (repository);
- (void) walklist (ulist, precommit_list_proc, NULL);
+ (void) walklist (saved_ulist, precommit_list_proc, NULL);
return (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY));
}
@@ -1165,12 +1153,12 @@ check_filesdoneproc (callerdat, err, repos, update_dir, entries)
/* find the update list for this dir */
p = findnode (mulist, update_dir);
if (p != NULL)
- ulist = ((struct master_lists *) p->data)->ulist;
+ saved_ulist = ((struct master_lists *) p->data)->ulist;
else
- ulist = (List *) NULL;
+ saved_ulist = (List *) NULL;
/* skip the checks if there's nothing to do */
- if (ulist == NULL || ulist->list->next == ulist->list)
+ if (saved_ulist == NULL || saved_ulist->list->next == saved_ulist->list)
return (err);
/* run any pre-commit checks */
@@ -1238,8 +1226,9 @@ commit_fileproc (callerdat, finfo)
{
got_message = 1;
if (use_editor)
- do_editor (finfo->update_dir, &message, finfo->repository, ulist);
- do_verify (message, finfo->repository);
+ do_editor (finfo->update_dir, &saved_message,
+ finfo->repository, ulist);
+ do_verify (saved_message, finfo->repository);
}
p = findnode (cilist, finfo->file);
@@ -1279,7 +1268,7 @@ commit_fileproc (callerdat, finfo)
error (1, 0, "internal error: no parsed RCS file");
ci->rev = RCS_whatbranch (finfo->rcs, ci->tag);
err = Checkin ('A', finfo, finfo->rcs->path, ci->rev,
- ci->tag, ci->options, message);
+ ci->tag, ci->options, saved_message);
if (err != 0)
{
unlockrcs (finfo->rcs);
@@ -1319,7 +1308,7 @@ commit_fileproc (callerdat, finfo)
{
err = Checkin ('M', finfo,
finfo->rcs->path, ci->rev, ci->tag,
- ci->options, message);
+ ci->options, saved_message);
(void) time (&last_register_time);
@@ -1331,7 +1320,7 @@ commit_fileproc (callerdat, finfo)
}
else if (ci->status == T_REMOVED)
{
- err = remove_file (finfo, ci->tag, message);
+ err = remove_file (finfo, ci->tag, saved_message);
#ifdef SERVER_SUPPORT
if (server_active) {
server_scratch_entry_only ();
@@ -1371,7 +1360,7 @@ out:
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);
@@ -1379,7 +1368,7 @@ out:
{
Vers_TS *vers;
struct logfile_info *li;
-
+
(void) classify_file_internal (finfo, &vers);
li = (struct logfile_info *) p->data;
li->rev_new = xstrdup (vers->vn_rcs);
@@ -1415,7 +1404,7 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
got_message = 0;
- Update_Logfile (repository, message, (FILE *) 0, ulist);
+ Update_Logfile (repository, saved_message, (FILE *) 0, ulist);
/* Build the administrative files if necessary. */
{
@@ -1423,11 +1412,17 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
if (strncmp (CVSroot_directory, repository,
strlen (CVSroot_directory)) != 0)
- error (0, 0, "internal error: repository (%s) doesn't begin with root (%s)", repository, CVSroot_directory);
+ error (0, 0,
+ "internal error: repository (%s) doesn't begin with root (%s)",
+ repository, CVSroot_directory);
p = repository + strlen (CVSroot_directory);
if (*p == '/')
++p;
- if (strcmp ("CVSROOT", p) == 0)
+ 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
@@ -1435,11 +1430,21 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
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 (command_name, 0);
cvs_output (": Rebuilding administrative file database\n", 0);
- mkmodules (repository);
+ mkmodules (admin_dir);
+ free (admin_dir);
}
}
@@ -1452,7 +1457,7 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
char *line;
int line_length;
size_t line_chars_allocated;
- char *repository;
+ char *repos;
line = NULL;
line_chars_allocated = 0;
@@ -1462,9 +1467,9 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
/* Remove any trailing newline. */
if (line[line_length - 1] == '\n')
line[--line_length] = '\0';
- repository = Name_Repository ((char *) NULL, update_dir);
+ repos = Name_Repository ((char *) NULL, update_dir);
run_setup (line);
- run_arg (repository);
+ run_arg (repos);
cvs_output (program_name, 0);
cvs_output (" ", 1);
cvs_output (command_name, 0);
@@ -1472,7 +1477,7 @@ commit_filesdoneproc (callerdat, err, repository, update_dir, entries)
run_print (stdout);
cvs_output ("'\n", 0);
(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
- free (repository);
+ free (repos);
}
else
{
@@ -1529,8 +1534,8 @@ commit_direntproc (callerdat, dir, repos, update_dir, entries)
real_repos = Name_Repository (dir, update_dir);
got_message = 1;
if (use_editor)
- do_editor (update_dir, &message, real_repos, ulist);
- do_verify (message, real_repos);
+ do_editor (update_dir, &saved_message, real_repos, ulist);
+ do_verify (saved_message, real_repos);
free (real_repos);
return (R_PROCESS);
}
@@ -1622,7 +1627,7 @@ remove_file (finfo, tag, message)
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 ((retcode = RCS_deltag (finfo->rcs, tag)) != 0)
{
if (!quiet)
error (0, retcode == -1 ? errno : 0,
@@ -1655,7 +1660,7 @@ remove_file (finfo, tag, message)
error (0, 0, "cannot find branch \"%s\".", tag);
return (1);
}
-
+
branchname = RCS_getbranch (finfo->rcs, rev, 1);
if (branchname == NULL)
{
@@ -1676,12 +1681,12 @@ remove_file (finfo, tag, message)
/* 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)
+ if (RCS_setbranch (finfo->rcs, NULL) != 0)
{
error (0, 0, "cannot change branch to default for %s",
finfo->fullname);
@@ -1740,7 +1745,7 @@ remove_file (finfo, tag, message)
if (!branch)
{
/* this was the head; really move it into the Attic */
- tmp = xmalloc(strlen(finfo->repository) +
+ tmp = xmalloc(strlen(finfo->repository) +
sizeof('/') +
sizeof(CVSATTIC) +
sizeof('/') +
@@ -1750,8 +1755,9 @@ remove_file (finfo, tag, message)
omask = umask (cvsumask);
(void) CVS_MKDIR (tmp, 0777);
(void) umask (omask);
- (void) sprintf (tmp, "%s/%s/%s%s", finfo->repository, CVSATTIC, finfo->file, RCSEXT);
-
+ (void) sprintf (tmp, "%s/%s/%s%s", finfo->repository, CVSATTIC,
+ finfo->file, RCSEXT);
+
if (strcmp (finfo->rcs->path, tmp) != 0
&& CVS_RENAME (finfo->rcs->path, tmp) == -1
&& (isreadable (finfo->rcs->path) || !isreadable (tmp)))
@@ -1794,7 +1800,7 @@ finaladd (finfo, rev, tag, options)
char *rcs;
rcs = locate_rcs (finfo->file, finfo->repository);
- ret = Checkin ('A', finfo, rcs, rev, tag, options, message);
+ ret = Checkin ('A', finfo, rcs, rev, tag, options, saved_message);
if (ret == 0)
{
char *tmp = xmalloc (strlen (finfo->file) + sizeof (CVSADM)
@@ -1931,7 +1937,7 @@ checkaddfile (file, repository, tag, options, rcsnode)
Attic. */
oldfile = xstrdup (rcs);
sprintf (rcs, "%s/%s%s", repository, file, RCSEXT);
-
+
if (strcmp (oldfile, rcs) == 0)
{
error (0, 0, "internal error: confused about attic for %s",
@@ -2154,7 +2160,7 @@ internal error: `%s' didn't move out of the attic",
retval = 1;
goto out;
}
- }
+ }
if (rcsnode && *rcsnode != rcsfile)
{
@@ -2200,7 +2206,7 @@ lock_RCS (user, rcs, rev, repository)
* 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.
diff --git a/contrib/cvs/src/cvs.h b/contrib/cvs/src/cvs.h
index 3a7e9e4febd0..f8b1552d4a1d 100644
--- a/contrib/cvs/src/cvs.h
+++ b/contrib/cvs/src/cvs.h
@@ -385,6 +385,8 @@ extern int trace; /* Show all commands */
extern int noexec; /* Don't modify disk anywhere */
extern int logoff; /* Don't write history entry */
+extern int top_level_admin;
+
#ifdef AUTH_SERVER_SUPPORT
extern char *Pserver_Repos; /* used to check that same repos is
transmitted in pserver auth and in
@@ -429,6 +431,8 @@ 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));
+
char *Name_Repository PROTO((char *dir, char *update_dir));
char *Short_Repository PROTO((char *repository));
void Sanitize_Repository_Name PROTO((char *repository));
@@ -476,7 +480,6 @@ 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 link_file PROTO ((const char *from, const char *to));
int unlink_file_dir PROTO((const char *f));
int update PROTO((int argc, char *argv[]));
int xcmp PROTO((const char *file1, const char *file2));
@@ -834,7 +837,7 @@ 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 status PROTO((int argc, char **argv));
+extern int cvsstatus PROTO((int argc, char **argv));
extern int cvstag PROTO((int argc, char **argv));
extern unsigned long int lookup_command_attribute PROTO((char *));
diff --git a/contrib/cvs/src/diff.c b/contrib/cvs/src/diff.c
index 7a4c105b9d3d..341c04c248f1 100644
--- a/contrib/cvs/src/diff.c
+++ b/contrib/cvs/src/diff.c
@@ -434,7 +434,15 @@ diff_fileproc (callerdat, finfo)
exists = 0;
/* special handling for TAG_HEAD */
if (diff_rev1 && strcmp (diff_rev1, TAG_HEAD) == 0)
- exists = vers->vn_rcs != NULL;
+ {
+ char *head =
+ (vers->vn_rcs == NULL
+ ? NULL
+ : RCS_branch_head (vers->srcfile, vers->vn_rcs));
+ exists = head != NULL;
+ if (head != NULL)
+ free (head);
+ }
else
{
Vers_TS *xvers;
@@ -814,7 +822,9 @@ diff_file_nodiff (finfo, vers, empty_file)
{
/* special handling for TAG_HEAD */
if (diff_rev1 && strcmp (diff_rev1, TAG_HEAD) == 0)
- use_rev1 = xstrdup (vers->vn_rcs);
+ use_rev1 = ((vers->vn_rcs == NULL || vers->srcfile == NULL)
+ ? NULL
+ : RCS_branch_head (vers->srcfile, vers->vn_rcs));
else
{
xvers = Version_TS (finfo, NULL, diff_rev1, diff_date1, 1, 0);
@@ -827,7 +837,9 @@ diff_file_nodiff (finfo, vers, empty_file)
{
/* special handling for TAG_HEAD */
if (diff_rev2 && strcmp (diff_rev2, TAG_HEAD) == 0)
- use_rev2 = xstrdup (vers->vn_rcs);
+ use_rev2 = ((vers->vn_rcs == NULL || vers->srcfile == NULL)
+ ? NULL
+ : RCS_branch_head (vers->srcfile, vers->vn_rcs));
else
{
xvers = Version_TS (finfo, NULL, diff_rev2, diff_date2, 1, 0);
diff --git a/contrib/cvs/src/edit.c b/contrib/cvs/src/edit.c
index 6c6f04014492..aa0f4c481424 100644
--- a/contrib/cvs/src/edit.c
+++ b/contrib/cvs/src/edit.c
@@ -521,6 +521,26 @@ unedit_fileproc (callerdat, finfo)
if (node != NULL)
{
entdata = (Entnode *) 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);
diff --git a/contrib/cvs/src/error.c b/contrib/cvs/src/error.c
index cb69bdeff4fd..9dcc162261e7 100644
--- a/contrib/cvs/src/error.c
+++ b/contrib/cvs/src/error.c
@@ -89,7 +89,15 @@ error_exit PROTO ((void))
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. */
+ 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 (HAVE_VPRINTF) && defined (__STDC__)
@@ -102,6 +110,9 @@ error (status, errnum, message, va_alist)
va_dcl
#endif
{
+ /* Prevent strtoul (via int_vasprintf) from clobbering it. */
+ int save_errno = errno;
+
#ifdef HAVE_VPRINTF
if (message[0] != '\0')
{
@@ -211,6 +222,7 @@ error (status, errnum, message, va_alist)
if (status)
error_exit ();
+ errno = save_errno;
}
/* Print the program name and error message MESSAGE, which is a printf-style
diff --git a/contrib/cvs/src/fileattr.c b/contrib/cvs/src/fileattr.c
index a5abea0605a3..4042d2a528e8 100644
--- a/contrib/cvs/src/fileattr.c
+++ b/contrib/cvs/src/fileattr.c
@@ -111,6 +111,10 @@ fileattr_read ()
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;
@@ -130,6 +134,10 @@ fileattr_read ()
/* 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;
fileattr_default_attrs = xstrdup (p);
}
diff --git a/contrib/cvs/src/filesubr.c b/contrib/cvs/src/filesubr.c
index 0ccc3df91801..1c24b2f64faa 100644
--- a/contrib/cvs/src/filesubr.c
+++ b/contrib/cvs/src/filesubr.c
@@ -415,29 +415,6 @@ rename_file (from, to)
}
/*
- * link a file, if possible. Warning: the Windows NT version of this
- * function just copies the file, so only use this function in ways
- * that can deal with either a link or a copy.
- */
-int
-link_file (from, to)
- const char *from;
- const char *to;
-{
- if (trace)
-#ifdef SERVER_SUPPORT
- (void) fprintf (stderr, "%c-> link(%s,%s)\n",
- (server_active) ? 'S' : ' ', from, to);
-#else
- (void) fprintf (stderr, "-> link(%s,%s)\n", from, to);
-#endif
- if (noexec)
- return (0);
-
- return (link (from, to));
-}
-
-/*
* unlink a file, if possible.
*/
int
@@ -770,7 +747,9 @@ xreadlink (link)
const char *link;
{
char *file = NULL;
- int buflen = BUFSIZ;
+ char *tfile;
+ int buflen = 128;
+ int link_name_len;
if (!islink (link))
return NULL;
@@ -781,18 +760,21 @@ xreadlink (link)
do
{
file = xrealloc (file, buflen);
- errno = 0;
- readlink (link, file, buflen);
+ link_name_len = readlink (link, file, buflen - 1);
buflen *= 2;
}
- while (errno == ENAMETOOLONG);
+ while (link_name_len < 0 && errno == ENAMETOOLONG);
- if (errno)
+ if (link_name_len < 0)
error (1, errno, "cannot readlink %s", link);
- return file;
-}
+ file[link_name_len] = '\0';
+ tfile = xstrdup (file);
+ free (file);
+
+ return tfile;
+}
/* Return a pointer into PATH's last component. */
diff --git a/contrib/cvs/src/hardlink.c b/contrib/cvs/src/hardlink.c
index 51bd2a60567b..b279aa9c3d0b 100644
--- a/contrib/cvs/src/hardlink.c
+++ b/contrib/cvs/src/hardlink.c
@@ -41,96 +41,6 @@ List *hardlist; /* Record hardlink information for working files */
char *working_dir; /* The top-level working directory, used for
constructing full pathnames. */
-/* For check_link_proc: list all of the files named in an inode list. */
-static int
-list_files_proc (node, vstrp)
- Node *node;
- void *vstrp;
-{
- char **strp, *file;
- int len;
-
- /* Get the file's basename. This is because -- VERY IMPORTANT --
- the `hardlinks' field is presently defined only to include links
- within a directory. So the hardlinks field might be `foo' or
- `mumble grump flink', but not `foo bar com/baz' or `wham ../bam
- ../thank/you'. Someday it would be nice to extend this to
- permit cross-directory links, but the issues involved are
- hideous. */
-
- file = strrchr (node->key, '/');
- if (file)
- ++file;
- else
- file = node->key;
-
- /* Is it safe to cast vstrp to (char **) here, and then play with
- the contents? I think so, since vstrp will have started out
- a char ** to begin with, so we should not have alignment bugs. */
- strp = (char **) vstrp;
- len = (*strp == NULL ? 0 : strlen (*strp));
- *strp = (char *) xrealloc (*strp, len + strlen (file) + 2);
- if (*strp == NULL)
- {
- error (0, errno, "could not allocate memory");
- return 1;
- }
- if (sprintf (*strp + len, "%s ", file) < 0)
- {
- error (0, errno, "could not compile file list");
- return 1;
- }
-
- return 0;
-}
-
-/* Set the link field of each hardlink_info node to `data', which is a
- list of linked files. */
-static int
-set_hardlink_field_proc (node, data)
- Node *node;
- void *data;
-{
- struct hardlink_info *hlinfo = (struct hardlink_info *) node->data;
- hlinfo->links = xstrdup ((char *) data);
-
- return 0;
-}
-
-/* For each file being checked in, compile a list of the files linked
- to it, and cache the list in the file's hardlink_info field. */
-int
-cache_hardlinks_proc (node, data)
- Node *node;
- void *data;
-{
- List *inode_links;
- char *p, *linked_files = NULL;
- int err;
-
- inode_links = (List *) node->data;
-
- /* inode->data is a list of hardlink_info structures: all the
- files linked to this inode. We compile a string of each file
- named in this list, in alphabetical order, separated by spaces.
- Then store this string in the `links' field of each
- hardlink_info structure, so that RCS_checkin can easily add
- it to the `hardlinks' field of a new delta node. */
-
- sortlist (inode_links, fsortcmp);
- err = walklist (inode_links, list_files_proc, &linked_files);
- if (err)
- return err;
-
- /* Trim trailing whitespace. */
- p = linked_files + strlen(linked_files) - 1;
- while (p > linked_files && isspace (*p))
- *p-- = '\0';
-
- err = walklist (inode_links, set_hardlink_field_proc, linked_files);
- return err;
-}
-
/* 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
@@ -237,26 +147,28 @@ update_hardlink_info (file)
hlinfo = (struct hardlink_info *) n->data;
hlinfo->status = T_UPTODATE;
hlinfo->checked_out = 1;
- hlinfo->links = NULL;
}
-/* Return a string listing all the files known to be linked to FILE in
+/* 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. */
-char *
-list_files_linked_to (file)
- const char *file;
+ 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, *filelist, *path;
+ char *inodestr, *path;
struct stat sb;
Node *n;
- int err;
/* 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 string. */
+ (cvs update, cvs commit, etc). Return an empty list. */
if (hardlist == NULL)
- return xstrdup ("");
+ return getlist();
/* Get the full pathname of file (assuming the working directory) */
if (file[0] == '/')
@@ -288,11 +200,107 @@ list_files_linked_to (file)
n = findnode (hardlist, inodestr);
sortlist ((List *) n->data, fsortcmp);
- filelist = NULL;
- err = walklist ((List *) n->data, list_files_proc, &filelist);
- if (err)
- error (1, 0, "cannot get list of hardlinks for %s", file);
-
free (inodestr);
- return filelist;
+ return (List *) 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 (sizeof(char) * (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 = (struct hardlink_info *) 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;
+}
+
diff --git a/contrib/cvs/src/hardlink.h b/contrib/cvs/src/hardlink.h
index cce3f33a265e..f9df34448ed7 100644
--- a/contrib/cvs/src/hardlink.h
+++ b/contrib/cvs/src/hardlink.h
@@ -21,13 +21,13 @@ struct hardlink_info
{
Ctype status; /* as returned from Classify_File() */
int checked_out; /* has this file been checked out lately? */
- char *links; /* contents of `hardlinks' RCS field */
};
extern List *hardlist;
extern char *working_dir;
-int cache_hardlinks_proc PROTO ((Node *, void *));
Node *lookup_file_by_inode PROTO ((const char *));
void update_hardlink_info PROTO ((const char *));
-char *list_files_linked_to 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 *));
diff --git a/contrib/cvs/src/history.c b/contrib/cvs/src/history.c
index 223e5a770fb4..8f1e254720ed 100644
--- a/contrib/cvs/src/history.c
+++ b/contrib/cvs/src/history.c
@@ -200,7 +200,6 @@ 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 time_t date_and_time PROTO((char *date_str));
static void expand_modules PROTO((void));
static void read_hrecs PROTO((char *fname));
static void report_hrecs PROTO((void));
@@ -242,8 +241,8 @@ static char *tz_name = "+0000";
static char *since_rev;
static char *since_tag;
static char *backto;
-/* -D option, or 0 if not specified. */
-static time_t since_date;
+/* -D option, or 0 if not specified. RCS format. */
+static char * since_date;
static struct hrec *last_since_tag;
static struct hrec *last_backto;
@@ -364,18 +363,6 @@ sort_order (l, r)
return (left->idx - right->idx);
}
-static time_t
-date_and_time (date_str)
- char *date_str;
-{
- time_t t;
-
- t = get_date (date_str, (struct timeb *) NULL);
- if (t == (time_t) - 1)
- error (1, 0, "Can't parse date/time: %s", date_str);
- return (t);
-}
-
int
history (argc, argv)
int argc;
@@ -432,14 +419,16 @@ history (argc, argv)
error (0, 0, "date overriding rev/tag/backto");
*since_rev = *since_tag = *backto = '\0';
}
- since_date = date_and_time (optarg);
+ 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';
- since_date = 0;
+ if (since_date != NULL)
+ free (since_date);
+ since_date = NULL;
}
free (backto);
backto = xstrdup (optarg);
@@ -461,7 +450,9 @@ history (argc, argv)
{
error (0, 0, "rev overriding date/tag/backto");
*since_tag = *backto = '\0';
- since_date = 0;
+ if (since_date != NULL)
+ free (since_date);
+ since_date = NULL;
}
free (since_rev);
since_rev = xstrdup (optarg);
@@ -471,7 +462,9 @@ history (argc, argv)
{
error (0, 0, "tag overriding date/marker/file/repos");
*since_rev = *backto = '\0';
- since_date = 0;
+ if (since_date != NULL)
+ free (since_date);
+ since_date = NULL;
}
free (since_tag);
since_tag = xstrdup (optarg);
@@ -564,7 +557,7 @@ history (argc, argv)
if (histfile)
send_arg("-X");
if (since_date)
- option_with_arg ("-D", asctime (gmtime (&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)
@@ -683,6 +676,8 @@ history (argc, argv)
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);
@@ -1157,7 +1152,7 @@ select_hrec (hr)
/* "Since" checking: The argument parser guarantees that only one of the
* following four choices is set:
*
- * 1. If "since_date" is set, it contains a Unix time_t specified on the
+ * 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
@@ -1177,8 +1172,12 @@ select_hrec (hr)
*/
if (since_date)
{
- if (hr->date < since_date)
+ char *ourdate = date_from_time_t (hr->date);
+
+ if (RCS_datecmp (ourdate, since_date) < 0)
return (0);
+
+ free (ourdate);
}
else if (*since_rev)
{
diff --git a/contrib/cvs/src/import.c b/contrib/cvs/src/import.c
index d79a10e31464..77c617a195c8 100644
--- a/contrib/cvs/src/import.c
+++ b/contrib/cvs/src/import.c
@@ -20,8 +20,6 @@
#include "savecwd.h"
#include <assert.h>
-#define FILE_HOLDER ".#cvsxxx"
-
static char *get_comment PROTO((char *user));
static int add_rev PROTO((char *message, RCSNode *rcs, char *vfile,
char *vers));
@@ -655,39 +653,15 @@ add_rev (message, rcs, vfile, vers)
RCS_rewrite (rcs, NULL, NULL);
}
tocvsPath = wrap_tocvs_process_file (vfile);
- if (tocvsPath == NULL)
- {
- /* We play with hard links rather than passing -u to ci to avoid
- expanding RCS keywords (see test 106.5 in sanity.sh). */
- if (link_file (vfile, FILE_HOLDER) < 0)
- {
- if (errno == EEXIST)
- {
- (void) unlink_file (FILE_HOLDER);
- (void) link_file (vfile, FILE_HOLDER);
- }
- else
- {
- ierrno = errno;
- fperror (logfp, 0, ierrno,
- "ERROR: cannot create link to %s", vfile);
- error (0, ierrno, "ERROR: cannot create link to %s", vfile);
- return (1);
- }
- }
- }
status = RCS_checkin (rcs, tocvsPath == NULL ? vfile : tocvsPath,
message, vbranch,
- (RCS_FLAGS_QUIET
+ (RCS_FLAGS_QUIET | RCS_FLAGS_KEEPFILE
| (use_file_modtime ? RCS_FLAGS_MODTIME : 0)));
ierrno = errno;
- if (tocvsPath == NULL)
- rename_file (FILE_HOLDER, vfile);
- else
- if (unlink_file_dir (tocvsPath) < 0)
- error (0, errno, "cannot remove %s", tocvsPath);
+ if ((tocvsPath != NULL) && (unlink_file_dir (tocvsPath) < 0))
+ error (0, errno, "cannot remove %s", tocvsPath);
if (status)
{
diff --git a/contrib/cvs/src/main.c b/contrib/cvs/src/main.c
index 9465be615783..68513df4033d 100644
--- a/contrib/cvs/src/main.c
+++ b/contrib/cvs/src/main.c
@@ -41,6 +41,12 @@ int quiet = 0;
int trace = 0;
int noexec = 0;
int logoff = 0;
+
+/* 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;
@@ -108,7 +114,7 @@ static const struct cmd
{ "rdiff", "patch", "pa", patch },
{ "release", "re", "rel", release },
{ "remove", "rm", "delete", cvsremove },
- { "status", "st", "stat", status },
+ { "status", "st", "stat", cvsstatus },
{ "rtag", "rt", "rfreeze", rtag },
{ "tag", "ta", "freeze", cvstag },
{ "unedit", NULL, NULL, unedit },
@@ -281,6 +287,10 @@ lookup_command_attribute (cmd_name)
}
+ /* The following commands do not use a checked-out working
+ directory. We conservatively assume that everything else does.
+ Feel free to add to this list if you are _certain_ something
+ something doesn't use the WD. */
if ((strcmp (cmd_name, "checkout") != 0) &&
(strcmp (cmd_name, "init") != 0) &&
(strcmp (cmd_name, "login") != 0) &&
@@ -296,8 +306,10 @@ lookup_command_attribute (cmd_name)
/* The following commands do not modify the repository; we
conservatively assume that everything else does. Feel free to
add to this list if you are _certain_ something is safe. */
- if ((strcmp (cmd_name, "checkout") != 0) &&
+ if ((strcmp (cmd_name, "annotate") != 0) &&
+ (strcmp (cmd_name, "checkout") != 0) &&
(strcmp (cmd_name, "diff") != 0) &&
+ (strcmp (cmd_name, "rdiff") != 0) &&
(strcmp (cmd_name, "update") != 0) &&
(strcmp (cmd_name, "history") != 0) &&
(strcmp (cmd_name, "editors") != 0) &&
@@ -967,20 +979,37 @@ char *
Make_Date (rawdate)
char *rawdate;
{
- struct tm *ftm;
time_t unixtime;
- char date[MAXDATELEN];
- char *ret;
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. */
+ 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,
diff --git a/contrib/cvs/src/mkmodules.c b/contrib/cvs/src/mkmodules.c
index c3c530d803c5..e716222b1e3f 100644
--- a/contrib/cvs/src/mkmodules.c
+++ b/contrib/cvs/src/mkmodules.c
@@ -283,6 +283,11 @@ static const char *const config_contents[] = {
"# Set `PreservePermissions' to `yes' to save file status information\n",
"# in the repository.\n",
"#PreservePermissions=no\n",
+ "\n",
+ "# 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",
NULL
};
diff --git a/contrib/cvs/src/options.h.in b/contrib/cvs/src/options.h.in
index 144980e068a5..67e8c40aa048 100644
--- a/contrib/cvs/src/options.h.in
+++ b/contrib/cvs/src/options.h.in
@@ -15,13 +15,12 @@
* or the configure script directly. Sorry.
*/
-/*
- * For portability and heterogeneity reasons, CVS is shipped by
- * default using my own text-file version of the ndbm database library
- * in the src/myndbm.c file. If you want better performance and are
- * not concerned about heterogeneous hosts accessing your modules
- * file, turn this option off.
- */
+/* By default, CVS stores its modules and other such items in flat
+ text files (MY_NDBM enables this). Turning off MY_NDBM causes CVS
+ to look for a system-supplied ndbm database library and use it
+ instead. That may speed things up, but the default setting
+ generally works fine too. */
+
#ifndef MY_NDBM
#define MY_NDBM
#endif
diff --git a/contrib/cvs/src/parseinfo.c b/contrib/cvs/src/parseinfo.c
index a8a1b4a39180..9847ab952196 100644
--- a/contrib/cvs/src/parseinfo.c
+++ b/contrib/cvs/src/parseinfo.c
@@ -346,6 +346,18 @@ warning: this CVS does not support PreservePermissions");
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
{
/* We may be dealing with a keyword which was added in a
diff --git a/contrib/cvs/src/rcs.c b/contrib/cvs/src/rcs.c
index 89af760725aa..951736e80b30 100644
--- a/contrib/cvs/src/rcs.c
+++ b/contrib/cvs/src/rcs.c
@@ -81,6 +81,9 @@ 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 *,
@@ -563,7 +566,9 @@ RCS_reparsercsfile (rdata, pfp, rcsbufp)
key, rcsfile);
free (rdata->desc);
}
- rdata->desc = rcsbuf_valcopy (&rcsbuf, value, 0, (size_t *) NULL);
+ /* Don't need to rcsbuf_valcopy `value' because
+ getdelta already did that. */
+ rdata->desc = xstrdup (value);
}
rdata->delta_pos = rcsbuf_ftell (&rcsbuf);
@@ -799,6 +804,9 @@ free_rcsnode_contents (rnode)
/* 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)
@@ -1281,6 +1289,480 @@ rcsbuf_getkey (rcsbuf, keyp, valp)
#undef my_whitespace
}
+/* TODO: Eliminate redundant code in rcsbuf_getkey, rcsbuf_getid,
+ rcsbuf_getstring, rcsbuf_getword. These last three functions were
+ all created by hacking monstrous swaths of code from rcsbuf_getkey,
+ and some engineering would make the code easier to read and
+ maintain.
+
+ Note that the extreme hair in rcsbuf_getkey is because profiling
+ statistics show that it was worth it.
+
+ We probably could be processing "hardlinks" by first calling
+ rcsbuf_getkey, and breaking up the value afterwards; the code to
+ break it up would not need to be hacked for speed. This would
+ remove the need for rcsbuf_getword, rcsbuf_getid, and
+ rcsbuf_getstring, as the other calls are easy to remove. */
+
+/* Read an `id' (in the sense of rcsfile(5)) from RCSBUF, and store in
+ IDP. */
+
+static int
+rcsbuf_getid (rcsbuf, idp)
+ struct rcsbuffer *rcsbuf;
+ char **idp;
+{
+ 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. */
+ if (ptr < rcsbuf_buffer || ptr > rcsbuf_buffer + rcsbuf_buffer_size)
+ abort ();
+
+ /* 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 (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. */
+ if (len > RCSBUF_BUFSIZE)
+ abort ();
+
+ /* 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. */
+
+ *idp = ptr;
+
+ if (c != ';')
+ {
+ while (1)
+ {
+ ++ptr;
+ if (ptr >= ptrend)
+ {
+ ptr = rcsbuf_fill (rcsbuf, ptr, idp, (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 *IDP points to the id in the buffer, C is the character
+ we found at the end of the key, and PTR points to the location in
+ the buffer where we found C. We may not set *PTR to \0, because
+ it may overwrite a terminating semicolon. The calling function
+ must copy and terminate the id on its own. */
+
+ rcsbuf->ptr = ptr;
+ return 1;
+
+#undef my_whitespace
+}
+
+/* Read an RCS @-delimited string. Store the result in STRP. */
+
+static int
+rcsbuf_getstring (rcsbuf, strp)
+ struct rcsbuffer *rcsbuf;
+ char **strp;
+{
+ register const char * const my_spacetab = spacetab;
+ register char *ptr, *ptrend;
+ char *pat;
+ size_t vlen;
+ 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. */
+ if (ptr < rcsbuf_buffer || ptr > rcsbuf_buffer + rcsbuf_buffer_size)
+ abort ();
+
+ /* 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 (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. */
+ if (len > RCSBUF_BUFSIZE)
+ abort ();
+
+ /* 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)
+ error (1, 0, "unexpected end of file reading %s",
+ rcsbuf->filename);
+ ptrend = rcsbuf->ptrend;
+ }
+
+ c = *ptr;
+ if (! my_whitespace (c))
+ break;
+
+ ++ptr;
+ }
+
+ /* PTR should now point to the start of a string. */
+ if (c != '@')
+ error (1, 0, "expected @-string at `%c' in %s", c, rcsbuf->filename);
+
+ /* Optimize the common case of a value composed of a single
+ '@' string. */
+
+ rcsbuf->at_string = 1;
+
+ ++ptr;
+
+ *strp = 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, NULL, strp);
+ 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, NULL, strp);
+ 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 - *strp;
+ if (vlen == 0)
+ *strp = NULL;
+ rcsbuf->vlen = vlen;
+ rcsbuf->ptr = pat + 1;
+
+ return 1;
+
+#undef my_whitespace
+}
+
+/* Read an RCS `word', in the sense of rcsfile(5) (an id, a num, a
+ @-delimited string, or `:'). Store the result in WORDP. If a
+ `;' is reached without reading any text, the result is NULL. */
+
+static int
+rcsbuf_getword (rcsbuf, wordp)
+ struct rcsbuffer *rcsbuf;
+ char **wordp;
+{
+ 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. */
+ if (ptr < rcsbuf_buffer || ptr > rcsbuf_buffer + rcsbuf_buffer_size)
+ abort ();
+
+ /* 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 (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. */
+ if (len > RCSBUF_BUFSIZE)
+ abort ();
+
+ /* 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)
+ error (1, 0, "unexpected end of file reading %s",
+ rcsbuf->filename);
+ ptrend = rcsbuf->ptrend;
+ }
+
+ c = *ptr;
+ if (! my_whitespace (c))
+ break;
+
+ ++ptr;
+ }
+
+ /* If we have reached `;', there is no value. */
+ if (c == ';')
+ {
+ *wordp = NULL;
+ *ptr++ = '\0';
+ rcsbuf->ptr = ptr;
+ rcsbuf->vlen = 0;
+ return 1;
+ }
+
+ /* PTR now points to the start of a value. Find out whether it is
+ a num, an id, a string or a colon. */
+ if (c == ':')
+ {
+ *wordp = ptr++;
+ rcsbuf->ptr = ptr;
+ rcsbuf->vlen = 1;
+ return 1;
+ }
+
+ if (c == '@')
+ {
+ char *pat;
+ size_t vlen;
+
+ /* Optimize the common case of a value composed of a single
+ '@' string. */
+
+ rcsbuf->at_string = 1;
+
+ ++ptr;
+
+ *wordp = 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, NULL, wordp);
+ 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, NULL, wordp);
+ 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 - *wordp;
+ if (vlen == 0)
+ *wordp = NULL;
+ rcsbuf->vlen = vlen;
+ rcsbuf->ptr = pat + 1;
+
+ return 1;
+ }
+
+ /* C 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, "illegal special character in RCS field in %s",
+ rcsbuf->filename);
+ }
+
+ *wordp = ptr;
+ while (1)
+ {
+ if (ptr >= ptrend)
+ {
+ ptr = rcsbuf_fill (rcsbuf, ptr, (char **) NULL, wordp);
+ if (ptr == NULL)
+ error (1, 0, "unexpected end of file reading %s",
+ rcsbuf->filename);
+ ptrend = rcsbuf->ptrend;
+ }
+
+ /* Legitimate ID characters are digits, dots and any `graphic
+ printing character that is not a special.' This test ought
+ to do the trick. */
+ c = *ptr;
+ if (isprint (c) &&
+ c != ';' && c != '$' && c != ',' && c != '@' && c != ':')
+ {
+ ++ptr;
+ continue;
+ }
+ break;
+ }
+
+ /* PTR 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 semicolon. */
+ if (c == ';' || my_whitespace (c))
+ {
+ rcsbuf->vlen = ptr - *wordp;
+ rcsbuf->ptr = ptr;
+ return 1;
+ }
+
+ error (1, 0, "illegal special character in RCS field in %s",
+ rcsbuf->filename);
+ /* Shut up compiler warnings. */
+ return 0;
+
+#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
@@ -1875,6 +2357,89 @@ RCS_getversion (rcs, tag, date, force_tag_match, simple_tag)
}
/*
+ * 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,
+ * exit with error.
+ */
+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);
+ }
+ }
+
+ /* 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, '.');
+ 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 && (strcmp (tag, TAG_HEAD) == 0))
+ return (RCS_head (rcs));
+
+ /* If valid tag let translate_symtag say yea or nay. */
+ rev = translate_symtag (rcs, tag);
+
+ if (rev)
+ return rev;
+
+ error (1, 0, "tag `%s' does not exist", tag);
+ /* NOT REACHED -- error (1 ... ) does not return here */
+ return 0;
+}
+
+/*
* 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
@@ -2344,6 +2909,41 @@ RCS_getbranch (rcs, tag, force_tag_match)
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 (*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
@@ -2871,6 +3471,40 @@ RCS_check_tag (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 (last))
+ return 0;
+ while ((c = *rev++)) /* Extra parens placate -Wall gcc option */
+ {
+ if (c == '.')
+ {
+ if (last == '.')
+ return 0;
+ continue;
+ }
+ last = c;
+ if (!isdigit (c))
+ return 0;
+ }
+ if (!isdigit (last))
+ return 0;
+ return 1;
+}
+
+/*
* Return true if RCS revision with TAG is a dead revision.
*/
int
@@ -3525,11 +4159,10 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
size_t loglen;
Node *vp = NULL;
#ifdef PRESERVE_PERMISSIONS_SUPPORT
- uid_t rcs_owner;
- gid_t rcs_group;
+ uid_t rcs_owner = (uid_t) -1;
+ gid_t rcs_group = (gid_t) -1;
mode_t rcs_mode;
- int change_rcs_owner = 0;
- int change_rcs_group = 0;
+ int change_rcs_owner_or_group = 0;
int change_rcs_mode = 0;
int special_file = 0;
unsigned long devnum_long;
@@ -3681,7 +4314,6 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
{
RCSVers *vers;
Node *info;
- struct hardlink_info *hlinfo;
vp = findnode (rcs->versions, rev == NULL ? rcs->head : rev);
if (vp == NULL)
@@ -3708,7 +4340,7 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
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 (unlink (dest) < 0 && existence_error (errno))
+ if (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",
@@ -3730,64 +4362,36 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
if (workfile != NULL)
{
- info = findnode (vers->other_delta, "hardlinks");
- if (info != NULL)
+ List *links = vers->hardlinks;
+ if (links != NULL)
{
- char *links = xstrdup (info->data);
- char *working_dir = xgetwd();
- char *p, *file = NULL;
- Node *n, *uptodate_link;
+ 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. */
- uptodate_link = NULL;
- for (p = strtok (links, " ");
- p != NULL && uptodate_link == NULL;
- p = strtok (NULL, " "))
- {
- file = (char *)
- xmalloc (sizeof(char) *
- (strlen(working_dir) + strlen(p) + 2));
- sprintf (file, "%s/%s", working_dir, p);
- n = lookup_file_by_inode (file);
- if (n == NULL)
- {
- if (strcmp (p, workfile) != 0)
- {
- /* One of the files that WORKFILE should be
- linked to is not even in the working directory.
- The user should probably be warned. */
- error (0, 0,
- "warning: %s should be hardlinked to %s, but is missing",
- p, workfile);
- }
- free (file);
- continue;
- }
+ 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. */
- /* hlinfo may be NULL if, for instance, a file is being
- removed. */
- hlinfo = (struct hardlink_info *) n->data;
- if (hlinfo && hlinfo->checked_out)
- uptodate_link = n;
- free (file);
- }
- free (links);
- free (working_dir);
+ 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.
+ invoked, then simply link workfile to that file and return.
- If one of these conditions is not met, then we're
- checking out workfile to a temp file or stdout, or
- workfile is the first one in its hardlink group to be
- checked out. Either way we must continue with a full
+ 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 =
+ (struct hardlink_info *) uptodate_link->data;
+
if (link (uptodate_link->key, workfile) < 0)
error (1, errno, "cannot link %s to %s",
workfile, uptodate_link->key);
@@ -3804,13 +4408,13 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
info = findnode (vers->other_delta, "owner");
if (info != NULL)
{
- change_rcs_owner = 1;
+ 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_group = 1;
+ change_rcs_owner_or_group = 1;
rcs_group = (gid_t) strtoul (info->data, NULL, 10);
}
info = findnode (vers->other_delta, "permissions");
@@ -3866,6 +4470,9 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
}
}
+ if (free_rev)
+ free (rev);
+
if (log != NULL)
{
free (log);
@@ -3935,9 +4542,25 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
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 (1, errno, "cannot open %s", workfile);
+ {
+ error (0, errno, "cannot open %s", workfile);
+ if (free_value)
+ free (value);
+ return 1;
+ }
}
if (workfile == NULL && sout == RUN_TTY)
@@ -3969,10 +4592,15 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
while (nleft > 0)
{
if (fwrite (p, 1, nstep, ofp) != nstep)
- error (1, errno, "cannot write %s",
+ {
+ 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)
@@ -3981,18 +4609,24 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
}
}
+ if (free_value)
+ free (value);
+
if (workfile != NULL)
{
int ret;
#ifdef PRESERVE_PERMISSIONS_SUPPORT
if (!special_file && fclose (ofp) < 0)
- error (1, errno, "cannot close %s", workfile);
+ {
+ error (0, errno, "cannot close %s", workfile);
+ return 1;
+ }
- if (change_rcs_owner || change_rcs_group)
+ if (change_rcs_owner_or_group)
{
if (chown (workfile, rcs_owner, rcs_group) < 0)
- error (0, errno, "could not change file ownership on %s",
+ error (0, errno, "could not change owner or group of %s",
workfile);
}
@@ -4002,7 +4636,10 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
: sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH));
#else
if (fclose (ofp) < 0)
- error (1, errno, "cannot close %s", workfile);
+ {
+ error (0, errno, "cannot close %s", workfile);
+ return 1;
+ }
ret = chmod (workfile,
sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH));
@@ -4020,7 +4657,10 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
!special_file &&
#endif
fclose (ofp) < 0)
- error (1, errno, "cannot close %s", sout);
+ {
+ error (0, errno, "cannot close %s", sout);
+ return 1;
+ }
}
#ifdef PRESERVE_PERMISSIONS_SUPPORT
@@ -4030,11 +4670,6 @@ RCS_checkout (rcs, workfile, rev, nametag, options, sout, pfn, callerdat)
update_hardlink_info (workfile);
#endif
- if (free_value)
- free (value);
- if (free_rev)
- free (rev);
-
return 0;
}
@@ -4361,6 +4996,7 @@ RCS_checkin (rcs, workfile, message, rev, flags)
int status, checkin_quiet, allocated_workfile;
struct tm *ftm;
time_t modtime;
+ int adding_branch = 0;
commitpt = NULL;
@@ -4381,6 +5017,41 @@ RCS_checkin (rcs, workfile, message, rev, flags)
allocated_workfile = 1;
}
+ /* Is the backend file a symbolic link? Follow it and replace the
+ filename with the destination of the link. */
+
+ while (islink (rcs->path))
+ {
+ char *newname;
+#ifdef HAVE_READLINK
+ /* The clean thing to do is probably to have each filesubr.c
+ implement this (with an error if not supported by the
+ platform, in which case islink would presumably return 0).
+ But that would require editing each filesubr.c and so the
+ expedient hack seems to be looking at HAVE_READLINK. */
+ newname = xreadlink (rcs->path);
+#else
+ error (1, 0, "internal error: islink doesn't like readlink");
+#endif
+
+ if (isabsolute (newname))
+ {
+ free (rcs->path);
+ rcs->path = newname;
+ }
+ else
+ {
+ char *oldname = last_component (rcs->path);
+ int dirlen = oldname - rcs->path;
+ char *fullnewname = xmalloc (dirlen + strlen (newname) + 1);
+ strncpy (fullnewname, rcs->path, dirlen);
+ strcpy (fullnewname + dirlen, newname);
+ free (newname);
+ free (rcs->path);
+ rcs->path = fullnewname;
+ }
+ }
+
checkin_quiet = flags & RCS_FLAGS_QUIET;
if (!checkin_quiet)
{
@@ -4427,7 +5098,6 @@ RCS_checkin (rcs, workfile, message, rev, flags)
Node *np;
struct stat sb;
char buf[64]; /* static buffer should be safe: see usage. -twp */
- char *fullpath;
delta->other_delta = getlist();
@@ -4482,25 +5152,7 @@ RCS_checkin (rcs, workfile, message, rev, flags)
}
/* Save hardlinks. */
- fullpath = xgetwd();
- fullpath = xrealloc (fullpath,
- strlen(fullpath) + strlen(workfile) + 2);
- sprintf (fullpath + strlen(fullpath), "/%s", workfile);
-
- np = lookup_file_by_inode (fullpath);
- if (np == NULL)
- {
- error (1, 0, "lost information on %s's linkage", workfile);
- }
- else
- {
- struct hardlink_info *hlinfo;
- hlinfo = (struct hardlink_info *) np->data;
- np = getnode();
- np->key = xstrdup ("hardlinks");
- np->data = xstrdup (hlinfo->links);
- (void) addnode (delta->other_delta, np);
- }
+ delta->hardlinks = list_linked_files_on_disk (workfile);
}
}
#endif
@@ -4674,6 +5326,7 @@ RCS_checkin (rcs, workfile, message, rev, flags)
goto checkin_done;
}
delta->version = RCS_addbranch (rcs, branch);
+ adding_branch = 1;
p = strrchr (branch, '.');
*p = '\0';
tip = xstrdup (branch);
@@ -4719,13 +5372,26 @@ RCS_checkin (rcs, workfile, message, rev, flags)
{
if (! STREQ (nodep->data, delta->author))
{
- error (0, 0, "%s: revision %s locked by %s",
- rcs->path,
- nodep->key, nodep->data);
- status = 1;
- goto checkin_done;
+ /* 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, nodep->data);
+ status = 1;
+ goto checkin_done;
+ }
}
- delnode (nodep);
+ else
+ delnode (nodep);
}
dtext->version = xstrdup (delta->version);
@@ -4992,6 +5658,9 @@ RCS_cmp_file (rcs, rev, options, filename)
#endif
{
fp = CVS_FOPEN (filename, 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", filename);
data.filename = filename;
data.fp = fp;
@@ -5183,8 +5852,11 @@ RCS_setbranch (rcs, rev)
}
/* Lock revision REV. LOCK_QUIET is 1 to suppress output. FIXME:
- This is only required because the RCS ci program requires a lock.
- If we eventually do the checkin ourselves, this can become a no-op. */
+ 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
@@ -5253,6 +5925,18 @@ RCS_lock (rcs, rev, lock_quiet)
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)
{
@@ -5260,6 +5944,9 @@ RCS_lock (rcs, rev, lock_quiet)
cvs_output (" unlocked\n", 0);
}
delnode (p);
+#else
+ error (1, 0, "Revision %s is already locked by %s", xrev, p->data);
+#endif
}
/* Create a new lock. */
@@ -5790,6 +6477,18 @@ RCS_delete_revs (rcs, tag1, tag2, inclusive)
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:
@@ -5802,8 +6501,6 @@ RCS_delete_revs (rcs, tag1, tag2, inclusive)
RCS_exec_rcsdiff with some changes, like being able
to suppress diagnostic messages and to direct output. */
- assert (before != NULL || after != NULL);
-
if (after != NULL)
{
char *diffbuf;
@@ -5975,6 +6672,52 @@ RCS_delete_revs (rcs, tag1, tag2, inclusive)
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. */
@@ -6771,7 +7514,7 @@ getdelta (rcsbuf, rcsfile, keyp, valp)
char **valp;
{
RCSVers *vnode;
- char *key, *value, *cp;
+ char *key, *value, *keybuf, *valbuf, *cp;
Node *kv;
/* Get revision number if it wasn't passed in. This uses
@@ -6835,7 +7578,8 @@ unable to parse %s; `author' not in the expected place", rcsfile);
error (1, 0, "\
unable to parse %s; `state' not in the expected place", rcsfile);
vnode->state = rcsbuf_valcopy (rcsbuf, value, 0, (size_t *) NULL);
- if (STREQ (value, "dead"))
+ /* The value is optional, according to rcsfile(5). */
+ if (value != NULL && STREQ (value, "dead"))
{
vnode->dead = 1;
}
@@ -6886,11 +7630,80 @@ unable to parse %s; `state' not in the expected place", rcsfile);
*/
while (1)
{
- if (! rcsbuf_getkey (rcsbuf, &key, &value))
+ int len;
+ size_t valbuflen;
+
+ key = NULL;
+
+ if (! rcsbuf_getid (rcsbuf, &keybuf))
error (1, 0, "unexpected end of file reading %s", rcsfile);
+ /* rcsbuf_getid did not terminate the key, so copy it to new space. */
+ len = rcsbuf->ptr - keybuf;
+ key = (char *) xmalloc (sizeof(char) * (len + 1));
+ strncpy (key, keybuf, len);
+ key[len] = '\0';
+
+ /* The `desc' keyword has only a single string value, with no
+ trailing semicolon, so it must be handled specially. */
if (STREQ (key, RCSDESC))
+ {
+ (void) rcsbuf_getstring (rcsbuf, &valbuf);
+ value = rcsbuf_valcopy (rcsbuf, valbuf, 1, &valbuflen);
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 (STREQ (key, "hardlinks"))
+ {
+ Node *n;
+
+ vnode->hardlinks = getlist();
+ while (1)
+ {
+ if (! rcsbuf_getword (rcsbuf, &valbuf))
+ error (1, 0, "unexpected end of file reading %s", rcsfile);
+ if (valbuf == NULL)
+ break;
+ n = getnode();
+ n->key = rcsbuf_valcopy (rcsbuf, valbuf, 1, NULL);
+ addnode (vnode->hardlinks, n);
+ }
+ continue;
+ }
+#endif
+
+ /* Get the value. */
+ value = NULL;
+ while (1)
+ {
+ if (! rcsbuf_getword (rcsbuf, &valbuf))
+ error (1, 0, "unexpected end of file reading %s", rcsfile);
+ if (valbuf == NULL)
+ break;
+
+ /* Copy valbuf to new space so we can polish it, then
+ append it to value. */
+
+ if (value == NULL)
+ {
+ value = rcsbuf_valcopy (rcsbuf, valbuf, 1, &valbuflen);
+ }
+ else
+ {
+ char *temp_value;
+
+ temp_value = rcsbuf_valcopy (rcsbuf, valbuf, 1, &valbuflen);
+ len = strlen (value);
+ value = (char *) xrealloc
+ (value, sizeof(char) * (len + valbuflen + 2));
+ value[len] = ' ';
+ strcpy (value + len + 1, temp_value);
+ free (temp_value);
+ }
+ }
/* Enable use of repositories created by certain obsolete
versions of CVS. This code should remain indefinately;
@@ -6919,8 +7732,8 @@ unable to parse %s; `state' not in the expected place", rcsfile);
vnode->other_delta = getlist ();
kv = getnode ();
kv->type = RCSFIELD;
- kv->key = xstrdup (key);
- kv->data = rcsbuf_valcopy (rcsbuf, value, 1, (size_t *) NULL);
+ kv->key = key;
+ kv->data = value;
if (addnode (vnode->other_delta, kv) != 0)
{
/* Complaining about duplicate keys in newphrases seems
@@ -7110,6 +7923,36 @@ putrcsfield_proc (node, vfp)
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
@@ -7195,6 +8038,14 @@ putdelta (vers, fp)
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);
}
@@ -7428,7 +8279,7 @@ RCS_copydeltas (rcs, fin, rcsbufin, fout, newdtext, insertpt)
to count the number of RCS revisions for which some special action
is required. */
-int
+static int
count_delta_actions (np, ignore)
Node *np;
void *ignore;
@@ -7524,8 +8375,6 @@ rcs_internal_lockfile (rcsfile)
error (1, errno, "could not open lock file `%s'", lockfile);
}
- free (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. */
@@ -7536,6 +8385,9 @@ rcs_internal_lockfile (rcsfile)
fp = fdopen (fd, FOPEN_BINARY_WRITE);
if (fp == NULL)
error (1, errno, "cannot fdopen %s", lockfile);
+
+ free (lockfile);
+
return fp;
}
@@ -7767,6 +8619,9 @@ annotate (argc, argv)
}
#endif /* CLIENT_SUPPORT */
+ if (tag != NULL)
+ tag_check_valid (tag, argc, argv, local, 0, "");
+
return start_recursion (annotate_fileproc, (FILESDONEPROC) NULL,
(DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
argc, argv, local, W_LOCAL, 0, 1, (char *)NULL,
diff --git a/contrib/cvs/src/rcs.h b/contrib/cvs/src/rcs.h
index 400d1a0a13f1..f92988f4b1e4 100644
--- a/contrib/cvs/src/rcs.h
+++ b/contrib/cvs/src/rcs.h
@@ -154,6 +154,10 @@ struct rcsversnode
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;
@@ -185,6 +189,9 @@ char *RCS_check_kflag PROTO((const char *arg));
char *RCS_getdate PROTO((RCSNode * rcs, char *date, int force_tag_match));
char *RCS_gettag PROTO((RCSNode * rcs, 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, char *tag, char *date,
int force_tag_match, int *simple_tag));
char *RCS_magicrev PROTO((RCSNode *rcs, char *rev));
@@ -196,9 +203,11 @@ int RCS_datecmp PROTO((char *date1, char *date2));
time_t RCS_getrevtime PROTO((RCSNode * rcs, 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, 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 *));
diff --git a/contrib/cvs/src/rcscmds.c b/contrib/cvs/src/rcscmds.c
index 3086b57e10c7..f8892338b421 100644
--- a/contrib/cvs/src/rcscmds.c
+++ b/contrib/cvs/src/rcscmds.c
@@ -11,6 +11,8 @@
#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.
@@ -75,6 +77,11 @@ static void call_diff_setup PROTO ((const char *prog));
static int call_diff PROTO ((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 *));
+
/* VARARGS */
static void
call_diff_setup (prog)
@@ -132,51 +139,92 @@ call_diff_add_arg (s)
call_diff_argv[call_diff_argc] = (char *) 0;
}
-/* diff_run is imported from libdiff.a. */
-extern int diff_run PROTO ((int argc, char **argv, char *out));
+/* 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;
+{
+ 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)
char *out;
{
- /* Try to keep the out-of-order bugs at bay (protocol_pipe for cvs_output
- with has "Index: foo" and such; stdout and/or stderr for diff's
- output). I think the only reason that this used to not be such
- a problem is that the time spent on the fork() and exec() of diff
- slowed us down enough to let the "Index:" make it through first.
-
- The real fix, of course, will be to have the diff library do all
- its output through callbacks (which CVS will supply as cvs_output
- and cvs_outerr). */
- sleep (1);
-
if (out == RUN_TTY)
- return diff_run (call_diff_argc, call_diff_argv, NULL);
+ 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);
+ return diff_run (call_diff_argc, call_diff_argv, out,
+ &call_diff_file_callbacks);
}
-extern int diff3_run PROTO ((int argc, char **argv, char *out));
-
static int
call_diff3 (out)
char *out;
{
- /* Try to keep the out-of-order bugs at bay (protocol_pipe for cvs_output
- with has "Index: foo" and such; stdout and/or stderr for diff's
- output). I think the only reason that this used to not be such
- a problem is that the time spent on the fork() and exec() of diff
- slowed us down enough to let the "Index:" make it through first.
-
- The real fix, of course, will be to have the diff library do all
- its output through callbacks (which CVS will supply as cvs_output
- and cvs_outerr). */
- sleep (1);
-
if (out == RUN_TTY)
- return diff3_run (call_diff_argc, call_diff_argv, NULL);
+ 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);
+ return diff3_run (call_diff_argc, call_diff_argv, out,
+ &call_diff_file_callbacks);
}
diff --git a/contrib/cvs/src/recurse.c b/contrib/cvs/src/recurse.c
index 3896bc737a58..d88bf2be30a1 100644
--- a/contrib/cvs/src/recurse.c
+++ b/contrib/cvs/src/recurse.c
@@ -13,6 +13,9 @@
#include "fileattr.h"
#include "edit.h"
+#ifdef CLIENT_SUPPORT
+static int do_argument_proc PROTO((Node * p, void *closure));
+#endif
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));
@@ -58,6 +61,24 @@ struct frame_and_entries {
List *entries;
};
+#ifdef CLIENT_SUPPORT
+/* This is a callback to send "Argument" commands to the server in the
+ case we've done a "cvs update" or "cvs commit" in a top-level
+ directory where there is no CVSADM directory. */
+
+static int
+do_argument_proc (p, closure)
+ Node *p;
+ void *closure;
+{
+ char *dir = p->key;
+ send_to_server ("Argument ", 0);
+ send_to_server (dir, 0);
+ send_to_server ("\012", 1);
+ return 0;
+}
+#endif
+
/* Start a recursive command.
Command line arguments (ARGC, ARGV) dictate the directories and
@@ -175,6 +196,19 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc, callerdat,
"there is no version here; run '%s checkout' first",
program_name);
}
+#ifdef CLIENT_SUPPORT
+ else if (client_active && 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. */
+
+ err += walklist (dirlist, do_argument_proc, NULL);
+ }
+#endif
}
else
addlist (&dirlist, ".");
@@ -586,7 +620,6 @@ do_dir_proc (p, closure)
char *newrepos;
List *sdirlist;
char *srepository;
- char *cp;
Dtype dir_return = R_PROCESS;
int stripped_dot = 0;
int err = 0;
@@ -790,16 +823,8 @@ but CVS uses %s for its own purposes; skipping %s directory",
repository = srepository;
}
- /* Put back update_dir. I think this is the same as just setting
- update_dir back to saved_update_dir, but there are a few cases I'm
- not sure about (in particular, if DIR is "." and update_dir is
- not ""), so for conservatism I'm leaving this here. */
- cp = last_component (update_dir);
- if (cp > update_dir)
- cp[-1] = '\0';
- else
- update_dir[0] = '\0';
- free (saved_update_dir);
+ free (update_dir);
+ update_dir = saved_update_dir;
return (err);
}
diff --git a/contrib/cvs/src/rtag.c b/contrib/cvs/src/rtag.c
index 93539e27f6a7..3207c1b3c3c5 100644
--- a/contrib/cvs/src/rtag.c
+++ b/contrib/cvs/src/rtag.c
@@ -477,7 +477,7 @@ pretag_proc(repository, filter)
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|RUN_REALLY));
+ return (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL));
}
static void
diff --git a/contrib/cvs/src/sanity.sh b/contrib/cvs/src/sanity.sh
index 1d877fee0b26..f97e0369a05b 100755
--- a/contrib/cvs/src/sanity.sh
+++ b/contrib/cvs/src/sanity.sh
@@ -512,8 +512,12 @@ dotest_sort ()
dotest_internal "$@"
}
-# clean any old remnants
-rm -rf ${TESTDIR}
+# 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
mkdir ${TESTDIR}
cd ${TESTDIR}
# This will show up in cvs history output where it prints the working
@@ -549,24 +553,30 @@ RCSINIT=; export RCSINIT
if test x"$*" = x; then
# Basic/miscellaneous functionality
- tests="basica basicb basicc basic1 deep basic2"
+ tests="basica basicb basicc basic1 deep basic2 commit-readonly"
# Branching, tagging, removing, adding, multiple directories
tests="${tests} rdiff death death2 branches branches2"
- tests="${tests} rcslib multibranch import importb join join2 join3"
+ tests="${tests} rcslib multibranch import importb importc"
+ tests="${tests} join join2 join3"
tests="${tests} new newb conflicts conflicts2 conflicts3"
# Checking out various places (modules, checkout -d, &c)
tests="${tests} modules modules2 modules3 modules4"
- tests="${tests} cvsadm abspath toplevel"
+ tests="${tests} cvsadm emptydir abspath toplevel toplevel2"
# Log messages, error messages.
tests="${tests} mflag editor errmsg1 errmsg2"
# Watches, binary files, history browsing, &c.
tests="${tests} devcom devcom2 devcom3 watch4"
+ tests="${tests} unedit-without-baserev"
tests="${tests} ignore binfiles binfiles2 mcopy binwrap binwrap2"
- tests="${tests} binwrap3 mwrap info config"
- tests="${tests} serverpatch log log2 ann crerepos rcs big modes stamps"
+ tests="${tests} binwrap3 mwrap info taginfo config"
+ tests="${tests} serverpatch log log2 ann ann-id crerepos rcs rcs2"
+ tests="${tests} history"
+ tests="${tests} big modes modes2 stamps"
+ # PreservePermissions stuff: permissions, symlinks et al.
+ tests="${tests} perms symlinks hardlinks"
# More tag and branch tests, keywords.
tests="${tests} sticky keyword keywordlog"
- tests="${tests} head tagdate multibranch2"
+ tests="${tests} head tagdate multibranch2 tag8k"
# "cvs admin", reserved checkouts.
tests="${tests} admin reserved"
# Nuts and bolts of diffing/merging (diff library, &c)
@@ -888,15 +898,19 @@ done"
cd ..
rm -r 2
-: mkdir ${CVSROOT_DIRNAME}/first-dir
dotest basicb-1 "${testcvs} -q co first-dir" ''
- dotest basicb-1a "test -d CVS" ''
+
+ # 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" ''
# In 1b and 1c, the first string matches if we're using absolute
# paths, while the second matches if RELATIVE_REPOS is defined
# (we're using relative paths).
- dotest basicb-1b "cat CVS/Repository" \
+: dotest basicb-1b "cat CVS/Repository" \
"${TESTDIR}/cvsroot/\." \
"\."
dotest basicb-1c "cat first-dir/CVS/Repository" \
@@ -1001,13 +1015,16 @@ U first-dir1/sdir2/sfile2'
"${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'
- dotest basicb-9a "test -d CVS" ''
+
+ # basicb-9a and basicb-9b: see note about basicb-1a
+
+ dotest_fail basicb-9a "test -d CVS" ''
# In 9b through 9f, the first string matches if we're using
# absolute paths, while the second matches if RELATIVE_REPOS
# is defined (we're using relative paths).
- dotest basicb-9b "cat CVS/Repository" \
+: dotest basicb-9b "cat CVS/Repository" \
"${TESTDIR}/cvsroot/\." \
"\."
dotest basicb-9c "cat newdir/CVS/Repository" \
@@ -1063,33 +1080,24 @@ Checking in aa;
${TESTDIR}/cvsroot/second-dir/aa,v <-- aa
initial revision: 1\.1
done"
- cd ../..
- rm -r 1
+ cd ..
- # Let's see if we can add something to Emptydir.
- dotest basicb-18 "${testcvs} -q co -d t2/t3 first-dir second-dir" \
-"U t2/t3/first-dir/Emptydir/sfile1
-U t2/t3/first-dir/sdir2/sfile2
-U t2/t3/second-dir/aa"
- cd t2
- touch emptyfile
- # The fact that CVS lets us add a file here is a CVS bug, right?
- # I can just make this an error message (on the add and/or the
- # commit) without getting flamed, right?
- # Right?
- # Right?
- dotest basicb-19 "${testcvs} add emptyfile" \
-"${PROG} [a-z]*: scheduling file .emptyfile. for addition
-${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
- dotest basicb-20 "${testcvs} -q ci -m add" \
-"RCS file: ${TESTDIR}/cvsroot/CVSROOT/Emptydir/emptyfile,v
-done
-Checking in emptyfile;
-${TESTDIR}/cvsroot/CVSROOT/Emptydir/emptyfile,v <-- emptyfile
-initial revision: 1\.1
-done"
+ # Try to remove all revisions in a file.
+ dotest_fail basicb-o1 "${testcvs} admin -o1.1 topfile" \
+"RCS file: ${TESTDIR}/cvsroot/topfile,v
+deleting revision 1\.1
+${PROG} \[[a-z]* 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: ${TESTDIR}/cvsroot/first-dir/sdir2/sfile2,v
+deleting revision 1\.2
+deleting revision 1\.1
+${PROG} \[[a-z]* aborted\]: attempt to delete all revisions"
cd ..
- rm -r t2
+ rm -r 1
mkdir 1; cd 1
# Note that -H is an illegal option.
@@ -1105,18 +1113,6 @@ ${PROG} \[admin aborted\]: specify ${PROG} -H admin for usage information"
cd ..
rmdir 1
- # OK, while we have an Emptydir around, test a few obscure
- # things about it.
- mkdir edir; cd edir
- dotest basicb-edir-1 "${testcvs} -q co -l CVSROOT" \
-"U CVSROOT${DOTSTAR}"
- cd CVSROOT
- dotest_fail basicb-edir-2 "test -d Emptydir" ''
- # This tests the code in find_dirs which skips Emptydir.
- dotest basicb-edir-3 "${testcvs} -q -n update -d -P" ''
- cd ../..
- rm -r edir
-
if test "$keep" = yes; then
echo Keeping ${TESTDIR} and exiting due to --keep
exit 0
@@ -1124,7 +1120,6 @@ ${PROG} \[admin aborted\]: specify ${PROG} -H admin for usage information"
rm -rf ${CVSROOT_DIRNAME}/first-dir
rm -rf ${CVSROOT_DIRNAME}/second-dir
- rm -rf ${CVSROOT_DIRNAME}/CVSROOT/Emptydir
rm -f ${CVSROOT_DIRNAME}/topfile,v
;;
@@ -1141,10 +1136,11 @@ ${PROG} \[[a-z]* aborted\]: there is no version here; run .${PROG} checkout. fir
Directory ${TESTDIR}/cvsroot/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 avoid it currently is to let CVS create it, and
- # then blow it away. But that is perfectly legal; people who
- # are used to the old behavior especially may be interested.
- rm -r CVS
+ # 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.
+ rm -rf CVS
dotest basicc-4 "echo *" "first-dir second-dir"
dotest basicc-5 "${testcvs} update" \
"${PROG} [a-z]*: Updating first-dir
@@ -2051,6 +2047,47 @@ O [0-9/]* [0-9:]* ${PLUS}0000 ${username} \[1\.1\] first-dir =first-di
rm -rf ${CVSROOT_DIRNAME}/second-dir
;;
+ 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} [a-z]*: scheduling file .$file. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest commit-readonly-4 "$testcvs -Q ci -m . $file" \
+"RCS file: ${TESTDIR}/cvsroot/$module/$file,v
+done
+Checking in $file;
+${TESTDIR}/cvsroot/$module/$file,v <-- $file
+initial revision: 1\.1
+done"
+
+ echo line2 >> $file
+ # Make the file read-only.
+ chmod a-w $file
+
+ dotest commit-readonly-5 "$testcvs -Q ci -m . $file" \
+"Checking in $file;
+${TESTDIR}/cvsroot/$module/$file,v <-- $file
+new revision: 1\.2; previous revision: 1\.1
+done"
+
+ cd ../..
+ rm -rf 1
+ rm -rf ${CVSROOT_DIRNAME}/$module
+ ;;
+
+
rdiff)
# Test rdiff
# XXX for now this is just the most essential test...
@@ -3557,6 +3594,17 @@ two
3
[>]>>>>>> 1\.2"
+ # Test behavior of symlinks in the repository.
+ dotest rcslib-symlink-1 "ln -s file1,v ${CVSROOT_DIRNAME}/first-dir/file2,v"
+ 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;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file2
+new revision: 1\.1\.2\.2; previous revision: 1\.1\.2\.1
+done"
+ dotest rcslib-symlink-4 "test -L ${CVSROOT_DIRNAME}/first-dir/file2,v"
+
cd ..
if test "$keep" = yes; then
@@ -3657,6 +3705,7 @@ modify-on-br1
# 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
@@ -3787,6 +3836,7 @@ modify-on-br1
fail 106.5
fi
cd ..
+ rm imported-f2-orig.tmp
# co
if ${CVS} co first-dir ; then
@@ -3972,6 +4022,83 @@ add
rm -rf ${CVSROOT_DIRNAME}/first-dir ${CVSROOT_DIRNAME}/second-dir
;;
+ importc)
+ # Test importing a bunch o' files in a bunch o' directories.
+ mkdir 1; cd 1
+ mkdir adir bdir cdir
+ mkdir adir/sub1 adir/sub2
+ mkdir adir/sub1/ssdir
+ mkdir bdir/subdir
+ touch adir/sub1/file1 adir/sub2/file2 adir/sub1/ssdir/ssfile
+ touch bdir/subdir/file1
+ touch cdir/cfile
+ dotest_sort importc-1 \
+"${testcvs} import -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} [a-z]*: Importing ${TESTDIR}/cvsroot/first-dir/adir
+${PROG} [a-z]*: Importing ${TESTDIR}/cvsroot/first-dir/adir/sub1
+${PROG} [a-z]*: Importing ${TESTDIR}/cvsroot/first-dir/adir/sub1/ssdir
+${PROG} [a-z]*: Importing ${TESTDIR}/cvsroot/first-dir/adir/sub2
+${PROG} [a-z]*: Importing ${TESTDIR}/cvsroot/first-dir/bdir
+${PROG} [a-z]*: Importing ${TESTDIR}/cvsroot/first-dir/bdir/subdir
+${PROG} [a-z]*: Importing ${TESTDIR}/cvsroot/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} [a-z]*: Updating adir/sub1
+${PROG} [a-z]*: Updating adir/sub1/ssdir"
+ dotest importc-4 "${testcvs} update adir/sub1 bdir/subdir" \
+"${PROG} [a-z]*: Updating adir/sub1
+${PROG} [a-z]*: Updating adir/sub1/ssdir
+${PROG} [a-z]*: Updating bdir/subdir"
+
+ echo modify >>cdir/cfile
+ dotest importc-5 \
+"${testcvs} -q rtag -b -r release wip_test first-dir" ""
+ dotest importc-6 "${testcvs} -q update -r wip_test" "M cdir/cfile"
+
+ if test "$remote" = no; then
+ # This checkin should just succeed. That it doesn't is a
+ # bug (CVS 1.9.16 through the present seem to have it; CVS
+ # 1.9 did not).
+ dotest_fail importc-7 "${testcvs} -q ci -m modify -r wip_test" \
+"${PROG} [a-z]*: in directory adir/sub1/ssdir:
+${PROG} \[[a-z]* aborted\]: there is no version here; do .cvs checkout. first"
+ # The workaround is to leave off the "-r wip_test".
+ dotest importc-8 "${testcvs} -q ci -m modify" \
+"Checking in cdir/cfile;
+${TESTDIR}/cvsroot/first-dir/cdir/cfile,v <-- cfile
+new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1
+done"
+ else
+ # Remote doesn't have the bug in the first place.
+ dotest importc-7 "${testcvs} -q ci -m modify -r wip_test" \
+"Checking in cdir/cfile;
+${TESTDIR}/cvsroot/first-dir/cdir/cfile,v <-- cfile
+new revision: 1\.1\.1\.1\.2\.1; previous revision: 1\.1\.1\.1
+done"
+ fi
+ cd ..
+
+ cd ..
+ rm -r 1 2
+ 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:
@@ -5779,6 +5906,10 @@ ${PROG} [a-z]*: Rebuilding administrative file database"
dotest modules2-5 "test -d ampermodule/second-dir" ''
# Test ability of cvs release to handle multiple arguments
+ # Other CVS release tests:
+ # info-cleanup-0 for "cvs -n release".
+ # ignore-193 for the text of the question that cvs release asks.
+ # Also for interactions with cvsignore.
cd ampermodule
if ${testcvs} release -d first-dir second-dir <<EOF >>${LOGFILE}
yes
@@ -5803,9 +5934,11 @@ EOF
"${PROG} [a-z]*: Updating first-dir
${PROG} [a-z]*: Updating second-dir"
touch ampermodule/first-dir/amper1
- dotest modules2-10 "${testcvs} add ampermodule/first-dir/amper1" \
-"${PROG} [a-z]*: scheduling file .ampermodule/first-dir/amper1. for addition
+ cd ampermodule
+ dotest modules2-10 "${testcvs} add first-dir/amper1" \
+"${PROG} [a-z]*: scheduling file .first-dir/amper1. for addition
${PROG} [a-z]*: 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
@@ -6131,6 +6264,7 @@ done"
cat >modules <<EOF
all -a first-dir
some -a !first-dir/subdir first-dir
+somewhat -a first-dir !first-dir/subdir
EOF
dotest modules4-8 "${testcvs} -q ci -m add-modules" \
"Checking in modules;
@@ -6152,6 +6286,21 @@ U first-dir/subdir/file2"
dotest_fail modules4-11 "test -d first-dir/subdir" ''
rm -r first-dir
+ if test "$remote" = no; then
+ # 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-11a "${testcvs} -q co somewhat" \
+"U first-dir/file1
+U first-dir/subdir/file2"
+ else
+ # But remote seems to do it the other way.
+ dotest modules4-11a "${testcvs} -q co somewhat" "U first-dir/file1"
+ dotest_fail modules4-11b "test -d first-dir/subdir" ''
+ fi
+ rm -r first-dir
+
cd ..
rm -r 2
@@ -6222,7 +6371,23 @@ add-it
# convenience variables
REP=${CVSROOT}
- # First, check out the modules file and edit it.
+ # 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;
+${TESTDIR}/cvsroot/CVSROOT/config,v <-- config
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
+done
+${PROG} [a-z]*: Rebuilding administrative file database"
+ cd ../..
+ rm -r 1
+
+ # Second, check out the modules file and edit it.
mkdir 1; cd 1
dotest cvsadm-1 "${testcvs} co CVSROOT/modules" \
"U CVSROOT/modules"
@@ -6278,26 +6443,27 @@ ${PROG} [a-z]*: Rebuilding administrative file database"
rm -rf CVS CVSROOT;
# Create the various modules
- mkdir ${CVSROOT_DIRNAME}/mod1
- mkdir ${CVSROOT_DIRNAME}/mod1-2
- mkdir ${CVSROOT_DIRNAME}/mod2
- mkdir ${CVSROOT_DIRNAME}/mod2/sub2
- mkdir ${CVSROOT_DIRNAME}/mod2-2
- mkdir ${CVSROOT_DIRNAME}/mod2-2/sub2-2
- dotest cvsadm-2 "${testcvs} co mod1 mod1-2 mod2 mod2-2" \
-"${PROG} [a-z]*: Updating mod1
-${PROG} [a-z]*: Updating mod1-2
-${PROG} [a-z]*: Updating mod2
-${PROG} [a-z]*: Updating mod2/sub2
-${PROG} [a-z]*: Updating mod2-2
-${PROG} [a-z]*: Updating mod2-2/sub2-2"
+ 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 ${TESTDIR}/cvsroot/mod1 added to the repository
+Directory ${TESTDIR}/cvsroot/mod1-2 added to the repository
+Directory ${TESTDIR}/cvsroot/mod2 added to the repository
+Directory ${TESTDIR}/cvsroot/mod2/sub2 added to the repository
+Directory ${TESTDIR}/cvsroot/mod2-2 added to the repository
+Directory ${TESTDIR}/cvsroot/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-2a "${testcvs} add mod1/file1 mod1-2/file1-2 mod2/sub2/file2 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} [a-z]*: scheduling file .mod1/file1. for addition
${PROG} [a-z]*: scheduling file .mod1-2/file1-2. for addition
${PROG} [a-z]*: scheduling file .mod2/sub2/file2. for addition
@@ -7287,68 +7453,71 @@ U dir/dir2d2-2/sub2d2-2/file2-2"
## on the command line, but use a longer path.
##################################################
+ dotest_fail cvsadm-2d3-1 "${testcvs} co -d dir/dir2 1mod" \
+"${PROG} [a-z]*: cannot chdir to dir: No such file or directory
+${PROG} [a-z]*: ignoring module 1mod"
+
+ if test "$remote" = no; then
+ # 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} [a-z]*: Updating dir/dir2
U dir/dir2/file1"
dotest cvsadm-2d3b "cat CVS/Repository" \
"${AREP}\."
- dotest cvsadm-2d3d "cat dir/CVS/Repository" \
-"${AREP}CVSROOT/Emptydir"
+ dotest_fail cvsadm-2d3d "test -f dir/CVS/Repository" ""
dotest cvsadm-2d3f "cat dir/dir2/CVS/Repository" \
"${AREP}mod1"
rm -rf CVS dir
+ mkdir dir
dotest cvsadm-2d4 "${testcvs} co -d dir/dir2 2mod" \
"${PROG} [a-z]*: Updating dir/dir2
U dir/dir2/file2"
dotest cvsadm-2d4b "cat CVS/Repository" \
"${AREP}\."
- dotest cvsadm-2d4d "cat dir/CVS/Repository" \
-"${AREP}CVSROOT/Emptydir"
dotest cvsadm-2d4f "cat dir/dir2/CVS/Repository" \
"${AREP}mod2/sub2"
rm -rf CVS dir
+ mkdir dir
dotest cvsadm-2d5 "${testcvs} co -d dir/dir2 1d1mod" \
"${PROG} [a-z]*: Updating dir/dir2
U dir/dir2/file1"
dotest cvsadm-2d5b "cat CVS/Repository" \
"${AREP}\."
- dotest cvsadm-2d5d "cat dir/CVS/Repository" \
-"${AREP}CVSROOT/Emptydir"
dotest cvsadm-2d5f "cat dir/dir2/CVS/Repository" \
"${AREP}mod1"
rm -rf CVS dir
+ mkdir dir
dotest cvsadm-2d6 "${testcvs} co -d dir/dir2 1d2mod" \
"${PROG} [a-z]*: Updating dir/dir2
U dir/dir2/file2"
dotest cvsadm-2d6b "cat CVS/Repository" \
"${AREP}\."
- dotest cvsadm-2d6d "cat dir/CVS/Repository" \
-"${AREP}CVSROOT/Emptydir"
dotest cvsadm-2d6f "cat dir/dir2/CVS/Repository" \
"${AREP}mod2/sub2"
rm -rf CVS dir
+ mkdir dir
dotest cvsadm-2d7 "${testcvs} co -d dir/dir2 2d1mod" \
"${PROG} [a-z]*: Updating dir/dir2
U dir/dir2/file1"
dotest cvsadm-2d7b "cat CVS/Repository" \
"${AREP}\."
- dotest cvsadm-2d7d "cat dir/CVS/Repository" \
-"${AREP}CVSROOT/Emptydir"
dotest cvsadm-2d7f "cat dir/dir2/CVS/Repository" \
"${AREP}mod1"
rm -rf CVS dir
+ mkdir dir
dotest cvsadm-2d8 "${testcvs} co -d dir/dir2 2d2mod" \
"${PROG} [a-z]*: Updating dir/dir2
U dir/dir2/file2"
dotest cvsadm-2d8b "cat CVS/Repository" \
"${AREP}\."
- dotest cvsadm-2d8d "cat dir/CVS/Repository" \
-"${AREP}CVSROOT/Emptydir"
dotest cvsadm-2d8f "cat dir/dir2/CVS/Repository" \
"${AREP}mod2/sub2"
rm -rf CVS dir
@@ -7490,65 +7659,60 @@ U dir/dir2d2/sub2d2/file2"
## the ones in two-deep directories
+ mkdir dir
dotest cvsadm-N2d3 "${testcvs} co -N -d dir/dir2 1mod" \
"${PROG} [a-z]*: Updating dir/dir2/1mod
U dir/dir2/1mod/file1"
dotest cvsadm-N2d3b "cat CVS/Repository" \
"${AREP}\."
- dotest cvsadm-N2d3d "cat dir/CVS/Repository" \
-"${AREP}CVSROOT/Emptydir"
dotest cvsadm-N2d3f "cat dir/dir2/CVS/Repository" \
"${AREP}\."
dotest cvsadm-N2d3h "cat dir/dir2/1mod/CVS/Repository" \
"${AREP}mod1"
rm -rf CVS dir
+ mkdir dir
dotest cvsadm-N2d4 "${testcvs} co -N -d dir/dir2 2mod" \
"${PROG} [a-z]*: Updating dir/dir2/2mod
U dir/dir2/2mod/file2"
dotest cvsadm-N2d4b "cat CVS/Repository" \
"${AREP}\."
- dotest cvsadm-N2d4d "cat dir/CVS/Repository" \
-"${AREP}CVSROOT/Emptydir"
dotest cvsadm-N2d4f "cat dir/dir2/CVS/Repository" \
"${AREP}\."
dotest cvsadm-N2d4h "cat dir/dir2/2mod/CVS/Repository" \
"${AREP}mod2/sub2"
rm -rf CVS dir
+ mkdir dir
dotest cvsadm-N2d5 "${testcvs} co -N -d dir/dir2 1d1mod" \
"${PROG} [a-z]*: Updating dir/dir2/dir1d1
U dir/dir2/dir1d1/file1"
dotest cvsadm-N2d5b "cat CVS/Repository" \
"${AREP}\."
- dotest cvsadm-N2d5d "cat dir/CVS/Repository" \
-"${AREP}CVSROOT/Emptydir"
dotest cvsadm-N2d5f "cat dir/dir2/CVS/Repository" \
"${AREP}\."
dotest cvsadm-N2d5h "cat dir/dir2/dir1d1/CVS/Repository" \
"${AREP}mod1"
rm -rf CVS dir
+ mkdir dir
dotest cvsadm-N2d6 "${testcvs} co -N -d dir/dir2 1d2mod" \
"${PROG} [a-z]*: Updating dir/dir2/dir1d2
U dir/dir2/dir1d2/file2"
dotest cvsadm-N2d6b "cat CVS/Repository" \
"${AREP}\."
- dotest cvsadm-N2d6d "cat dir/CVS/Repository" \
-"${AREP}CVSROOT/Emptydir"
dotest cvsadm-N2d6f "cat dir/dir2/CVS/Repository" \
"${AREP}\."
dotest cvsadm-N2d6h "cat dir/dir2/dir1d2/CVS/Repository" \
"${AREP}mod2/sub2"
rm -rf CVS dir
+ mkdir dir
dotest cvsadm-N2d7 "${testcvs} co -N -d dir/dir2 2d1mod" \
"${PROG} [a-z]*: Updating dir/dir2/dir2d1/sub2d1
U dir/dir2/dir2d1/sub2d1/file1"
dotest cvsadm-N2d7b "cat CVS/Repository" \
"${AREP}\."
- dotest cvsadm-N2d7d "cat dir/CVS/Repository" \
-"${AREP}CVSROOT/Emptydir"
dotest cvsadm-N2d7f "cat dir/dir2/CVS/Repository" \
"${AREP}\."
dotest cvsadm-N2d7f "cat dir/dir2/dir2d1/CVS/Repository" \
@@ -7557,13 +7721,12 @@ U dir/dir2/dir2d1/sub2d1/file1"
"${AREP}mod1"
rm -rf CVS dir
+ mkdir dir
dotest cvsadm-N2d8 "${testcvs} co -N -d dir/dir2 2d2mod" \
"${PROG} [a-z]*: Updating dir/dir2/dir2d2/sub2d2
U dir/dir2/dir2d2/sub2d2/file2"
dotest cvsadm-N2d8b "cat CVS/Repository" \
"${AREP}\."
- dotest cvsadm-N2d8d "cat dir/CVS/Repository" \
-"${AREP}CVSROOT/Emptydir"
dotest cvsadm-N2d8f "cat dir/dir2/CVS/Repository" \
"${AREP}\."
dotest cvsadm-N2d8h "cat dir/dir2/dir2d2/CVS/Repository" \
@@ -7572,10 +7735,25 @@ U dir/dir2/dir2d2/sub2d2/file2"
"${AREP}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;
+${TESTDIR}/cvsroot/CVSROOT/config,v <-- config
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
+done
+${PROG} [a-z]*: Rebuilding administrative file database"
+ cd ..
+ rm -rf CVSROOT CVS
+
# remove our junk
cd ..
rm -rf 1
@@ -7589,6 +7767,90 @@ U dir/dir2/dir2d2/sub2d2/file2"
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/sub2d1 mod1" >> 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} [a-z]*: Rebuilding administrative file database"
+ rm -rf CVS CVSROOT
+
+ mkdir ${CVSROOT_DIRNAME}/mod1
+ # Populate. Not sure we really need to do this.
+ dotest emptydir-3 "${testcvs} co mod1" \
+"${PROG} [a-z]*: Updating mod1"
+ echo "file1" > mod1/file1
+ cd mod1
+ dotest emptydir-4 "${testcvs} add file1" \
+"${PROG} [a-z]*: scheduling file .file1. for addition
+${PROG} [a-z]*: use '${PROG} commit' to add this file permanently"
+ cd ..
+ dotest emptydir-5 "${testcvs} -q ci -m yup mod1" \
+"RCS file: ${CVSROOT_DIRNAME}/mod1/file1,v
+done
+Checking in mod1/file1;
+${CVSROOT_DIRNAME}/mod1/file1,v <-- file1
+initial revision: 1\.1
+done"
+ rm -rf mod1 CVS
+ # End Populate.
+
+ dotest emptydir-6 "${testcvs} co 2d1mod" \
+"${PROG} [a-z]*: Updating dir2d1/sub2d1
+U dir2d1/sub2d1/file1"
+ cd dir2d1
+ touch emptyfile
+ # The fact that CVS lets us add a file here is a CVS bug, right?
+ # I can just make this an error message (on the add and/or the
+ # commit) without getting flamed, right?
+ # Right?
+ # Right?
+ dotest emptydir-7 "${testcvs} add emptyfile" \
+"${PROG} [a-z]*: scheduling file .emptyfile. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest emptydir-8 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/CVSROOT/Emptydir/emptyfile,v
+done
+Checking in emptyfile;
+${TESTDIR}/cvsroot/CVSROOT/Emptydir/emptyfile,v <-- emptyfile
+initial revision: 1\.1
+done
+${PROG} [a-z]*: Rebuilding administrative file database"
+ 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 ..
+
+ rm -r 1
+ rm -rf ${CVSROOT_DIRNAME}/mod1
+ # 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
@@ -7607,10 +7869,16 @@ ${PROG} [a-z]*: Updating mod2"
# Populate the module
echo "file1" > mod1/file1
echo "file2" > mod2/file2
- dotest abspath-1b "${testcvs} add mod1/file1 mod2/file2" \
-"${PROG} [a-z]*: scheduling file .mod1/file1. for addition
-${PROG} [a-z]*: scheduling file .mod2/file2. for addition
-${PROG} [a-z]*: use '${PROG} commit' to add these files permanently"
+ cd mod1
+ dotest abspath-1ba "${testcvs} add file1" \
+"${PROG} [a-z]*: scheduling file .file1. for addition
+${PROG} [a-z]*: use '${PROG} commit' to add this file permanently"
+ cd ..
+ cd mod2
+ dotest abspath-1bb "${testcvs} add file2" \
+"${PROG} [a-z]*: scheduling file .file2. for addition
+${PROG} [a-z]*: use '${PROG} commit' to add this file permanently"
+ cd ..
dotest abspath-1c "${testcvs} ci -m yup mod1 mod2" \
"${PROG} [a-z]*: Examining mod1
@@ -7632,9 +7900,17 @@ done"
# Done.
# Try checking out the module in a local directory
+ if test "$remote" = yes; then
+ dotest_fail abspath-2a "${testcvs} co -d ${TESTDIR}/1 mod1" \
+"${PROG} \[server aborted\]: absolute pathname .${TESTDIR}/1. illegal for server"
+ dotest abspath-2a-try2 "${testcvs} co -d 1 mod1" \
+"${PROG} [a-z]*: Updating 1
+U 1/file1"
+ else
dotest abspath-2a "${testcvs} co -d ${TESTDIR}/1 mod1" \
"${PROG} [a-z]*: Updating ${TESTDIR}/1
U ${TESTDIR}/1/file1"
+ fi # remote workaround
# Are we relative or absolute in our Repository file?
echo "${CVSROOT_DIRNAME}/mod1" > ${TESTDIR}/dotest.abs
@@ -7658,11 +7934,47 @@ U ${TESTDIR}/1/file1"
# 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 test "$remote" = no; then
+ dotest_fail abspath-3.1 "${testcvs} co -d ${TESTDIR}/1/2 mod1" \
+"${PROG} [a-z]*: cannot chdir to 1: No such file or directory
+${PROG} [a-z]*: ignoring module mod1"
+ fi
+ dotest_fail abspath-3.2 "${testcvs} co -d 1/2 mod1" \
+"${PROG} [a-z]*: cannot chdir to 1: No such file or directory
+${PROG} [a-z]*: ignoring module mod1"
+ mkdir 1
+
+ if test "$remote" = yes; 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} [a-z]*: cannot chdir to 1: No such file or directory
+${PROG} [a-z]*: ignoring module mod1"
+ cd 1
+ dotest abspath-3a-try2 "${testcvs} co -d 2 mod1" \
+"${PROG} [a-z]*: Updating 2
+U 2/file1"
+ cd ..
+ rm -rf 1/CVS
+ else
dotest abspath-3a "${testcvs} co -d ${TESTDIR}/1/2 mod1" \
"${PROG} [a-z]*: Updating ${TESTDIR}/1/2
U ${TESTDIR}/1/2/file1"
+ fi # remote workaround
dotest abspath-3b "cat ${TESTDIR}/1/2/CVS/Repository" \
"${AREP}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
@@ -7670,19 +7982,32 @@ U ${TESTDIR}/1/2/file1"
# Now try someplace where we don't have permission.
mkdir ${TESTDIR}/barf
chmod -w ${TESTDIR}/barf
- dotest_fail abspath-4 "${testcvs} co -d ${TESTDIR}/barf/sub mod1" \
+ if test "$remote" = yes; then
+ dotest_fail abspath-4 "${testcvs} co -d ${TESTDIR}/barf/sub mod1" \
+"${PROG} \[server aborted\]: absolute pathname .${TESTDIR}/barf/sub. illegal for server"
+ else
+ dotest_fail abspath-4 "${testcvs} co -d ${TESTDIR}/barf/sub mod1" \
"${PROG} \[[a-z]* aborted\]: cannot make directory sub: No such file or directory"
+ fi
chmod +w ${TESTDIR}/barf
rmdir ${TESTDIR}/barf
# Done. Nothing to clean up.
# Try checking out two modules into the same directory.
- dotest abspath-5a "${testcvs} co -d ${TESTDIR}/1 mod1 mod2" \
+ if test "$remote" = yes; then
+ dotest abspath-5a "${testcvs} co -d 1 mod1 mod2" \
+"${PROG} [a-z]*: Updating 1/mod1
+U 1/mod1/file1
+${PROG} [a-z]*: Updating 1/mod2
+U 1/mod2/file2"
+ else
+ dotest abspath-5a "${testcvs} co -d ${TESTDIR}/1 mod1 mod2" \
"${PROG} [a-z]*: Updating ${TESTDIR}/1/mod1
U ${TESTDIR}/1/mod1/file1
${PROG} [a-z]*: Updating ${TESTDIR}/1/mod2
U ${TESTDIR}/1/mod2/file2"
+ fi # end remote workaround
dotest abspath-5b "cat ${TESTDIR}/1/CVS/Repository" \
"${AREP}."
dotest abspath-5c "cat ${TESTDIR}/1/mod1/CVS/Repository" \
@@ -7694,7 +8019,17 @@ U ${TESTDIR}/1/mod2/file2"
# Try checking out the top-level module.
- dotest abspath-6a "${testcvs} co -d ${TESTDIR}/1 ." \
+ if test "$remote" = yes; then
+ dotest abspath-6a "${testcvs} co -d 1 ." \
+"${PROG} [a-z]*: Updating 1
+${PROG} [a-z]*: Updating 1/CVSROOT
+${DOTSTAR}
+${PROG} [a-z]*: Updating 1/mod1
+U 1/mod1/file1
+${PROG} [a-z]*: Updating 1/mod2
+U 1/mod2/file2"
+ else
+ dotest abspath-6a "${testcvs} co -d ${TESTDIR}/1 ." \
"${PROG} [a-z]*: Updating ${TESTDIR}/1
${PROG} [a-z]*: Updating ${TESTDIR}/1/CVSROOT
${DOTSTAR}
@@ -7702,6 +8037,7 @@ ${PROG} [a-z]*: Updating ${TESTDIR}/1/mod1
U ${TESTDIR}/1/mod1/file1
${PROG} [a-z]*: Updating ${TESTDIR}/1/mod2
U ${TESTDIR}/1/mod2/file2"
+ fi # end of remote workaround
dotest abspath-6b "cat ${TESTDIR}/1/CVS/Repository" \
"${AREP}."
dotest abspath-6c "cat ${TESTDIR}/1/CVSROOT/CVS/Repository" \
@@ -7713,17 +8049,45 @@ U ${TESTDIR}/1/mod2/file2"
# 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 test "$remote" = yes; then
+ dotest_fail abspath-7a "${testcvs} -q co -d ../2 mod2" \
+"${PROG} server: protocol error: .\.\./2. contains more leading \.\.
+${PROG} \[server aborted\]: than the 0 which Max-dotdot specified"
+ cd ..
+ dotest abspath-7a-try2 "${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 test "$remote" = yes; then
+ cd ../..
+ dotest abspath-7d "${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}/mod1
-
- # FIXME: the absolute pathname fixes create CVS directories
- # wherever they can. That means for the standard TESTDIR, a
- # /tmp/CVS directory will be created as well. It's not safe
- # to remove it, however.
+ rm -rf ${CVSROOT_DIRNAME}/mod1 ${CVSROOT_DIRNAME}/mod2
;;
@@ -7733,9 +8097,26 @@ U ${TESTDIR}/1/mod2/file2"
# Some test, somewhere, is creating Emptydir. That test
# should, perhaps, clean up for itself, but I don't know which
- # one it is.
+ # one it is (cvsadm, emptydir, &c).
+ # (On the other hand, should CVS care whether there is an
+ # Emptydir? That would seem a bit odd).
rm -rf ${CVSROOT_DIRNAME}/CVSROOT/Emptydir
+ # 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;
+${TESTDIR}/cvsroot/CVSROOT/config,v <-- config
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
+done
+${PROG} [a-z]*: Rebuilding administrative file database"
+ cd ../..
+ rm -r 1
+
mkdir 1; cd 1
dotest toplevel-1 "${testcvs} -q co -l ." ''
mkdir top-dir second-dir
@@ -7806,6 +8187,7 @@ ${PROG} [a-z]*: Updating top-dir"
dotest toplevel-10 "${testcvs} co top-dir" \
"${PROG} [a-z]*: 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" \
@@ -7819,12 +8201,124 @@ U top-dir/file1"
# Now set the permissions so we can't recreate it.
chmod -w ../1
# 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} [a-z]*: warning: cannot make directory CVS in \.: Permission denied
+${PROG} [a-z]*: Updating top-dir" \
+"${PROG} [a-z]*: warning: cannot make directory CVS in \.: Permission denied
+${PROG} [a-z]*: in directory \.:
+${PROG} [a-z]*: cannot open CVS/Entries for reading: No such file or directory
${PROG} [a-z]*: 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;
+${TESTDIR}/cvsroot/CVSROOT/config,v <-- config
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
+done
+${PROG} [a-z]*: Rebuilding administrative file database"
+
+ cd ../..
+ rm -r 1
+ rm -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;
+${TESTDIR}/cvsroot/CVSROOT/config,v <-- config
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
+done
+${PROG} [a-z]*: Rebuilding administrative file database"
+ cd ../..
+ rm -r 1
+
+ # 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 ${TESTDIR}/cvsroot/top-dir added to the repository
+Directory ${TESTDIR}/cvsroot/second-dir added to the repository"
+ cd top-dir
+
+ touch file1
+ dotest toplevel2-3 "${testcvs} add file1" \
+"${PROG} [a-z]*: scheduling file .file1. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest toplevel2-4 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/top-dir/file1,v
+done
+Checking in file1;
+${TESTDIR}/cvsroot/top-dir/file1,v <-- file1
+initial revision: 1\.1
+done"
+ cd ..
+
+ cd second-dir
+ touch file2
+ dotest toplevel2-3s "${testcvs} add file2" \
+"${PROG} [a-z]*: scheduling file .file2. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest toplevel2-4s "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/second-dir/file2,v
+done
+Checking in file2;
+${TESTDIR}/cvsroot/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} [a-z]*: Updating top-dir
+U top-dir/file1"
+
+ dotest toplevel2-6 "${testcvs} update top-dir" \
+"${PROG} [a-z]*: Updating top-dir"
+ dotest toplevel2-7 "${testcvs} update" \
+"${PROG} [a-z]*: Updating top-dir"
+
+ dotest toplevel2-8 "${testcvs} update -d top-dir" \
+"${PROG} [a-z]*: Updating top-dir"
+ # Contrast this with toplevel-9, which has TopLevelAdmin=yes.
+ dotest toplevel2-9 "${testcvs} update -d" \
+"${PROG} [a-z]*: Updating top-dir"
+
cd ..
+ rm -r 1; mkdir 1; cd 1
+ dotest toplevel2-10 "${testcvs} co top-dir" \
+"${PROG} [a-z]*: 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;
+${TESTDIR}/cvsroot/CVSROOT/config,v <-- config
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
+done
+${PROG} [a-z]*: Rebuilding administrative file database"
+ cd ../..
rm -r 1
rm -rf ${CVSROOT_DIRNAME}/top-dir ${CVSROOT_DIRNAME}/second-dir
;;
@@ -7894,7 +8388,7 @@ ${PROG} [a-z]*: Updating top-dir"
cat >${TESTDIR}/editme <<EOF
#!${TESTSHELL}
sleep 1
-sed <\$1 -e 's/^/x&/g' >${TESTDIR}/edit.new
+sed <\$1 -e 's/^/x/' >${TESTDIR}/edit.new
mv ${TESTDIR}/edit.new \$1
exit 0
EOF
@@ -8619,9 +9113,20 @@ Enew line here
G@#..!@#=&"
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} \[[a-z]* 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
+ rm -rf 1 2
rm -rf ${CVSROOT_DIRNAME}/first-dir
;;
@@ -8716,6 +9221,106 @@ C file1"
rm -rf ${CVSROOT_DIRNAME}/first-dir
;;
+ 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.
+ if echo "yes" | ${testcvs} -Q unedit $file \
+ >${TESTDIR}/test.tmp 2>&1 ; then
+ dotest unedit-without-baserev-4 "cat ${TESTDIR}/test.tmp" \
+"m has been modified; revert changes${QUESTION} ${PROG} unedit: m not mentioned in CVS/Baserev
+${PROG} unedit: run update to complete the unedit"
+ else
+ fail unedit-without-baserev-4
+ fi
+
+ # 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/.*"
+
+ if test "$remote" = yes; then
+ dotest unedit-without-baserev-6 "${testcvs} -q update" "U m"
+ else
+ dotest unedit-without-baserev-6 "${testcvs} -q update" \
+"${PROG} update: warning: m was lost
+U m"
+ fi
+
+ # 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;
+${TESTDIR}/cvsroot/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: ${TESTDIR}/cvsroot/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} [a-z]*: conflicts found in m
+C m"
+ rm CVS/Baserev
+ if (echo yes | ${testcvs} unedit m) >${TESTDIR}/test.tmp 2>&1; then
+ dotest unedit-without-baserev-14 "cat ${TESTDIR}/test.tmp" \
+"m has been modified; revert changes${QUESTION} ${PROG} unedit: m not mentioned in CVS/Baserev
+${PROG} unedit: run update to complete the unedit"
+ else
+ fail unedit-without-baserev-14
+ fi
+ if test "$remote" = yes; then
+ dotest unedit-without-baserev-15 "${testcvs} -q update" "U m"
+ else
+ dotest unedit-without-baserev-15 "${testcvs} -q update" \
+"${PROG} update: warning: m was lost
+U m"
+ fi
+ # 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.
@@ -9876,6 +10481,7 @@ ${PROG} [a-z]*: Rebuilding administrative file database"
# cvsignore: ignore
# verifymsg: info
# cvswrappers: mwrap
+ # taginfo: taginfo
# config: config
# On Windows, we can't check out CVSROOT, because the case
@@ -10009,6 +10615,9 @@ done
${PROG} [a-z]*: Rebuilding administrative file database"
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
@@ -10024,6 +10633,112 @@ ${PROG} [a-z]*: Rebuilding administrative file database"
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
+ # -d
+ # rtag
+
+ 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
+ chmod +x ${TESTDIR}/1/loggit
+ echo "ALL ${TESTDIR}/1/loggit" >taginfo
+ dotest taginfo-2 "${testcvs} -q ci -m check-in-taginfo" \
+"Checking in taginfo;
+${TESTDIR}/cvsroot/CVSROOT/taginfo,v <-- taginfo
+new revision: 1\.2; previous revision: 1\.1
+done
+${PROG} [a-z]*: 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} [a-z]*: scheduling file .file1. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest taginfo-5 "${testcvs} -q ci -m add-it" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
+done
+Checking in file1;
+${TESTDIR}/cvsroot/first-dir/file1,v <-- file1
+initial revision: 1\.1
+done"
+ 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" ""
+ echo add text on branch >>file1
+ dotest taginfo-9 "${testcvs} -q ci -m modify-on-br" \
+"Checking in file1;
+${TESTDIR}/cvsroot/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} [a-z]*: Pre-tag check failed
+${PROG} \[[a-z]* 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"
+
+ # 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 ${TESTDIR}/cvsroot/first-dir file1 1.1
+br add ${TESTDIR}/cvsroot/first-dir file1 1.1
+brtag mov ${TESTDIR}/cvsroot/first-dir file1 1.1.2.1"
+
+ cd ..
+ cd CVSROOT
+ echo '# Keep life simple' > taginfo
+ dotest taginfo-cleanup-1 "${testcvs} -q ci -m check-in-taginfo" \
+"Checking in taginfo;
+${TESTDIR}/cvsroot/CVSROOT/taginfo,v <-- taginfo
+new revision: 1\.3; previous revision: 1\.2
+done
+${PROG} [a-z]*: 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.
@@ -10036,10 +10751,12 @@ ${PROG} [a-z]*: Rebuilding administrative file database"
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;
${TESTDIR}/cvsroot/CVSROOT/config,v <-- config
-new revision: 1\.2; previous revision: 1\.1
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
done
${PROG} [a-z]*: Rebuilding administrative file database"
echo 'BogusOption=yes' >config
@@ -10047,7 +10764,7 @@ ${PROG} [a-z]*: Rebuilding administrative file database"
"${PROG} [a-z]*: syntax error in ${TESTDIR}/cvsroot/CVSROOT/config: line 'bogus line' is missing '='
Checking in config;
${TESTDIR}/cvsroot/CVSROOT/config,v <-- config
-new revision: 1\.3; previous revision: 1\.2
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
done
${PROG} [a-z]*: Rebuilding administrative file database"
echo '# No config is a good config' > config
@@ -10055,7 +10772,7 @@ ${PROG} [a-z]*: Rebuilding administrative file database"
"${PROG} [a-z]*: ${TESTDIR}/cvsroot/CVSROOT/config: unrecognized keyword 'BogusOption'
Checking in config;
${TESTDIR}/cvsroot/CVSROOT/config,v <-- config
-new revision: 1\.4; previous revision: 1\.3
+new revision: 1\.[0-9]*; previous revision: 1\.[0-9]*
done
${PROG} [a-z]*: Rebuilding administrative file database"
dotest config-6 "${testcvs} -q update" ''
@@ -10105,7 +10822,7 @@ done"
# Remove the tag. This will leave the tag string in the
# expansion of the Name keyword.
- dotest serverpatch-6 "${testcvs} -q update -A" ''
+ dotest serverpatch-6 "${testcvs} -q update -A first-dir" ''
# Modify and check in the first copy.
cd ../1/first-dir
@@ -10520,7 +11237,9 @@ date: [0-9/]* [0-9:]*; author: ${username}; state: Exp;
;;
ann)
- # Tests of "cvs annotate". See also basica-10.
+ # Tests of "cvs annotate". See also:
+ # basica-10 A simple annotate test
+ # rcs Annotate and the year 2000
mkdir 1; cd 1
dotest ann-1 "${testcvs} -q co -l ." ''
mkdir first-dir
@@ -10626,12 +11345,77 @@ done"
1\.2 (${username} *[0-9a-zA-Z-]*): line
1\.2\.2\.1 (${username} *[0-9a-zA-Z-]*): and some
1\.2\.2\.1 (${username} *[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 (${username} *[0-9a-zA-Z-]*): this
+1\.1 (${username} *[0-9a-zA-Z-]*): is
+1\.2 (${username} *[0-9a-zA-Z-]*): a
+1\.1 (${username} *[0-9a-zA-Z-]*): file
+1\.2 (${username} *[0-9a-zA-Z-]*):
+1\.2 (${username} *[0-9a-zA-Z-]*): with
+1\.2 (${username} *[0-9a-zA-Z-]*): a
+1\.2 (${username} *[0-9a-zA-Z-]*): blank
+1\.2 (${username} *[0-9a-zA-Z-]*): line
+1\.2\.2\.1 (${username} *[0-9a-zA-Z-]*): and some
+1\.2\.2\.1 (${username} *[0-9a-zA-Z-]*): branched content"
+ dotest_fail ann-14 "${testcvs} ann -r bill-clintons-chastity file1" \
+"${PROG} \[[a-z]* aborted\]: no such tag bill-clintons-chastity"
cd ../..
rm -r 1
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 ${TESTDIR}/cvsroot/$module added to the repository"
+ cd $module
+
+ file=m
+ echo '$Id''$' > $file
+
+ dotest ann-id-3 "$testcvs add $file" \
+"${PROG} [a-z]*: scheduling file .$file. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest ann-id-4 "$testcvs -Q ci -m . $file" \
+"RCS file: ${TESTDIR}/cvsroot/$module/$file,v
+done
+Checking in $file;
+${TESTDIR}/cvsroot/$module/$file,v <-- $file
+initial revision: 1\.1
+done"
+
+ echo line2 >> $file
+ dotest ann-id-5 "$testcvs -Q ci -m . $file" \
+"Checking in $file;
+${TESTDIR}/cvsroot/$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 ($username *[0-9a-zA-Z-]*): "'\$'"Id: $file,v 1.1 [0-9/]* [0-9:]* $username Exp "'\$'"
+1.2 ($username *[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.
@@ -10673,7 +11457,7 @@ ${testcvs} -d ${TESTDIR}/crerepos release -d CVSROOT >>${LOGFILE}; then
else
fail crerepos-5
fi
- rm -r CVS
+ rm -rf CVS
cd ..
# The directory tmp should be empty
dotest crerepos-6 "rmdir tmp" ''
@@ -10777,7 +11561,7 @@ U first-dir/file1"
"${PROG} [a-z]*: Updating crerepos-dir
U crerepos-dir/cfile"
- if test x`cat CVS/Repository` = x.; then
+ if test x`cat crerepos-dir/CVS/Repository` = xcrerepos-dir; then
# RELATIVE_REPOS
# Fatal error so that we don't go traipsing through the
# directories which happen to have the same names from the
@@ -10984,8 +11768,33 @@ add file1
fail rcs-4
fi
+ # 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.
+ # 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;
@@ -11018,6 +11827,8 @@ start revision@
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"
@@ -11160,10 +11971,6 @@ a1 1
next branch revision
@"
- # For remote, the "update -p -D" usage seems not to work.
- # I'm not sure what is going on.
- if test "x$remote" = "xno"; then
-
if ${testcvs} -q update -p -D '1970-12-31 11:30 UT' file2 \
>${TESTDIR}/rcs4.tmp
then
@@ -11206,8 +12013,6 @@ next branch revision
fail rcs-13
fi
- fi # end of tests skipped for remote
-
# OK, now make sure cvs log doesn't have any trouble with the
# newphrases and such.
dotest rcs-14 "${testcvs} -q log file2" "
@@ -11258,6 +12063,145 @@ date: 1971/01/01 08:00:05; author: joe; state: Exp; lines: ${PLUS}1 -1
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
+ if ${testcvs} -q update -p -D '1999-09-09 11:30 UT' file1 \
+ >${TESTDIR}/rcs4.tmp
+ then
+ dotest rcs2-2 "cat ${TESTDIR}/rcs4.tmp" \
+"Tonight we're going to party like it's a certain year"
+ else
+ fail rcs2-2
+ fi
+ # 1 Jan 2001.
+ if ${testcvs} -q update -p -D '2001-01-01 11:30 UT' file1 \
+ >${TESTDIR}/rcs4.tmp
+ then
+ dotest rcs2-3 "cat ${TESTDIR}/rcs4.tmp" \
+"two year hiatus"
+ else
+ fail rcs2-3
+ fi
+ # 29 Feb 2000
+ if ${testcvs} -q update -p -D '2000-02-29 11:30 UT' file1 \
+ >${TESTDIR}/rcs4.tmp
+ then
+ dotest rcs2-4 "cat ${TESTDIR}/rcs4.tmp" \
+"2000 is also a good year for leaping"
+ else
+ fail rcs2-4
+ fi
+ # 29 Feb 2003 is invalid
+ if ${testcvs} -q update -p -D '2003-02-29 11:30 UT' file1 \
+ >${TESTDIR}/rcs4.tmp 2>&1
+ then
+ fail rcs2-5
+ else
+ dotest rcs2-5 "cat ${TESTDIR}/rcs4.tmp" \
+"${PROG} \[[a-z]* aborted\]: Can't parse date/time: 2003-02-29 11:30 UT"
+ fi
+ rm ${TESTDIR}/rcs4.tmp
+
+ cd ..
+ rm -r first-dir
+ rm -rf ${CVSROOT_DIRNAME}/first-dir
+ ;;
+
+ 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
+M339cafae|nk|<remote>|ccvs/src|1.229|sanity.sh
+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 06/04 19:48 ${PLUS}0000 anonymous ccvs =ccvs= <remote>/\*
+W 06/17 19:51 ${PLUS}0000 anonymous Makefile\.in ccvs/emx == <remote>/emx
+M 06/10 21:12 ${PLUS}0000 kingdon 1\.231 sanity\.sh ccvs/src == ~/work/ccvs/src
+C 06/10 11:51 ${PLUS}0000 kingdon 1\.3 README ccvs/emx == <remote>
+M 06/10 17:33 ${PLUS}0000 kingdon 1\.281 cvs\.texinfo ccvs/doc == ~/work/ccvs/doc
+M 06/10 01:36 ${PLUS}0000 nk 1\.229 sanity\.sh ccvs/src == <remote>"
+ if ${testcvs} history -e -a -D '10 Jun 1997 13:00 UT' \
+ >${TESTDIR}/output.tmp
+ then
+ dotest history-2 "cat ${TESTDIR}/output.tmp" \
+"W 06/17 19:51 ${PLUS}0000 anonymous Makefile\.in ccvs/emx == <remote>/emx
+M 06/10 21:12 ${PLUS}0000 kingdon 1\.231 sanity\.sh ccvs/src == ~/work/ccvs/src
+C 06/10 11:51 ${PLUS}0000 kingdon 1\.3 README ccvs/emx == <remote>
+M 06/10 17:33 ${PLUS}0000 kingdon 1\.281 cvs\.texinfo ccvs/doc == ~/work/ccvs/doc"
+ else
+ fail history-2
+ fi
+ if ${testcvs} history -e -a -D '10 Jun 2001 13:00 UT' \
+ >${TESTDIR}/output.tmp
+ then
+ # For reasons that are completely unclear to me, the number
+ # of spaces betwen "kingdon" and "1.281" is different than
+ # for the other tests.
+ dotest history-3 "cat ${TESTDIR}/output.tmp" \
+"M 06/10 17:33 ${PLUS}0000 kingdon 1\.281 cvs\.texinfo ccvs/doc == ~/work/ccvs/doc"
+ else
+ fail history-3
+ fi
+ rm ${TESTDIR}/output.tmp
+ ;;
+
big)
# Test ability to operate on big files. Intention is to
@@ -11441,6 +12385,52 @@ done"
# 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 ${TESTDIR}/cvsroot/first-dir added to the repository"
+ cd first-dir
+ touch aa
+ dotest modes2-3 "${testcvs} add aa" \
+"${PROG} [a-z]*: scheduling file .aa. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest modes2-4 "${testcvs} -q ci -m add" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/aa,v
+done
+Checking in aa;
+${TESTDIR}/cvsroot/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;
+${TESTDIR}/cvsroot/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
+ 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"
+
+ chmod u+rwx aa
+ cd ../..
+ rm -r 1
+ rm -rf ${CVSROOT_DIRNAME}/first-dir
+ ;;
+
stamps)
# Test timestamps.
mkdir 1; cd 1
@@ -11581,6 +12571,202 @@ done"
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 ${TESTDIR}/cvsroot/first-dir added to the repository"
+ cd first-dir
+
+ touch foo
+ chmod 431 foo
+ dotest perms-3 "${testcvs} add foo" \
+"${PROG} [a-z]*: scheduling file .foo. for addition
+${PROG} [a-z]*: 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;
+${TESTDIR}/cvsroot/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 test "$remote" = no; then
+ # 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 ${TESTDIR}/cvsroot/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} [a-z]*: scheduling file .slink. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ if test "$remote" = yes; then
+ # Remote doesn't implement PreservePermissions, and in its
+ # absence the correct behavior is to follow the symlink.
+ dotest_fail symlinks-4 "${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;
+${TESTDIR}/cvsroot/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
+ ;;
+
+ 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 ${TESTDIR}/cvsroot/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} [a-z]*: scheduling file .aaaa. for addition
+${PROG} [a-z]*: scheduling file .b\.b\.b\.b. for addition
+${PROG} [a-z]*: scheduling file .dd dd dd. for addition
+${PROG} [a-z]*: 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;
+${TESTDIR}/cvsroot/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;
+${TESTDIR}/cvsroot/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;
+${TESTDIR}/cvsroot/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 test "$remote" = yes; then
+ # Remote does not implement PreservePermissions.
+ 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
+ dotest hardlinks-6 "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
@@ -12131,24 +13317,11 @@ add a line on trunk after trunktag"
"imported contents
add a line on trunk
add a line on trunk after trunktag"
- # But diff thinks that HEAD is "brtag". Case (c) from
- # cvs.texinfo (the "strange, maybe accidental" case).
- dotest_fail head-brtag-diff "${testcvs} -q diff -c -r HEAD -r br1" \
-"Index: file1
-===================================================================
-RCS file: ${TESTDIR}/cvsroot/first-dir/file1,v
-retrieving revision 1\.3\.2\.1
-retrieving revision 1\.3\.2\.2
-diff -c -r1\.3\.2\.1 -r1\.3\.2\.2
-\*\*\* file1 [0-9/]* [0-9:]* 1\.3\.2\.1
---- file1 [0-9/]* [0-9:]* 1\.3\.2\.2
-\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 2,4 \*\*\*\*
---- 2,5 ----
- add a line on trunk
- add a line on trunk after trunktag
- modify on branch
-${PLUS} modify on branch after brtag"
+
+ # 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.
@@ -12160,24 +13333,23 @@ add a line on trunk"
"imported contents
add a line on trunk
add a line on trunk after trunktag"
- # Like head-brtag-diff, HEAD is the sticky tag. Similarly
- # questionable.
+ # 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: ${TESTDIR}/cvsroot/first-dir/file1,v
-retrieving revision 1\.2
+retrieving revision 1\.3
retrieving revision 1\.3\.2\.2
-diff -c -r1\.2 -r1\.3\.2\.2
-\*\*\* file1 [0-9/]* [0-9:]* 1\.2
+diff -c -r1\.3 -r1\.3\.2\.2
+\*\*\* file1 [0-9/]* [0-9:]* 1\.3
--- file1 [0-9/]* [0-9:]* 1\.3\.2\.2
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
-\*\*\* 1,2 \*\*\*\*
+\*\*\* 1,3 \*\*\*\*
--- 1,5 ----
imported contents
add a line on trunk
-${PLUS} add a line on trunk after trunktag
+ add a line on trunk after trunktag
${PLUS} modify on branch
${PLUS} modify on branch after brtag"
@@ -12390,6 +13562,91 @@ done"
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} [a-z]*: scheduling file .$file. for addition
+${PROG} [a-z]*: use .${PROG} commit. to add this file permanently"
+ dotest tag8k-4 "$testcvs -Q ci -m . $file" \
+"RCS file: ${TESTDIR}/cvsroot/$module/$file,v
+done
+Checking in $file;
+${TESTDIR}/cvsroot/$module/$file,v <-- $file
+initial revision: 1\.1
+done"
+
+ # It seems there have to be at least two versions.
+ echo a > $file
+ dotest tag8k-5 "$testcvs -Q ci -m . $file" \
+"Checking in $file;
+${TESTDIR}/cvsroot/$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" ''
+
+ # Determine the length of the author value.
+ name=`sed -n 's/.*; author \([^;]*\);.*/\1/p' ${TESTDIR}/cvsroot/$module/$file,v|head -1`
+ name_len=`expr length $name`
+
+ # CAREFUL: this will lose if $name is longer than 16.
+ # Then, form a string of length 16 - $name_len.
+ add_len=`expr 16 - $name_len`
+ suffix=`expr substr 1234567890123456 1 $add_len`
+
+ # 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;
+${TESTDIR}/cvsroot/$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.
@@ -12401,6 +13658,7 @@ done"
# 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)
@@ -12996,6 +14254,192 @@ text
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: ${TESTDIR}/cvsroot/first-dir/file2,v
+done"
+
+ # br1 should be a branch
+ #
+ dotest admin-26-2 "${testcvs} admin -nbr1:br file2" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file2,v
+done"
+
+ # Attach some tags using RCS versions
+ #
+ dotest admin-26-3 "${testcvs} admin -ntagthree:1.1 file2" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file2,v
+done"
+
+ dotest admin-26-4 "${testcvs} admin -nbr2:1.1.2 file2" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file2,v
+done"
+
+ dotest admin-26-5 "${testcvs} admin -nbr4:1.1.0.2 file2" \
+"RCS file: ${TESTDIR}/cvsroot/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 ${TESTDIR}/cvsroot/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;
+${TESTDIR}/cvsroot/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;
+${TESTDIR}/cvsroot/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: ${TESTDIR}/cvsroot/first-dir/file2,v
+done"
+
+ dotest_fail admin-27-4 "${testcvs} admin -ntagfour:1.3 file2" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file2,v
+${PROG} [a-z]*: ${TESTDIR}/cvsroot/first-dir/file2,v: symbolic name tagfour already bound to 1\.1
+${PROG} [a-z]*: cannot modify RCS file for .file2."
+
+ # Succeed at reattaching existing tag, using -N
+ #
+ dotest admin-27-5 "${testcvs} admin -Ntagfour:1.3 file2" \
+"RCS file: ${TESTDIR}/cvsroot/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: ${TESTDIR}/cvsroot/first-dir/file2,v
+${PROG} \[[a-z]* aborted\]: tag .tagfive. does not exist"
+
+ # Try a some nonexisting numeric target tags
+ #
+ dotest_fail admin-28-2 "${testcvs} admin -ntagseven:2.1 file2" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file2,v
+${PROG} \[[a-z]* aborted\]: revision .2\.1. does not exist"
+
+ dotest_fail admin-28-3 "${testcvs} admin -ntageight:2.1.2 file2" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file2,v
+${PROG} \[[a-z]* 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: ${TESTDIR}/cvsroot/first-dir/file2,v
+${PROG} \[[a-z]* aborted\]: tag .1\.a\.2. must start with a letter"
+
+ dotest_fail admin-28-5 "${testcvs} admin -ntagten:BO+GUS file2" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file2,v
+${PROG} \[[a-z]* aborted\]: tag .BO${PLUS}GUS. does not exist"
+
+ dotest_fail admin-28-6 "${testcvs} admin -nq.werty:tagfour file2" \
+"RCS file: ${TESTDIR}/cvsroot/first-dir/file2,v
+${PROG} \[[a-z]* aborted\]: tag .q\.werty. must not contain the characters ..*"
+
+ # Verify the archive
+ #
+ dotest admin-29 "cat ${TESTDIR}/cvsroot/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
+@"
+
cd ../..
rm -r 1
rm -rf ${CVSROOT_DIRNAME}/first-dir
@@ -13141,6 +14585,11 @@ ${PROG} [a-z]*: Rebuilding administrative file database"
"fred has file a-lock locked for version 1\.1
${PROG} [a-z]*: Pre-commit check failed
${PROG} \[[a-z]* 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: ${TESTDIR}/cvsroot/first-dir/a-lock,v
+${PROG} \[[a-z]* aborted\]: Revision 1\.1 is already locked by fred"
dotest reserved-14 "${testcvs} admin -u1.1 a-lock" \
"RCS file: ${TESTDIR}/cvsroot/first-dir/a-lock,v
@@ -13152,10 +14601,25 @@ ${TESTDIR}/cvsroot/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;/' ${TESTDIR}/cvsroot/first-dir/a-lock,v > a-lock,v
+ chmod 644 ${TESTDIR}/cvsroot/first-dir/a-lock,v
+ dotest reserved-16 \
+"mv a-lock,v ${TESTDIR}/cvsroot/first-dir/a-lock,v" ""
+ chmod 444 ${TESTDIR}/cvsroot/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" ""
+ echo edit it >>a-lock
+ dotest reserved-19 "${testcvs} -q ci -m modify a-lock" \
+"Checking in a-lock;
+${TESTDIR}/cvsroot/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-16 "${testcvs} -q ci -m back commitinfo" \
+ dotest reserved-cleanup-1 "${testcvs} -q ci -m back commitinfo" \
"Checking in commitinfo;
${TESTDIR}/cvsroot/CVSROOT/commitinfo,v <-- commitinfo
new revision: 1\.3; previous revision: 1\.2
diff --git a/contrib/cvs/src/server.c b/contrib/cvs/src/server.c
index a005646fb402..f6e64a56822e 100644
--- a/contrib/cvs/src/server.c
+++ b/contrib/cvs/src/server.c
@@ -42,8 +42,20 @@ static Key_schedule sched;
#ifdef HAVE_GSSAPI
#include <netdb.h>
+
+#ifdef HAVE_GSSAPI_H
+#include <gssapi.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_H
#include <gssapi/gssapi.h>
+#endif
+#ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H
#include <gssapi/gssapi_generic.h>
+#endif
+
+#ifndef HAVE_GSS_C_NT_HOSTBASED_SERVICE
+#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
+#endif
/* We use Kerberos 5 routines to map the GSSAPI credential to a user
name. */
@@ -366,7 +378,8 @@ mkdir_p (dir)
int saved_errno = errno;
if (saved_errno != EEXIST
- && (saved_errno != EACCES || !isdir (q)))
+ && ((saved_errno != EACCES && saved_errno != EROFS)
+ || !isdir (q)))
{
retval = saved_errno;
goto done;
@@ -635,6 +648,18 @@ server_pathname_check (path)
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)
{
@@ -2256,6 +2281,9 @@ error \n");
/* 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');
@@ -2326,6 +2354,19 @@ error \n");
exitstatus = (*command) (argument_count, argument_vector);
+ /* Output any partial lines. If the client doesn't support
+ "MT", we just throw out the partial line, like old versions
+ of CVS did, since the protocol can't support this. */
+ if (supported_response ("MT") && ! buf_empty_p (saved_output))
+ {
+ buf_output0 (protocol, "MT text ");
+ 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. */
+
/*
* When we exit, that will close the pipes, giving an EOF to
* the parent.
@@ -2840,8 +2881,9 @@ server_register (name, version, timestamp, options, tag, date, conflict)
(void) fprintf (stderr,
"%c-> server_register(%s, %s, %s, %s, %s, %s, %s)\n",
(server_active) ? 'S' : ' ', /* silly */
- name, version, timestamp, options, tag ? tag : "",
- date ? date : "", conflict ? conflict : "");
+ name, version, timestamp ? timestamp : "", options,
+ tag ? tag : "", date ? date : "",
+ conflict ? conflict : "");
}
if (entries_line != NULL)
@@ -3071,21 +3113,21 @@ static void
serve_remove (arg)
char *arg;
{
- do_cvs_command ("cvsremove", cvsremove);
+ do_cvs_command ("remove", cvsremove);
}
static void
serve_status (arg)
char *arg;
{
- do_cvs_command ("status", status);
+ do_cvs_command ("status", cvsstatus);
}
static void
serve_rdiff (arg)
char *arg;
{
- do_cvs_command ("patch", patch);
+ do_cvs_command ("rdiff", patch);
}
static void
@@ -3354,6 +3396,17 @@ server_modtime (finfo, vers_ts)
/* 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;
@@ -3362,6 +3415,7 @@ server_updated (finfo, vers, updated, mode, checksum, filebuf)
mode_t mode;
unsigned char *checksum;
struct buffer *filebuf;
+#endif
{
if (noexec)
{
@@ -3580,7 +3634,7 @@ CVS server internal error: unhandled case in server_updated");
if ((updated == SERVER_UPDATED
|| updated == SERVER_PATCHED
|| updated == SERVER_RCS_DIFF)
- && filebuf != NULL
+ && filebuf == NULL
/* But if we are joining, we'll need the file when we call
join_file. */
&& !joining ())
@@ -4779,25 +4833,23 @@ check_password (username, password, repository)
/* No cvs password found, so try /etc/passwd. */
const char *found_passwd = NULL;
+ struct passwd *pw;
#ifdef HAVE_GETSPNAM
- struct spwd *pw;
+ struct spwd *spw;
- pw = getspnam (username);
- if (pw != NULL)
+ spw = getspnam (username);
+ if (spw != NULL)
{
- found_passwd = pw->sp_pwdp;
+ found_passwd = spw->sp_pwdp;
}
-#else
- struct passwd *pw;
+#endif
- pw = getpwnam (username);
- if (pw != NULL)
+ if (found_passwd == NULL && (pw = getpwnam (username)) != NULL)
{
found_passwd = pw->pw_passwd;
}
-#endif
- if (pw == NULL)
+ if (found_passwd == NULL)
{
printf ("E Fatal error, aborting.\n\
error 0 %s: no such user\n", username);
@@ -4815,8 +4867,9 @@ error 0 %s: no such user\n", username);
exit (EXIT_FAILURE);
}
- if (found_passwd && *found_passwd)
+ if (*found_passwd)
{
+ /* user exists and has a password */
host_user = ((! strcmp (found_passwd,
crypt (password, found_passwd)))
? username : NULL);
@@ -4824,11 +4877,14 @@ error 0 %s: no such user\n", username);
}
else if (password && *password)
{
+ /* user exists and has no system password, but we got
+ one as parameter */
host_user = username;
goto handle_return;
}
else
{
+ /* user exists but has no password at all */
host_user = NULL;
goto handle_return;
}
@@ -5186,7 +5242,7 @@ gserver_authenticate_connection ()
tok_in.value = buf;
tok_in.length = strlen (buf);
- if (gss_import_name (&stat_min, &tok_in, gss_nt_service_name,
+ 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);
@@ -5587,7 +5643,7 @@ cvs_output_binary (str, len)
if (error_use_protocol)
buf = buf_to_net;
- else if (server_active)
+ else
buf = protocol;
if (!supported_response ("Mbinary"))
diff --git a/contrib/cvs/src/status.c b/contrib/cvs/src/status.c
index 98be085fb6c9..541a969a711d 100644
--- a/contrib/cvs/src/status.c
+++ b/contrib/cvs/src/status.c
@@ -31,7 +31,7 @@ static const char *const status_usage[] =
};
int
-status (argc, argv)
+cvsstatus (argc, argv)
int argc;
char **argv;
{
diff --git a/contrib/cvs/src/tag.c b/contrib/cvs/src/tag.c
index a97da5c1237c..a5b8794fe10e 100644
--- a/contrib/cvs/src/tag.c
+++ b/contrib/cvs/src/tag.c
@@ -275,8 +275,17 @@ check_fileproc (callerdat, finfo)
error (0, 0, "nothing known about %s", finfo->file);
return (1);
}
- p->data = RCS_getversion(vers->srcfile, numtag, date, force_tag_match,
- (int *) NULL);
+
+ /* 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 (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;
@@ -377,7 +386,7 @@ pretag_proc(repository, filter)
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|RUN_REALLY));
+ return (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL));
}
static void
diff --git a/contrib/cvs/src/update.c b/contrib/cvs/src/update.c
index 2e7bda39febb..d25eeb2e967a 100644
--- a/contrib/cvs/src/update.c
+++ b/contrib/cvs/src/update.c
@@ -530,7 +530,6 @@ get_linkinfo_proc (callerdat, finfo)
hlinfo->status = (Ctype) 0; /* is this dumb? */
hlinfo->checked_out = 0;
- hlinfo->links = NULL;
linkp->data = (char *) hlinfo;
@@ -1639,8 +1638,6 @@ patch_file (finfo, vers_ts, docheckout, file_info, checksum)
{
char *diff_options;
- /* FIXME: It might be better to come up with a diff library
- which can be shared with the diffutils. */
/* 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
@@ -1649,8 +1646,10 @@ patch_file (finfo, vers_ts, docheckout, file_info, checksum)
program. */
if (! rcs_diff_patches)
{
- /* We use -c, not -u, because we have no way of knowing
- which DIFF is in use. */
+ /* 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. */
diff_options = "-c";
}
else
@@ -1922,14 +1921,21 @@ merge_file (finfo, vers)
if (strcmp (vers->options, "-V4") == 0)
vers->options[0] = '\0';
- (void) time (&last_register_time);
+
+ /* 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 = 0;
if (status)
+ {
+ (void) time (&last_register_time);
cp = time_stamp (finfo->file);
- Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_rcs, vers->options,
- vers->tag, vers->date, cp);
+ }
+ Register (finfo->entries, finfo->file, vers->vn_rcs,
+ "Result of merge", vers->options, vers->tag,
+ vers->date, cp);
if (cp)
free (cp);
}
@@ -2428,25 +2434,27 @@ join_file (finfo, vers)
free (rev1);
free (rev2);
-#ifdef SERVER_SUPPORT
- /*
- * If we're in server mode, then we need to re-register the file
- * even if there were no conflicts (status == 0).
- * This tells server_updated() to send the modified file back to
- * the client.
- */
- if (status == 1 || (status == 0 && server_active))
-#else
- if (status == 1)
-#endif
+ /* 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. */
{
char *cp = 0;
if (status)
+ {
+ (void) time (&last_register_time);
cp = time_stamp (finfo->file);
- Register (finfo->entries, finfo->file,
- vers->vn_rcs, vers->ts_rcs, vers->options,
- vers->tag, vers->date, cp);
+ }
+ Register (finfo->entries, finfo->file, vers->vn_rcs,
+ "Result of merge", vers->options, vers->tag,
+ vers->date, cp);
if (cp)
free(cp);
}
@@ -2494,8 +2502,8 @@ special_file_mismatch (finfo, rev1, rev2)
dev_t rev1_dev, rev2_dev;
char *rev1_symlink = NULL;
char *rev2_symlink = NULL;
- char *rev1_hardlinks = NULL;
- char *rev2_hardlinks = NULL;
+ List *rev1_hardlinks;
+ List *rev2_hardlinks;
int check_uids, check_gids, check_modes;
int result;
@@ -2533,7 +2541,7 @@ special_file_mismatch (finfo, rev1, rev2)
if (S_ISBLK (rev1_mode) || S_ISCHR (rev1_mode))
rev1_dev = sb.st_rdev;
}
- rev1_hardlinks = list_files_linked_to (finfo->file);
+ rev1_hardlinks = list_linked_files_on_disk (finfo->file);
}
else
{
@@ -2584,11 +2592,9 @@ special_file_mismatch (finfo, rev1, rev2)
finfo->file, rev1, ftype);
}
- n = findnode (vp->other_delta, "hardlinks");
- if (n == NULL)
- rev1_hardlinks = xstrdup ("");
- else
- rev1_hardlinks = xstrdup (n->data);
+ rev1_hardlinks = vp->hardlinks;
+ if (rev1_hardlinks == NULL)
+ rev1_hardlinks = getlist();
}
}
@@ -2608,7 +2614,7 @@ special_file_mismatch (finfo, rev1, rev2)
if (S_ISBLK (rev2_mode) || S_ISCHR (rev2_mode))
rev2_dev = sb.st_rdev;
}
- rev2_hardlinks = list_files_linked_to (finfo->file);
+ rev2_hardlinks = list_linked_files_on_disk (finfo->file);
}
else
{
@@ -2659,11 +2665,9 @@ special_file_mismatch (finfo, rev1, rev2)
finfo->file, rev2, ftype);
}
- n = findnode (vp->other_delta, "hardlinks");
- if (n == NULL)
- rev2_hardlinks = xstrdup ("");
- else
- rev2_hardlinks = xstrdup (n->data);
+ rev2_hardlinks = vp->hardlinks;
+ if (rev2_hardlinks == NULL)
+ rev2_hardlinks = getlist();
}
}
@@ -2744,7 +2748,7 @@ special_file_mismatch (finfo, rev1, rev2)
}
/* Compare hard links. */
- if (strcmp (rev1_hardlinks, rev2_hardlinks) != 0)
+ if (compare_linkage_lists (rev1_hardlinks, rev2_hardlinks) == 0)
{
error (0, 0, "%s: hard linkage of %s and %s do not match",
finfo->file,
@@ -2759,9 +2763,9 @@ special_file_mismatch (finfo, rev1, rev2)
if (rev2_symlink != NULL)
free (rev2_symlink);
if (rev1_hardlinks != NULL)
- free (rev1_hardlinks);
+ dellist (&rev1_hardlinks);
if (rev2_hardlinks != NULL)
- free (rev2_hardlinks);
+ dellist (&rev2_hardlinks);
return result;
#else
diff --git a/contrib/cvs/src/version.c b/contrib/cvs/src/version.c
index f386895559b5..479e5e6af776 100644
--- a/contrib/cvs/src/version.c
+++ b/contrib/cvs/src/version.c
@@ -12,7 +12,8 @@
#include "cvs.h"
-char *version_string = "\nConcurrent Versions System (CVS) 1.9.26";
+/* NOTE: remember to remove `Halibut' when patching this code. */
+char *version_string = "\nConcurrent Versions System (CVS) 1.10 `Halibut'";
#ifdef CLIENT_SUPPORT
#ifdef SERVER_SUPPORT
diff --git a/contrib/cvs/src/wrapper.c b/contrib/cvs/src/wrapper.c
index 645ce5c10304..e7c540d63cfd 100644
--- a/contrib/cvs/src/wrapper.c
+++ b/contrib/cvs/src/wrapper.c
@@ -395,6 +395,11 @@ wrap_add (line, isTemp)
*line='\0';
switch(opt){
case 'f':
+ /* Before this is reenabled, need to address the problem in
+ commit.c (see http://www.cyclic.com/cvs/dev-wrap.txt). */
+ 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
@@ -404,6 +409,11 @@ wrap_add (line, isTemp)
error (1, 0, "Correct above errors first");
break;
case 't':
+ /* Before this is reenabled, need to address the problem in
+ commit.c (see http://www.cyclic.com/cvs/dev-wrap.txt). */
+ 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