xref: /openbsd-src/gnu/usr.bin/cvs/src/update.c (revision b2b690de91472dfa44e2c5247e600d75b64de0ce)
1 /*
2  * Copyright (c) 1992, Brian Berliner and Jeff Polk
3  * Copyright (c) 1989-1992, Brian Berliner
4  *
5  * You may distribute under the terms of the GNU General Public License as
6  * specified in the README file that comes with the CVS source distribution.
7  *
8  * "update" updates the version in the present directory with respect to the RCS
9  * repository.  The present version must have been created by "checkout". The
10  * user can keep up-to-date by calling "update" whenever he feels like it.
11  *
12  * The present version can be committed by "commit", but this keeps the version
13  * in tact.
14  *
15  * Arguments following the options are taken to be file names to be updated,
16  * rather than updating the entire directory.
17  *
18  * Modified or non-existent RCS files are checked out and reported as U
19  * <user_file>
20  *
21  * Modified user files are reported as M <user_file>.  If both the RCS file and
22  * the user file have been modified, the user file is replaced by the result
23  * of rcsmerge, and a backup file is written for the user in .#file.version.
24  * If this throws up irreconcilable differences, the file is reported as C
25  * <user_file>, and as M <user_file> otherwise.
26  *
27  * Files added but not yet committed are reported as A <user_file>. Files
28  * removed but not yet committed are reported as R <user_file>.
29  *
30  * If the current directory contains subdirectories that hold concurrent
31  * versions, these are updated too.  If the -d option was specified, new
32  * directories added to the repository are automatically created and updated
33  * as well.
34  */
35 
36 #include "cvs.h"
37 #include "savecwd.h"
38 #ifdef SERVER_SUPPORT
39 #include "md5.h"
40 #endif
41 #include "watch.h"
42 #include "fileattr.h"
43 #include "edit.h"
44 #include "getline.h"
45 
46 static int checkout_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts,
47 				 int adding));
48 #ifdef SERVER_SUPPORT
49 static int patch_file PROTO ((struct file_info *finfo,
50 			      Vers_TS *vers_ts,
51 			      int *docheckout, struct stat *file_info,
52 			      unsigned char *checksum));
53 static void patch_file_write PROTO ((void *, const char *, size_t));
54 #endif
55 static int merge_file PROTO ((struct file_info *finfo, Vers_TS *vers));
56 static int scratch_file PROTO((struct file_info *finfo));
57 static Dtype update_dirent_proc PROTO ((void *callerdat, char *dir,
58 					char *repository, char *update_dir,
59 					List *entries));
60 static int update_dirleave_proc PROTO ((void *callerdat, char *dir,
61 					int err, char *update_dir,
62 					List *entries));
63 static int update_fileproc PROTO ((void *callerdat, struct file_info *));
64 static int update_filesdone_proc PROTO ((void *callerdat, int err,
65 					 char *repository, char *update_dir,
66 					 List *entries));
67 static void write_letter PROTO ((struct file_info *finfo, int letter));
68 static void join_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts));
69 
70 static char *options = NULL;
71 static char *tag = NULL;
72 static char *date = NULL;
73 /* This is a bit of a kludge.  We call WriteTag at the beginning
74    before we know whether nonbranch is set or not.  And then at the
75    end, once we have the right value for nonbranch, we call WriteTag
76    again.  I don't know whether the first call is necessary or not.
77    rewrite_tag is nonzero if we are going to have to make that second
78    call.  */
79 static int rewrite_tag;
80 static int nonbranch;
81 
82 static char *join_rev1, *date_rev1;
83 static char *join_rev2, *date_rev2;
84 static int aflag = 0;
85 static int force_tag_match = 1;
86 static int update_build_dirs = 0;
87 static int update_prune_dirs = 0;
88 static int pipeout = 0;
89 #ifdef SERVER_SUPPORT
90 static int patches = 0;
91 static int rcs_diff_patches = 0;
92 #endif
93 static List *ignlist = (List *) NULL;
94 static time_t last_register_time;
95 static const char *const update_usage[] =
96 {
97     "Usage: %s %s [-APdflRp] [-k kopt] [-r rev|-D date] [-j rev]\n",
98     "    [-I ign] [-W spec] [files...]\n",
99     "\t-A\tReset any sticky tags/date/kopts.\n",
100     "\t-P\tPrune empty directories.\n",
101     "\t-d\tBuild directories, like checkout does.\n",
102     "\t-f\tForce a head revision match if tag/date not found.\n",
103     "\t-l\tLocal directory only, no recursion.\n",
104     "\t-R\tProcess directories recursively.\n",
105     "\t-p\tSend updates to standard output (avoids stickiness).\n",
106     "\t-k kopt\tUse RCS kopt -k option on checkout.\n",
107     "\t-r rev\tUpdate using specified revision/tag (is sticky).\n",
108     "\t-D date\tSet date to update from (is sticky).\n",
109     "\t-j rev\tMerge in changes made between current revision and rev.\n",
110     "\t-I ign\tMore files to ignore (! to reset).\n",
111     "\t-W spec\tWrappers specification line.\n",
112     "(Specify the --help global option for a list of other help options)\n",
113     NULL
114 };
115 
116 /*
117  * update is the argv,argc based front end for arg parsing
118  */
119 int
120 update (argc, argv)
121     int argc;
122     char **argv;
123 {
124     int c, err;
125     int local = 0;			/* recursive by default */
126     int which;				/* where to look for files and dirs */
127 
128     if (argc == -1)
129 	usage (update_usage);
130 
131     ign_setup ();
132     wrap_setup ();
133 
134     /* parse the args */
135     optind = 0;
136     while ((c = getopt (argc, argv, "+ApPflRQqduk:r:D:j:I:W:")) != -1)
137     {
138 	switch (c)
139 	{
140 	    case 'A':
141 		aflag = 1;
142 		break;
143 	    case 'I':
144 		ign_add (optarg, 0);
145 		break;
146 	    case 'W':
147 		wrap_add (optarg, 0);
148 		break;
149 	    case 'k':
150 		if (options)
151 		    free (options);
152 		options = RCS_check_kflag (optarg);
153 		break;
154 	    case 'l':
155 		local = 1;
156 		break;
157 	    case 'R':
158 		local = 0;
159 		break;
160 	    case 'Q':
161 	    case 'q':
162 #ifdef SERVER_SUPPORT
163 		/* The CVS 1.5 client sends these options (in addition to
164 		   Global_option requests), so we must ignore them.  */
165 		if (!server_active)
166 #endif
167 		    error (1, 0,
168 			   "-q or -Q must be specified before \"%s\"",
169 			   command_name);
170 		break;
171 	    case 'd':
172 		update_build_dirs = 1;
173 		break;
174 	    case 'f':
175 		force_tag_match = 0;
176 		break;
177 	    case 'r':
178 		tag = optarg;
179 		break;
180 	    case 'D':
181 		date = Make_Date (optarg);
182 		break;
183 	    case 'P':
184 		update_prune_dirs = 1;
185 		break;
186 	    case 'p':
187 		pipeout = 1;
188 		noexec = 1;		/* so no locks will be created */
189 		break;
190 	    case 'j':
191 		if (join_rev2)
192 		    error (1, 0, "only two -j options can be specified");
193 		if (join_rev1)
194 		    join_rev2 = optarg;
195 		else
196 		    join_rev1 = optarg;
197 		break;
198 	    case 'u':
199 #ifdef SERVER_SUPPORT
200 		if (server_active)
201 		{
202 		    patches = 1;
203 		    rcs_diff_patches = server_use_rcs_diff ();
204 		}
205 		else
206 #endif
207 		    usage (update_usage);
208 		break;
209 	    case '?':
210 	    default:
211 		usage (update_usage);
212 		break;
213 	}
214     }
215     argc -= optind;
216     argv += optind;
217 
218 #ifdef CLIENT_SUPPORT
219     if (client_active)
220     {
221 	int pass;
222 
223 	/* The first pass does the regular update.  If we receive at least
224 	   one patch which failed, we do a second pass and just fetch
225 	   those files whose patches failed.  */
226 	pass = 1;
227 	do
228 	{
229 	    int status;
230 
231 	    start_server ();
232 
233 	    if (local)
234 		send_arg("-l");
235 	    if (update_build_dirs)
236 		send_arg("-d");
237 	    if (pipeout)
238 		send_arg("-p");
239 	    if (!force_tag_match)
240 		send_arg("-f");
241 	    if (aflag)
242 		send_arg("-A");
243 	    if (update_prune_dirs)
244 		send_arg("-P");
245 	    client_prune_dirs = update_prune_dirs;
246 	    option_with_arg ("-r", tag);
247 	    if (options && options[0] != '\0')
248 		send_arg (options);
249 	    if (date)
250 		client_senddate (date);
251 	    if (join_rev1)
252 		option_with_arg ("-j", join_rev1);
253 	    if (join_rev2)
254 		option_with_arg ("-j", join_rev2);
255 	    wrap_send ();
256 
257 	    /* If the server supports the command "update-patches", that means
258 	       that it knows how to handle the -u argument to update, which
259 	       means to send patches instead of complete files.
260 
261 	       We don't send -u if failed_patches != NULL, so that the
262 	       server doesn't try to send patches which will just fail
263 	       again.  At least currently, the client also clobbers the
264 	       file and tells the server it is lost, which also will get
265 	       a full file instead of a patch, but it seems clean to omit
266 	       -u.  */
267 	    if (failed_patches == NULL)
268 	    {
269 		if (supported_request ("update-patches"))
270 		    send_arg ("-u");
271 	    }
272 
273 	    if (failed_patches == NULL)
274 	    {
275 		send_file_names (argc, argv, SEND_EXPAND_WILD);
276 		/* If noexec, probably could be setting SEND_NO_CONTENTS.
277 		   Same caveats as for "cvs status" apply.  */
278 		send_files (argc, argv, local, aflag,
279 			    update_build_dirs ? SEND_BUILD_DIRS : 0);
280 	    }
281 	    else
282 	    {
283 		int i;
284 
285 		(void) printf ("%s client: refetching unpatchable files\n",
286 			       program_name);
287 
288 		if (toplevel_wd != NULL
289 		    && CVS_CHDIR (toplevel_wd) < 0)
290 		{
291 		    error (1, errno, "could not chdir to %s", toplevel_wd);
292 		}
293 
294 		for (i = 0; i < failed_patches_count; i++)
295 		    (void) unlink_file (failed_patches[i]);
296 		send_file_names (failed_patches_count, failed_patches, 0);
297 		send_files (failed_patches_count, failed_patches, local,
298 			    aflag, update_build_dirs ? SEND_BUILD_DIRS : 0);
299 	    }
300 
301 	    failed_patches = NULL;
302 	    failed_patches_count = 0;
303 
304 	    send_to_server ("update\012", 0);
305 
306 	    status = get_responses_and_close ();
307 
308 	    /* If there are any conflicts, the server will return a
309                non-zero exit status.  If any patches failed, we still
310                want to run the update again.  We use a pass count to
311                avoid an endless loop.  */
312 
313 	    /* Notes: (1) assuming that status != 0 implies a
314 	       potential conflict is the best we can cleanly do given
315 	       the current protocol.  I suppose that trying to
316 	       re-fetch in cases where there was a more serious error
317 	       is probably more or less harmless, but it isn't really
318 	       ideal.  (2) it would be nice to have a testsuite case for the
319 	       conflict-and-patch-failed case.  */
320 
321 	    if (status != 0
322 		&& (failed_patches == NULL || pass > 1))
323 	    {
324 		return status;
325 	    }
326 
327 	    ++pass;
328 	} while (failed_patches != NULL);
329 
330 	return 0;
331     }
332 #endif
333 
334     if (tag != NULL)
335 	tag_check_valid (tag, argc, argv, local, aflag, "");
336     if (join_rev1 != NULL)
337         tag_check_valid_join (join_rev1, argc, argv, local, aflag, "");
338     if (join_rev2 != NULL)
339         tag_check_valid_join (join_rev2, argc, argv, local, aflag, "");
340 
341     /*
342      * If we are updating the entire directory (for real) and building dirs
343      * as we go, we make sure there is no static entries file and write the
344      * tag file as appropriate
345      */
346     if (argc <= 0 && !pipeout)
347     {
348 	if (update_build_dirs)
349 	{
350 	    if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno))
351 		error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
352 #ifdef SERVER_SUPPORT
353 	    if (server_active)
354 		server_clear_entstat (".", Name_Repository (NULL, NULL));
355 #endif
356 	}
357 
358 	/* keep the CVS/Tag file current with the specified arguments */
359 	if (aflag || tag || date)
360 	{
361 	    WriteTag ((char *) NULL, tag, date, 0,
362 		      ".", Name_Repository (NULL, NULL));
363 	    rewrite_tag = 1;
364 	    nonbranch = 0;
365 	}
366     }
367 
368     /* look for files/dirs locally and in the repository */
369     which = W_LOCAL | W_REPOS;
370 
371     /* look in the attic too if a tag or date is specified */
372     if (tag != NULL || date != NULL || joining())
373 	which |= W_ATTIC;
374 
375     /* call the command line interface */
376     err = do_update (argc, argv, options, tag, date, force_tag_match,
377 		     local, update_build_dirs, aflag, update_prune_dirs,
378 		     pipeout, which, join_rev1, join_rev2, (char *) NULL);
379 
380     /* free the space Make_Date allocated if necessary */
381     if (date != NULL)
382 	free (date);
383 
384     return (err);
385 }
386 
387 /*
388  * Command line interface to update (used by checkout)
389  */
390 int
391 do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
392 	   xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir)
393     int argc;
394     char **argv;
395     char *xoptions;
396     char *xtag;
397     char *xdate;
398     int xforce;
399     int local;
400     int xbuild;
401     int xaflag;
402     int xprune;
403     int xpipeout;
404     int which;
405     char *xjoin_rev1;
406     char *xjoin_rev2;
407     char *preload_update_dir;
408 {
409     int err = 0;
410     char *cp;
411 
412     /* fill in the statics */
413     options = xoptions;
414     tag = xtag;
415     date = xdate;
416     force_tag_match = xforce;
417     update_build_dirs = xbuild;
418     aflag = xaflag;
419     update_prune_dirs = xprune;
420     pipeout = xpipeout;
421 
422     /* setup the join support */
423     join_rev1 = xjoin_rev1;
424     join_rev2 = xjoin_rev2;
425     if (join_rev1 && (cp = strchr (join_rev1, ':')) != NULL)
426     {
427 	*cp++ = '\0';
428 	date_rev1 = Make_Date (cp);
429     }
430     else
431 	date_rev1 = (char *) NULL;
432     if (join_rev2 && (cp = strchr (join_rev2, ':')) != NULL)
433     {
434 	*cp++ = '\0';
435 	date_rev2 = Make_Date (cp);
436     }
437     else
438 	date_rev2 = (char *) NULL;
439 
440     /* call the recursion processor */
441     err = start_recursion (update_fileproc, update_filesdone_proc,
442 			   update_dirent_proc, update_dirleave_proc, NULL,
443 			   argc, argv, local, which, aflag, 1,
444 			   preload_update_dir, 1);
445 
446     /* see if we need to sleep before returning */
447     if (last_register_time)
448     {
449 	time_t now;
450 
451 	(void) time (&now);
452 	if (now == last_register_time)
453 	    sleep (1);			/* to avoid time-stamp races */
454     }
455 
456     return (err);
457 }
458 
459 /*
460  * This is the callback proc for update.  It is called for each file in each
461  * directory by the recursion code.  The current directory is the local
462  * instantiation.  file is the file name we are to operate on. update_dir is
463  * set to the path relative to where we started (for pretty printing).
464  * repository is the repository. entries and srcfiles are the pre-parsed
465  * entries and source control files.
466  *
467  * This routine decides what needs to be done for each file and does the
468  * appropriate magic for checkout
469  */
470 static int
471 update_fileproc (callerdat, finfo)
472     void *callerdat;
473     struct file_info *finfo;
474 {
475     int retval;
476     Ctype status;
477     Vers_TS *vers;
478     int resurrecting;
479 
480     resurrecting = 0;
481 
482     status = Classify_File (finfo, tag, date, options, force_tag_match,
483 			    aflag, &vers, pipeout);
484 
485     /* Keep track of whether TAG is a branch tag.
486        Note that if it is a branch tag in some files and a nonbranch tag
487        in others, treat it as a nonbranch tag.  It is possible that case
488        should elicit a warning or an error.  */
489     if (rewrite_tag
490 	&& tag != NULL
491 	&& finfo->rcs != NULL)
492     {
493 	char *rev = RCS_getversion (finfo->rcs, tag, NULL, 1, NULL);
494 	if (rev != NULL
495 	    && !RCS_nodeisbranch (finfo->rcs, tag))
496 	    nonbranch = 1;
497 	if (rev != NULL)
498 	    free (rev);
499     }
500 
501     if (pipeout)
502     {
503 	/*
504 	 * We just return success without doing anything if any of the really
505 	 * funky cases occur
506 	 *
507 	 * If there is still a valid RCS file, do a regular checkout type
508 	 * operation
509 	 */
510 	switch (status)
511 	{
512 	    case T_UNKNOWN:		/* unknown file was explicitly asked
513 					 * about */
514 	    case T_REMOVE_ENTRY:	/* needs to be un-registered */
515 	    case T_ADDED:		/* added but not committed */
516 		retval = 0;
517 		break;
518 	    case T_CONFLICT:		/* old punt-type errors */
519 		retval = 1;
520 		break;
521 	    case T_UPTODATE:		/* file was already up-to-date */
522 	    case T_NEEDS_MERGE:		/* needs merging */
523 	    case T_MODIFIED:		/* locally modified */
524 	    case T_REMOVED:		/* removed but not committed */
525 	    case T_CHECKOUT:		/* needs checkout */
526 #ifdef SERVER_SUPPORT
527 	    case T_PATCH:		/* needs patch */
528 #endif
529 		retval = checkout_file (finfo, vers, 0);
530 		break;
531 
532 	    default:			/* can't ever happen :-) */
533 		error (0, 0,
534 		       "unknown file status %d for file %s", status, finfo->file);
535 		retval = 0;
536 		break;
537 	}
538     }
539     else
540     {
541 	switch (status)
542 	{
543 	    case T_UNKNOWN:		/* unknown file was explicitly asked
544 					 * about */
545 	    case T_UPTODATE:		/* file was already up-to-date */
546 		retval = 0;
547 		break;
548 	    case T_CONFLICT:		/* old punt-type errors */
549 		retval = 1;
550 		write_letter (finfo, 'C');
551 		break;
552 	    case T_NEEDS_MERGE:		/* needs merging */
553 		if (noexec)
554 		{
555 		    retval = 1;
556 		    write_letter (finfo, 'C');
557 		}
558 		else
559 		{
560 		    retval = merge_file (finfo, vers);
561 		}
562 		break;
563 	    case T_MODIFIED:		/* locally modified */
564 		retval = 0;
565 		if (vers->ts_conflict)
566 		{
567 		    char *filestamp;
568 		    int retcode;
569 
570 		    /*
571 		     * If the timestamp has changed and no conflict indicators
572 		     * are found, it isn't a 'C' any more.
573 		     */
574 #ifdef SERVER_SUPPORT
575 		    if (server_active)
576 			retcode = vers->ts_conflict[0] != '=';
577 		    else {
578 			filestamp = time_stamp (finfo->file);
579 			retcode = strcmp (vers->ts_conflict, filestamp);
580 			free (filestamp);
581 		    }
582 #else
583 		    filestamp = time_stamp (finfo->file);
584 		    retcode = strcmp (vers->ts_conflict, filestamp);
585 		    free (filestamp);
586 #endif
587 
588 		    if (retcode)
589 		    {
590 			/* The timestamps differ.  But if there are conflict
591 			   markers print 'C' anyway.  */
592 			retcode = !file_has_markers (finfo);
593 		    }
594 
595 		    if (!retcode)
596 		    {
597 			write_letter (finfo, 'C');
598 			retval = 1;
599 		    }
600 		    else
601 		    {
602 			/* Reregister to clear conflict flag. */
603 			Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_rcs,
604 				  vers->options, vers->tag,
605 				  vers->date, (char *)0);
606 		    }
607 		}
608 		if (!retval)
609 		{
610 		    write_letter (finfo, 'M');
611 		    retval = 0;
612 		}
613 		break;
614 #ifdef SERVER_SUPPORT
615 	    case T_PATCH:		/* needs patch */
616 		if (patches)
617 		{
618 		    int docheckout;
619 		    struct stat file_info;
620 		    unsigned char checksum[16];
621 
622 		    retval = patch_file (finfo,
623 					 vers, &docheckout,
624 					 &file_info, checksum);
625 		    if (! docheckout)
626 		    {
627 		        if (server_active && retval == 0)
628 			    server_updated (finfo, vers,
629 					    (rcs_diff_patches
630 					     ? SERVER_RCS_DIFF
631 					     : SERVER_PATCHED),
632 					    &file_info, checksum);
633 			break;
634 		    }
635 		}
636 		/* If we're not running as a server, just check the
637 		   file out.  It's simpler and faster than producing
638 		   and applying patches.  */
639 		/* Fall through.  */
640 #endif
641 	    case T_CHECKOUT:		/* needs checkout */
642 		retval = checkout_file (finfo, vers, 0);
643 #ifdef SERVER_SUPPORT
644 		if (server_active && retval == 0)
645 		    server_updated (finfo, vers,
646 				    SERVER_UPDATED, (struct stat *) NULL,
647 				    (unsigned char *) NULL);
648 #endif
649 		break;
650 	    case T_ADDED:		/* added but not committed */
651 		write_letter (finfo, 'A');
652 		retval = 0;
653 		break;
654 	    case T_REMOVED:		/* removed but not committed */
655 		write_letter (finfo, 'R');
656 		retval = 0;
657 		break;
658 	    case T_REMOVE_ENTRY:	/* needs to be un-registered */
659 		retval = scratch_file (finfo);
660 #ifdef SERVER_SUPPORT
661 		if (server_active && retval == 0)
662 		{
663 		    if (vers->ts_user == NULL)
664 			server_scratch_entry_only ();
665 		    server_updated (finfo, vers,
666 				    SERVER_UPDATED, (struct stat *) NULL,
667 				    (unsigned char *) NULL);
668 		}
669 #endif
670 		break;
671 	    default:			/* can't ever happen :-) */
672 		error (0, 0,
673 		       "unknown file status %d for file %s", status, finfo->file);
674 		retval = 0;
675 		break;
676 	}
677     }
678 
679     /* only try to join if things have gone well thus far */
680     if (retval == 0 && join_rev1)
681 	join_file (finfo, vers);
682 
683     /* if this directory has an ignore list, add this file to it */
684     if (ignlist)
685     {
686 	Node *p;
687 
688 	p = getnode ();
689 	p->type = FILES;
690 	p->key = xstrdup (finfo->file);
691 	if (addnode (ignlist, p) != 0)
692 	    freenode (p);
693     }
694 
695     freevers_ts (&vers);
696     return (retval);
697 }
698 
699 static void update_ignproc PROTO ((char *, char *));
700 
701 static void
702 update_ignproc (file, dir)
703     char *file;
704     char *dir;
705 {
706     struct file_info finfo;
707 
708     memset (&finfo, 0, sizeof (finfo));
709     finfo.file = file;
710     finfo.update_dir = dir;
711     if (dir[0] == '\0')
712 	finfo.fullname = xstrdup (file);
713     else
714     {
715 	finfo.fullname = xmalloc (strlen (file) + strlen (dir) + 10);
716 	strcpy (finfo.fullname, dir);
717 	strcat (finfo.fullname, "/");
718 	strcat (finfo.fullname, file);
719     }
720 
721     write_letter (&finfo, '?');
722     free (finfo.fullname);
723 }
724 
725 /* ARGSUSED */
726 static int
727 update_filesdone_proc (callerdat, err, repository, update_dir, entries)
728     void *callerdat;
729     int err;
730     char *repository;
731     char *update_dir;
732     List *entries;
733 {
734     if (rewrite_tag)
735     {
736 	WriteTag (NULL, tag, date, nonbranch, update_dir, repository);
737 	rewrite_tag = 0;
738     }
739 
740     /* if this directory has an ignore list, process it then free it */
741     if (ignlist)
742     {
743 	ignore_files (ignlist, entries, update_dir, update_ignproc);
744 	dellist (&ignlist);
745     }
746 
747     /* Clean up CVS admin dirs if we are export */
748     if (strcmp (command_name, "export") == 0)
749     {
750 	/* I'm not sure the existence_error is actually possible (except
751 	   in cases where we really should print a message), but since
752 	   this code used to ignore all errors, I'll play it safe.  */
753 	if (unlink_file_dir (CVSADM) < 0 && !existence_error (errno))
754 	    error (0, errno, "cannot remove %s directory", CVSADM);
755     }
756 #ifdef SERVER_SUPPORT
757     else if (!server_active && !pipeout)
758 #else
759     else if (!pipeout)
760 #endif /* SERVER_SUPPORT */
761     {
762         /* If there is no CVS/Root file, add one */
763         if (!isfile (CVSADM_ROOT))
764 	    Create_Root ((char *) NULL, CVSroot_original);
765     }
766 
767     return (err);
768 }
769 
770 /*
771  * update_dirent_proc () is called back by the recursion processor before a
772  * sub-directory is processed for update.  In this case, update_dirent proc
773  * will probably create the directory unless -d isn't specified and this is a
774  * new directory.  A return code of 0 indicates the directory should be
775  * processed by the recursion code.  A return of non-zero indicates the
776  * recursion code should skip this directory.
777  */
778 static Dtype
779 update_dirent_proc (callerdat, dir, repository, update_dir, entries)
780     void *callerdat;
781     char *dir;
782     char *repository;
783     char *update_dir;
784     List *entries;
785 {
786     if (ignore_directory (update_dir))
787     {
788 	/* print the warm fuzzy message */
789 	if (!quiet)
790 	  error (0, 0, "Ignoring %s", update_dir);
791         return R_SKIP_ALL;
792     }
793 
794     if (!isdir (dir))
795     {
796 	/* if we aren't building dirs, blow it off */
797 	if (!update_build_dirs)
798 	    return (R_SKIP_ALL);
799 
800 	if (noexec)
801 	{
802 	    /* ignore the missing dir if -n is specified */
803 	    error (0, 0, "New directory `%s' -- ignored", update_dir);
804 	    return (R_SKIP_ALL);
805 	}
806 	else
807 	{
808 	    /* otherwise, create the dir and appropriate adm files */
809 	    make_directory (dir);
810 	    Create_Admin (dir, update_dir, repository, tag, date,
811 			  /* This is a guess.  We will rewrite it later
812 			     via WriteTag.  */
813 			  0,
814 			  0);
815 	    rewrite_tag = 1;
816 	    nonbranch = 0;
817 	    Subdir_Register (entries, (char *) NULL, dir);
818 	}
819     }
820     /* Do we need to check noexec here? */
821     else if (!pipeout)
822     {
823 	char *cvsadmdir;
824 
825 	/* The directory exists.  Check to see if it has a CVS
826 	   subdirectory.  */
827 
828 	cvsadmdir = xmalloc (strlen (dir) + 80);
829 	strcpy (cvsadmdir, dir);
830 	strcat (cvsadmdir, "/");
831 	strcat (cvsadmdir, CVSADM);
832 
833 	if (!isdir (cvsadmdir))
834 	{
835 	    /* We cannot successfully recurse into a directory without a CVS
836 	       subdirectory.  Generally we will have already printed
837 	       "? foo".  */
838 	    free (cvsadmdir);
839 	    return R_SKIP_ALL;
840 	}
841 	free (cvsadmdir);
842     }
843 
844     /*
845      * If we are building dirs and not going to stdout, we make sure there is
846      * no static entries file and write the tag file as appropriate
847      */
848     if (!pipeout)
849     {
850 	if (update_build_dirs)
851 	{
852 	    char *tmp;
853 
854 	    tmp = xmalloc (strlen (dir) + sizeof (CVSADM_ENTSTAT) + 10);
855 	    (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENTSTAT);
856 	    if (unlink_file (tmp) < 0 && ! existence_error (errno))
857 		error (1, errno, "cannot remove file %s", tmp);
858 #ifdef SERVER_SUPPORT
859 	    if (server_active)
860 		server_clear_entstat (update_dir, repository);
861 #endif
862 	    free (tmp);
863 	}
864 
865 	/* keep the CVS/Tag file current with the specified arguments */
866 	if (aflag || tag || date)
867 	{
868 	    WriteTag (dir, tag, date, 0, update_dir, repository);
869 	    rewrite_tag = 1;
870 	    nonbranch = 0;
871 	}
872 
873 	/* initialize the ignore list for this directory */
874 	ignlist = getlist ();
875     }
876 
877     /* print the warm fuzzy message */
878     if (!quiet)
879 	error (0, 0, "Updating %s", update_dir);
880 
881     return (R_PROCESS);
882 }
883 
884 /*
885  * update_dirleave_proc () is called back by the recursion code upon leaving
886  * a directory.  It will prune empty directories if needed and will execute
887  * any appropriate update programs.
888  */
889 /* ARGSUSED */
890 static int
891 update_dirleave_proc (callerdat, dir, err, update_dir, entries)
892     void *callerdat;
893     char *dir;
894     int err;
895     char *update_dir;
896     List *entries;
897 {
898     FILE *fp;
899 
900     /* run the update_prog if there is one */
901     /* FIXME: should be checking for errors from CVS_FOPEN and printing
902        them if not existence_error.  */
903     if (err == 0 && !pipeout && !noexec &&
904 	(fp = CVS_FOPEN (CVSADM_UPROG, "r")) != NULL)
905     {
906 	char *cp;
907 	char *repository;
908 	char *line = NULL;
909 	size_t line_allocated = 0;
910 
911 	repository = Name_Repository ((char *) NULL, update_dir);
912 	if (getline (&line, &line_allocated, fp) >= 0)
913 	{
914 	    if ((cp = strrchr (line, '\n')) != NULL)
915 		*cp = '\0';
916 	    run_setup (line);
917 	    run_arg (repository);
918 	    cvs_output (program_name, 0);
919 	    cvs_output (" ", 1);
920 	    cvs_output (command_name, 0);
921 	    cvs_output (": Executing '", 0);
922 	    run_print (stdout);
923 	    cvs_output ("'\n", 0);
924 	    (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
925 	}
926 	else if (ferror (fp))
927 	    error (0, errno, "cannot read %s", CVSADM_UPROG);
928 	else
929 	    error (0, 0, "unexpected end of file on %s", CVSADM_UPROG);
930 
931 	if (fclose (fp) < 0)
932 	    error (0, errno, "cannot close %s", CVSADM_UPROG);
933 	if (line != NULL)
934 	    free (line);
935 	free (repository);
936     }
937 
938     if (strchr (dir, '/') == NULL)
939     {
940 	/* FIXME: chdir ("..") loses with symlinks.  */
941 	/* Prune empty dirs on the way out - if necessary */
942 	(void) CVS_CHDIR ("..");
943 	if (update_prune_dirs && isemptydir (dir, 0))
944 	{
945 	    /* I'm not sure the existence_error is actually possible (except
946 	       in cases where we really should print a message), but since
947 	       this code used to ignore all errors, I'll play it safe.	*/
948 	    if (unlink_file_dir (dir) < 0 && !existence_error (errno))
949 		error (0, errno, "cannot remove %s directory", dir);
950 	    Subdir_Deregister (entries, (char *) NULL, dir);
951 	}
952     }
953 
954     return (err);
955 }
956 
957 static int isremoved PROTO ((Node *, void *));
958 
959 /* Returns 1 if the file indicated by node has been removed.  */
960 static int
961 isremoved (node, closure)
962     Node *node;
963     void *closure;
964 {
965     Entnode *entdata = (Entnode*) node->data;
966 
967     /* If the first character of the version is a '-', the file has been
968        removed. */
969     return (entdata->version && entdata->version[0] == '-') ? 1 : 0;
970 }
971 
972 /* Returns 1 if the argument directory is completely empty, other than the
973    existence of the CVS directory entry.  Zero otherwise.  If MIGHT_NOT_EXIST
974    and the directory doesn't exist, then just return 0.  */
975 int
976 isemptydir (dir, might_not_exist)
977     char *dir;
978     int might_not_exist;
979 {
980     DIR *dirp;
981     struct dirent *dp;
982 
983     if ((dirp = CVS_OPENDIR (dir)) == NULL)
984     {
985 	if (might_not_exist && existence_error (errno))
986 	    return 0;
987 	error (0, errno, "cannot open directory %s for empty check", dir);
988 	return (0);
989     }
990     errno = 0;
991     while ((dp = readdir (dirp)) != NULL)
992     {
993 	if (strcmp (dp->d_name, ".") != 0
994 	    && strcmp (dp->d_name, "..") != 0)
995 	{
996 	    if (strcmp (dp->d_name, CVSADM) != 0)
997 	    {
998 		/* An entry other than the CVS directory.  The directory
999 		   is certainly not empty. */
1000 		(void) closedir (dirp);
1001 		return (0);
1002 	    }
1003 	    else
1004 	    {
1005 		/* The CVS directory entry.  We don't have to worry about
1006 		   this unless the Entries file indicates that files have
1007 		   been removed, but not committed, in this directory.
1008 		   (Removing the directory would prevent people from
1009 		   comitting the fact that they removed the files!) */
1010 		List *l;
1011 		int files_removed;
1012 		struct saved_cwd cwd;
1013 
1014 		if (save_cwd (&cwd))
1015 		    error_exit ();
1016 
1017 		if (CVS_CHDIR (dir) < 0)
1018 		    error (1, errno, "cannot change directory to %s", dir);
1019 		l = Entries_Open (0);
1020 		files_removed = walklist (l, isremoved, 0);
1021 		Entries_Close (l);
1022 
1023 		if (restore_cwd (&cwd, NULL))
1024 		    error_exit ();
1025 		free_cwd (&cwd);
1026 
1027 		if (files_removed != 0)
1028 		{
1029 		    /* There are files that have been removed, but not
1030 		       committed!  Do not consider the directory empty. */
1031 		    (void) closedir (dirp);
1032 		    return (0);
1033 		}
1034 	    }
1035 	}
1036 	errno = 0;
1037     }
1038     if (errno != 0)
1039     {
1040 	error (0, errno, "cannot read directory %s", dir);
1041 	(void) closedir (dirp);
1042 	return (0);
1043     }
1044     (void) closedir (dirp);
1045     return (1);
1046 }
1047 
1048 /*
1049  * scratch the Entries file entry associated with a file
1050  */
1051 static int
1052 scratch_file (finfo)
1053     struct file_info *finfo;
1054 {
1055     history_write ('W', finfo->update_dir, "", finfo->file, finfo->repository);
1056     Scratch_Entry (finfo->entries, finfo->file);
1057     if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1058 	error (0, errno, "unable to remove %s", finfo->fullname);
1059     return (0);
1060 }
1061 
1062 /*
1063  * Check out a file.
1064  */
1065 static int
1066 checkout_file (finfo, vers_ts, adding)
1067     struct file_info *finfo;
1068     Vers_TS *vers_ts;
1069     int adding;
1070 {
1071     char *backup;
1072     int set_time, retval = 0;
1073     int retcode = 0;
1074     int status;
1075     int file_is_dead;
1076 
1077     /* Solely to suppress a warning from gcc -Wall.  */
1078     backup = NULL;
1079 
1080     /* don't screw with backup files if we're going to stdout */
1081     if (!pipeout)
1082     {
1083 	backup = xmalloc (strlen (finfo->file)
1084 			  + sizeof (CVSADM)
1085 			  + sizeof (CVSPREFIX)
1086 			  + 10);
1087 	(void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
1088 	if (isfile (finfo->file))
1089 	    rename_file (finfo->file, backup);
1090 	else
1091 	    /* If -f/-t wrappers are being used to wrap up a directory,
1092 	       then backup might be a directory instead of just a file.  */
1093 	    if (unlink_file_dir (backup) < 0)
1094 	    {
1095 		/* Not sure if the existence_error check is needed here.  */
1096 		if (!existence_error (errno))
1097 		    /* FIXME: should include update_dir in message.  */
1098 		    error (0, errno, "error removing %s", backup);
1099 	    }
1100     }
1101 
1102     file_is_dead = RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs);
1103 
1104     if (!file_is_dead)
1105     {
1106 	/*
1107 	 * if we are checking out to stdout, print a nice message to
1108 	 * stderr, and add the -p flag to the command */
1109 	if (pipeout)
1110 	{
1111 	    if (!quiet)
1112 	    {
1113 		cvs_outerr ("\
1114 ===================================================================\n\
1115 Checking out ", 0);
1116 		cvs_outerr (finfo->fullname, 0);
1117 		cvs_outerr ("\n\
1118 RCS:  ", 0);
1119 		cvs_outerr (vers_ts->srcfile->path, 0);
1120 		cvs_outerr ("\n\
1121 VERS: ", 0);
1122 		cvs_outerr (vers_ts->vn_rcs, 0);
1123 		cvs_outerr ("\n***************\n", 0);
1124 	    }
1125 	}
1126 
1127 	status = RCS_checkout (vers_ts->srcfile,
1128 			       pipeout ? NULL : finfo->file,
1129 			       vers_ts->vn_rcs, vers_ts->vn_tag,
1130 			       vers_ts->options, RUN_TTY,
1131 			       (RCSCHECKOUTPROC) NULL, (void *) NULL);
1132     }
1133     if (file_is_dead || status == 0)
1134     {
1135 	if (!pipeout)
1136 	{
1137 	    Vers_TS *xvers_ts;
1138 
1139 	    if (cvswrite
1140 		&& !file_is_dead
1141 		&& !fileattr_get (finfo->file, "_watched"))
1142 		xchmod (finfo->file, 1);
1143 
1144 	    {
1145 		/* A newly checked out file is never under the spell
1146 		   of "cvs edit".  If we think we were editing it
1147 		   from a previous life, clean up.  Would be better to
1148 		   check for same the working directory instead of
1149 		   same user, but that is hairy.  */
1150 
1151 		struct addremove_args args;
1152 
1153 		editor_set (finfo->file, getcaller (), NULL);
1154 
1155 		memset (&args, 0, sizeof args);
1156 		args.remove_temp = 1;
1157 		watch_modify_watchers (finfo->file, &args);
1158 	    }
1159 
1160 	    /* set the time from the RCS file iff it was unknown before */
1161 	    set_time =
1162 		(!noexec
1163 		 && (vers_ts->vn_user == NULL ||
1164 		     strncmp (vers_ts->ts_rcs, "Initial", 7) == 0)
1165 		 && !file_is_dead);
1166 
1167 	    wrap_fromcvs_process_file (finfo->file);
1168 
1169 	    xvers_ts = Version_TS (finfo, options, tag, date,
1170 				   force_tag_match, set_time);
1171 	    if (strcmp (xvers_ts->options, "-V4") == 0)
1172 		xvers_ts->options[0] = '\0';
1173 
1174 	    (void) time (&last_register_time);
1175 
1176 	    if (file_is_dead)
1177 	    {
1178 		if (xvers_ts->vn_user != NULL)
1179 		{
1180 		    error (0, 0,
1181 			   "warning: %s is not (any longer) pertinent",
1182 			   finfo->fullname);
1183 		}
1184 		Scratch_Entry (finfo->entries, finfo->file);
1185 #ifdef SERVER_SUPPORT
1186 		if (server_active && xvers_ts->ts_user == NULL)
1187 		    server_scratch_entry_only ();
1188 #endif
1189 		/* FIXME: Rather than always unlink'ing, and ignoring the
1190 		   existence_error, we should do the unlink only if
1191 		   vers_ts->ts_user is non-NULL.  Then there would be no
1192 		   need to ignore an existence_error (for example, if the
1193 		   user removes the file while we are running).  */
1194 		if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1195 		{
1196 		    error (0, errno, "cannot remove %s", finfo->fullname);
1197 		}
1198 	    }
1199 	    else
1200 		Register (finfo->entries, finfo->file,
1201 			  adding ? "0" : xvers_ts->vn_rcs,
1202 			  xvers_ts->ts_user, xvers_ts->options,
1203 			  xvers_ts->tag, xvers_ts->date,
1204 			  (char *)0); /* Clear conflict flag on fresh checkout */
1205 
1206 	    /* fix up the vers structure, in case it is used by join */
1207 	    if (join_rev1)
1208 	    {
1209 		if (vers_ts->vn_user != NULL)
1210 		    free (vers_ts->vn_user);
1211 		if (vers_ts->vn_rcs != NULL)
1212 		    free (vers_ts->vn_rcs);
1213 		vers_ts->vn_user = xstrdup (xvers_ts->vn_rcs);
1214 		vers_ts->vn_rcs = xstrdup (xvers_ts->vn_rcs);
1215 	    }
1216 
1217 	    /* If this is really Update and not Checkout, recode history */
1218 	    if (strcmp (command_name, "update") == 0)
1219 		history_write ('U', finfo->update_dir, xvers_ts->vn_rcs, finfo->file,
1220 			       finfo->repository);
1221 
1222 	    freevers_ts (&xvers_ts);
1223 
1224 	    if (!really_quiet && !file_is_dead)
1225 	    {
1226 		write_letter (finfo, 'U');
1227 	    }
1228 	}
1229     }
1230     else
1231     {
1232 	int old_errno = errno;		/* save errno value over the rename */
1233 
1234 	if (!pipeout && isfile (backup))
1235 	    rename_file (backup, finfo->file);
1236 
1237 	error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0,
1238 	       "could not check out %s", finfo->fullname);
1239 
1240 	retval = retcode;
1241     }
1242 
1243     if (!pipeout)
1244     {
1245 	/* If -f/-t wrappers are being used to wrap up a directory,
1246 	   then backup might be a directory instead of just a file.  */
1247 	if (unlink_file_dir (backup) < 0)
1248 	{
1249 	    /* Not sure if the existence_error check is needed here.  */
1250 	    if (!existence_error (errno))
1251 		/* FIXME: should include update_dir in message.  */
1252 		error (0, errno, "error removing %s", backup);
1253 	}
1254 	free (backup);
1255     }
1256 
1257     return (retval);
1258 }
1259 
1260 #ifdef SERVER_SUPPORT
1261 
1262 /* This structure is used to pass information between patch_file and
1263    patch_file_write.  */
1264 
1265 struct patch_file_data
1266 {
1267     /* File name, for error messages.  */
1268     const char *filename;
1269     /* File to which to write.  */
1270     FILE *fp;
1271     /* Whether to compute the MD5 checksum.  */
1272     int compute_checksum;
1273     /* Data structure for computing the MD5 checksum.  */
1274     struct MD5Context context;
1275     /* Set if the file has a final newline.  */
1276     int final_nl;
1277 };
1278 
1279 /* Patch a file.  Runs diff.  This is only done when running as the
1280  * server.  The hope is that the diff will be smaller than the file
1281  * itself.
1282  */
1283 static int
1284 patch_file (finfo, vers_ts, docheckout, file_info, checksum)
1285     struct file_info *finfo;
1286     Vers_TS *vers_ts;
1287     int *docheckout;
1288     struct stat *file_info;
1289     unsigned char *checksum;
1290 {
1291     char *backup;
1292     char *file1;
1293     char *file2;
1294     int retval = 0;
1295     int retcode = 0;
1296     int fail;
1297     long file_size;
1298     FILE *e;
1299     struct patch_file_data data;
1300 
1301     *docheckout = 0;
1302 
1303     if (noexec || pipeout || joining ())
1304     {
1305 	*docheckout = 1;
1306 	return 0;
1307     }
1308 
1309     /* If this file has been marked as being binary, then never send a
1310        patch.  */
1311     if (strcmp (vers_ts->options, "-kb") == 0)
1312     {
1313 	*docheckout = 1;
1314 	return 0;
1315     }
1316 
1317     /* First check that the first revision exists.  If it has been nuked
1318        by cvs admin -o, then just fall back to checking out entire
1319        revisions.  In some sense maybe we don't have to do this; after
1320        all cvs.texinfo says "Make sure that no-one has checked out a
1321        copy of the revision you outdate" but then again, that advice
1322        doesn't really make complete sense, because "cvs admin" operates
1323        on a working directory and so _someone_ will almost always have
1324        _some_ revision checked out.  */
1325     {
1326 	char *rev;
1327 
1328 	rev = RCS_gettag (finfo->rcs, vers_ts->vn_user, 1, NULL);
1329 	if (rev == NULL)
1330 	{
1331 	    *docheckout = 1;
1332 	    return 0;
1333 	}
1334 	else
1335 	    free (rev);
1336     }
1337 
1338     backup = xmalloc (strlen (finfo->file)
1339 		      + sizeof (CVSADM)
1340 		      + sizeof (CVSPREFIX)
1341 		      + 10);
1342     (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
1343     if (isfile (finfo->file))
1344         rename_file (finfo->file, backup);
1345     else
1346         (void) unlink_file (backup);
1347 
1348     file1 = xmalloc (strlen (finfo->file)
1349 		     + sizeof (CVSADM)
1350 		     + sizeof (CVSPREFIX)
1351 		     + 10);
1352     (void) sprintf (file1, "%s/%s%s-1", CVSADM, CVSPREFIX, finfo->file);
1353     file2 = xmalloc (strlen (finfo->file)
1354 		     + sizeof (CVSADM)
1355 		     + sizeof (CVSPREFIX)
1356 		     + 10);
1357     (void) sprintf (file2, "%s/%s%s-2", CVSADM, CVSPREFIX, finfo->file);
1358 
1359     fail = 0;
1360 
1361     /* We need to check out both revisions first, to see if either one
1362        has a trailing newline.  Because of this, we don't use rcsdiff,
1363        but just use diff.  */
1364 
1365     e = CVS_FOPEN (file1, "w");
1366     if (e == NULL)
1367 	error (1, errno, "cannot open %s", file1);
1368 
1369     data.filename = file1;
1370     data.fp = e;
1371     data.final_nl = 0;
1372     data.compute_checksum = 0;
1373 
1374     retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL,
1375 			    vers_ts->vn_user, (char *) NULL,
1376 			    vers_ts->options, RUN_TTY,
1377 			    patch_file_write, (void *) &data);
1378 
1379     if (fclose (e) < 0)
1380 	error (1, errno, "cannot close %s", file1);
1381 
1382     if (retcode != 0 || ! data.final_nl)
1383 	fail = 1;
1384 
1385     if (! fail)
1386     {
1387 	e = CVS_FOPEN (file2, "w");
1388 	if (e == NULL)
1389 	    error (1, errno, "cannot open %s", file2);
1390 
1391 	data.filename = file2;
1392 	data.fp = e;
1393 	data.final_nl = 0;
1394 	data.compute_checksum = 1;
1395 	MD5Init (&data.context);
1396 
1397 	retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL,
1398 				vers_ts->vn_rcs, (char *) NULL,
1399 				vers_ts->options, RUN_TTY,
1400 				patch_file_write, (void *) &data);
1401 
1402 	if (fclose (e) < 0)
1403 	    error (1, errno, "cannot close %s", file2);
1404 
1405 	if (retcode != 0 || ! data.final_nl)
1406 	    fail = 1;
1407 	else
1408 	    MD5Final (checksum, &data.context);
1409     }
1410 
1411     retcode = 0;
1412     if (! fail)
1413     {
1414 	char *diff_options;
1415 
1416 	/* FIXME: It might be better to come up with a diff library
1417            which can be shared with the diffutils.  */
1418 	/* If the client does not support the Rcs-diff command, we
1419            send a context diff, and the client must invoke patch.
1420            That approach was problematical for various reasons.  The
1421            new approach only requires running diff in the server; the
1422            client can handle everything without invoking an external
1423            program.  */
1424 	if (! rcs_diff_patches)
1425 	{
1426 	    /* We use -c, not -u, because we have no way of knowing
1427 	       which DIFF is in use.  */
1428 	    diff_options = "-c";
1429 	}
1430 	else
1431 	{
1432 	    /* Now that diff is librarified, we could be passing -a if
1433 	       we wanted to.  However, it is unclear to me whether we
1434 	       would want to.  Does diff -a, in any significant
1435 	       percentage of cases, produce patches which are smaller
1436 	       than the files it is patching?  I guess maybe text
1437 	       files with character sets which diff regards as
1438 	       'binary'.  Conversely, do they tend to be much larger
1439 	       in the bad cases?  This needs some more
1440 	       thought/investigation, I suspect.  */
1441 
1442 	    diff_options = "-n";
1443 	}
1444 	retcode = diff_exec (file1, file2, diff_options, finfo->file);
1445 
1446 	/* A retcode of 0 means no differences.  1 means some differences.  */
1447 	if (retcode != 0
1448 	    && retcode != 1)
1449 	{
1450 	    fail = 1;
1451 	}
1452 	else
1453 	{
1454 #define BINARY "Binary"
1455 	    char buf[sizeof BINARY];
1456 	    unsigned int c;
1457 
1458 	    /* Stat the original RCS file, and then adjust it the way
1459 	       that RCS_checkout would.  FIXME: This is an abstraction
1460 	       violation.  */
1461 	    if (CVS_STAT (vers_ts->srcfile->path, file_info) < 0)
1462 		error (1, errno, "could not stat %s", vers_ts->srcfile->path);
1463 	    if (chmod (finfo->file,
1464 		       file_info->st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH))
1465 		< 0)
1466 		error (0, errno, "cannot change mode of file %s", finfo->file);
1467 	    if (cvswrite
1468 		&& !fileattr_get (finfo->file, "_watched"))
1469 		xchmod (finfo->file, 1);
1470 
1471 	    /* Check the diff output to make sure patch will be handle it.  */
1472 	    e = CVS_FOPEN (finfo->file, "r");
1473 	    if (e == NULL)
1474 		error (1, errno, "could not open diff output file %s",
1475 		       finfo->fullname);
1476 	    c = fread (buf, 1, sizeof BINARY - 1, e);
1477 	    buf[c] = '\0';
1478 	    if (strcmp (buf, BINARY) == 0)
1479 	    {
1480 		/* These are binary files.  We could use diff -a, but
1481 		   patch can't handle that.  */
1482 		fail = 1;
1483 	    }
1484 	    else {
1485 		/*
1486 		 * Don't send a diff if just sending the entire file
1487 		 * would be smaller
1488 		 */
1489 		fseek(e, 0L, SEEK_END);
1490 		if (file_size < ftell(e))
1491 		    fail = 1;
1492 	    }
1493 
1494 	    fclose (e);
1495 	}
1496     }
1497 
1498     if (! fail)
1499     {
1500         Vers_TS *xvers_ts;
1501 
1502         /* This stuff is just copied blindly from checkout_file.  I
1503 	   don't really know what it does.  */
1504         xvers_ts = Version_TS (finfo, options, tag, date,
1505 			       force_tag_match, 0);
1506 	if (strcmp (xvers_ts->options, "-V4") == 0)
1507 	    xvers_ts->options[0] = '\0';
1508 
1509 	Register (finfo->entries, finfo->file, xvers_ts->vn_rcs,
1510 		  xvers_ts->ts_user, xvers_ts->options,
1511 		  xvers_ts->tag, xvers_ts->date, NULL);
1512 
1513 	if (CVS_STAT (finfo->file, file_info) < 0)
1514 	    error (1, errno, "could not stat %s", finfo->file);
1515 
1516 	/* If this is really Update and not Checkout, recode history */
1517 	if (strcmp (command_name, "update") == 0)
1518 	    history_write ('P', finfo->update_dir, xvers_ts->vn_rcs, finfo->file,
1519 			   finfo->repository);
1520 
1521 	freevers_ts (&xvers_ts);
1522 
1523 	if (!really_quiet)
1524 	{
1525 	    write_letter (finfo, 'P');
1526 	}
1527     }
1528     else
1529     {
1530 	int old_errno = errno;		/* save errno value over the rename */
1531 
1532 	if (isfile (backup))
1533 	    rename_file (backup, finfo->file);
1534 
1535 	if (retcode != 0 && retcode != 1)
1536 	    error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0,
1537 		   "could not diff %s", finfo->fullname);
1538 
1539 	*docheckout = 1;
1540 	retval = retcode;
1541     }
1542 
1543     (void) unlink_file (backup);
1544     (void) unlink_file (file1);
1545     (void) unlink_file (file2);
1546 
1547     free (backup);
1548     free (file1);
1549     free (file2);
1550     return (retval);
1551 }
1552 
1553 /* Write data to a file.  Record whether the last byte written was a
1554    newline.  Optionally compute a checksum.  This is called by
1555    patch_file via RCS_checkout.  */
1556 
1557 static void
1558 patch_file_write (callerdat, buffer, len)
1559      void *callerdat;
1560      const char *buffer;
1561      size_t len;
1562 {
1563     struct patch_file_data *data = (struct patch_file_data *) callerdat;
1564 
1565     if (fwrite (buffer, 1, len, data->fp) != len)
1566 	error (1, errno, "cannot write %s", data->filename);
1567 
1568     data->final_nl = (buffer[len - 1] == '\n');
1569 
1570     if (data->compute_checksum)
1571 	MD5Update (&data->context, (unsigned char *) buffer, len);
1572 }
1573 
1574 #endif /* SERVER_SUPPORT */
1575 
1576 /*
1577  * Several of the types we process only print a bit of information consisting
1578  * of a single letter and the name.
1579  */
1580 static void
1581 write_letter (finfo, letter)
1582     struct file_info *finfo;
1583     int letter;
1584 {
1585     if (!really_quiet)
1586     {
1587 	char *tag = NULL;
1588 	/* Big enough for "+updated" or any of its ilk.  */
1589 	char buf[80];
1590 
1591 	switch (letter)
1592 	{
1593 	    case 'U':
1594 		tag = "updated";
1595 		break;
1596 	    default:
1597 		/* We don't yet support tagged output except for "U".  */
1598 		break;
1599 	}
1600 
1601 	if (tag != NULL)
1602 	{
1603 	    sprintf (buf, "+%s", tag);
1604 	    cvs_output_tagged (buf, NULL);
1605 	}
1606 	buf[0] = letter;
1607 	buf[1] = ' ';
1608 	buf[2] = '\0';
1609 	cvs_output_tagged ("text", buf);
1610 	cvs_output_tagged ("fname", finfo->fullname);
1611 	cvs_output_tagged ("newline", NULL);
1612 	if (tag != NULL)
1613 	{
1614 	    sprintf (buf, "-%s", tag);
1615 	    cvs_output_tagged (buf, NULL);
1616 	}
1617     }
1618     return;
1619 }
1620 
1621 /*
1622  * Do all the magic associated with a file which needs to be merged
1623  */
1624 static int
1625 merge_file (finfo, vers)
1626     struct file_info *finfo;
1627     Vers_TS *vers;
1628 {
1629     char *backup;
1630     int status;
1631     int retcode = 0;
1632     int retval;
1633 
1634     /*
1635      * The users currently modified file is moved to a backup file name
1636      * ".#filename.version", so that it will stay around for a few days
1637      * before being automatically removed by some cron daemon.  The "version"
1638      * is the version of the file that the user was most up-to-date with
1639      * before the merge.
1640      */
1641     backup = xmalloc (strlen (finfo->file)
1642 		      + strlen (vers->vn_user)
1643 		      + sizeof (BAKPREFIX)
1644 		      + 10);
1645     (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
1646 
1647     (void) unlink_file (backup);
1648     copy_file (finfo->file, backup);
1649     xchmod (finfo->file, 1);
1650 
1651     if (strcmp (vers->options, "-kb") == 0
1652 	|| wrap_merge_is_copy (finfo->file))
1653     {
1654 	/* For binary files, a merge is always a conflict.  We give the
1655 	   user the two files, and let them resolve it.  It is possible
1656 	   that we should require a "touch foo" or similar step before
1657 	   we allow a checkin.  */
1658 	status = checkout_file (finfo, vers, 0);
1659 #ifdef SERVER_SUPPORT
1660 	/* Send the new contents of the file before the message.  If we
1661 	   wanted to be totally correct, we would have the client write
1662 	   the message only after the file has safely been written.  */
1663 	if (server_active)
1664 	{
1665 	    server_copy_file (finfo->file, finfo->update_dir,
1666 			      finfo->repository, backup);
1667 	    server_updated (finfo, vers, SERVER_MERGED,
1668 			    (struct stat *) NULL, (unsigned char *) NULL);
1669 	}
1670 #endif
1671 	/* Is there a better term than "nonmergeable file"?  What we
1672 	   really mean is, not something that CVS cannot or does not
1673 	   want to merge (there might be an external manual or
1674 	   automatic merge process).  */
1675 	error (0, 0, "nonmergeable file needs merge");
1676 	error (0, 0, "revision %s from repository is now in %s",
1677 	       vers->vn_rcs, finfo->fullname);
1678 	error (0, 0, "file from working directory is now in %s", backup);
1679 	write_letter (finfo, 'C');
1680 
1681 	history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file,
1682 		       finfo->repository);
1683 	retval = 0;
1684 	goto out;
1685     }
1686 
1687     status = RCS_merge(finfo->rcs, vers->srcfile->path, finfo->file,
1688 		       vers->options, vers->vn_user, vers->vn_rcs);
1689     if (status != 0 && status != 1)
1690     {
1691 	error (0, status == -1 ? errno : 0,
1692 	       "could not merge revision %s of %s", vers->vn_user, finfo->fullname);
1693 	error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
1694 	       finfo->fullname, backup);
1695 	rename_file (backup, finfo->file);
1696 	retval = 1;
1697 	goto out;
1698     }
1699 
1700     if (strcmp (vers->options, "-V4") == 0)
1701 	vers->options[0] = '\0';
1702     (void) time (&last_register_time);
1703     {
1704 	char *cp = 0;
1705 
1706 	if (status)
1707 	    cp = time_stamp (finfo->file);
1708 	Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_rcs, vers->options,
1709 		  vers->tag, vers->date, cp);
1710 	if (cp)
1711 	    free (cp);
1712     }
1713 
1714     /* fix up the vers structure, in case it is used by join */
1715     if (join_rev1)
1716     {
1717 	if (vers->vn_user != NULL)
1718 	    free (vers->vn_user);
1719 	vers->vn_user = xstrdup (vers->vn_rcs);
1720     }
1721 
1722 #ifdef SERVER_SUPPORT
1723     /* Send the new contents of the file before the message.  If we
1724        wanted to be totally correct, we would have the client write
1725        the message only after the file has safely been written.  */
1726     if (server_active)
1727     {
1728         server_copy_file (finfo->file, finfo->update_dir, finfo->repository,
1729 			  backup);
1730 	server_updated (finfo, vers, SERVER_MERGED,
1731 			(struct stat *) NULL, (unsigned char *) NULL);
1732     }
1733 #endif
1734 
1735     if (!noexec && !xcmp (backup, finfo->file))
1736     {
1737 	printf ("%s already contains the differences between %s and %s\n",
1738 		finfo->fullname, vers->vn_user, vers->vn_rcs);
1739 	history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file,
1740 		       finfo->repository);
1741 	retval = 0;
1742 	goto out;
1743     }
1744 
1745     if (status == 1)
1746     {
1747 	if (!noexec)
1748 	    error (0, 0, "conflicts found in %s", finfo->fullname);
1749 
1750 	write_letter (finfo, 'C');
1751 
1752 	history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file, finfo->repository);
1753 
1754     }
1755     else if (retcode == -1)
1756     {
1757 	error (1, errno, "fork failed while examining update of %s",
1758 	       finfo->fullname);
1759     }
1760     else
1761     {
1762 	write_letter (finfo, 'M');
1763 	history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file,
1764 		       finfo->repository);
1765     }
1766     retval = 0;
1767  out:
1768     free (backup);
1769     return retval;
1770 }
1771 
1772 /*
1773  * Do all the magic associated with a file which needs to be joined
1774  * (-j option)
1775  */
1776 static void
1777 join_file (finfo, vers)
1778     struct file_info *finfo;
1779     Vers_TS *vers;
1780 {
1781     char *backup;
1782     char *options;
1783     int status;
1784 
1785     char *rev1;
1786     char *rev2;
1787     char *jrev1;
1788     char *jrev2;
1789     char *jdate1;
1790     char *jdate2;
1791 
1792     jrev1 = join_rev1;
1793     jrev2 = join_rev2;
1794     jdate1 = date_rev1;
1795     jdate2 = date_rev2;
1796 
1797     /* Determine if we need to do anything at all.  */
1798     if (vers->srcfile == NULL ||
1799 	vers->srcfile->path == NULL)
1800     {
1801 	return;
1802     }
1803 
1804     /* If only one join revision is specified, it becomes the second
1805        revision.  */
1806     if (jrev2 == NULL)
1807     {
1808 	jrev2 = jrev1;
1809 	jrev1 = NULL;
1810 	jdate2 = jdate1;
1811 	jdate1 = NULL;
1812     }
1813 
1814     /* Convert the second revision, walking branches and dates.  */
1815     rev2 = RCS_getversion (vers->srcfile, jrev2, jdate2, 1, (int *) NULL);
1816 
1817     /* If this is a merge of two revisions, get the first revision.
1818        If only one join tag was specified, then the first revision is
1819        the greatest common ancestor of the second revision and the
1820        working file.  */
1821     if (jrev1 != NULL)
1822 	rev1 = RCS_getversion (vers->srcfile, jrev1, jdate1, 1, (int *) NULL);
1823     else
1824     {
1825 	/* Note that we use vn_rcs here, since vn_user may contain a
1826            special string such as "-nn".  */
1827 	if (vers->vn_rcs == NULL)
1828 	    rev1 = NULL;
1829 	else if (rev2 == NULL)
1830 	{
1831 	    /* This means that the file never existed on the branch.
1832                It does not mean that the file was removed on the
1833                branch: that case is represented by a dead rev2.  If
1834                the file never existed on the branch, then we have
1835                nothing to merge, so we just return.  */
1836 	    return;
1837 	}
1838 	else
1839 	    rev1 = gca (vers->vn_rcs, rev2);
1840     }
1841 
1842     /* Handle a nonexistent or dead merge target.  */
1843     if (rev2 == NULL || RCS_isdead (vers->srcfile, rev2))
1844     {
1845 	char *mrev;
1846 
1847 	if (rev2 != NULL)
1848 	    free (rev2);
1849 
1850 	/* If the first revision doesn't exist either, then there is
1851            no change between the two revisions, so we don't do
1852            anything.  */
1853 	if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
1854 	{
1855 	    if (rev1 != NULL)
1856 		free (rev1);
1857 	    return;
1858 	}
1859 
1860 	/* If we are merging two revisions, then the file was removed
1861 	   between the first revision and the second one.  In this
1862 	   case we want to mark the file for removal.
1863 
1864 	   If we are merging one revision, then the file has been
1865 	   removed between the greatest common ancestor and the merge
1866 	   revision.  From the perspective of the branch on to which
1867 	   we ar emerging, which may be the trunk, either 1) the file
1868 	   does not currently exist on the target, or 2) the file has
1869 	   not been modified on the target branch since the greatest
1870 	   common ancestor, or 3) the file has been modified on the
1871 	   target branch since the greatest common ancestor.  In case
1872 	   1 there is nothing to do.  In case 2 we mark the file for
1873 	   removal.  In case 3 we have a conflict.
1874 
1875 	   Note that the handling is slightly different depending upon
1876 	   whether one or two join targets were specified.  If two
1877 	   join targets were specified, we don't check whether the
1878 	   file was modified since a given point.  My reasoning is
1879 	   that if you ask for an explicit merge between two tags,
1880 	   then you want to merge in whatever was changed between
1881 	   those two tags.  If a file was removed between the two
1882 	   tags, then you want it to be removed.  However, if you ask
1883 	   for a merge of a branch, then you want to merge in all
1884 	   changes which were made on the branch.  If a file was
1885 	   removed on the branch, that is a change to the file.  If
1886 	   the file was also changed on the main line, then that is
1887 	   also a change.  These two changes--the file removal and the
1888 	   modification--must be merged.  This is a conflict.  */
1889 
1890 	/* If the user file is dead, or does not exist, or has been
1891            marked for removal, then there is nothing to do.  */
1892 	if (vers->vn_user == NULL
1893 	    || vers->vn_user[0] == '-'
1894 	    || RCS_isdead (vers->srcfile, vers->vn_user))
1895 	{
1896 	    if (rev1 != NULL)
1897 		free (rev1);
1898 	    return;
1899 	}
1900 
1901 	/* If the user file has been marked for addition, or has been
1902 	   locally modified, then we have a conflict which we can not
1903 	   resolve.  No_Difference will already have been called in
1904 	   this case, so comparing the timestamps is sufficient to
1905 	   determine whether the file is locally modified.  */
1906 	if (strcmp (vers->vn_user, "0") == 0
1907 	    || (vers->ts_user != NULL
1908 		&& strcmp (vers->ts_user, vers->ts_rcs) != 0))
1909 	{
1910 	    if (jdate2 != NULL)
1911 		error (0, 0,
1912 		       "file %s is locally modified, but has been removed in revision %s as of %s",
1913 		       finfo->fullname, jrev2, jdate2);
1914 	    else
1915 		error (0, 0,
1916 		       "file %s is locally modified, but has been removed in revision %s",
1917 		       finfo->fullname, jrev2);
1918 
1919 	    /* FIXME: Should we arrange to return a non-zero exit
1920                status?  */
1921 
1922 	    if (rev1 != NULL)
1923 		free (rev1);
1924 
1925 	    return;
1926 	}
1927 
1928 	/* If only one join tag was specified, and the user file has
1929            been changed since the greatest common ancestor (rev1),
1930            then there is a conflict we can not resolve.  See above for
1931            the rationale.  */
1932 	if (join_rev2 == NULL
1933 	    && strcmp (rev1, vers->vn_user) != 0)
1934 	{
1935 	    if (jdate2 != NULL)
1936 		error (0, 0,
1937 		       "file %s has been modified, but has been removed in revision %s as of %s",
1938 		       finfo->fullname, jrev2, jdate2);
1939 	    else
1940 		error (0, 0,
1941 		       "file %s has been modified, but has been removed in revision %s",
1942 		       finfo->fullname, jrev2);
1943 
1944 	    /* FIXME: Should we arrange to return a non-zero exit
1945                status?  */
1946 
1947 	    if (rev1 != NULL)
1948 		free (rev1);
1949 
1950 	    return;
1951 	}
1952 
1953 	if (rev1 != NULL)
1954 	    free (rev1);
1955 
1956 	/* The user file exists and has not been modified.  Mark it
1957            for removal.  FIXME: If we are doing a checkout, this has
1958            the effect of first checking out the file, and then
1959            removing it.  It would be better to just register the
1960            removal.  */
1961 #ifdef SERVER_SUPPORT
1962 	if (server_active)
1963 	{
1964 	    server_scratch (finfo->file);
1965 	    server_updated (finfo, vers, SERVER_UPDATED, (struct stat *) NULL,
1966 			    (unsigned char *) NULL);
1967 	}
1968 #endif
1969 	mrev = xmalloc (strlen (vers->vn_user) + 2);
1970 	sprintf (mrev, "-%s", vers->vn_user);
1971 	Register (finfo->entries, finfo->file, mrev, vers->ts_rcs,
1972 		  vers->options, vers->tag, vers->date, vers->ts_conflict);
1973 	free (mrev);
1974 	/* We need to check existence_error here because if we are
1975            running as the server, and the file is up to date in the
1976            working directory, the client will not have sent us a copy.  */
1977 	if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1978 	    error (0, errno, "cannot remove file %s", finfo->fullname);
1979 #ifdef SERVER_SUPPORT
1980 	if (server_active)
1981 	    server_checked_in (finfo->file, finfo->update_dir,
1982 			       finfo->repository);
1983 #endif
1984 	if (! really_quiet)
1985 	    error (0, 0, "scheduling %s for removal", finfo->fullname);
1986 
1987 	return;
1988     }
1989 
1990     /* If the target of the merge is the same as the working file
1991        revision, then there is nothing to do.  */
1992     if (vers->vn_user != NULL && strcmp (rev2, vers->vn_user) == 0)
1993     {
1994 	if (rev1 != NULL)
1995 	    free (rev1);
1996 	free (rev2);
1997 	return;
1998     }
1999 
2000     /* If rev1 is dead or does not exist, then the file was added
2001        between rev1 and rev2.  */
2002     if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
2003     {
2004 	if (rev1 != NULL)
2005 	    free (rev1);
2006 	free (rev2);
2007 
2008 	/* If the file does not exist in the working directory, then
2009            we can just check out the new revision and mark it for
2010            addition.  */
2011 	if (vers->vn_user == NULL)
2012 	{
2013 	    Vers_TS *xvers;
2014 
2015 	    xvers = Version_TS (finfo, vers->options, jrev2, jdate2, 1, 0);
2016 
2017 	    /* FIXME: If checkout_file fails, we should arrange to
2018                return a non-zero exit status.  */
2019 	    status = checkout_file (finfo, xvers, 1);
2020 
2021 #ifdef SERVER_SUPPORT
2022 	    if (server_active && status == 0)
2023 		server_updated (finfo, xvers,
2024 				SERVER_UPDATED, (struct stat *) NULL,
2025 				(unsigned char *) NULL);
2026 #endif
2027 
2028 	    freevers_ts (&xvers);
2029 
2030 	    return;
2031 	}
2032 
2033 	/* The file currently exists in the working directory, so we
2034            have a conflict which we can not resolve.  Note that this
2035            is true even if the file is marked for addition or removal.  */
2036 
2037 	if (jdate2 != NULL)
2038 	    error (0, 0,
2039 		   "file %s exists, but has been added in revision %s as of %s",
2040 		   finfo->fullname, jrev2, jdate2);
2041 	else
2042 	    error (0, 0,
2043 		   "file %s exists, but has been added in revision %s",
2044 		   finfo->fullname, jrev2);
2045 
2046 	return;
2047     }
2048 
2049     /* If the two merge revisions are the same, then there is nothing
2050        to do.  */
2051     if (strcmp (rev1, rev2) == 0)
2052     {
2053 	free (rev1);
2054 	free (rev2);
2055 	return;
2056     }
2057 
2058     /* If there is no working file, then we can't do the merge.  */
2059     if (vers->vn_user == NULL)
2060     {
2061 	free (rev1);
2062 	free (rev2);
2063 
2064 	if (jdate2 != NULL)
2065 	    error (0, 0,
2066 		   "file %s is present in revision %s as of %s",
2067 		   finfo->fullname, jrev2, jdate2);
2068 	else
2069 	    error (0, 0,
2070 		   "file %s is present in revision %s",
2071 		   finfo->fullname, jrev2);
2072 
2073 	/* FIXME: Should we arrange to return a non-zero exit status?  */
2074 
2075 	return;
2076     }
2077 
2078 #ifdef SERVER_SUPPORT
2079     if (server_active && !isreadable (finfo->file))
2080     {
2081 	int retcode;
2082 	/* The file is up to date.  Need to check out the current contents.  */
2083 	retcode = RCS_checkout (vers->srcfile, finfo->file,
2084 				vers->vn_user, (char *) NULL,
2085 				(char *) NULL, RUN_TTY,
2086 				(RCSCHECKOUTPROC) NULL, (void *) NULL);
2087 	if (retcode != 0)
2088 	    error (1, retcode == -1 ? errno : 0,
2089 		   "failed to check out %s file", finfo->fullname);
2090     }
2091 #endif
2092 
2093     /*
2094      * The users currently modified file is moved to a backup file name
2095      * ".#filename.version", so that it will stay around for a few days
2096      * before being automatically removed by some cron daemon.  The "version"
2097      * is the version of the file that the user was most up-to-date with
2098      * before the merge.
2099      */
2100     backup = xmalloc (strlen (finfo->file)
2101 		      + strlen (vers->vn_user)
2102 		      + sizeof (BAKPREFIX)
2103 		      + 10);
2104     (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
2105 
2106     (void) unlink_file (backup);
2107     copy_file (finfo->file, backup);
2108     xchmod (finfo->file, 1);
2109 
2110     options = vers->options;
2111 #if 0
2112     if (*options == '\0')
2113 	options = "-kk";		/* to ignore keyword expansions */
2114 #endif
2115 
2116     /* If the source of the merge is the same as the working file
2117        revision, then we can just RCS_checkout the target (no merging
2118        as such).  In the text file case, this is probably quite
2119        similar to the RCS_merge, but in the binary file case,
2120        RCS_merge gives all kinds of trouble.  */
2121     if (vers->vn_user != NULL
2122 	&& strcmp (rev1, vers->vn_user) == 0
2123 	/* See comments above about how No_Difference has already been
2124 	   called.  */
2125 	&& vers->ts_user != NULL
2126 	&& strcmp (vers->ts_user, vers->ts_rcs) == 0
2127 
2128 	/* This is because of the worry below about $Name.  If that
2129 	   isn't a problem, I suspect this code probably works for
2130 	   text files too.  */
2131 	&& (strcmp (options, "-kb") == 0
2132 	    || wrap_merge_is_copy (finfo->file)))
2133     {
2134 	/* FIXME: what about nametag?  What does RCS_merge do with
2135 	   $Name?  */
2136 	if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, options,
2137 			  RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0)
2138 	    status = 2;
2139 	else
2140 	    status = 0;
2141 
2142 	/* OK, this is really stupid.  RCS_checkout carefully removes
2143 	   write permissions, and we carefully put them back.  But
2144 	   until someone gets around to fixing it, that seems like the
2145 	   easiest way to get what would seem to be the right mode.
2146 	   I don't check CVSWRITE or _watched; I haven't thought about
2147 	   that in great detail, but it seems like a watched file should
2148 	   be checked out (writable) after a merge.  */
2149 	xchmod (finfo->file, 1);
2150 
2151 	/* Traditionally, the text file case prints a whole bunch of
2152 	   scary looking and verbose output which fails to tell the user
2153 	   what is really going on (it gives them rev1 and rev2 but doesn't
2154 	   indicate in any way that rev1 == vn_user).  I think just a
2155 	   simple "U foo" is good here; it seems analogous to the case in
2156 	   which the file was added on the branch in terms of what to
2157 	   print.  */
2158 	write_letter (finfo, 'U');
2159     }
2160     else if (strcmp (options, "-kb") == 0
2161 	     || wrap_merge_is_copy (finfo->file))
2162     {
2163 	/* We are dealing with binary files, but real merging would
2164 	   need to take place.  This is a conflict.  We give the user
2165 	   the two files, and let them resolve it.  It is possible
2166 	   that we should require a "touch foo" or similar step before
2167 	   we allow a checkin.  */
2168 	if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, options,
2169 			  RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0)
2170 	    status = 2;
2171 	else
2172 	    status = 0;
2173 
2174 	/* OK, this is really stupid.  RCS_checkout carefully removes
2175 	   write permissions, and we carefully put them back.  But
2176 	   until someone gets around to fixing it, that seems like the
2177 	   easiest way to get what would seem to be the right mode.
2178 	   I don't check CVSWRITE or _watched; I haven't thought about
2179 	   that in great detail, but it seems like a watched file should
2180 	   be checked out (writable) after a merge.  */
2181 	xchmod (finfo->file, 1);
2182 
2183 	/* Hmm.  We don't give them REV1 anywhere.  I guess most people
2184 	   probably don't have a 3-way merge tool for the file type in
2185 	   question, and might just get confused if we tried to either
2186 	   provide them with a copy of the file from REV1, or even just
2187 	   told them what REV1 is so they can get it themself, but it
2188 	   might be worth thinking about.  */
2189 	/* See comment in merge_file about the "nonmergeable file"
2190 	   terminology.  */
2191 	error (0, 0, "nonmergeable file needs merge");
2192 	error (0, 0, "revision %s from repository is now in %s",
2193 	       rev2, finfo->fullname);
2194 	error (0, 0, "file from working directory is now in %s", backup);
2195 	write_letter (finfo, 'C');
2196     }
2197     else
2198 	status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
2199 			    options, rev1, rev2);
2200 
2201     if (status != 0 && status != 1)
2202     {
2203 	error (0, status == -1 ? errno : 0,
2204 	       "could not merge revision %s of %s", rev2, finfo->fullname);
2205 	error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
2206 	       finfo->fullname, backup);
2207 	rename_file (backup, finfo->file);
2208     }
2209     free (rev1);
2210     free (rev2);
2211 
2212 #ifdef SERVER_SUPPORT
2213     /*
2214      * If we're in server mode, then we need to re-register the file
2215      * even if there were no conflicts (status == 0).
2216      * This tells server_updated() to send the modified file back to
2217      * the client.
2218      */
2219     if (status == 1 || (status == 0 && server_active))
2220 #else
2221     if (status == 1)
2222 #endif
2223     {
2224 	char *cp = 0;
2225 
2226 	if (status)
2227 	    cp = time_stamp (finfo->file);
2228 	Register (finfo->entries, finfo->file,
2229 		  vers->vn_rcs, vers->ts_rcs, vers->options,
2230 		  vers->tag, vers->date, cp);
2231 	if (cp)
2232 	    free(cp);
2233     }
2234 
2235 #ifdef SERVER_SUPPORT
2236     if (server_active)
2237     {
2238 	server_copy_file (finfo->file, finfo->update_dir, finfo->repository,
2239 			  backup);
2240 	server_updated (finfo, vers, SERVER_MERGED,
2241 			(struct stat *) NULL, (unsigned char *) NULL);
2242     }
2243 #endif
2244     free (backup);
2245 }
2246 
2247 int
2248 joining ()
2249 {
2250     return (join_rev1 != NULL);
2251 }
2252