update.c revision 25839
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 = 1;
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			/* Should we be warning the user that we are
563			 * overwriting the user's copy of the file?  */
564			retval =
565			  checkout_file (finfo, vers, 0);
566		    else
567			retval = merge_file (finfo, vers);
568		}
569		break;
570	    case T_MODIFIED:		/* locally modified */
571		retval = 0;
572		if (vers->ts_conflict)
573		{
574		    char *filestamp;
575		    int retcode;
576
577		    /*
578		     * If the timestamp has changed and no conflict indicators
579		     * are found, it isn't a 'C' any more.
580		     */
581#ifdef SERVER_SUPPORT
582		    if (server_active)
583			retcode = vers->ts_conflict[0] != '=';
584		    else {
585			filestamp = time_stamp (finfo->file);
586			retcode = strcmp (vers->ts_conflict, filestamp);
587			free (filestamp);
588		    }
589#else
590		    filestamp = time_stamp (finfo->file);
591		    retcode = strcmp (vers->ts_conflict, filestamp);
592		    free (filestamp);
593#endif
594
595		    if (retcode)
596		    {
597			/* The timestamps differ.  But if there are conflict
598			   markers print 'C' anyway.  */
599			retcode = !file_has_markers (finfo);
600		    }
601
602		    if (!retcode)
603		    {
604			(void) write_letter (finfo->file, 'C', finfo->update_dir);
605			retval = 1;
606		    }
607		    else
608		    {
609			/* Reregister to clear conflict flag. */
610			Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_rcs,
611				  vers->options, vers->tag,
612				  vers->date, (char *)0);
613		    }
614		}
615		if (!retval)
616		    retval = write_letter (finfo->file, 'M', finfo->update_dir);
617		break;
618#ifdef SERVER_SUPPORT
619	    case T_PATCH:		/* needs patch */
620		if (patches)
621		{
622		    int docheckout;
623		    struct stat file_info;
624		    unsigned char checksum[16];
625
626		    retval = patch_file (finfo,
627					 vers, &docheckout,
628					 &file_info, checksum);
629		    if (! docheckout)
630		    {
631		        if (server_active && retval == 0)
632			    server_updated (finfo, vers,
633					    (rcs_diff_patches
634					     ? SERVER_RCS_DIFF
635					     : SERVER_PATCHED),
636					    &file_info, checksum);
637			break;
638		    }
639		}
640		/* Fall through.  */
641		/* If we're not running as a server, just check the
642		   file out.  It's simpler and faster than starting up
643		   two new processes (diff and patch).  */
644		/* Fall through.  */
645#endif
646	    case T_CHECKOUT:		/* needs checkout */
647		retval = checkout_file (finfo, vers, 0);
648#ifdef SERVER_SUPPORT
649		if (server_active && retval == 0)
650		    server_updated (finfo, vers,
651				    SERVER_UPDATED, (struct stat *) NULL,
652				    (unsigned char *) NULL);
653#endif
654		break;
655	    case T_ADDED:		/* added but not committed */
656		retval = write_letter (finfo->file, 'A', finfo->update_dir);
657		break;
658	    case T_REMOVED:		/* removed but not committed */
659		retval = write_letter (finfo->file, 'R', finfo->update_dir);
660		break;
661	    case T_REMOVE_ENTRY:	/* needs to be un-registered */
662		retval = scratch_file (finfo);
663#ifdef SERVER_SUPPORT
664		if (server_active && retval == 0)
665		{
666		    if (vers->ts_user == NULL)
667			server_scratch_entry_only ();
668		    server_updated (finfo, vers,
669				    SERVER_UPDATED, (struct stat *) NULL,
670				    (unsigned char *) NULL);
671		}
672#endif
673		break;
674	    default:			/* can't ever happen :-) */
675		error (0, 0,
676		       "unknown file status %d for file %s", status, finfo->file);
677		retval = 0;
678		break;
679	}
680    }
681
682    /* only try to join if things have gone well thus far */
683    if (retval == 0 && join_rev1)
684	join_file (finfo, vers);
685
686    /* if this directory has an ignore list, add this file to it */
687    if (ignlist)
688    {
689	Node *p;
690
691	p = getnode ();
692	p->type = FILES;
693	p->key = xstrdup (finfo->file);
694	if (addnode (ignlist, p) != 0)
695	    freenode (p);
696    }
697
698    freevers_ts (&vers);
699    return (retval);
700}
701
702static void update_ignproc PROTO ((char *, char *));
703
704static void
705update_ignproc (file, dir)
706    char *file;
707    char *dir;
708{
709    (void) write_letter (file, '?', dir);
710}
711
712/* ARGSUSED */
713static int
714update_filesdone_proc (callerdat, err, repository, update_dir, entries)
715    void *callerdat;
716    int err;
717    char *repository;
718    char *update_dir;
719    List *entries;
720{
721    if (rewrite_tag)
722    {
723	WriteTag (NULL, tag, date, nonbranch, update_dir, repository);
724	rewrite_tag = 0;
725    }
726
727    /* if this directory has an ignore list, process it then free it */
728    if (ignlist)
729    {
730	ignore_files (ignlist, entries, update_dir, update_ignproc);
731	dellist (&ignlist);
732    }
733
734    /* Clean up CVS admin dirs if we are export */
735    if (strcmp (command_name, "export") == 0)
736    {
737	/* I'm not sure the existence_error is actually possible (except
738	   in cases where we really should print a message), but since
739	   this code used to ignore all errors, I'll play it safe.  */
740	if (unlink_file_dir (CVSADM) < 0 && !existence_error (errno))
741	    error (0, errno, "cannot remove %s directory", CVSADM);
742    }
743#ifdef SERVER_SUPPORT
744    else if (!server_active && !pipeout)
745#else
746    else if (!pipeout)
747#endif /* SERVER_SUPPORT */
748    {
749        /* If there is no CVS/Root file, add one */
750        if (!isfile (CVSADM_ROOT))
751	    Create_Root ((char *) NULL, CVSroot_original);
752    }
753
754    return (err);
755}
756
757/*
758 * update_dirent_proc () is called back by the recursion processor before a
759 * sub-directory is processed for update.  In this case, update_dirent proc
760 * will probably create the directory unless -d isn't specified and this is a
761 * new directory.  A return code of 0 indicates the directory should be
762 * processed by the recursion code.  A return of non-zero indicates the
763 * recursion code should skip this directory.
764 */
765static Dtype
766update_dirent_proc (callerdat, dir, repository, update_dir, entries)
767    void *callerdat;
768    char *dir;
769    char *repository;
770    char *update_dir;
771    List *entries;
772{
773    if (ignore_directory (update_dir))
774    {
775	/* print the warm fuzzy message */
776	if (!quiet)
777	  error (0, 0, "Ignoring %s", update_dir);
778        return R_SKIP_ALL;
779    }
780
781    if (!isdir (dir))
782    {
783	/* if we aren't building dirs, blow it off */
784	if (!update_build_dirs)
785	    return (R_SKIP_ALL);
786
787	if (noexec)
788	{
789	    /* ignore the missing dir if -n is specified */
790	    error (0, 0, "New directory `%s' -- ignored", dir);
791	    return (R_SKIP_ALL);
792	}
793	else
794	{
795	    /* otherwise, create the dir and appropriate adm files */
796	    make_directory (dir);
797	    Create_Admin (dir, update_dir, repository, tag, date,
798			  /* This is a guess.  We will rewrite it later
799			     via WriteTag.  */
800			  0);
801	    rewrite_tag = 1;
802	    nonbranch = 0;
803	    Subdir_Register (entries, (char *) NULL, dir);
804	}
805    }
806    /* Do we need to check noexec here? */
807    else if (!pipeout)
808    {
809	char *cvsadmdir;
810
811	/* The directory exists.  Check to see if it has a CVS
812	   subdirectory.  */
813
814	cvsadmdir = xmalloc (strlen (dir) + 80);
815	strcpy (cvsadmdir, dir);
816	strcat (cvsadmdir, "/");
817	strcat (cvsadmdir, CVSADM);
818
819	if (!isdir (cvsadmdir))
820	{
821	    /* We cannot successfully recurse into a directory without a CVS
822	       subdirectory.  Generally we will have already printed
823	       "? foo".  */
824	    free (cvsadmdir);
825	    return R_SKIP_ALL;
826	}
827	free (cvsadmdir);
828    }
829
830    /*
831     * If we are building dirs and not going to stdout, we make sure there is
832     * no static entries file and write the tag file as appropriate
833     */
834    if (!pipeout)
835    {
836	if (update_build_dirs)
837	{
838	    char *tmp;
839
840	    tmp = xmalloc (strlen (dir) + sizeof (CVSADM_ENTSTAT) + 10);
841	    (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENTSTAT);
842	    if (unlink_file (tmp) < 0 && ! existence_error (errno))
843		error (1, errno, "cannot remove file %s", tmp);
844#ifdef SERVER_SUPPORT
845	    if (server_active)
846		server_clear_entstat (update_dir, repository);
847#endif
848	    free (tmp);
849	}
850
851	/* keep the CVS/Tag file current with the specified arguments */
852	if (aflag || tag || date)
853	{
854	    WriteTag (dir, tag, date, 0, update_dir, repository);
855	    rewrite_tag = 1;
856	    nonbranch = 0;
857	}
858
859	/* initialize the ignore list for this directory */
860	ignlist = getlist ();
861    }
862
863    /* print the warm fuzzy message */
864    if (!quiet)
865	error (0, 0, "Updating %s", update_dir);
866
867    return (R_PROCESS);
868}
869
870/*
871 * update_dirleave_proc () is called back by the recursion code upon leaving
872 * a directory.  It will prune empty directories if needed and will execute
873 * any appropriate update programs.
874 */
875/* ARGSUSED */
876static int
877update_dirleave_proc (callerdat, dir, err, update_dir, entries)
878    void *callerdat;
879    char *dir;
880    int err;
881    char *update_dir;
882    List *entries;
883{
884    FILE *fp;
885
886    /* run the update_prog if there is one */
887    /* FIXME: should be checking for errors from CVS_FOPEN and printing
888       them if not existence_error.  */
889    if (err == 0 && !pipeout && !noexec &&
890	(fp = CVS_FOPEN (CVSADM_UPROG, "r")) != NULL)
891    {
892	char *cp;
893	char *repository;
894	char *line = NULL;
895	size_t line_allocated = 0;
896
897	repository = Name_Repository ((char *) NULL, update_dir);
898	if (getline (&line, &line_allocated, fp) >= 0)
899	{
900	    if ((cp = strrchr (line, '\n')) != NULL)
901		*cp = '\0';
902	    run_setup ("%s %s", line, repository);
903	    cvs_output (program_name, 0);
904	    cvs_output (" ", 1);
905	    cvs_output (command_name, 0);
906	    cvs_output (": Executing '", 0);
907	    run_print (stdout);
908	    cvs_output ("'\n", 0);
909	    (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
910	}
911	else if (ferror (fp))
912	    error (0, errno, "cannot read %s", CVSADM_UPROG);
913	else
914	    error (0, 0, "unexpected end of file on %s", CVSADM_UPROG);
915
916	if (fclose (fp) < 0)
917	    error (0, errno, "cannot close %s", CVSADM_UPROG);
918	if (line != NULL)
919	    free (line);
920	free (repository);
921    }
922
923    if (strchr (dir, '/') == NULL)
924    {
925	/* FIXME: chdir ("..") loses with symlinks.  */
926	/* Prune empty dirs on the way out - if necessary */
927	(void) CVS_CHDIR ("..");
928	if (update_prune_dirs && isemptydir (dir, 0))
929	{
930	    /* I'm not sure the existence_error is actually possible (except
931	       in cases where we really should print a message), but since
932	       this code used to ignore all errors, I'll play it safe.	*/
933	    if (unlink_file_dir (dir) < 0 && !existence_error (errno))
934		error (0, errno, "cannot remove %s directory", dir);
935	    Subdir_Deregister (entries, (char *) NULL, dir);
936	}
937    }
938
939    return (err);
940}
941
942static int isremoved PROTO ((Node *, void *));
943
944/* Returns 1 if the file indicated by node has been removed.  */
945static int
946isremoved (node, closure)
947    Node *node;
948    void *closure;
949{
950    Entnode *entdata = (Entnode*) node->data;
951
952    /* If the first character of the version is a '-', the file has been
953       removed. */
954    return (entdata->version && entdata->version[0] == '-') ? 1 : 0;
955}
956
957/* Returns 1 if the argument directory is completely empty, other than the
958   existence of the CVS directory entry.  Zero otherwise.  If MIGHT_NOT_EXIST
959   and the directory doesn't exist, then just return 0.  */
960int
961isemptydir (dir, might_not_exist)
962    char *dir;
963    int might_not_exist;
964{
965    DIR *dirp;
966    struct dirent *dp;
967
968    if ((dirp = CVS_OPENDIR (dir)) == NULL)
969    {
970	if (might_not_exist && existence_error (errno))
971	    return 0;
972	error (0, errno, "cannot open directory %s for empty check", dir);
973	return (0);
974    }
975    errno = 0;
976    while ((dp = readdir (dirp)) != NULL)
977    {
978	if (strcmp (dp->d_name, ".") != 0
979	    && strcmp (dp->d_name, "..") != 0)
980	{
981	    if (strcmp (dp->d_name, CVSADM) != 0)
982	    {
983		/* An entry other than the CVS directory.  The directory
984		   is certainly not empty. */
985		(void) closedir (dirp);
986		return (0);
987	    }
988	    else
989	    {
990		/* The CVS directory entry.  We don't have to worry about
991		   this unless the Entries file indicates that files have
992		   been removed, but not committed, in this directory.
993		   (Removing the directory would prevent people from
994		   comitting the fact that they removed the files!) */
995		List *l;
996		int files_removed;
997		struct saved_cwd cwd;
998
999		if (save_cwd (&cwd))
1000		    error_exit ();
1001
1002		if (CVS_CHDIR (dir) < 0)
1003		    error (1, errno, "cannot change directory to %s", dir);
1004		l = Entries_Open (0);
1005		files_removed = walklist (l, isremoved, 0);
1006		Entries_Close (l);
1007
1008		if (restore_cwd (&cwd, NULL))
1009		    error_exit ();
1010		free_cwd (&cwd);
1011
1012		if (files_removed != 0)
1013		{
1014		    /* There are files that have been removed, but not
1015		       committed!  Do not consider the directory empty. */
1016		    (void) closedir (dirp);
1017		    return (0);
1018		}
1019	    }
1020	}
1021	errno = 0;
1022    }
1023    if (errno != 0)
1024    {
1025	error (0, errno, "cannot read directory %s", dir);
1026	(void) closedir (dirp);
1027	return (0);
1028    }
1029    (void) closedir (dirp);
1030    return (1);
1031}
1032
1033/*
1034 * scratch the Entries file entry associated with a file
1035 */
1036static int
1037scratch_file (finfo)
1038    struct file_info *finfo;
1039{
1040    history_write ('W', finfo->update_dir, "", finfo->file, finfo->repository);
1041    Scratch_Entry (finfo->entries, finfo->file);
1042    if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1043	error (0, errno, "unable to remove %s", finfo->fullname);
1044    return (0);
1045}
1046
1047/*
1048 * Check out a file.
1049 */
1050static int
1051checkout_file (finfo, vers_ts, adding)
1052    struct file_info *finfo;
1053    Vers_TS *vers_ts;
1054    int adding;
1055{
1056    char *backup;
1057    int set_time, retval = 0;
1058    int retcode = 0;
1059    int status;
1060    int file_is_dead;
1061
1062    /* don't screw with backup files if we're going to stdout */
1063    if (!pipeout)
1064    {
1065	backup = xmalloc (strlen (finfo->file)
1066			  + sizeof (CVSADM)
1067			  + sizeof (CVSPREFIX)
1068			  + 10);
1069	(void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
1070	if (isfile (finfo->file))
1071	    rename_file (finfo->file, backup);
1072	else
1073	    /* If -f/-t wrappers are being used to wrap up a directory,
1074	       then backup might be a directory instead of just a file.  */
1075	    (void) unlink_file_dir (backup);
1076    }
1077
1078    file_is_dead = RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs);
1079
1080    if (!file_is_dead)
1081    {
1082	/*
1083	 * if we are checking out to stdout, print a nice message to
1084	 * stderr, and add the -p flag to the command */
1085	if (pipeout)
1086	{
1087	    if (!quiet)
1088	    {
1089		cvs_outerr ("\
1090===================================================================\n\
1091Checking out ", 0);
1092		cvs_outerr (finfo->fullname, 0);
1093		cvs_outerr ("\n\
1094RCS:  ", 0);
1095		cvs_outerr (vers_ts->srcfile->path, 0);
1096		cvs_outerr ("\n\
1097VERS: ", 0);
1098		cvs_outerr (vers_ts->vn_rcs, 0);
1099		cvs_outerr ("\n***************\n", 0);
1100	    }
1101	}
1102
1103	status = RCS_checkout (vers_ts->srcfile,
1104			       pipeout ? NULL : finfo->file,
1105			       vers_ts->vn_rcs, vers_ts->vn_tag,
1106			       vers_ts->options, RUN_TTY,
1107			       (RCSCHECKOUTPROC) NULL, (void *) NULL);
1108    }
1109    if (file_is_dead || status == 0)
1110    {
1111	if (!pipeout)
1112	{
1113	    Vers_TS *xvers_ts;
1114
1115	    if (cvswrite == TRUE
1116		&& !file_is_dead
1117		&& !fileattr_get (finfo->file, "_watched"))
1118		xchmod (finfo->file, 1);
1119
1120	    {
1121		/* A newly checked out file is never under the spell
1122		   of "cvs edit".  If we think we were editing it
1123		   from a previous life, clean up.  Would be better to
1124		   check for same the working directory instead of
1125		   same user, but that is hairy.  */
1126
1127		struct addremove_args args;
1128
1129		editor_set (finfo->file, getcaller (), NULL);
1130
1131		memset (&args, 0, sizeof args);
1132		args.remove_temp = 1;
1133		watch_modify_watchers (finfo->file, &args);
1134	    }
1135
1136	    /* set the time from the RCS file iff it was unknown before */
1137	    if (vers_ts->vn_user == NULL ||
1138		strncmp (vers_ts->ts_rcs, "Initial", 7) == 0)
1139	    {
1140		set_time = 1;
1141	    }
1142	    else
1143		set_time = 0;
1144
1145	    wrap_fromcvs_process_file (finfo->file);
1146
1147	    xvers_ts = Version_TS (finfo, options, tag, date,
1148				   force_tag_match, set_time);
1149	    if (strcmp (xvers_ts->options, "-V4") == 0)
1150		xvers_ts->options[0] = '\0';
1151
1152	    (void) time (&last_register_time);
1153
1154	    if (file_is_dead)
1155	    {
1156		if (xvers_ts->vn_user != NULL)
1157		{
1158		    error (0, 0,
1159			   "warning: %s is not (any longer) pertinent",
1160			   finfo->fullname);
1161		}
1162		Scratch_Entry (finfo->entries, finfo->file);
1163#ifdef SERVER_SUPPORT
1164		if (server_active && xvers_ts->ts_user == NULL)
1165		    server_scratch_entry_only ();
1166#endif
1167		/* FIXME: Rather than always unlink'ing, and ignoring the
1168		   existence_error, we should do the unlink only if
1169		   vers_ts->ts_user is non-NULL.  Then there would be no
1170		   need to ignore an existence_error (for example, if the
1171		   user removes the file while we are running).  */
1172		if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1173		{
1174		    error (0, errno, "cannot remove %s", finfo->fullname);
1175		}
1176	    }
1177	    else
1178		Register (finfo->entries, finfo->file,
1179			  adding ? "0" : xvers_ts->vn_rcs,
1180			  xvers_ts->ts_user, xvers_ts->options,
1181			  xvers_ts->tag, xvers_ts->date,
1182			  (char *)0); /* Clear conflict flag on fresh checkout */
1183
1184	    /* fix up the vers structure, in case it is used by join */
1185	    if (join_rev1)
1186	    {
1187		if (vers_ts->vn_user != NULL)
1188		    free (vers_ts->vn_user);
1189		if (vers_ts->vn_rcs != NULL)
1190		    free (vers_ts->vn_rcs);
1191		vers_ts->vn_user = xstrdup (xvers_ts->vn_rcs);
1192		vers_ts->vn_rcs = xstrdup (xvers_ts->vn_rcs);
1193	    }
1194
1195	    /* If this is really Update and not Checkout, recode history */
1196	    if (strcmp (command_name, "update") == 0)
1197		history_write ('U', finfo->update_dir, xvers_ts->vn_rcs, finfo->file,
1198			       finfo->repository);
1199
1200	    freevers_ts (&xvers_ts);
1201
1202	    if (!really_quiet && !file_is_dead)
1203	    {
1204		write_letter (finfo->file, 'U', finfo->update_dir);
1205	    }
1206	}
1207    }
1208    else
1209    {
1210	int old_errno = errno;		/* save errno value over the rename */
1211
1212	if (!pipeout && isfile (backup))
1213	    rename_file (backup, finfo->file);
1214
1215	error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0,
1216	       "could not check out %s", finfo->fullname);
1217
1218	retval = retcode;
1219    }
1220
1221    if (!pipeout)
1222    {
1223	/* If -f/-t wrappers are being used to wrap up a directory,
1224	   then backup might be a directory instead of just a file.  */
1225	(void) unlink_file_dir (backup);
1226	free (backup);
1227    }
1228
1229    return (retval);
1230}
1231
1232#ifdef SERVER_SUPPORT
1233
1234/* This structure is used to pass information between patch_file and
1235   patch_file_write.  */
1236
1237struct patch_file_data
1238{
1239    /* File name, for error messages.  */
1240    const char *filename;
1241    /* File to which to write.  */
1242    FILE *fp;
1243    /* Whether to compute the MD5 checksum.  */
1244    int compute_checksum;
1245    /* Data structure for computing the MD5 checksum.  */
1246    struct MD5Context context;
1247    /* Set if the file has a final newline.  */
1248    int final_nl;
1249};
1250
1251/* Patch a file.  Runs diff.  This is only done when running as the
1252 * server.  The hope is that the diff will be smaller than the file
1253 * itself.
1254 */
1255static int
1256patch_file (finfo, vers_ts, docheckout, file_info, checksum)
1257    struct file_info *finfo;
1258    Vers_TS *vers_ts;
1259    int *docheckout;
1260    struct stat *file_info;
1261    unsigned char *checksum;
1262{
1263    char *backup;
1264    char *file1;
1265    char *file2;
1266    int retval = 0;
1267    int retcode = 0;
1268    int fail;
1269    FILE *e;
1270    struct patch_file_data data;
1271
1272    *docheckout = 0;
1273
1274    if (noexec || pipeout || joining ())
1275    {
1276	*docheckout = 1;
1277	return 0;
1278    }
1279
1280    /* If this file has been marked as being binary, then never send a
1281       patch.  */
1282    if (strcmp (vers_ts->options, "-kb") == 0)
1283    {
1284	*docheckout = 1;
1285	return 0;
1286    }
1287
1288    backup = xmalloc (strlen (finfo->file)
1289		      + sizeof (CVSADM)
1290		      + sizeof (CVSPREFIX)
1291		      + 10);
1292    (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
1293    if (isfile (finfo->file))
1294        rename_file (finfo->file, backup);
1295    else
1296        (void) unlink_file (backup);
1297
1298    file1 = xmalloc (strlen (finfo->file)
1299		     + sizeof (CVSADM)
1300		     + sizeof (CVSPREFIX)
1301		     + 10);
1302    (void) sprintf (file1, "%s/%s%s-1", CVSADM, CVSPREFIX, finfo->file);
1303    file2 = xmalloc (strlen (finfo->file)
1304		     + sizeof (CVSADM)
1305		     + sizeof (CVSPREFIX)
1306		     + 10);
1307    (void) sprintf (file2, "%s/%s%s-2", CVSADM, CVSPREFIX, finfo->file);
1308
1309    fail = 0;
1310
1311    /* We need to check out both revisions first, to see if either one
1312       has a trailing newline.  Because of this, we don't use rcsdiff,
1313       but just use diff.  */
1314
1315    e = CVS_FOPEN (file1, "w");
1316    if (e == NULL)
1317	error (1, errno, "cannot open %s", file1);
1318
1319    data.filename = file1;
1320    data.fp = e;
1321    data.final_nl = 0;
1322    data.compute_checksum = 0;
1323
1324    retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL,
1325			    vers_ts->vn_user, (char *) NULL,
1326			    vers_ts->options, RUN_TTY,
1327			    patch_file_write, (void *) &data);
1328
1329    if (fclose (e) < 0)
1330	error (1, errno, "cannot close %s", file1);
1331
1332    if (retcode != 0 || ! data.final_nl)
1333	fail = 1;
1334
1335    if (! fail)
1336    {
1337	e = CVS_FOPEN (file2, "w");
1338	if (e == NULL)
1339	    error (1, errno, "cannot open %s", file2);
1340
1341	data.filename = file2;
1342	data.fp = e;
1343	data.final_nl = 0;
1344	data.compute_checksum = 1;
1345	MD5Init (&data.context);
1346
1347	retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL,
1348				vers_ts->vn_rcs, (char *) NULL,
1349				vers_ts->options, RUN_TTY,
1350				patch_file_write, (void *) &data);
1351
1352	if (fclose (e) < 0)
1353	    error (1, errno, "cannot close %s", file2);
1354
1355	if (retcode != 0 || ! data.final_nl)
1356	    fail = 1;
1357	else
1358	    MD5Final (checksum, &data.context);
1359    }
1360
1361    retcode = 0;
1362    if (! fail)
1363    {
1364	const char *diff_options;
1365
1366	/* FIXME: It might be better to come up with a diff library
1367           which can be shared with the diffutils.  */
1368	/* If the client does not support the Rcs-diff command, we
1369           send a context diff, and the client must invoke patch.
1370           That approach was problematical for various reasons.  The
1371           new approach only requires running diff in the server; the
1372           client can handle everything without invoking an external
1373           program.  */
1374	if (! rcs_diff_patches)
1375	{
1376	    /* We use -c, not -u, because we have no way of knowing
1377	       which DIFF is in use.  */
1378	    diff_options = "-c";
1379	}
1380	else
1381	{
1382	    /* FIXME: We should use -a if diff supports it.  We should
1383               probably just copy over most or all of the diff
1384               handling in the RCS configure script.  */
1385	    /* IMHO, we shouldn't copy over anything which even
1386	       vaguely resembles the RCS configure script.  That kind of
1387	       thing tends to be ugly, slow, and fragile.  It also is a
1388	       a support headache for CVS to behave differently in subtle
1389	       ways based on whether it was installed correctly.  Instead we
1390	       should come up with a diff library.  -kingdon, Apr 1997.  */
1391	    diff_options = "-n";
1392	}
1393	run_setup ("%s %s %s %s", DIFF, diff_options, file1, file2);
1394
1395	/* A retcode of 0 means no differences.  1 means some differences.  */
1396	if ((retcode = run_exec (RUN_TTY, finfo->file, RUN_TTY, RUN_NORMAL)) != 0
1397	    && retcode != 1)
1398	{
1399	    fail = 1;
1400	}
1401	else
1402	{
1403#define BINARY "Binary"
1404	    char buf[sizeof BINARY];
1405	    unsigned int c;
1406
1407	    /* Stat the original RCS file, and then adjust it the way
1408	       that RCS_checkout would.  FIXME: This is an abstraction
1409	       violation.  */
1410	    if (CVS_STAT (vers_ts->srcfile->path, file_info) < 0)
1411		error (1, errno, "could not stat %s", vers_ts->srcfile->path);
1412	    if (chmod (finfo->file,
1413		       file_info->st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH))
1414		< 0)
1415		error (0, errno, "cannot change mode of file %s", finfo->file);
1416	    if (cvswrite == TRUE
1417		&& !fileattr_get (finfo->file, "_watched"))
1418		xchmod (finfo->file, 1);
1419
1420	    /* Check the diff output to make sure patch will be handle it.  */
1421	    e = CVS_FOPEN (finfo->file, "r");
1422	    if (e == NULL)
1423		error (1, errno, "could not open diff output file %s",
1424		       finfo->fullname);
1425	    c = fread (buf, 1, sizeof BINARY - 1, e);
1426	    buf[c] = '\0';
1427	    if (strcmp (buf, BINARY) == 0)
1428	    {
1429		/* These are binary files.  We could use diff -a, but
1430		   patch can't handle that.  */
1431		fail = 1;
1432	    }
1433	    fclose (e);
1434	}
1435    }
1436
1437    if (! fail)
1438    {
1439        Vers_TS *xvers_ts;
1440
1441        /* This stuff is just copied blindly from checkout_file.  I
1442	   don't really know what it does.  */
1443        xvers_ts = Version_TS (finfo, options, tag, date,
1444			       force_tag_match, 0);
1445	if (strcmp (xvers_ts->options, "-V4") == 0)
1446	    xvers_ts->options[0] = '\0';
1447
1448	Register (finfo->entries, finfo->file, xvers_ts->vn_rcs,
1449		  xvers_ts->ts_user, xvers_ts->options,
1450		  xvers_ts->tag, xvers_ts->date, NULL);
1451
1452	if (CVS_STAT (finfo->file, file_info) < 0)
1453	    error (1, errno, "could not stat %s", finfo->file);
1454
1455	/* If this is really Update and not Checkout, recode history */
1456	if (strcmp (command_name, "update") == 0)
1457	    history_write ('P', finfo->update_dir, xvers_ts->vn_rcs, finfo->file,
1458			   finfo->repository);
1459
1460	freevers_ts (&xvers_ts);
1461
1462	if (!really_quiet)
1463	{
1464	    write_letter (finfo->file, 'P', finfo->update_dir);
1465	}
1466    }
1467    else
1468    {
1469	int old_errno = errno;		/* save errno value over the rename */
1470
1471	if (isfile (backup))
1472	    rename_file (backup, finfo->file);
1473
1474	if (retcode != 0 && retcode != 1)
1475	    error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0,
1476		   "could not diff %s", finfo->fullname);
1477
1478	*docheckout = 1;
1479	retval = retcode;
1480    }
1481
1482    (void) unlink_file (backup);
1483    (void) unlink_file (file1);
1484    (void) unlink_file (file2);
1485
1486    free (backup);
1487    free (file1);
1488    free (file2);
1489    return (retval);
1490}
1491
1492/* Write data to a file.  Record whether the last byte written was a
1493   newline.  Optionally compute a checksum.  This is called by
1494   patch_file via RCS_checkout.  */
1495
1496static void
1497patch_file_write (callerdat, buffer, len)
1498     void *callerdat;
1499     const char *buffer;
1500     size_t len;
1501{
1502    struct patch_file_data *data = (struct patch_file_data *) callerdat;
1503
1504    if (fwrite (buffer, 1, len, data->fp) != len)
1505	error (1, errno, "cannot write %s", data->filename);
1506
1507    data->final_nl = (buffer[len - 1] == '\n');
1508
1509    if (data->compute_checksum)
1510	MD5Update (&data->context, buffer, len);
1511}
1512
1513#endif /* SERVER_SUPPORT */
1514
1515/*
1516 * Several of the types we process only print a bit of information consisting
1517 * of a single letter and the name.
1518 */
1519static int
1520write_letter (file, letter, update_dir)
1521    char *file;
1522    int letter;
1523    char *update_dir;
1524{
1525    if (!really_quiet)
1526    {
1527	char buf[2];
1528	buf[0] = letter;
1529	buf[1] = ' ';
1530	cvs_output (buf, 2);
1531	if (update_dir[0])
1532	{
1533	    cvs_output (update_dir, 0);
1534	    cvs_output ("/", 1);
1535	}
1536	cvs_output (file, 0);
1537	cvs_output ("\n", 1);
1538    }
1539    return (0);
1540}
1541
1542/*
1543 * Do all the magic associated with a file which needs to be merged
1544 */
1545static int
1546merge_file (finfo, vers)
1547    struct file_info *finfo;
1548    Vers_TS *vers;
1549{
1550    char *backup;
1551    int status;
1552    int retcode = 0;
1553    int retval;
1554
1555    /*
1556     * The users currently modified file is moved to a backup file name
1557     * ".#filename.version", so that it will stay around for a few days
1558     * before being automatically removed by some cron daemon.  The "version"
1559     * is the version of the file that the user was most up-to-date with
1560     * before the merge.
1561     */
1562    backup = xmalloc (strlen (finfo->file)
1563		      + strlen (vers->vn_user)
1564		      + sizeof (BAKPREFIX)
1565		      + 10);
1566    (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
1567
1568    (void) unlink_file (backup);
1569    copy_file (finfo->file, backup);
1570    xchmod (finfo->file, 1);
1571
1572    if (strcmp (vers->options, "-kb") == 0)
1573    {
1574	/* For binary files, a merge is always a conflict.  We give the
1575	   user the two files, and let them resolve it.  It is possible
1576	   that we should require a "touch foo" or similar step before
1577	   we allow a checkin.  */
1578	status = checkout_file (finfo, vers, 0);
1579#ifdef SERVER_SUPPORT
1580	/* Send the new contents of the file before the message.  If we
1581	   wanted to be totally correct, we would have the client write
1582	   the message only after the file has safely been written.  */
1583	if (server_active)
1584	{
1585	    server_copy_file (finfo->file, finfo->update_dir,
1586			      finfo->repository, backup);
1587	    server_updated (finfo, vers, SERVER_MERGED,
1588			    (struct stat *) NULL, (unsigned char *) NULL);
1589	}
1590#endif
1591	error (0, 0, "binary file needs merge");
1592	error (0, 0, "revision %s from repository is now in %s",
1593	       vers->vn_rcs, finfo->fullname);
1594	error (0, 0, "file from working directory is now in %s", backup);
1595	write_letter (finfo->file, 'C', finfo->update_dir);
1596
1597	history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file,
1598		       finfo->repository);
1599	retval = 0;
1600	goto out;
1601    }
1602
1603    status = RCS_merge(vers->srcfile->path,
1604		       vers->options, vers->vn_user, vers->vn_rcs);
1605    if (status != 0 && status != 1)
1606    {
1607	error (0, status == -1 ? errno : 0,
1608	       "could not merge revision %s of %s", vers->vn_user, finfo->fullname);
1609	error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
1610	       finfo->fullname, backup);
1611	rename_file (backup, finfo->file);
1612	retval = 1;
1613	goto out;
1614    }
1615
1616    if (strcmp (vers->options, "-V4") == 0)
1617	vers->options[0] = '\0';
1618    (void) time (&last_register_time);
1619    {
1620	char *cp = 0;
1621
1622	if (status)
1623	    cp = time_stamp (finfo->file);
1624	Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_rcs, vers->options,
1625		  vers->tag, vers->date, cp);
1626	if (cp)
1627	    free (cp);
1628    }
1629
1630    /* fix up the vers structure, in case it is used by join */
1631    if (join_rev1)
1632    {
1633	if (vers->vn_user != NULL)
1634	    free (vers->vn_user);
1635	vers->vn_user = xstrdup (vers->vn_rcs);
1636    }
1637
1638#ifdef SERVER_SUPPORT
1639    /* Send the new contents of the file before the message.  If we
1640       wanted to be totally correct, we would have the client write
1641       the message only after the file has safely been written.  */
1642    if (server_active)
1643    {
1644        server_copy_file (finfo->file, finfo->update_dir, finfo->repository,
1645			  backup);
1646	server_updated (finfo, vers, SERVER_MERGED,
1647			(struct stat *) NULL, (unsigned char *) NULL);
1648    }
1649#endif
1650
1651    if (!noexec && !xcmp (backup, finfo->file))
1652    {
1653	printf ("%s already contains the differences between %s and %s\n",
1654		finfo->fullname, vers->vn_user, vers->vn_rcs);
1655	history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file,
1656		       finfo->repository);
1657	retval = 0;
1658	goto out;
1659    }
1660
1661    if (status == 1)
1662    {
1663	if (!noexec)
1664	    error (0, 0, "conflicts found in %s", finfo->fullname);
1665
1666	write_letter (finfo->file, 'C', finfo->update_dir);
1667
1668	history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file, finfo->repository);
1669
1670    }
1671    else if (retcode == -1)
1672    {
1673	error (1, errno, "fork failed while examining update of %s",
1674	       finfo->fullname);
1675    }
1676    else
1677    {
1678	write_letter (finfo->file, 'M', finfo->update_dir);
1679	history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file,
1680		       finfo->repository);
1681    }
1682    retval = 0;
1683 out:
1684    free (backup);
1685    return retval;
1686}
1687
1688/*
1689 * Do all the magic associated with a file which needs to be joined
1690 * (-j option)
1691 */
1692static void
1693join_file (finfo, vers)
1694    struct file_info *finfo;
1695    Vers_TS *vers;
1696{
1697    char *backup;
1698    char *options;
1699    int status;
1700
1701    char *rev1;
1702    char *rev2;
1703    char *jrev1;
1704    char *jrev2;
1705    char *jdate1;
1706    char *jdate2;
1707
1708    jrev1 = join_rev1;
1709    jrev2 = join_rev2;
1710    jdate1 = date_rev1;
1711    jdate2 = date_rev2;
1712
1713    if (wrap_merge_is_copy (finfo->file))
1714    {
1715	error (0, 0,
1716	       "Cannot merge %s because it is a merge-by-copy file.",
1717	       finfo->fullname);
1718	return;
1719    }
1720
1721    /* Determine if we need to do anything at all.  */
1722    if (vers->srcfile == NULL ||
1723	vers->srcfile->path == NULL)
1724    {
1725	return;
1726    }
1727
1728    /* If only one join revision is specified, it becomes the second
1729       revision.  */
1730    if (jrev2 == NULL)
1731    {
1732	jrev2 = jrev1;
1733	jrev1 = NULL;
1734	jdate2 = jdate1;
1735	jdate1 = NULL;
1736    }
1737
1738    /* Convert the second revision, walking branches and dates.  */
1739    rev2 = RCS_getversion (vers->srcfile, jrev2, jdate2, 1, (int *) NULL);
1740
1741    /* If this is a merge of two revisions, get the first revision.
1742       If only one join tag was specified, then the first revision is
1743       the greatest common ancestor of the second revision and the
1744       working file.  */
1745    if (jrev1 != NULL)
1746	rev1 = RCS_getversion (vers->srcfile, jrev1, jdate1, 1, (int *) NULL);
1747    else
1748    {
1749	/* Note that we use vn_rcs here, since vn_user may contain a
1750           special string such as "-nn".  */
1751	if (vers->vn_rcs == NULL)
1752	    rev1 = NULL;
1753	else if (rev2 == NULL)
1754	{
1755	    /* This means that the file never existed on the branch.
1756               It does not mean that the file was removed on the
1757               branch: that case is represented by a dead rev2.  If
1758               the file never existed on the branch, then we have
1759               nothing to merge, so we just return.  */
1760	    return;
1761	}
1762	else
1763	    rev1 = gca (vers->vn_rcs, rev2);
1764    }
1765
1766    /* Handle a nonexistent or dead merge target.  */
1767    if (rev2 == NULL || RCS_isdead (vers->srcfile, rev2))
1768    {
1769	char *mrev;
1770
1771	if (rev2 != NULL)
1772	    free (rev2);
1773
1774	/* If the first revision doesn't exist either, then there is
1775           no change between the two revisions, so we don't do
1776           anything.  */
1777	if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
1778	{
1779	    if (rev1 != NULL)
1780		free (rev1);
1781	    return;
1782	}
1783
1784	/* If we are merging two revisions, then the file was removed
1785	   between the first revision and the second one.  In this
1786	   case we want to mark the file for removal.
1787
1788	   If we are merging one revision, then the file has been
1789	   removed between the greatest common ancestor and the merge
1790	   revision.  From the perspective of the branch on to which
1791	   we ar emerging, which may be the trunk, either 1) the file
1792	   does not currently exist on the target, or 2) the file has
1793	   not been modified on the target branch since the greatest
1794	   common ancestor, or 3) the file has been modified on the
1795	   target branch since the greatest common ancestor.  In case
1796	   1 there is nothing to do.  In case 2 we mark the file for
1797	   removal.  In case 3 we have a conflict.
1798
1799	   Note that the handling is slightly different depending upon
1800	   whether one or two join targets were specified.  If two
1801	   join targets were specified, we don't check whether the
1802	   file was modified since a given point.  My reasoning is
1803	   that if you ask for an explicit merge between two tags,
1804	   then you want to merge in whatever was changed between
1805	   those two tags.  If a file was removed between the two
1806	   tags, then you want it to be removed.  However, if you ask
1807	   for a merge of a branch, then you want to merge in all
1808	   changes which were made on the branch.  If a file was
1809	   removed on the branch, that is a change to the file.  If
1810	   the file was also changed on the main line, then that is
1811	   also a change.  These two changes--the file removal and the
1812	   modification--must be merged.  This is a conflict.  */
1813
1814	/* If the user file is dead, or does not exist, or has been
1815           marked for removal, then there is nothing to do.  */
1816	if (vers->vn_user == NULL
1817	    || vers->vn_user[0] == '-'
1818	    || RCS_isdead (vers->srcfile, vers->vn_user))
1819	{
1820	    if (rev1 != NULL)
1821		free (rev1);
1822	    return;
1823	}
1824
1825	/* If the user file has been marked for addition, or has been
1826	   locally modified, then we have a conflict which we can not
1827	   resolve.  No_Difference will already have been called in
1828	   this case, so comparing the timestamps is sufficient to
1829	   determine whether the file is locally modified.  */
1830	if (strcmp (vers->vn_user, "0") == 0
1831	    || (vers->ts_user != NULL
1832		&& strcmp (vers->ts_user, vers->ts_rcs) != 0))
1833	{
1834	    if (jdate2 != NULL)
1835		error (0, 0,
1836		       "file %s is locally modified, but has been removed in revision %s as of %s",
1837		       finfo->fullname, jrev2, jdate2);
1838	    else
1839		error (0, 0,
1840		       "file %s is locally modified, but has been removed in revision %s",
1841		       finfo->fullname, jrev2);
1842
1843	    /* FIXME: Should we arrange to return a non-zero exit
1844               status?  */
1845
1846	    if (rev1 != NULL)
1847		free (rev1);
1848
1849	    return;
1850	}
1851
1852	/* If only one join tag was specified, and the user file has
1853           been changed since the greatest common ancestor (rev1),
1854           then there is a conflict we can not resolve.  See above for
1855           the rationale.  */
1856	if (join_rev2 == NULL
1857	    && strcmp (rev1, vers->vn_user) != 0)
1858	{
1859	    if (jdate2 != NULL)
1860		error (0, 0,
1861		       "file %s has been modified, but has been removed in revision %s as of %s",
1862		       finfo->fullname, jrev2, jdate2);
1863	    else
1864		error (0, 0,
1865		       "file %s has been modified, but has been removed in revision %s",
1866		       finfo->fullname, jrev2);
1867
1868	    /* FIXME: Should we arrange to return a non-zero exit
1869               status?  */
1870
1871	    if (rev1 != NULL)
1872		free (rev1);
1873
1874	    return;
1875	}
1876
1877	if (rev1 != NULL)
1878	    free (rev1);
1879
1880	/* The user file exists and has not been modified.  Mark it
1881           for removal.  FIXME: If we are doing a checkout, this has
1882           the effect of first checking out the file, and then
1883           removing it.  It would be better to just register the
1884           removal.  */
1885#ifdef SERVER_SUPPORT
1886	if (server_active)
1887	{
1888	    server_scratch (finfo->file);
1889	    server_updated (finfo, vers, SERVER_UPDATED, (struct stat *) NULL,
1890			    (unsigned char *) NULL);
1891	}
1892#endif
1893	mrev = xmalloc (strlen (vers->vn_user) + 2);
1894	sprintf (mrev, "-%s", vers->vn_user);
1895	Register (finfo->entries, finfo->file, mrev, vers->ts_rcs,
1896		  vers->options, vers->tag, vers->date, vers->ts_conflict);
1897	free (mrev);
1898	/* We need to check existence_error here because if we are
1899           running as the server, and the file is up to date in the
1900           working directory, the client will not have sent us a copy.  */
1901	if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1902	    error (0, errno, "cannot remove file %s", finfo->fullname);
1903#ifdef SERVER_SUPPORT
1904	if (server_active)
1905	    server_checked_in (finfo->file, finfo->update_dir,
1906			       finfo->repository);
1907#endif
1908	if (! really_quiet)
1909	    error (0, 0, "scheduling %s for removal", finfo->fullname);
1910
1911	return;
1912    }
1913
1914    /* If the target of the merge is the same as the working file
1915       revision, then there is nothing to do.  */
1916    if (vers->vn_user != NULL && strcmp (rev2, vers->vn_user) == 0)
1917    {
1918	if (rev1 != NULL)
1919	    free (rev1);
1920	free (rev2);
1921	return;
1922    }
1923
1924    /* If rev1 is dead or does not exist, then the file was added
1925       between rev1 and rev2.  */
1926    if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
1927    {
1928	if (rev1 != NULL)
1929	    free (rev1);
1930	free (rev2);
1931
1932	/* If the file does not exist in the working directory, then
1933           we can just check out the new revision and mark it for
1934           addition.  */
1935	if (vers->vn_user == NULL)
1936	{
1937	    Vers_TS *xvers;
1938
1939	    xvers = Version_TS (finfo, vers->options, jrev2, jdate2, 1, 0);
1940
1941	    /* FIXME: If checkout_file fails, we should arrange to
1942               return a non-zero exit status.  */
1943	    status = checkout_file (finfo, xvers, 1);
1944
1945#ifdef SERVER_SUPPORT
1946	    if (server_active && status == 0)
1947		server_updated (finfo, xvers,
1948				SERVER_UPDATED, (struct stat *) NULL,
1949				(unsigned char *) NULL);
1950#endif
1951
1952	    freevers_ts (&xvers);
1953
1954	    return;
1955	}
1956
1957	/* The file currently exists in the working directory, so we
1958           have a conflict which we can not resolve.  Note that this
1959           is true even if the file is marked for addition or removal.  */
1960
1961	if (jdate2 != NULL)
1962	    error (0, 0,
1963		   "file %s exists, but has been added in revision %s as of %s",
1964		   finfo->fullname, jrev2, jdate2);
1965	else
1966	    error (0, 0,
1967		   "file %s exists, but has been added in revision %s",
1968		   finfo->fullname, jrev2);
1969
1970	return;
1971    }
1972
1973    /* If the two merge revisions are the same, then there is nothing
1974       to do.  */
1975    if (strcmp (rev1, rev2) == 0)
1976    {
1977	free (rev1);
1978	free (rev2);
1979	return;
1980    }
1981
1982    /* If there is no working file, then we can't do the merge.  */
1983    if (vers->vn_user == NULL)
1984    {
1985	free (rev1);
1986	free (rev2);
1987
1988	if (jdate2 != NULL)
1989	    error (0, 0,
1990		   "file %s is present in revision %s as of %s",
1991		   finfo->fullname, jrev2, jdate2);
1992	else
1993	    error (0, 0,
1994		   "file %s is present in revision %s",
1995		   finfo->fullname, jrev2);
1996
1997	/* FIXME: Should we arrange to return a non-zero exit status?  */
1998
1999	return;
2000    }
2001
2002#ifdef SERVER_SUPPORT
2003    if (server_active && !isreadable (finfo->file))
2004    {
2005	int retcode;
2006	/* The file is up to date.  Need to check out the current contents.  */
2007	retcode = RCS_checkout (vers->srcfile, finfo->file,
2008				vers->vn_user, (char *) NULL,
2009				(char *) NULL, RUN_TTY,
2010				(RCSCHECKOUTPROC) NULL, (void *) NULL);
2011	if (retcode != 0)
2012	    error (1, retcode == -1 ? errno : 0,
2013		   "failed to check out %s file", finfo->fullname);
2014    }
2015#endif
2016
2017    /*
2018     * The users currently modified file is moved to a backup file name
2019     * ".#filename.version", so that it will stay around for a few days
2020     * before being automatically removed by some cron daemon.  The "version"
2021     * is the version of the file that the user was most up-to-date with
2022     * before the merge.
2023     */
2024    backup = xmalloc (strlen (finfo->file)
2025		      + strlen (vers->vn_user)
2026		      + sizeof (BAKPREFIX)
2027		      + 10);
2028    (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
2029
2030    (void) unlink_file (backup);
2031    copy_file (finfo->file, backup);
2032    xchmod (finfo->file, 1);
2033
2034    options = vers->options;
2035#ifdef HAVE_RCS5
2036#if 0
2037    if (*options == '\0')
2038	options = "-kk";		/* to ignore keyword expansions */
2039#endif
2040#endif
2041
2042    status = RCS_merge (vers->srcfile->path, options, rev1, rev2);
2043    if (status != 0 && status != 1)
2044    {
2045	error (0, status == -1 ? errno : 0,
2046	       "could not merge revision %s of %s", rev2, finfo->fullname);
2047	error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
2048	       finfo->fullname, backup);
2049	rename_file (backup, finfo->file);
2050    }
2051    free (rev1);
2052    free (rev2);
2053
2054#ifdef SERVER_SUPPORT
2055    /*
2056     * If we're in server mode, then we need to re-register the file
2057     * even if there were no conflicts (status == 0).
2058     * This tells server_updated() to send the modified file back to
2059     * the client.
2060     */
2061    if (status == 1 || (status == 0 && server_active))
2062#else
2063    if (status == 1)
2064#endif
2065    {
2066	char *cp = 0;
2067
2068	if (status)
2069	    cp = time_stamp (finfo->file);
2070	Register (finfo->entries, finfo->file,
2071		  vers->vn_rcs, vers->ts_rcs, vers->options,
2072		  vers->tag, vers->date, cp);
2073	if (cp)
2074	    free(cp);
2075    }
2076
2077#ifdef SERVER_SUPPORT
2078    if (server_active)
2079    {
2080	server_copy_file (finfo->file, finfo->update_dir, finfo->repository,
2081			  backup);
2082	server_updated (finfo, vers, SERVER_MERGED,
2083			(struct stat *) NULL, (unsigned char *) NULL);
2084    }
2085#endif
2086    free (backup);
2087}
2088
2089int
2090joining ()
2091{
2092    return (join_rev1 != NULL);
2093}
2094