[comp.sources.bugs] CVS 1.2 bug: CVS update doesn't handle merge correctly

lowell@tc.fluke.COM (Lowell Skoog) (05/24/91)

Symptom:

    When you run CVS update to merge changes that have been committed
    to the repository with changes made in your working file, the
    command bails out if there are any conflicts during the merge.
    It does not register that the update took place.  If you resolve
    the conflicts and attempt to commit the working file, the CVS
    commit command will tell you that the file needs to be updated
    first.  It is vicious cycle.

Work-around:

    Save your original working file by renaming it.  Run CVS update
    to get an updated copy.  Perform the merge by hand.  Then commit
    your changes.

Cause:

    In RCS 5.5, rcsmerge returns a status similar to diff(1).  (0 =
    no conflicts, 1 = conflicts, 2 = trouble)  CVS 1.0 was written
    for an older version of rcsmerge.  (CVS 1.2 failed to correct
    this.)  It assumed that the return status would be 0 when there
    were conflicts.  In that case it would grep for a "<<<<<<" string
    in the merged working file to determine whether there had been
    any conflicts.

    When rcsmerge version 5.5 returns a status of 1, CVS assumes that
    there was a fatal error.  Instead, it should treat this as a
    successful merge, with conflicts.

Solution:

    Revise src/update.c to use the status values returned by rcsmerge
    version 5.5.

A patch file (produced by CVS, of course) is attached below.  I have
sent a copy of this message to berliner@sun.com.

----------------------------------------------------------------------
Lowell Skoog  M/S 223B                             lowell@tc.fluke.COM
John Fluke Mfg. Co. Inc.  {uunet,uw-beaver,microsoft,sun}!fluke!lowell
P.O. Box 9090
Everett, WA, USA  98206-9090                            (206) 356-5283
----------------------------------------------------------------------

diff -c cvs/src/update.c:1.1.1.1 cvs/src/update.c:1.2
*** cvs/src/update.c:1.1.1.1	Thu May 23 14:46:19 1991
--- cvs/src/update.c	Thu May 23 14:46:20 1991
***************
*** 1,5 ****
  #ifndef lint
! static char rcsid[] = "$Id: update.c,v 1.1.1.1 1991/02/22 16:35:34 lowell Exp $";
  #endif !lint
  
  /*
--- 1,5 ----
  #ifndef lint
! static char rcsid[] = "$Id: update.c,v 1.2 1991/05/23 19:43:53 lowell Exp $";
  #endif !lint
  
  /*
***************
*** 53,58 ****
--- 53,59 ----
  #include <sys/param.h>
  #include <sys/types.h>
  #include <sys/stat.h>
+ #include <sys/wait.h>		/* UNOFFICIAL - bug fix */
  #include <dirent.h>
  #include "cvs.h"
  
***************
*** 182,187 ****
--- 183,189 ----
      FILE *fp;
      char *cp;
      int update_Files = 0, err = 0;
+     int status;		/* UNOFFICIAL - bug fix */
  
      /*
       * Wlist is the "remove entry" list.
***************
*** 293,299 ****
--- 295,312 ----
  	xchmod(User, 1);
  	(void) sprintf(prog, "%s/%s -r%s %s", Rcsbin, RCS_MERGE,
  		       VN_User, Rcs);
+ /*	UNOFFICIAL CHANGE - original code commented out
  	if (system(prog) != 0) {
+  */
+ 	/* UNOFFICIAL - start of bug fix 
+ 	 * rcsmerge now provides a return status similar to diff(1).
+ 	 * If there were conflicts, the return status is 1.  It
+ 	 * appears that this version of CVS was written assuming that
+ 	 * rcsmerge returned 0 in this case.
+ 	 */
+ 	status = system(prog);
+  	if (WEXITSTATUS(status) == 2) {
+ 	/* UNOFFICIAL - end of bug fix */
  	    warn(0, "could not merge revision %s of %s",
  		 VN_User, User);
  	    warn(0, "backup file for %s is in %s", User, backup);
***************
*** 301,308 ****
--- 314,324 ----
  	    continue;
  	}
  	Register(User, VN_Rcs, TS_Rcs);
+ /*	UNOFFICIAL CHANGE - original code commented out
  	(void) sprintf(prog, "%s -s '%s' %s", GREP, RCS_MERGE_PAT, User);
  	if (system(prog) == 0) {
+  */
+  	if (WEXITSTATUS(status) == 1) {		/* UNOFFICIAL - bug fix */
  	    warn(0, "conflicts found in %s", User);
  	    if (!really_quiet) {
  		if (update_dir[0])