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