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