Sync usage with man page.
[netbsd-mini2440.git] / external / gpl2 / xcvs / dist / src / update.c
bloba633f8a417ccb0ec39ab1b67fb5193d2a32c929b
1 /*
2 * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
4 * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
5 * and others.
7 * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8 * Portions Copyright (C) 1989-1992, Brian Berliner
10 * You may distribute under the terms of the GNU General Public License as
11 * specified in the README file that comes with the CVS source distribution.
13 * "update" updates the version in the present directory with respect to the RCS
14 * repository. The present version must have been created by "checkout". The
15 * user can keep up-to-date by calling "update" whenever he feels like it.
17 * The present version can be committed by "commit", but this keeps the version
18 * in tact.
20 * Arguments following the options are taken to be file names to be updated,
21 * rather than updating the entire directory.
23 * Modified or non-existent RCS files are checked out and reported as U
24 * <user_file>
26 * Modified user files are reported as M <user_file>. If both the RCS file and
27 * the user file have been modified, the user file is replaced by the result
28 * of rcsmerge, and a backup file is written for the user in .#file.version.
29 * If this throws up irreconcilable differences, the file is reported as C
30 * <user_file>, and as M <user_file> otherwise.
32 * Files added but not yet committed are reported as A <user_file>. Files
33 * removed but not yet committed are reported as R <user_file>.
35 * If the current directory contains subdirectories that hold concurrent
36 * versions, these are updated too. If the -d option was specified, new
37 * directories added to the repository are automatically created and updated
38 * as well.
41 #include "cvs.h"
42 #include <assert.h>
43 #include "save-cwd.h"
44 #ifdef SERVER_SUPPORT
45 # include "md5.h"
46 #endif
47 #include "watch.h"
48 #include "fileattr.h"
49 #include "edit.h"
50 #include "getline.h"
51 #include "buffer.h"
52 #include "hardlink.h"
54 static int checkout_file (struct file_info *finfo, Vers_TS *vers_ts,
55 int adding, int merging, int update_server);
56 #ifdef SERVER_SUPPORT
57 static void checkout_to_buffer (void *, const char *, size_t);
58 static int patch_file (struct file_info *finfo,
59 Vers_TS *vers_ts,
60 int *docheckout, struct stat *file_info,
61 unsigned char *checksum);
62 static void patch_file_write (void *, const char *, size_t);
63 #endif
64 static int merge_file (struct file_info *finfo, Vers_TS *vers);
65 static int scratch_file (struct file_info *finfo, Vers_TS *vers);
66 static Dtype update_dirent_proc (void *callerdat, const char *dir,
67 const char *repository,
68 const char *update_dir,
69 List *entries);
70 static int update_dirleave_proc (void *callerdat, const char *dir,
71 int err, const char *update_dir,
72 List *entries);
73 static int update_fileproc (void *callerdat, struct file_info *);
74 static int update_filesdone_proc (void *callerdat, int err,
75 const char *repository,
76 const char *update_dir, List *entries);
77 #ifdef PRESERVE_PERMISSIONS_SUPPORT
78 static int get_linkinfo_proc( void *_callerdat, struct _finfo * );
79 #endif
80 static void join_file (struct file_info *finfo, Vers_TS *vers_ts);
82 static char *options = NULL;
83 static char *tag = NULL;
84 static char *date = NULL;
85 /* This is a bit of a kludge. We call WriteTag at the beginning
86 before we know whether nonbranch is set or not. And then at the
87 end, once we have the right value for nonbranch, we call WriteTag
88 again. I don't know whether the first call is necessary or not.
89 rewrite_tag is nonzero if we are going to have to make that second
90 call. warned is nonzero if we've already warned the user that the
91 tag occurs as both a revision tag and a branch tag. */
92 static int rewrite_tag;
93 static int nonbranch;
94 static int warned;
96 /* If we set the tag or date for a subdirectory, we use this to undo
97 the setting. See update_dirent_proc. */
98 static char *tag_update_dir;
100 static char *join_rev1, *join_date1;
101 static char *join_rev2, *join_date2;
102 static int aflag = 0;
103 static int toss_local_changes = 0;
104 static int force_tag_match = 1;
105 static int update_build_dirs = 0;
106 static int update_prune_dirs = 0;
107 static int pipeout = 0;
108 static int dotemplate = 0;
109 #ifdef SERVER_SUPPORT
110 static int patches = 0;
111 static int rcs_diff_patches = 0;
112 #endif
113 static List *ignlist = NULL;
114 static time_t last_register_time;
115 static const char *const update_usage[] =
117 "Usage: %s %s [-APCdflRp] [-k kopt] [-r rev] [-D date] [-j rev]\n",
118 " [-I ign] [-W spec] [files...]\n",
119 "\t-A\tReset any sticky tags/date/kopts.\n",
120 "\t-P\tPrune empty directories.\n",
121 "\t-C\tOverwrite locally modified files with clean repository copies.\n",
122 "\t-d\tBuild directories, like checkout does.\n",
123 "\t-f\tForce a head revision match if tag/date not found.\n",
124 "\t-l\tLocal directory only, no recursion.\n",
125 "\t-R\tProcess directories recursively.\n",
126 "\t-p\tSend updates to standard output (avoids stickiness).\n",
127 "\t-k kopt\tUse RCS kopt -k option on checkout. (is sticky)\n",
128 "\t-r rev\tUpdate using specified revision/tag (is sticky).\n",
129 "\t-D date\tSet date to update from (is sticky).\n",
130 "\t-j rev\tMerge in changes made between current revision and rev.\n",
131 "\t-I ign\tMore files to ignore (! to reset).\n",
132 "\t-W spec\tWrappers specification line.\n",
133 "(Specify the --help global option for a list of other help options)\n",
134 NULL
140 * update is the argv,argc based front end for arg parsing
143 update (int argc, char **argv)
145 int c, err;
146 int local = 0; /* recursive by default */
147 int which; /* where to look for files and dirs */
148 char *xjoin_rev1, *xjoin_date1,
149 *xjoin_rev2, *xjoin_date2,
150 *join_orig1, *join_orig2;
152 if (argc == -1)
153 usage (update_usage);
155 xjoin_rev1 = xjoin_date1 = xjoin_rev2 = xjoin_date2 = join_orig1 =
156 join_orig2 = NULL;
158 ign_setup ();
159 wrap_setup ();
161 /* parse the args */
162 getoptreset ();
163 while ((c = getopt (argc, argv, "+ApCPflRQqduk:r:D:j:I:W:")) != -1)
165 switch (c)
167 case 'A':
168 aflag = 1;
169 break;
170 case 'C':
171 toss_local_changes = 1;
172 break;
173 case 'I':
174 ign_add (optarg, 0);
175 break;
176 case 'W':
177 wrap_add (optarg, 0);
178 break;
179 case 'k':
180 if (options)
181 free (options);
182 options = RCS_check_kflag (optarg);
183 break;
184 case 'l':
185 local = 1;
186 break;
187 case 'R':
188 local = 0;
189 break;
190 case 'Q':
191 case 'q':
192 /* The CVS 1.5 client sends these options (in addition to
193 Global_option requests), so we must ignore them. */
194 if (!server_active)
195 error (1, 0,
196 "-q or -Q must be specified before \"%s\"",
197 cvs_cmd_name);
198 break;
199 case 'd':
200 update_build_dirs = 1;
201 break;
202 case 'f':
203 force_tag_match = 0;
204 break;
205 case 'r':
206 parse_tagdate (&tag, &date, optarg);
207 break;
208 case 'D':
209 if (date) free (date);
210 date = Make_Date (optarg);
211 break;
212 case 'P':
213 update_prune_dirs = 1;
214 break;
215 case 'p':
216 pipeout = 1;
217 noexec = 1; /* so no locks will be created */
218 break;
219 case 'j':
220 if (join_orig2)
221 error (1, 0, "only two -j options can be specified");
222 if (join_orig1)
224 join_orig2 = xstrdup (optarg);
225 parse_tagdate (&xjoin_rev2, &xjoin_date2, optarg);
227 else
229 join_orig1 = xstrdup (optarg);
230 parse_tagdate (&xjoin_rev1, &xjoin_date1, optarg);
232 break;
233 case 'u':
234 #ifdef SERVER_SUPPORT
235 if (server_active)
237 patches = 1;
238 rcs_diff_patches = server_use_rcs_diff ();
240 else
241 #endif
242 usage (update_usage);
243 break;
244 case '?':
245 default:
246 usage (update_usage);
247 break;
250 argc -= optind;
251 argv += optind;
253 #ifdef CLIENT_SUPPORT
254 if (current_parsed_root->isremote)
256 int pass;
258 /* The first pass does the regular update. If we receive at least
259 one patch which failed, we do a second pass and just fetch
260 those files whose patches failed. */
261 pass = 1;
264 int status;
266 start_server ();
268 if (local)
269 send_arg("-l");
270 if (update_build_dirs)
271 send_arg("-d");
272 if (pipeout)
273 send_arg("-p");
274 if (!force_tag_match)
275 send_arg("-f");
276 if (aflag)
277 send_arg("-A");
278 if (toss_local_changes)
279 send_arg("-C");
280 if (update_prune_dirs)
281 send_arg("-P");
282 client_prune_dirs = update_prune_dirs;
283 option_with_arg ("-r", tag);
284 if (options && options[0] != '\0')
285 send_arg (options);
286 if (date)
287 client_senddate (date);
288 if (join_orig1)
289 option_with_arg ("-j", join_orig1);
290 if (join_orig2)
291 option_with_arg ("-j", join_orig2);
292 wrap_send ();
294 if (failed_patches_count == 0)
296 unsigned int flags = 0;
298 /* If the server supports the command "update-patches", that
299 means that it knows how to handle the -u argument to update,
300 which means to send patches instead of complete files.
302 We don't send -u if failed_patches != NULL, so that the
303 server doesn't try to send patches which will just fail
304 again. At least currently, the client also clobbers the
305 file and tells the server it is lost, which also will get
306 a full file instead of a patch, but it seems clean to omit
307 -u. */
308 if (supported_request ("update-patches"))
309 send_arg ("-u");
311 send_arg ("--");
313 if (update_build_dirs)
314 flags |= SEND_BUILD_DIRS;
316 if (toss_local_changes) {
317 flags |= SEND_NO_CONTENTS;
318 flags |= BACKUP_MODIFIED_FILES;
321 /* If noexec, probably could be setting SEND_NO_CONTENTS.
322 Same caveats as for "cvs status" apply. */
324 send_files (argc, argv, local, aflag, flags);
325 send_file_names (argc, argv, SEND_EXPAND_WILD);
327 else
329 int i;
331 (void) printf ("%s client: refetching unpatchable files\n",
332 program_name);
334 if (toplevel_wd != NULL
335 && CVS_CHDIR (toplevel_wd) < 0)
337 error (1, errno, "could not chdir to %s", toplevel_wd);
340 send_arg ("--");
342 for (i = 0; i < failed_patches_count; i++)
343 if (unlink_file (failed_patches[i]) < 0
344 && !existence_error (errno))
345 error (0, errno, "cannot remove %s",
346 failed_patches[i]);
347 send_files (failed_patches_count, failed_patches, local,
348 aflag, update_build_dirs ? SEND_BUILD_DIRS : 0);
349 send_file_names (failed_patches_count, failed_patches, 0);
350 free_names (&failed_patches_count, failed_patches);
353 send_to_server ("update\012", 0);
355 status = get_responses_and_close ();
357 /* If there are any conflicts, the server will return a
358 non-zero exit status. If any patches failed, we still
359 want to run the update again. We use a pass count to
360 avoid an endless loop. */
362 /* Notes: (1) assuming that status != 0 implies a
363 potential conflict is the best we can cleanly do given
364 the current protocol. I suppose that trying to
365 re-fetch in cases where there was a more serious error
366 is probably more or less harmless, but it isn't really
367 ideal. (2) it would be nice to have a testsuite case for the
368 conflict-and-patch-failed case. */
370 if (status != 0
371 && (failed_patches_count == 0 || pass > 1))
373 if (failed_patches_count > 0)
374 free_names (&failed_patches_count, failed_patches);
375 return status;
378 ++pass;
379 } while (failed_patches_count > 0);
381 return 0;
383 #endif
385 if (tag != NULL)
386 tag_check_valid (tag, argc, argv, local, aflag, "", false);
387 if (join_rev1 != NULL)
388 tag_check_valid (xjoin_rev1, argc, argv, local, aflag, "", false);
389 if (join_rev2 != NULL)
390 tag_check_valid (xjoin_rev2, argc, argv, local, aflag, "", false);
393 * If we are updating the entire directory (for real) and building dirs
394 * as we go, we make sure there is no static entries file and write the
395 * tag file as appropriate
397 if (argc <= 0 && !pipeout)
399 if (update_build_dirs)
401 if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno))
402 error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
403 #ifdef SERVER_SUPPORT
404 if (server_active)
406 char *repos = Name_Repository (NULL, NULL);
407 server_clear_entstat (".", repos);
408 free (repos);
410 #endif
413 /* keep the CVS/Tag file current with the specified arguments */
414 if (aflag || tag || date)
416 char *repos = Name_Repository (NULL, NULL);
417 WriteTag (NULL, tag, date, 0, ".", repos);
418 free (repos);
419 rewrite_tag = 1;
420 nonbranch = -1;
421 warned = 0;
425 /* look for files/dirs locally and in the repository */
426 which = W_LOCAL | W_REPOS;
428 /* look in the attic too if a tag or date is specified */
429 if (tag || date || join_orig1)
431 TRACE (TRACE_DATA, "update: searching attic");
432 which |= W_ATTIC;
435 /* call the command line interface */
436 err = do_update (argc, argv, options, tag, date, force_tag_match,
437 local, update_build_dirs, aflag, update_prune_dirs,
438 pipeout, which, xjoin_rev1, xjoin_date1, xjoin_rev2,
439 xjoin_date2, NULL, 1, NULL);
441 /* Free the space allocated for tags and dates, if necessary. */
442 if (tag) free (tag);
443 if (date) free (date);
445 return err;
451 * Command line interface to update (used by checkout)
453 * repository = cvsroot->repository + update_dir. This is necessary for
454 * checkout so that start_recursion can determine our repository. In the
455 * update case, start_recursion can use the CVS/Root & CVS/Repository file
456 * to determine this value.
459 do_update (int argc, char **argv, char *xoptions, char *xtag, char *xdate,
460 int xforce, int local, int xbuild, int xaflag, int xprune,
461 int xpipeout, int which, char *xjoin_rev1, char *xjoin_date1,
462 char *xjoin_rev2, char *xjoin_date2,
463 char *preload_update_dir, int xdotemplate, char *repository)
465 int err = 0;
467 TRACE (TRACE_FUNCTION,
468 "do_update (%s, %s, %s, %d, %d, %d, %d, %d, %d, %d, %s, %s, %s, %s, %s, %d, %s)",
469 xoptions ? xoptions : "(null)", xtag ? xtag : "(null)",
470 xdate ? xdate : "(null)", xforce, local, xbuild, xaflag, xprune,
471 xpipeout, which, xjoin_rev1 ? xjoin_rev1 : "(null)",
472 xjoin_date1 ? xjoin_date1 : "(null)",
473 xjoin_rev2 ? xjoin_rev2 : "(null)",
474 xjoin_date2 ? xjoin_date2 : "(null)",
475 preload_update_dir ? preload_update_dir : "(null)", xdotemplate,
476 repository ? repository : "(null)");
478 /* fill in the statics */
479 options = xoptions;
480 tag = xtag;
481 date = xdate;
482 force_tag_match = xforce;
483 update_build_dirs = xbuild;
484 aflag = xaflag;
485 update_prune_dirs = xprune;
486 pipeout = xpipeout;
487 dotemplate = xdotemplate;
489 /* setup the join support */
490 join_rev1 = xjoin_rev1;
491 join_date1 = xjoin_date1;
492 join_rev2 = xjoin_rev2;
493 join_date2 = xjoin_date2;
495 #ifdef PRESERVE_PERMISSIONS_SUPPORT
496 if (preserve_perms)
498 /* We need to do an extra recursion, bleah. It's to make sure
499 that we know as much as possible about file linkage. */
500 hardlist = getlist();
501 working_dir = xgetcwd (); /* save top-level working dir */
503 /* FIXME-twp: the arguments to start_recursion make me dizzy. This
504 function call was copied from the update_fileproc call that
505 follows it; someone should make sure that I did it right. */
506 err = start_recursion
507 (get_linkinfo_proc, NULL, NULL, NULL, NULL,
508 argc, argv, local, which, aflag, CVS_LOCK_READ,
509 preload_update_dir, 1, NULL);
510 if (err)
511 return err;
513 /* FIXME-twp: at this point we should walk the hardlist
514 and update the `links' field of each hardlink_info struct
515 to list the files that are linked on dist. That would make
516 it easier & more efficient to compare the disk linkage with
517 the repository linkage (a simple strcmp). */
519 #endif
521 /* call the recursion processor */
522 err = start_recursion (update_fileproc, update_filesdone_proc,
523 update_dirent_proc, update_dirleave_proc, NULL,
524 argc, argv, local, which, aflag, CVS_LOCK_READ,
525 preload_update_dir, 1, repository);
527 /* see if we need to sleep before returning to avoid time-stamp races */
528 if (!server_active && last_register_time)
530 sleep_past (last_register_time);
533 return err;
538 #ifdef PRESERVE_PERMISSIONS_SUPPORT
540 * The get_linkinfo_proc callback adds each file to the hardlist
541 * (see hardlink.c).
544 static int
545 get_linkinfo_proc (void *callerdat, struct file_info *finfo)
547 char *fullpath;
548 Node *linkp;
549 struct hardlink_info *hlinfo;
551 /* Get the full pathname of the current file. */
552 fullpath = Xasprintf ("%s/%s", working_dir, finfo->fullname);
554 /* To permit recursing into subdirectories, files
555 are keyed on the full pathname and not on the basename. */
556 linkp = lookup_file_by_inode (fullpath);
557 if (linkp == NULL)
559 /* The file isn't on disk; we are probably restoring
560 a file that was removed. */
561 return 0;
564 /* Create a new, empty hardlink_info node. */
565 hlinfo = xmalloc (sizeof (struct hardlink_info));
567 hlinfo->status = (Ctype) 0; /* is this dumb? */
568 hlinfo->checked_out = 0;
570 linkp->data = hlinfo;
572 return 0;
574 #endif
579 * This is the callback proc for update. It is called for each file in each
580 * directory by the recursion code. The current directory is the local
581 * instantiation. file is the file name we are to operate on. update_dir is
582 * set to the path relative to where we started (for pretty printing).
583 * repository is the repository. entries and srcfiles are the pre-parsed
584 * entries and source control files.
586 * This routine decides what needs to be done for each file and does the
587 * appropriate magic for checkout
589 static int
590 update_fileproc (void *callerdat, struct file_info *finfo)
592 int retval, nb;
593 Ctype status;
594 Vers_TS *vers;
596 status = Classify_File (finfo, tag, date, options, force_tag_match,
597 aflag, &vers, pipeout);
599 /* Keep track of whether TAG is a branch tag.
600 Note that if it is a branch tag in some files and a nonbranch tag
601 in others, treat it as a nonbranch tag. */
602 if (rewrite_tag
603 && tag != NULL
604 && finfo->rcs != NULL)
606 char *rev = RCS_getversion (finfo->rcs, tag, NULL, 1, NULL);
607 if (rev != NULL
608 && nonbranch != (nb = !RCS_nodeisbranch (finfo->rcs, tag)))
610 if (nonbranch >= 0 && !warned && !quiet)
612 error (0, 0,
613 "warning: %s is a branch tag in some files and a revision tag in others.",
614 tag);
615 warned = 1;
617 if (nonbranch < nb) nonbranch = nb;
619 if (rev != NULL)
620 free (rev);
623 if (pipeout)
626 * We just return success without doing anything if any of the really
627 * funky cases occur
629 * If there is still a valid RCS file, do a regular checkout type
630 * operation
632 switch (status)
634 case T_UNKNOWN: /* unknown file was explicitly asked
635 * about */
636 case T_REMOVE_ENTRY: /* needs to be un-registered */
637 case T_ADDED: /* added but not committed */
638 retval = 0;
639 break;
640 case T_CONFLICT: /* old punt-type errors */
641 retval = 1;
642 break;
643 case T_UPTODATE: /* file was already up-to-date */
644 case T_NEEDS_MERGE: /* needs merging */
645 case T_MODIFIED: /* locally modified */
646 case T_REMOVED: /* removed but not committed */
647 case T_CHECKOUT: /* needs checkout */
648 case T_PATCH: /* needs patch */
649 retval = checkout_file (finfo, vers, 0, 0, 0);
650 break;
652 default: /* can't ever happen :-) */
653 error (0, 0,
654 "unknown file status %d for file %s", status, finfo->file);
655 retval = 0;
656 break;
659 else
661 switch (status)
663 case T_UNKNOWN: /* unknown file was explicitly asked
664 * about */
665 case T_UPTODATE: /* file was already up-to-date */
666 retval = 0;
667 break;
668 case T_CONFLICT: /* old punt-type errors */
669 retval = 1;
670 write_letter (finfo, 'C');
671 break;
672 case T_NEEDS_MERGE: /* needs merging */
673 if (! toss_local_changes)
675 retval = merge_file (finfo, vers);
676 break;
678 /* else FALL THROUGH */
679 case T_MODIFIED: /* locally modified */
680 retval = 0;
681 if (toss_local_changes)
683 char *bakname;
684 bakname = backup_file (finfo->file, vers->vn_user);
685 /* This behavior is sufficiently unexpected to
686 justify overinformativeness, I think. */
687 if (!really_quiet && !server_active)
688 (void) printf ("(Locally modified %s moved to %s)\n",
689 finfo->file, bakname);
690 free (bakname);
692 /* The locally modified file is still present, but
693 it will be overwritten by the repository copy
694 after this. */
695 status = T_CHECKOUT;
696 retval = checkout_file (finfo, vers, 0, 0, 1);
698 else
700 if (vers->ts_conflict)
702 if (file_has_markers (finfo))
704 write_letter (finfo, 'C');
705 retval = 1;
707 else
709 /* Reregister to clear conflict flag. */
710 Register (finfo->entries, finfo->file,
711 vers->vn_rcs, vers->ts_rcs,
712 vers->options, vers->tag,
713 vers->date, NULL);
716 if (!retval)
717 write_letter (finfo, 'M');
719 break;
720 case T_PATCH: /* needs patch */
721 #ifdef SERVER_SUPPORT
722 if (patches)
724 int docheckout;
725 struct stat file_info;
726 unsigned char checksum[16];
728 retval = patch_file (finfo,
729 vers, &docheckout,
730 &file_info, checksum);
731 if (! docheckout)
733 if (server_active && retval == 0)
734 server_updated (finfo, vers,
735 (rcs_diff_patches
736 ? SERVER_RCS_DIFF
737 : SERVER_PATCHED),
738 file_info.st_mode, checksum,
739 NULL);
740 break;
743 #endif
744 /* If we're not running as a server, just check the
745 file out. It's simpler and faster than producing
746 and applying patches. */
747 /* Fall through. */
748 case T_CHECKOUT: /* needs checkout */
749 retval = checkout_file (finfo, vers, 0, 0, 1);
750 break;
751 case T_ADDED: /* added but not committed */
752 write_letter (finfo, 'A');
753 retval = 0;
754 break;
755 case T_REMOVED: /* removed but not committed */
756 write_letter (finfo, 'R');
757 retval = 0;
758 break;
759 case T_REMOVE_ENTRY: /* needs to be un-registered */
760 retval = scratch_file (finfo, vers);
761 break;
762 default: /* can't ever happen :-) */
763 error (0, 0,
764 "unknown file status %d for file %s", status, finfo->file);
765 retval = 0;
766 break;
770 /* only try to join if things have gone well thus far */
771 if (retval == 0 && join_rev1)
772 join_file (finfo, vers);
774 /* if this directory has an ignore list, add this file to it */
775 if (ignlist && (status != T_UNKNOWN || vers->ts_user == NULL))
777 Node *p;
779 p = getnode ();
780 p->type = FILES;
781 p->key = xstrdup (finfo->file);
782 if (addnode (ignlist, p) != 0)
783 freenode (p);
786 freevers_ts (&vers);
787 return retval;
792 static void
793 update_ignproc (const char *file, const char *dir)
795 struct file_info finfo;
796 char *tmp;
798 memset (&finfo, 0, sizeof (finfo));
799 finfo.file = file;
800 finfo.update_dir = dir;
802 finfo.fullname = tmp = Xasprintf ("%s%s%s",
803 dir[0] == '\0' ? "" : dir,
804 dir[0] == '\0' ? "" : "/",
805 file);
806 write_letter (&finfo, '?');
807 free (tmp);
812 /* ARGSUSED */
813 static int
814 update_filesdone_proc (void *callerdat, int err, const char *repository,
815 const char *update_dir, List *entries)
817 if (nonbranch < 0) nonbranch = 0;
818 if (rewrite_tag)
820 WriteTag (NULL, tag, date, nonbranch, update_dir, repository);
821 rewrite_tag = 0;
824 /* if this directory has an ignore list, process it then free it */
825 if (ignlist)
827 ignore_files (ignlist, entries, update_dir, update_ignproc);
828 dellist (&ignlist);
831 /* Clean up CVS admin dirs if we are export */
832 if (strcmp (cvs_cmd_name, "export") == 0)
834 /* I'm not sure the existence_error is actually possible (except
835 in cases where we really should print a message), but since
836 this code used to ignore all errors, I'll play it safe. */
837 if (unlink_file_dir (CVSADM) < 0 && !existence_error (errno))
838 error (0, errno, "cannot remove %s directory", CVSADM);
840 else if (!server_active && !pipeout)
842 /* If there is no CVS/Root file, add one */
843 if (!isfile (CVSADM_ROOT))
844 Create_Root (NULL, original_parsed_root->original);
847 return err;
853 * update_dirent_proc () is called back by the recursion processor before a
854 * sub-directory is processed for update. In this case, update_dirent proc
855 * will probably create the directory unless -d isn't specified and this is a
856 * new directory. A return code of 0 indicates the directory should be
857 * processed by the recursion code. A return of non-zero indicates the
858 * recursion code should skip this directory.
860 static Dtype
861 update_dirent_proc (void *callerdat, const char *dir, const char *repository,
862 const char *update_dir, List *entries)
864 if (ignore_directory (update_dir))
866 /* print the warm fuzzy message */
867 if (!quiet)
868 error (0, 0, "Ignoring %s", update_dir);
869 return R_SKIP_ALL;
872 if (!isdir (dir))
874 /* if we aren't building dirs, blow it off */
875 if (!update_build_dirs)
876 return R_SKIP_ALL;
878 /* Various CVS administrators are in the habit of removing
879 the repository directory for things they don't want any
880 more. I've even been known to do it myself (on rare
881 occasions). Not the usual recommended practice, but we
882 want to try to come up with some kind of
883 reasonable/documented/sensible behavior. Generally
884 the behavior is to just skip over that directory (see
885 dirs test in sanity.sh; the case which reaches here
886 is when update -d is specified, and the working directory
887 is gone but the subdirectory is still mentioned in
888 CVS/Entries). */
889 /* In the remote case, the client should refrain from
890 sending us the directory in the first place. So we
891 want to continue to give an error, so clients make
892 sure to do this. */
893 if (!server_active && !isdir (repository))
894 return R_SKIP_ALL;
896 if (noexec)
898 /* ignore the missing dir if -n is specified */
899 error (0, 0, "New directory `%s' -- ignored", update_dir);
900 return R_SKIP_ALL;
902 else
904 /* otherwise, create the dir and appropriate adm files */
906 /* If no tag or date were specified on the command line,
907 and we're not using -A, we want the subdirectory to use
908 the tag and date, if any, of the current directory.
909 That way, update -d will work correctly when working on
910 a branch.
912 We use TAG_UPDATE_DIR to undo the tag setting in
913 update_dirleave_proc. If we did not do this, we would
914 not correctly handle a working directory with multiple
915 tags (and maybe we should prohibit such working
916 directories, but they work now and we shouldn't make
917 them stop working without more thought). */
918 if ((tag == NULL && date == NULL) && ! aflag)
920 ParseTag (&tag, &date, &nonbranch);
921 if (tag != NULL || date != NULL)
922 tag_update_dir = xstrdup (update_dir);
925 make_directory (dir);
926 Create_Admin (dir, update_dir, repository, tag, date,
927 /* This is a guess. We will rewrite it later
928 via WriteTag. */
931 dotemplate);
932 rewrite_tag = 1;
933 nonbranch = -1;
934 warned = 0;
935 Subdir_Register (entries, NULL, dir);
938 /* Do we need to check noexec here? */
939 else if (!pipeout)
941 char *cvsadmdir;
943 /* The directory exists. Check to see if it has a CVS
944 subdirectory. */
946 cvsadmdir = Xasprintf ("%s/%s", dir, CVSADM);
948 if (!isdir (cvsadmdir))
950 /* We cannot successfully recurse into a directory without a CVS
951 subdirectory. Generally we will have already printed
952 "? foo". */
953 free (cvsadmdir);
954 return R_SKIP_ALL;
956 free (cvsadmdir);
960 * If we are building dirs and not going to stdout, we make sure there is
961 * no static entries file and write the tag file as appropriate
963 if (!pipeout)
965 if (update_build_dirs)
967 char *tmp = Xasprintf ("%s/%s", dir, CVSADM_ENTSTAT);
969 if (unlink_file (tmp) < 0 && ! existence_error (errno))
970 error (1, errno, "cannot remove file %s", tmp);
971 #ifdef SERVER_SUPPORT
972 if (server_active)
973 server_clear_entstat (update_dir, repository);
974 #endif
975 free (tmp);
978 /* keep the CVS/Tag file current with the specified arguments */
979 if (aflag || tag || date)
981 WriteTag (dir, tag, date, 0, update_dir, repository);
982 rewrite_tag = 1;
983 nonbranch = -1;
984 warned = 0;
987 WriteTemplate (update_dir, dotemplate, repository);
989 /* initialize the ignore list for this directory */
990 ignlist = getlist ();
993 /* print the warm fuzzy message */
994 if (!quiet)
995 error (0, 0, "Updating %s", update_dir);
997 return R_PROCESS;
1003 * update_dirleave_proc () is called back by the recursion code upon leaving
1004 * a directory. It will prune empty directories if needed and will execute
1005 * any appropriate update programs.
1007 /* ARGSUSED */
1008 static int
1009 update_dirleave_proc (void *callerdat, const char *dir, int err,
1010 const char *update_dir, List *entries)
1012 /* Delete the ignore list if it hasn't already been done. */
1013 if (ignlist)
1014 dellist (&ignlist);
1016 /* If we set the tag or date for a new subdirectory in
1017 update_dirent_proc, and we're now done with that subdirectory,
1018 undo the tag/date setting. Note that we know that the tag and
1019 date were both originally NULL in this case. */
1020 if (tag_update_dir != NULL && strcmp (update_dir, tag_update_dir) == 0)
1022 if (tag != NULL)
1024 free (tag);
1025 tag = NULL;
1027 if (date != NULL)
1029 free (date);
1030 date = NULL;
1032 nonbranch = -1;
1033 warned = 0;
1034 free (tag_update_dir);
1035 tag_update_dir = NULL;
1038 if (strchr (dir, '/') == NULL)
1040 /* FIXME: chdir ("..") loses with symlinks. */
1041 /* Prune empty dirs on the way out - if necessary */
1042 (void) CVS_CHDIR ("..");
1043 if (update_prune_dirs && isemptydir (dir, 0))
1045 /* I'm not sure the existence_error is actually possible (except
1046 in cases where we really should print a message), but since
1047 this code used to ignore all errors, I'll play it safe. */
1048 if (unlink_file_dir (dir) < 0 && !existence_error (errno))
1049 error (0, errno, "cannot remove %s directory", dir);
1050 Subdir_Deregister (entries, NULL, dir);
1054 return err;
1059 /* Returns 1 if the file indicated by node has been removed. */
1060 static int
1061 isremoved (Node *node, void *closure)
1063 Entnode *entdata = node->data;
1065 /* If the first character of the version is a '-', the file has been
1066 removed. */
1067 return (entdata->version && entdata->version[0] == '-') ? 1 : 0;
1072 /* Returns 1 if the argument directory is completely empty, other than the
1073 existence of the CVS directory entry. Zero otherwise. If MIGHT_NOT_EXIST
1074 and the directory doesn't exist, then just return 0. */
1076 isemptydir (const char *dir, int might_not_exist)
1078 DIR *dirp;
1079 struct dirent *dp;
1081 if ((dirp = CVS_OPENDIR (dir)) == NULL)
1083 if (might_not_exist && existence_error (errno))
1084 return 0;
1085 error (0, errno, "cannot open directory %s for empty check", dir);
1086 return 0;
1088 errno = 0;
1089 while ((dp = CVS_READDIR (dirp)) != NULL)
1091 if (strcmp (dp->d_name, ".") != 0
1092 && strcmp (dp->d_name, "..") != 0)
1094 if (strcmp (dp->d_name, CVSADM) != 0)
1096 /* An entry other than the CVS directory. The directory
1097 is certainly not empty. */
1098 (void) CVS_CLOSEDIR (dirp);
1099 return 0;
1101 else
1103 /* The CVS directory entry. We don't have to worry about
1104 this unless the Entries file indicates that files have
1105 been removed, but not committed, in this directory.
1106 (Removing the directory would prevent people from
1107 comitting the fact that they removed the files!) */
1108 List *l;
1109 int files_removed;
1110 struct saved_cwd cwd;
1112 if (save_cwd (&cwd))
1113 error (1, errno, "Failed to save current directory.");
1115 if (CVS_CHDIR (dir) < 0)
1116 error (1, errno, "cannot change directory to %s", dir);
1117 l = Entries_Open (0, NULL);
1118 files_removed = walklist (l, isremoved, 0);
1119 Entries_Close (l);
1121 if (restore_cwd (&cwd))
1122 error (1, errno,
1123 "Failed to restore current directory, `%s'.",
1124 cwd.name);
1125 free_cwd (&cwd);
1127 if (files_removed != 0)
1129 /* There are files that have been removed, but not
1130 committed! Do not consider the directory empty. */
1131 (void) CVS_CLOSEDIR (dirp);
1132 return 0;
1136 errno = 0;
1138 if (errno != 0)
1140 error (0, errno, "cannot read directory %s", dir);
1141 (void) CVS_CLOSEDIR (dirp);
1142 return 0;
1144 (void) CVS_CLOSEDIR (dirp);
1145 return 1;
1151 * scratch the Entries file entry associated with a file
1153 static int
1154 scratch_file (struct file_info *finfo, Vers_TS *vers)
1156 history_write ('W', finfo->update_dir, "", finfo->file, finfo->repository);
1157 Scratch_Entry (finfo->entries, finfo->file);
1158 #ifdef SERVER_SUPPORT
1159 if (server_active)
1161 if (vers->ts_user == NULL)
1162 server_scratch_entry_only ();
1163 server_updated (finfo, vers, SERVER_UPDATED, (mode_t) -1, NULL, NULL);
1165 #endif
1166 if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1167 error (0, errno, "unable to remove %s", finfo->fullname);
1168 else if (!server_active)
1170 /* skip this step when the server is running since
1171 * server_updated should have handled it */
1172 /* keep the vers structure up to date in case we do a join
1173 * - if there isn't a file, it can't very well have a version number, can it?
1175 if (vers->vn_user != NULL)
1177 free (vers->vn_user);
1178 vers->vn_user = NULL;
1180 if (vers->ts_user != NULL)
1182 free (vers->ts_user);
1183 vers->ts_user = NULL;
1186 return 0;
1192 * Check out a file.
1194 static int
1195 checkout_file (struct file_info *finfo, Vers_TS *vers_ts, int adding,
1196 int merging, int update_server)
1198 char *backup;
1199 int set_time, retval = 0;
1200 int status;
1201 int file_is_dead;
1202 struct buffer *revbuf;
1204 backup = NULL;
1205 revbuf = NULL;
1207 /* Don't screw with backup files if we're going to stdout, or if
1208 we are the server. */
1209 if (!pipeout && !server_active)
1211 backup = Xasprintf ("%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
1212 if (isfile (finfo->file))
1213 rename_file (finfo->file, backup);
1214 else
1216 /* If -f/-t wrappers are being used to wrap up a directory,
1217 then backup might be a directory instead of just a file. */
1218 if (unlink_file_dir (backup) < 0)
1220 /* Not sure if the existence_error check is needed here. */
1221 if (!existence_error (errno))
1222 /* FIXME: should include update_dir in message. */
1223 error (0, errno, "error removing %s", backup);
1225 free (backup);
1226 backup = NULL;
1230 file_is_dead = RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs);
1232 if (!file_is_dead)
1235 * if we are checking out to stdout, print a nice message to
1236 * stderr, and add the -p flag to the command */
1237 if (pipeout)
1239 if (!quiet)
1241 cvs_outerr ("\
1242 ===================================================================\n\
1243 Checking out ", 0);
1244 cvs_outerr (finfo->fullname, 0);
1245 cvs_outerr ("\n\
1246 RCS: ", 0);
1247 cvs_outerr (vers_ts->srcfile->print_path, 0);
1248 cvs_outerr ("\n\
1249 VERS: ", 0);
1250 cvs_outerr (vers_ts->vn_rcs, 0);
1251 cvs_outerr ("\n***************\n", 0);
1255 #ifdef SERVER_SUPPORT
1256 if (update_server
1257 && server_active
1258 && ! pipeout
1259 && ! file_gzip_level
1260 && ! joining ()
1261 && ! wrap_name_has (finfo->file, WRAP_FROMCVS))
1263 revbuf = buf_nonio_initialize (NULL);
1264 status = RCS_checkout (vers_ts->srcfile, NULL,
1265 vers_ts->vn_rcs, vers_ts->tag,
1266 vers_ts->options, RUN_TTY,
1267 checkout_to_buffer, revbuf);
1269 else
1270 #endif
1271 status = RCS_checkout (vers_ts->srcfile,
1272 pipeout ? NULL : finfo->file,
1273 vers_ts->vn_rcs, vers_ts->tag,
1274 vers_ts->options, RUN_TTY, NULL, NULL);
1276 if (file_is_dead || status == 0)
1278 mode_t mode;
1280 mode = (mode_t) -1;
1282 if (!pipeout)
1284 Vers_TS *xvers_ts;
1286 if (revbuf != NULL && !noexec)
1288 struct stat sb;
1290 /* FIXME: We should have RCS_checkout return the mode.
1291 That would also fix the kludge with noexec, above, which
1292 is here only because noexec doesn't write srcfile->path
1293 for us to stat. */
1294 if (stat (vers_ts->srcfile->path, &sb) < 0)
1296 #if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
1297 buf_free (revbuf);
1298 #endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
1299 error (1, errno, "cannot stat %s",
1300 vers_ts->srcfile->path);
1302 mode = sb.st_mode &~ (S_IWRITE | S_IWGRP | S_IWOTH);
1305 if (cvswrite
1306 && !file_is_dead
1307 && !fileattr_get (finfo->file, "_watched"))
1309 if (revbuf == NULL)
1310 xchmod (finfo->file, 1);
1311 else
1313 mode_t oumask, writeaccess;
1315 /* We know that we are the server here, so
1316 although xchmod checks umask, we don't bother. */
1317 /* Not bothering with the umask makes the files
1318 mode 0777 on old clients, though. -chb */
1319 oumask = umask(0);
1320 (void) umask(oumask);
1321 writeaccess = (((mode & S_IRUSR) ? S_IWUSR : 0)
1322 | ((mode & S_IRGRP) ? S_IWGRP : 0)
1323 | ((mode & S_IROTH) ? S_IWOTH : 0));
1324 mode |= (~oumask) & writeaccess;
1329 /* A newly checked out file is never under the spell
1330 of "cvs edit". If we think we were editing it
1331 from a previous life, clean up. Would be better to
1332 check for same the working directory instead of
1333 same user, but that is hairy. */
1335 struct addremove_args args;
1337 editor_set (finfo->file, getcaller (), NULL);
1339 memset (&args, 0, sizeof args);
1340 args.remove_temp = 1;
1341 watch_modify_watchers (finfo->file, &args);
1344 /* set the time from the RCS file iff it was unknown before */
1345 set_time =
1346 (!noexec
1347 && (vers_ts->vn_user == NULL ||
1348 strncmp (vers_ts->ts_rcs, "Initial", 7) == 0)
1349 && !file_is_dead);
1351 wrap_fromcvs_process_file (finfo->file);
1353 xvers_ts = Version_TS (finfo, options, tag, date,
1354 force_tag_match, set_time);
1355 if (strcmp (xvers_ts->options, "-V4") == 0)
1356 xvers_ts->options[0] = '\0';
1358 if (revbuf != NULL)
1360 /* If we stored the file data into a buffer, then we
1361 didn't create a file at all, so xvers_ts->ts_user
1362 is wrong. The correct value is to have it be the
1363 same as xvers_ts->ts_rcs, meaning that the working
1364 file is unchanged from the RCS file.
1366 FIXME: We should tell Version_TS not to waste time
1367 statting the nonexistent file.
1369 FIXME: Actually, I don't think the ts_user value
1370 matters at all here. The only use I know of is
1371 that it is printed in a trace message by
1372 Server_Register. */
1374 if (xvers_ts->ts_user != NULL)
1375 free (xvers_ts->ts_user);
1376 xvers_ts->ts_user = xstrdup (xvers_ts->ts_rcs);
1379 (void) time (&last_register_time);
1381 if (file_is_dead)
1383 if (xvers_ts->vn_user != NULL)
1385 error (0, 0,
1386 "warning: %s is not (any longer) pertinent",
1387 finfo->fullname);
1389 Scratch_Entry (finfo->entries, finfo->file);
1390 #ifdef SERVER_SUPPORT
1391 if (server_active && xvers_ts->ts_user == NULL)
1392 server_scratch_entry_only ();
1393 #endif
1394 /* FIXME: Rather than always unlink'ing, and ignoring the
1395 existence_error, we should do the unlink only if
1396 vers_ts->ts_user is non-NULL. Then there would be no
1397 need to ignore an existence_error (for example, if the
1398 user removes the file while we are running). */
1399 if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1401 error (0, errno, "cannot remove %s", finfo->fullname);
1404 else
1405 Register (finfo->entries, finfo->file,
1406 adding ? "0" : xvers_ts->vn_rcs,
1407 xvers_ts->ts_user, xvers_ts->options,
1408 xvers_ts->tag, xvers_ts->date,
1409 NULL); /* Clear conflict flag on fresh checkout */
1411 /* fix up the vers structure, in case it is used by join */
1412 if (join_rev1)
1414 /* FIXME: Throwing away the original revision info is almost
1415 certainly wrong -- what if join_rev1 is "BASE"? */
1416 if (vers_ts->vn_user != NULL)
1417 free (vers_ts->vn_user);
1418 if (vers_ts->vn_rcs != NULL)
1419 free (vers_ts->vn_rcs);
1420 vers_ts->vn_user = xstrdup (xvers_ts->vn_rcs);
1421 vers_ts->vn_rcs = xstrdup (xvers_ts->vn_rcs);
1424 /* If this is really Update and not Checkout, recode history */
1425 if (strcmp (cvs_cmd_name, "update") == 0)
1426 history_write ('U', finfo->update_dir, xvers_ts->vn_rcs, finfo->file,
1427 finfo->repository);
1429 freevers_ts (&xvers_ts);
1431 if (!really_quiet && !file_is_dead)
1433 write_letter (finfo, 'U');
1437 #ifdef SERVER_SUPPORT
1438 if (update_server && server_active)
1439 server_updated (finfo, vers_ts,
1440 merging ? SERVER_MERGED : SERVER_UPDATED,
1441 mode, NULL, revbuf);
1442 #endif
1444 else
1446 if (backup != NULL)
1448 rename_file (backup, finfo->file);
1449 free (backup);
1450 backup = NULL;
1453 error (0, 0, "could not check out %s", finfo->fullname);
1455 retval = status;
1458 if (backup != NULL)
1460 /* If -f/-t wrappers are being used to wrap up a directory,
1461 then backup might be a directory instead of just a file. */
1462 if (unlink_file_dir (backup) < 0)
1464 /* Not sure if the existence_error check is needed here. */
1465 if (!existence_error (errno))
1466 /* FIXME: should include update_dir in message. */
1467 error (0, errno, "error removing %s", backup);
1469 free (backup);
1472 #if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
1473 if (revbuf != NULL)
1474 buf_free (revbuf);
1475 #endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
1476 return retval;
1481 #ifdef SERVER_SUPPORT
1483 /* This function is used to write data from a file being checked out
1484 into a buffer. */
1486 static void
1487 checkout_to_buffer (void *callerdat, const char *data, size_t len)
1489 struct buffer *buf = (struct buffer *) callerdat;
1491 buf_output (buf, data, len);
1494 #endif /* SERVER_SUPPORT */
1496 #ifdef SERVER_SUPPORT
1498 /* This structure is used to pass information between patch_file and
1499 patch_file_write. */
1501 struct patch_file_data
1503 /* File name, for error messages. */
1504 const char *filename;
1505 /* File to which to write. */
1506 FILE *fp;
1507 /* Whether to compute the MD5 checksum. */
1508 int compute_checksum;
1509 /* Data structure for computing the MD5 checksum. */
1510 struct md5_ctx context;
1511 /* Set if the file has a final newline. */
1512 int final_nl;
1515 /* Patch a file. Runs diff. This is only done when running as the
1516 * server. The hope is that the diff will be smaller than the file
1517 * itself.
1519 static int
1520 patch_file (struct file_info *finfo, Vers_TS *vers_ts, int *docheckout,
1521 struct stat *file_info, unsigned char *checksum)
1523 char *backup;
1524 char *file1;
1525 char *file2;
1526 int retval = 0;
1527 int retcode = 0;
1528 int fail;
1529 FILE *e;
1530 struct patch_file_data data;
1532 *docheckout = 0;
1534 if (noexec || pipeout || joining ())
1536 *docheckout = 1;
1537 return 0;
1540 /* If this file has been marked as being binary, then never send a
1541 patch. */
1542 if (strcmp (vers_ts->options, "-kb") == 0)
1544 *docheckout = 1;
1545 return 0;
1548 /* First check that the first revision exists. If it has been nuked
1549 by cvs admin -o, then just fall back to checking out entire
1550 revisions. In some sense maybe we don't have to do this; after
1551 all cvs.texinfo says "Make sure that no-one has checked out a
1552 copy of the revision you outdate" but then again, that advice
1553 doesn't really make complete sense, because "cvs admin" operates
1554 on a working directory and so _someone_ will almost always have
1555 _some_ revision checked out. */
1557 char *rev;
1559 rev = RCS_gettag (finfo->rcs, vers_ts->vn_user, 1, NULL);
1560 if (rev == NULL)
1562 *docheckout = 1;
1563 return 0;
1565 else
1566 free (rev);
1569 /* If the revision is dead, let checkout_file handle it rather
1570 than duplicating the processing here. */
1571 if (RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs))
1573 *docheckout = 1;
1574 return 0;
1577 backup = Xasprintf ("%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
1578 if (isfile (finfo->file))
1579 rename_file (finfo->file, backup);
1580 else
1582 if (unlink_file (backup) < 0
1583 && !existence_error (errno))
1584 error (0, errno, "cannot remove %s", backup);
1587 file1 = Xasprintf ("%s/%s%s-1", CVSADM, CVSPREFIX, finfo->file);
1588 file2 = Xasprintf ("%s/%s%s-2", CVSADM, CVSPREFIX, finfo->file);
1590 fail = 0;
1592 /* We need to check out both revisions first, to see if either one
1593 has a trailing newline. Because of this, we don't use rcsdiff,
1594 but just use diff. */
1596 e = CVS_FOPEN (file1, "w");
1597 if (e == NULL)
1598 error (1, errno, "cannot open %s", file1);
1600 data.filename = file1;
1601 data.fp = e;
1602 data.final_nl = 0;
1603 data.compute_checksum = 0;
1605 /* FIXME - Passing vers_ts->tag here is wrong in the least number
1606 * of cases. Since we don't know whether vn_user was checked out
1607 * using a tag, we pass vers_ts->tag, which, assuming the user did
1608 * not specify a new TAG to -r, will be the branch we are on.
1610 * The only thing it is used for is to substitute in for the Name
1611 * RCS keyword, so in the error case, the patch fails to apply on
1612 * the client end and we end up resending the whole file.
1614 * At least, if we are keeping track of the tag vn_user came from,
1615 * I don't know where yet. -DRP
1617 retcode = RCS_checkout (vers_ts->srcfile, NULL,
1618 vers_ts->vn_user, vers_ts->tag,
1619 vers_ts->options, RUN_TTY,
1620 patch_file_write, (void *) &data);
1622 if (fclose (e) < 0)
1623 error (1, errno, "cannot close %s", file1);
1625 if (retcode != 0 || ! data.final_nl)
1626 fail = 1;
1628 if (! fail)
1630 e = CVS_FOPEN (file2, "w");
1631 if (e == NULL)
1632 error (1, errno, "cannot open %s", file2);
1634 data.filename = file2;
1635 data.fp = e;
1636 data.final_nl = 0;
1637 data.compute_checksum = 1;
1638 md5_init_ctx (&data.context);
1640 retcode = RCS_checkout (vers_ts->srcfile, NULL,
1641 vers_ts->vn_rcs, vers_ts->tag,
1642 vers_ts->options, RUN_TTY,
1643 patch_file_write, (void *) &data);
1645 if (fclose (e) < 0)
1646 error (1, errno, "cannot close %s", file2);
1648 if (retcode != 0 || ! data.final_nl)
1649 fail = 1;
1650 else
1651 md5_finish_ctx (&data.context, checksum);
1654 retcode = 0;
1655 if (! fail)
1657 int dargc = 0;
1658 size_t darg_allocated = 0;
1659 char **dargv = NULL;
1661 /* If the client does not support the Rcs-diff command, we
1662 send a context diff, and the client must invoke patch.
1663 That approach was problematical for various reasons. The
1664 new approach only requires running diff in the server; the
1665 client can handle everything without invoking an external
1666 program. */
1667 if (!rcs_diff_patches)
1668 /* We use -c, not -u, because that is what CVS has
1669 traditionally used. Kind of a moot point, now that
1670 Rcs-diff is preferred, so there is no point in making
1671 the compatibility issues worse. */
1672 run_add_arg_p (&dargc, &darg_allocated, &dargv, "-c");
1673 else
1674 /* Now that diff is librarified, we could be passing -a if
1675 we wanted to. However, it is unclear to me whether we
1676 would want to. Does diff -a, in any significant
1677 percentage of cases, produce patches which are smaller
1678 than the files it is patching? I guess maybe text
1679 files with character sets which diff regards as
1680 'binary'. Conversely, do they tend to be much larger
1681 in the bad cases? This needs some more
1682 thought/investigation, I suspect. */
1683 run_add_arg_p (&dargc, &darg_allocated, &dargv, "-n");
1684 retcode = diff_exec (file1, file2, NULL, NULL, dargc, dargv,
1685 finfo->file);
1686 run_arg_free_p (dargc, dargv);
1687 free (dargv);
1689 /* A retcode of 0 means no differences. 1 means some differences. */
1690 if (retcode != 0 && retcode != 1)
1691 fail = 1;
1694 if (!fail)
1696 struct stat file2_info;
1698 /* Check to make sure the patch is really shorter */
1699 if (stat (file2, &file2_info) < 0)
1700 error (1, errno, "could not stat %s", file2);
1701 if (stat (finfo->file, file_info) < 0)
1702 error (1, errno, "could not stat %s", finfo->file);
1703 if (file2_info.st_size <= file_info->st_size)
1704 fail = 1;
1707 if (! fail)
1709 # define BINARY "Binary"
1710 char buf[sizeof BINARY];
1711 unsigned int c;
1713 /* Check the diff output to make sure patch will be handle it. */
1714 e = CVS_FOPEN (finfo->file, "r");
1715 if (e == NULL)
1716 error (1, errno, "could not open diff output file %s",
1717 finfo->fullname);
1718 c = fread (buf, 1, sizeof BINARY - 1, e);
1719 buf[c] = '\0';
1720 if (strcmp (buf, BINARY) == 0)
1722 /* These are binary files. We could use diff -a, but
1723 patch can't handle that. */
1724 fail = 1;
1726 fclose (e);
1729 if (! fail)
1731 Vers_TS *xvers_ts;
1733 /* Stat the original RCS file, and then adjust it the way
1734 that RCS_checkout would. FIXME: This is an abstraction
1735 violation. */
1736 if (stat (vers_ts->srcfile->path, file_info) < 0)
1737 error (1, errno, "could not stat %s", vers_ts->srcfile->path);
1738 if (chmod (finfo->file,
1739 file_info->st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH))
1740 < 0)
1741 error (0, errno, "cannot change mode of file %s", finfo->file);
1742 if (cvswrite
1743 && !fileattr_get (finfo->file, "_watched"))
1744 xchmod (finfo->file, 1);
1746 /* This stuff is just copied blindly from checkout_file. I
1747 don't really know what it does. */
1748 xvers_ts = Version_TS (finfo, options, tag, date,
1749 force_tag_match, 0);
1750 if (strcmp (xvers_ts->options, "-V4") == 0)
1751 xvers_ts->options[0] = '\0';
1753 Register (finfo->entries, finfo->file, xvers_ts->vn_rcs,
1754 xvers_ts->ts_user, xvers_ts->options,
1755 xvers_ts->tag, xvers_ts->date, NULL);
1757 if (stat (finfo->file, file_info) < 0)
1758 error (1, errno, "could not stat %s", finfo->file);
1760 /* If this is really Update and not Checkout, record history. */
1761 if (strcmp (cvs_cmd_name, "update") == 0)
1762 history_write ('P', finfo->update_dir, xvers_ts->vn_rcs,
1763 finfo->file, finfo->repository);
1765 freevers_ts (&xvers_ts);
1767 if (!really_quiet)
1769 write_letter (finfo, 'P');
1772 else
1774 int old_errno = errno; /* save errno value over the rename */
1776 if (isfile (backup))
1777 rename_file (backup, finfo->file);
1779 if (retcode != 0 && retcode != 1)
1780 error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0,
1781 "could not diff %s", finfo->fullname);
1783 *docheckout = 1;
1784 retval = retcode;
1787 if (unlink_file (backup) < 0
1788 && !existence_error (errno))
1789 error (0, errno, "cannot remove %s", backup);
1790 if (unlink_file (file1) < 0
1791 && !existence_error (errno))
1792 error (0, errno, "cannot remove %s", file1);
1793 if (unlink_file (file2) < 0
1794 && !existence_error (errno))
1795 error (0, errno, "cannot remove %s", file2);
1797 free (backup);
1798 free (file1);
1799 free (file2);
1800 return retval;
1805 /* Write data to a file. Record whether the last byte written was a
1806 newline. Optionally compute a checksum. This is called by
1807 patch_file via RCS_checkout. */
1809 static void
1810 patch_file_write (void *callerdat, const char *buffer, size_t len)
1812 struct patch_file_data *data = (struct patch_file_data *) callerdat;
1814 if (fwrite (buffer, 1, len, data->fp) != len)
1815 error (1, errno, "cannot write %s", data->filename);
1817 data->final_nl = (buffer[len - 1] == '\n');
1819 if (data->compute_checksum)
1820 md5_process_bytes (buffer, len, &data->context);
1823 #endif /* SERVER_SUPPORT */
1826 * Several of the types we process only print a bit of information consisting
1827 * of a single letter and the name.
1829 void
1830 write_letter (struct file_info *finfo, int letter)
1832 if (!really_quiet)
1834 char *tag = NULL;
1835 /* Big enough for "+updated" or any of its ilk. */
1836 char buf[80];
1838 switch (letter)
1840 case 'U':
1841 tag = "updated";
1842 break;
1843 default:
1844 /* We don't yet support tagged output except for "U". */
1845 break;
1848 if (tag != NULL)
1850 sprintf (buf, "+%s", tag);
1851 cvs_output_tagged (buf, NULL);
1853 buf[0] = letter;
1854 buf[1] = ' ';
1855 buf[2] = '\0';
1856 cvs_output_tagged ("text", buf);
1857 cvs_output_tagged ("fname", finfo->fullname);
1858 cvs_output_tagged ("newline", NULL);
1859 if (tag != NULL)
1861 sprintf (buf, "-%s", tag);
1862 cvs_output_tagged (buf, NULL);
1865 return;
1870 /* Reregister a file after a merge. */
1871 static void
1872 RegisterMerge (struct file_info *finfo, Vers_TS *vers,
1873 const char *backup, int has_conflicts)
1875 /* This file is the result of a merge, which means that it has
1876 been modified. We use a special timestamp string which will
1877 not compare equal to any actual timestamp. */
1878 char *cp = NULL;
1880 if (has_conflicts)
1882 time (&last_register_time);
1883 cp = time_stamp (finfo->file);
1885 Register (finfo->entries, finfo->file, vers->vn_rcs ? vers->vn_rcs : "0",
1886 "Result of merge", vers->options, vers->tag, vers->date, cp);
1887 if (cp)
1888 free (cp);
1890 #ifdef SERVER_SUPPORT
1891 /* Send the new contents of the file before the message. If we
1892 wanted to be totally correct, we would have the client write
1893 the message only after the file has safely been written. */
1894 if (server_active)
1896 server_copy_file (finfo->file, finfo->update_dir, finfo->repository,
1897 backup);
1898 server_updated (finfo, vers, SERVER_MERGED, (mode_t) -1, NULL, NULL);
1900 #endif
1906 * Do all the magic associated with a file which needs to be merged
1908 static int
1909 merge_file (struct file_info *finfo, Vers_TS *vers)
1911 char *backup;
1912 int status;
1913 int retval;
1915 assert (vers->vn_user);
1918 * The users currently modified file is moved to a backup file name
1919 * ".#filename.version", so that it will stay around for a few days
1920 * before being automatically removed by some cron daemon. The "version"
1921 * is the version of the file that the user was most up-to-date with
1922 * before the merge.
1924 backup = Xasprintf ("%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
1926 if (unlink_file (backup) && !existence_error (errno))
1927 error (0, errno, "unable to remove %s", backup);
1928 copy_file (finfo->file, backup);
1929 xchmod (finfo->file, 1);
1931 if (strcmp (vers->options, "-kb") == 0
1932 || wrap_merge_is_copy (finfo->file)
1933 || special_file_mismatch (finfo, NULL, vers->vn_rcs))
1935 /* For binary files, a merge is always a conflict. Same for
1936 files whose permissions or linkage do not match. We give the
1937 user the two files, and let them resolve it. It is possible
1938 that we should require a "touch foo" or similar step before
1939 we allow a checkin. */
1941 /* TODO: it may not always be necessary to regard a permission
1942 mismatch as a conflict. The working file and the RCS file
1943 have a common ancestor `A'; if the working file's permissions
1944 match A's, then it's probably safe to overwrite them with the
1945 RCS permissions. Only if the working file, the RCS file, and
1946 A all disagree should this be considered a conflict. But more
1947 thought needs to go into this, and in the meantime it is safe
1948 to treat any such mismatch as an automatic conflict. -twp */
1950 status = RCS_checkout (finfo->rcs, finfo->file, vers->vn_rcs,
1951 vers->tag, vers->options, NULL, NULL, NULL);
1952 if (status)
1954 error (0, 0, "failed to check out `%s' file", finfo->fullname);
1955 error (0, 0, "restoring `%s' from backup file `%s'",
1956 finfo->fullname, backup);
1957 rename_file (backup, finfo->file);
1958 retval = 1;
1959 goto out;
1962 xchmod (finfo->file, 1);
1964 RegisterMerge (finfo, vers, backup, 1);
1966 /* Is there a better term than "nonmergeable file"? What we
1967 really mean is, not something that CVS cannot or does not
1968 want to merge (there might be an external manual or
1969 automatic merge process). */
1970 error (0, 0, "nonmergeable file needs merge");
1971 error (0, 0, "revision %s from repository is now in %s",
1972 vers->vn_rcs, finfo->fullname);
1973 error (0, 0, "file from working directory is now in %s", backup);
1974 write_letter (finfo, 'C');
1976 history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file,
1977 finfo->repository);
1978 retval = 0;
1979 goto out;
1982 status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
1983 vers->options, vers->vn_user, vers->vn_rcs);
1984 if (status != 0 && status != 1)
1986 error (0, status == -1 ? errno : 0,
1987 "could not merge revision %s of %s", vers->vn_user, finfo->fullname);
1988 error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
1989 finfo->fullname, backup);
1990 rename_file (backup, finfo->file);
1991 retval = 1;
1992 goto out;
1995 if (strcmp (vers->options, "-V4") == 0)
1996 vers->options[0] = '\0';
1998 /* fix up the vers structure, in case it is used by join */
1999 if (join_rev1)
2001 /* FIXME: Throwing away the original revision info is almost
2002 certainly wrong -- what if join_rev1 is "BASE"? */
2003 if (vers->vn_user != NULL)
2004 free (vers->vn_user);
2005 vers->vn_user = xstrdup (vers->vn_rcs);
2008 RegisterMerge (finfo, vers, backup, status);
2010 if (status == 1)
2012 error (0, 0, "conflicts found in %s", finfo->fullname);
2014 write_letter (finfo, 'C');
2016 history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file,
2017 finfo->repository);
2020 else /* status == 0 */
2022 history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file,
2023 finfo->repository);
2025 /* FIXME: the noexec case is broken. RCS_merge could be doing the
2026 xcmp on the temporary files without much hassle, I think. */
2027 if (!noexec && !xcmp (backup, finfo->file))
2029 cvs_output (finfo->fullname, 0);
2030 cvs_output (" already contains the differences between ", 0);
2031 cvs_output (vers->vn_user, 0);
2032 cvs_output (" and ", 0);
2033 cvs_output (vers->vn_rcs, 0);
2034 cvs_output ("\n", 1);
2036 retval = 0;
2037 goto out;
2040 write_letter (finfo, 'M');
2042 retval = 0;
2043 out:
2044 free (backup);
2045 return retval;
2051 * Do all the magic associated with a file which needs to be joined
2052 * (reached via the -j option to checkout or update).
2054 * INPUTS
2055 * finfo File information about the destination file.
2056 * vers The Vers_TS structure for finfo.
2058 * GLOBALS
2059 * join_rev1 From the command line.
2060 * join_rev2 From the command line.
2061 * server_active Natch.
2063 * ASSUMPTIONS
2064 * 1. Is not called in client mode.
2066 static void
2067 join_file (struct file_info *finfo, Vers_TS *vers)
2069 char *backup;
2070 char *t_options;
2071 int status;
2073 char *rev1;
2074 char *rev2;
2075 char *jrev1;
2076 char *jrev2;
2077 char *jdate1;
2078 char *jdate2;
2080 TRACE (TRACE_FUNCTION, "join_file(%s, %s%s%s%s, %s, %s)",
2081 finfo->file,
2082 vers->tag ? vers->tag : "",
2083 vers->tag ? " (" : "",
2084 vers->vn_rcs ? vers->vn_rcs : "",
2085 vers->tag ? ")" : "",
2086 join_rev1 ? join_rev1 : "",
2087 join_rev2 ? join_rev2 : "");
2089 jrev1 = join_rev1;
2090 jrev2 = join_rev2;
2091 jdate1 = join_date1;
2092 jdate2 = join_date2;
2094 /* Determine if we need to do anything at all. */
2095 if (vers->srcfile == NULL ||
2096 vers->srcfile->path == NULL)
2098 return;
2101 /* If only one join revision is specified, it becomes the second
2102 revision. */
2103 if (jrev2 == NULL)
2105 jrev2 = jrev1;
2106 jrev1 = NULL;
2107 jdate2 = jdate1;
2108 jdate1 = NULL;
2111 /* FIXME: Need to handle "BASE" for jrev1 and/or jrev2. Note caveat
2112 below about vn_user. */
2114 /* Convert the second revision, walking branches and dates. */
2115 rev2 = RCS_getversion (vers->srcfile, jrev2, jdate2, 1, NULL);
2117 /* If this is a merge of two revisions, get the first revision.
2118 If only one join tag was specified, then the first revision is
2119 the greatest common ancestor of the second revision and the
2120 working file. */
2121 if (jrev1 != NULL)
2122 rev1 = RCS_getversion (vers->srcfile, jrev1, jdate1, 1, NULL);
2123 else
2125 /* Note that we use vn_rcs here, since vn_user may contain a
2126 special string such as "-nn". */
2127 if (vers->vn_rcs == NULL)
2128 rev1 = NULL;
2129 else if (rev2 == NULL)
2131 /* This means that the file never existed on the branch.
2132 It does not mean that the file was removed on the
2133 branch: that case is represented by a dead rev2. If
2134 the file never existed on the branch, then we have
2135 nothing to merge, so we just return. */
2136 return;
2138 else
2139 rev1 = gca (vers->vn_rcs, rev2);
2142 /* Handle a nonexistent or dead merge target. */
2143 if (rev2 == NULL || RCS_isdead (vers->srcfile, rev2))
2145 char *mrev;
2147 if (rev2 != NULL)
2148 free (rev2);
2150 /* If the first revision doesn't exist either, then there is
2151 no change between the two revisions, so we don't do
2152 anything. */
2153 if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
2155 if (rev1 != NULL)
2156 free (rev1);
2157 return;
2160 /* If we are merging two revisions, then the file was removed
2161 between the first revision and the second one. In this
2162 case we want to mark the file for removal.
2164 If we are merging one revision, then the file has been
2165 removed between the greatest common ancestor and the merge
2166 revision. From the perspective of the branch on to which
2167 we ar emerging, which may be the trunk, either 1) the file
2168 does not currently exist on the target, or 2) the file has
2169 not been modified on the target branch since the greatest
2170 common ancestor, or 3) the file has been modified on the
2171 target branch since the greatest common ancestor. In case
2172 1 there is nothing to do. In case 2 we mark the file for
2173 removal. In case 3 we have a conflict.
2175 Note that the handling is slightly different depending upon
2176 whether one or two join targets were specified. If two
2177 join targets were specified, we don't check whether the
2178 file was modified since a given point. My reasoning is
2179 that if you ask for an explicit merge between two tags,
2180 then you want to merge in whatever was changed between
2181 those two tags. If a file was removed between the two
2182 tags, then you want it to be removed. However, if you ask
2183 for a merge of a branch, then you want to merge in all
2184 changes which were made on the branch. If a file was
2185 removed on the branch, that is a change to the file. If
2186 the file was also changed on the main line, then that is
2187 also a change. These two changes--the file removal and the
2188 modification--must be merged. This is a conflict. */
2190 /* If the user file is dead, or does not exist, or has been
2191 marked for removal, then there is nothing to do. */
2192 if (vers->vn_user == NULL
2193 || vers->vn_user[0] == '-'
2194 || RCS_isdead (vers->srcfile, vers->vn_user))
2196 if (rev1 != NULL)
2197 free (rev1);
2198 return;
2201 /* If the user file has been marked for addition, or has been
2202 locally modified, then we have a conflict which we can not
2203 resolve. No_Difference will already have been called in
2204 this case, so comparing the timestamps is sufficient to
2205 determine whether the file is locally modified. */
2206 if (strcmp (vers->vn_user, "0") == 0
2207 || (vers->ts_user != NULL
2208 && strcmp (vers->ts_user, vers->ts_rcs) != 0))
2210 if (jdate2 != NULL)
2211 error (0, 0,
2212 "file %s is locally modified, but has been removed in revision %s as of %s",
2213 finfo->fullname, jrev2, jdate2);
2214 else
2215 error (0, 0,
2216 "file %s is locally modified, but has been removed in revision %s",
2217 finfo->fullname, jrev2);
2219 /* FIXME: Should we arrange to return a non-zero exit
2220 status? */
2222 if (rev1 != NULL)
2223 free (rev1);
2225 return;
2228 /* If only one join tag was specified, and the user file has
2229 been changed since the greatest common ancestor (rev1),
2230 then there is a conflict we can not resolve. See above for
2231 the rationale. */
2232 if (join_rev2 == NULL
2233 && strcmp (rev1, vers->vn_user) != 0)
2235 if (jdate2 != NULL)
2236 error (0, 0,
2237 "file %s has been modified, but has been removed in revision %s as of %s",
2238 finfo->fullname, jrev2, jdate2);
2239 else
2240 error (0, 0,
2241 "file %s has been modified, but has been removed in revision %s",
2242 finfo->fullname, jrev2);
2244 /* FIXME: Should we arrange to return a non-zero exit
2245 status? */
2247 if (rev1 != NULL)
2248 free (rev1);
2250 return;
2253 if (rev1 != NULL)
2254 free (rev1);
2256 /* The user file exists and has not been modified. Mark it
2257 for removal. FIXME: If we are doing a checkout, this has
2258 the effect of first checking out the file, and then
2259 removing it. It would be better to just register the
2260 removal.
2262 The same goes for a removal then an add. e.g.
2263 cvs up -rbr -jbr2 could remove and readd the same file
2265 /* save the rev since server_updated might invalidate it */
2266 mrev = Xasprintf ("-%s", vers->vn_user);
2267 #ifdef SERVER_SUPPORT
2268 if (server_active)
2270 server_scratch (finfo->file);
2271 server_updated (finfo, vers, SERVER_UPDATED, (mode_t) -1,
2272 NULL, NULL);
2274 #endif
2275 Register (finfo->entries, finfo->file, mrev, vers->ts_rcs,
2276 vers->options, vers->tag, vers->date, vers->ts_conflict);
2277 free (mrev);
2278 /* We need to check existence_error here because if we are
2279 running as the server, and the file is up to date in the
2280 working directory, the client will not have sent us a copy. */
2281 if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
2282 error (0, errno, "cannot remove file %s", finfo->fullname);
2283 #ifdef SERVER_SUPPORT
2284 if (server_active)
2285 server_checked_in (finfo->file, finfo->update_dir,
2286 finfo->repository);
2287 #endif
2288 if (! really_quiet)
2289 error (0, 0, "scheduling `%s' for removal", finfo->fullname);
2291 return;
2294 /* If the two merge revisions are the same, then there is nothing
2295 * to do. This needs to be checked before the rev2 == up-to-date base
2296 * revision check tha comes next. Otherwise, rev1 can == rev2 and get an
2297 * "already contains the changes between <rev1> and <rev1>" message.
2299 if (rev1 && strcmp (rev1, rev2) == 0)
2301 free (rev1);
2302 free (rev2);
2303 return;
2306 /* If we know that the user file is up-to-date, then it becomes an
2307 * optimization to skip the merge when rev2 is the same as the base
2308 * revision. i.e. we know that diff3(file2,file1,file2) will produce
2309 * file2.
2311 if (vers->vn_user != NULL && vers->ts_user != NULL
2312 && strcmp (vers->ts_user, vers->ts_rcs) == 0
2313 && strcmp (rev2, vers->vn_user) == 0)
2315 if (!really_quiet)
2317 cvs_output (finfo->fullname, 0);
2318 cvs_output (" already contains the differences between ", 0);
2319 cvs_output (rev1 ? rev1 : "creation", 0);
2320 cvs_output (" and ", 0);
2321 cvs_output (rev2, 0);
2322 cvs_output ("\n", 1);
2325 if (rev1 != NULL)
2326 free (rev1);
2327 free (rev2);
2329 return;
2332 /* If rev1 is dead or does not exist, then the file was added
2333 between rev1 and rev2. */
2334 if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
2336 if (rev1 != NULL)
2337 free (rev1);
2338 free (rev2);
2340 /* If the file does not exist in the working directory, then
2341 we can just check out the new revision and mark it for
2342 addition. */
2343 if (vers->vn_user == NULL)
2345 char *saved_options = options;
2346 Vers_TS *xvers;
2348 xvers = Version_TS (finfo, vers->options, jrev2, jdate2, 1, 0);
2350 /* Reset any keyword expansion option. Otherwise, when a
2351 command like `cvs update -kk -jT1 -jT2' creates a new file
2352 (because a file had the T2 tag, but not T1), the subsequent
2353 commit of that just-added file effectively would set the
2354 admin `-kk' option for that file in the repository. */
2355 options = NULL;
2357 /* FIXME: If checkout_file fails, we should arrange to
2358 return a non-zero exit status. */
2359 status = checkout_file (finfo, xvers, 1, 0, 1);
2360 options = saved_options;
2362 freevers_ts (&xvers);
2364 return;
2367 /* The file currently exists in the working directory, so we
2368 have a conflict which we can not resolve. Note that this
2369 is true even if the file is marked for addition or removal. */
2371 if (jdate2 != NULL)
2372 error (0, 0,
2373 "file %s exists, but has been added in revision %s as of %s",
2374 finfo->fullname, jrev2, jdate2);
2375 else
2376 error (0, 0,
2377 "file %s exists, but has been added in revision %s",
2378 finfo->fullname, jrev2);
2380 return;
2383 /* If there is no working file, then we can't do the merge. */
2384 if (vers->vn_user == NULL || vers->vn_user[0] == '-')
2386 free (rev1);
2387 free (rev2);
2389 if (jdate2 != NULL)
2390 error (0, 0,
2391 "file %s does not exist, but is present in revision %s as of %s",
2392 finfo->fullname, jrev2, jdate2);
2393 else
2394 error (0, 0,
2395 "file %s does not exist, but is present in revision %s",
2396 finfo->fullname, jrev2);
2398 /* FIXME: Should we arrange to return a non-zero exit status? */
2400 return;
2403 #ifdef SERVER_SUPPORT
2404 if (server_active && !isreadable (finfo->file))
2406 int retcode;
2407 /* The file is up to date. Need to check out the current contents. */
2408 /* FIXME - see the FIXME comment above the call to RCS_checkout in the
2409 * patch_file function.
2411 retcode = RCS_checkout (vers->srcfile, finfo->file,
2412 vers->vn_user, vers->tag,
2413 NULL, RUN_TTY, NULL, NULL);
2414 if (retcode != 0)
2415 error (1, 0,
2416 "failed to check out %s file", finfo->fullname);
2418 #endif
2421 * The users currently modified file is moved to a backup file name
2422 * ".#filename.version", so that it will stay around for a few days
2423 * before being automatically removed by some cron daemon. The "version"
2424 * is the version of the file that the user was most up-to-date with
2425 * before the merge.
2427 backup = Xasprintf ("%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
2429 if (unlink_file (backup) < 0
2430 && !existence_error (errno))
2431 error (0, errno, "cannot remove %s", backup);
2432 copy_file (finfo->file, backup);
2433 xchmod (finfo->file, 1);
2435 t_options = vers->options;
2436 #if 0
2437 if (*t_options == '\0')
2438 t_options = "-kk"; /* to ignore keyword expansions */
2439 #endif
2441 /* If the source of the merge is the same as the working file
2442 revision, then we can just RCS_checkout the target (no merging
2443 as such). In the text file case, this is probably quite
2444 similar to the RCS_merge, but in the binary file case,
2445 RCS_merge gives all kinds of trouble. */
2446 if (vers->vn_user != NULL
2447 && strcmp (rev1, vers->vn_user) == 0
2448 /* See comments above about how No_Difference has already been
2449 called. */
2450 && vers->ts_user != NULL
2451 && strcmp (vers->ts_user, vers->ts_rcs) == 0
2453 /* Avoid this in the text file case. See below for why.
2455 && (strcmp (t_options, "-kb") == 0
2456 || wrap_merge_is_copy (finfo->file)))
2458 /* FIXME: Verify my comment below:
2460 * RCS_merge does nothing with keywords. It merges the changes between
2461 * two revisions without expanding the keywords (it might expand in
2462 * -kk mode before computing the diff between rev1 and rev2 - I'm not
2463 * sure). In other words, the keyword lines in the current work file
2464 * get left alone.
2466 * Therfore, checking out the destination revision (rev2) is probably
2467 * incorrect in the text case since we should see the keywords that were
2468 * substituted into the original file at the time it was checked out
2469 * and not the keywords from rev2.
2471 * Also, it is safe to pass in NULL for nametag since we know no
2472 * substitution is happening during the binary mode checkout.
2474 if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, t_options,
2475 RUN_TTY, NULL, NULL) != 0)
2476 status = 2;
2477 else
2478 status = 0;
2480 /* OK, this is really stupid. RCS_checkout carefully removes
2481 write permissions, and we carefully put them back. But
2482 until someone gets around to fixing it, that seems like the
2483 easiest way to get what would seem to be the right mode.
2484 I don't check CVSWRITE or _watched; I haven't thought about
2485 that in great detail, but it seems like a watched file should
2486 be checked out (writable) after a merge. */
2487 xchmod (finfo->file, 1);
2489 /* Traditionally, the text file case prints a whole bunch of
2490 scary looking and verbose output which fails to tell the user
2491 what is really going on (it gives them rev1 and rev2 but doesn't
2492 indicate in any way that rev1 == vn_user). I think just a
2493 simple "U foo" is good here; it seems analogous to the case in
2494 which the file was added on the branch in terms of what to
2495 print. */
2496 write_letter (finfo, 'U');
2498 else if (strcmp (t_options, "-kb") == 0
2499 || wrap_merge_is_copy (finfo->file)
2500 || special_file_mismatch (finfo, rev1, rev2))
2502 /* We are dealing with binary files, or files with a
2503 permission/linkage mismatch (this second case only occurs when
2504 PRESERVE_PERMISSIONS_SUPPORT is enabled), and real merging would
2505 need to take place. This is a conflict. We give the user
2506 the two files, and let them resolve it. It is possible
2507 that we should require a "touch foo" or similar step before
2508 we allow a checkin. */
2509 if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL,
2510 t_options, RUN_TTY, NULL, NULL) != 0)
2511 status = 2;
2512 else
2513 status = 0;
2515 /* OK, this is really stupid. RCS_checkout carefully removes
2516 write permissions, and we carefully put them back. But
2517 until someone gets around to fixing it, that seems like the
2518 easiest way to get what would seem to be the right mode.
2519 I don't check CVSWRITE or _watched; I haven't thought about
2520 that in great detail, but it seems like a watched file should
2521 be checked out (writable) after a merge. */
2522 xchmod (finfo->file, 1);
2524 /* Hmm. We don't give them REV1 anywhere. I guess most people
2525 probably don't have a 3-way merge tool for the file type in
2526 question, and might just get confused if we tried to either
2527 provide them with a copy of the file from REV1, or even just
2528 told them what REV1 is so they can get it themself, but it
2529 might be worth thinking about. */
2530 /* See comment in merge_file about the "nonmergeable file"
2531 terminology. */
2532 error (0, 0, "nonmergeable file needs merge");
2533 error (0, 0, "revision %s from repository is now in %s",
2534 rev2, finfo->fullname);
2535 error (0, 0, "file from working directory is now in %s", backup);
2536 write_letter (finfo, 'C');
2538 else
2539 status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
2540 t_options, rev1, rev2);
2542 if (status != 0)
2544 if (status != 1)
2546 error (0, status == -1 ? errno : 0,
2547 "could not merge revision %s of %s", rev2, finfo->fullname);
2548 error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
2549 finfo->fullname, backup);
2550 rename_file (backup, finfo->file);
2553 else /* status == 0 */
2555 /* FIXME: the noexec case is broken. RCS_merge could be doing the
2556 xcmp on the temporary files without much hassle, I think. */
2557 if (!noexec && !xcmp (backup, finfo->file))
2559 if (!really_quiet)
2561 cvs_output (finfo->fullname, 0);
2562 cvs_output (" already contains the differences between ", 0);
2563 cvs_output (rev1, 0);
2564 cvs_output (" and ", 0);
2565 cvs_output (rev2, 0);
2566 cvs_output ("\n", 1);
2569 /* and skip the registering and sending the new file since it
2570 * hasn't been updated.
2572 goto out;
2576 /* The file has changed, but if we just checked it out it may
2577 still have the same timestamp it did when it was first
2578 registered above in checkout_file. We register it again with a
2579 dummy timestamp to make sure that later runs of CVS will
2580 recognize that it has changed.
2582 We don't actually need to register again if we called
2583 RCS_checkout above, and we aren't running as the server.
2584 However, that is not the normal case, and calling Register
2585 again won't cost much in that case. */
2586 RegisterMerge (finfo, vers, backup, status);
2588 out:
2589 free (rev1);
2590 free (rev2);
2591 free (backup);
2597 * Report whether revisions REV1 and REV2 of FINFO agree on:
2598 * . file ownership
2599 * . permissions
2600 * . major and minor device numbers
2601 * . symbolic links
2602 * . hard links
2604 * If either REV1 or REV2 is NULL, the working copy is used instead.
2606 * Return 1 if the files differ on these data.
2610 special_file_mismatch (struct file_info *finfo, char *rev1, char *rev2)
2612 #ifdef PRESERVE_PERMISSIONS_SUPPORT
2613 struct stat sb;
2614 RCSVers *vp;
2615 Node *n;
2616 uid_t rev1_uid, rev2_uid;
2617 gid_t rev1_gid, rev2_gid;
2618 mode_t rev1_mode, rev2_mode;
2619 unsigned long dev_long;
2620 dev_t rev1_dev, rev2_dev;
2621 char *rev1_symlink = NULL;
2622 char *rev2_symlink = NULL;
2623 List *rev1_hardlinks = NULL;
2624 List *rev2_hardlinks = NULL;
2625 int check_uids, check_gids, check_modes;
2626 int result;
2628 /* If we don't care about special file info, then
2629 don't report a mismatch in any case. */
2630 if (!preserve_perms)
2631 return 0;
2633 /* When special_file_mismatch is called from No_Difference, the
2634 RCS file has been only partially parsed. We must read the
2635 delta tree in order to compare special file info recorded in
2636 the delta nodes. (I think this is safe. -twp) */
2637 if (finfo->rcs->flags & PARTIAL)
2638 RCS_reparsercsfile (finfo->rcs, NULL, NULL);
2640 check_uids = check_gids = check_modes = 1;
2642 /* Obtain file information for REV1. If this is null, then stat
2643 finfo->file and use that info. */
2644 /* If a revision does not know anything about its status,
2645 then presumably it doesn't matter, and indicates no conflict. */
2647 if (rev1 == NULL)
2649 ssize_t rsize;
2651 if ((rsize = islink (finfo->file)) > 0)
2652 rev1_symlink = Xreadlink (finfo->file, rsize);
2653 else
2655 # ifdef HAVE_STRUCT_STAT_ST_RDEV
2656 if (lstat (finfo->file, &sb) < 0)
2657 error (1, errno, "could not get file information for %s",
2658 finfo->file);
2659 rev1_uid = sb.st_uid;
2660 rev1_gid = sb.st_gid;
2661 rev1_mode = sb.st_mode;
2662 if (S_ISBLK (rev1_mode) || S_ISCHR (rev1_mode))
2663 rev1_dev = sb.st_rdev;
2664 # else
2665 error (1, 0, "cannot handle device files on this system (%s)",
2666 finfo->file);
2667 # endif
2669 rev1_hardlinks = list_linked_files_on_disk (finfo->file);
2671 else
2673 n = findnode (finfo->rcs->versions, rev1);
2674 vp = n->data;
2676 n = findnode (vp->other_delta, "symlink");
2677 if (n != NULL)
2678 rev1_symlink = xstrdup (n->data);
2679 else
2681 n = findnode (vp->other_delta, "owner");
2682 if (n == NULL)
2683 check_uids = 0; /* don't care */
2684 else
2685 rev1_uid = strtoul (n->data, NULL, 10);
2687 n = findnode (vp->other_delta, "group");
2688 if (n == NULL)
2689 check_gids = 0; /* don't care */
2690 else
2691 rev1_gid = strtoul (n->data, NULL, 10);
2693 n = findnode (vp->other_delta, "permissions");
2694 if (n == NULL)
2695 check_modes = 0; /* don't care */
2696 else
2697 rev1_mode = strtoul (n->data, NULL, 8);
2699 n = findnode (vp->other_delta, "special");
2700 if (n == NULL)
2701 rev1_mode |= S_IFREG;
2702 else
2704 /* If the size of `ftype' changes, fix the sscanf call also */
2705 char ftype[16];
2706 if (sscanf (n->data, "%15s %lu", ftype,
2707 &dev_long) < 2)
2708 error (1, 0, "%s:%s has bad `special' newphrase %s",
2709 finfo->file, rev1, (char *)n->data);
2710 rev1_dev = dev_long;
2711 if (strcmp (ftype, "character") == 0)
2712 rev1_mode |= S_IFCHR;
2713 else if (strcmp (ftype, "block") == 0)
2714 rev1_mode |= S_IFBLK;
2715 else
2716 error (0, 0, "%s:%s unknown file type `%s'",
2717 finfo->file, rev1, ftype);
2720 rev1_hardlinks = vp->hardlinks;
2721 if (rev1_hardlinks == NULL)
2722 rev1_hardlinks = getlist();
2726 /* Obtain file information for REV2. */
2727 if (rev2 == NULL)
2729 ssize_t rsize;
2731 if ((rsize = islink (finfo->file)) > 0)
2732 rev2_symlink = Xreadlink (finfo->file, rsize);
2733 else
2735 # ifdef HAVE_STRUCT_STAT_ST_RDEV
2736 if (lstat (finfo->file, &sb) < 0)
2737 error (1, errno, "could not get file information for %s",
2738 finfo->file);
2739 rev2_uid = sb.st_uid;
2740 rev2_gid = sb.st_gid;
2741 rev2_mode = sb.st_mode;
2742 if (S_ISBLK (rev2_mode) || S_ISCHR (rev2_mode))
2743 rev2_dev = sb.st_rdev;
2744 # else
2745 error (1, 0, "cannot handle device files on this system (%s)",
2746 finfo->file);
2747 # endif
2749 rev2_hardlinks = list_linked_files_on_disk (finfo->file);
2751 else
2753 n = findnode (finfo->rcs->versions, rev2);
2754 vp = n->data;
2756 n = findnode (vp->other_delta, "symlink");
2757 if (n != NULL)
2758 rev2_symlink = xstrdup (n->data);
2759 else
2761 n = findnode (vp->other_delta, "owner");
2762 if (n == NULL)
2763 check_uids = 0; /* don't care */
2764 else
2765 rev2_uid = strtoul (n->data, NULL, 10);
2767 n = findnode (vp->other_delta, "group");
2768 if (n == NULL)
2769 check_gids = 0; /* don't care */
2770 else
2771 rev2_gid = strtoul (n->data, NULL, 10);
2773 n = findnode (vp->other_delta, "permissions");
2774 if (n == NULL)
2775 check_modes = 0; /* don't care */
2776 else
2777 rev2_mode = strtoul (n->data, NULL, 8);
2779 n = findnode (vp->other_delta, "special");
2780 if (n == NULL)
2781 rev2_mode |= S_IFREG;
2782 else
2784 /* If the size of `ftype' changes, fix the sscanf call also */
2785 char ftype[16];
2786 if (sscanf (n->data, "%15s %lu", ftype,
2787 &dev_long) < 2)
2788 error (1, 0, "%s:%s has bad `special' newphrase %s",
2789 finfo->file, rev2, (char *)n->data);
2790 rev2_dev = dev_long;
2791 if (strcmp (ftype, "character") == 0)
2792 rev2_mode |= S_IFCHR;
2793 else if (strcmp (ftype, "block") == 0)
2794 rev2_mode |= S_IFBLK;
2795 else
2796 error (0, 0, "%s:%s unknown file type `%s'",
2797 finfo->file, rev2, ftype);
2800 rev2_hardlinks = vp->hardlinks;
2801 if (rev2_hardlinks == NULL)
2802 rev2_hardlinks = getlist();
2806 /* Check the user/group ownerships and file permissions, printing
2807 an error for each mismatch found. Return 0 if all characteristics
2808 matched, and 1 otherwise. */
2810 result = 0;
2812 /* Compare symlinks first, since symlinks are simpler (don't have
2813 any other characteristics). */
2814 if (rev1_symlink != NULL && rev2_symlink == NULL)
2816 error (0, 0, "%s is a symbolic link",
2817 (rev1 == NULL ? "working file" : rev1));
2818 result = 1;
2820 else if (rev1_symlink == NULL && rev2_symlink != NULL)
2822 error (0, 0, "%s is a symbolic link",
2823 (rev2 == NULL ? "working file" : rev2));
2824 result = 1;
2826 else if (rev1_symlink != NULL)
2827 result = (strcmp (rev1_symlink, rev2_symlink) == 0);
2828 else
2830 /* Compare user ownership. */
2831 if (check_uids && rev1_uid != rev2_uid)
2833 error (0, 0, "%s: owner mismatch between %s and %s",
2834 finfo->file,
2835 (rev1 == NULL ? "working file" : rev1),
2836 (rev2 == NULL ? "working file" : rev2));
2837 result = 1;
2840 /* Compare group ownership. */
2841 if (check_gids && rev1_gid != rev2_gid)
2843 error (0, 0, "%s: group mismatch between %s and %s",
2844 finfo->file,
2845 (rev1 == NULL ? "working file" : rev1),
2846 (rev2 == NULL ? "working file" : rev2));
2847 result = 1;
2850 /* Compare permissions. */
2851 if (check_modes &&
2852 (rev1_mode & 07777) != (rev2_mode & 07777))
2854 error (0, 0, "%s: permission mismatch between %s and %s",
2855 finfo->file,
2856 (rev1 == NULL ? "working file" : rev1),
2857 (rev2 == NULL ? "working file" : rev2));
2858 result = 1;
2861 /* Compare device file characteristics. */
2862 if ((rev1_mode & S_IFMT) != (rev2_mode & S_IFMT))
2864 error (0, 0, "%s: %s and %s are different file types",
2865 finfo->file,
2866 (rev1 == NULL ? "working file" : rev1),
2867 (rev2 == NULL ? "working file" : rev2));
2868 result = 1;
2870 else if (S_ISBLK (rev1_mode))
2872 if (rev1_dev != rev2_dev)
2874 error (0, 0, "%s: device numbers of %s and %s do not match",
2875 finfo->file,
2876 (rev1 == NULL ? "working file" : rev1),
2877 (rev2 == NULL ? "working file" : rev2));
2878 result = 1;
2882 /* Compare hard links. */
2883 if (compare_linkage_lists (rev1_hardlinks, rev2_hardlinks) == 0)
2885 error (0, 0, "%s: hard linkage of %s and %s do not match",
2886 finfo->file,
2887 (rev1 == NULL ? "working file" : rev1),
2888 (rev2 == NULL ? "working file" : rev2));
2889 result = 1;
2893 if (rev1_symlink != NULL)
2894 free (rev1_symlink);
2895 if (rev2_symlink != NULL)
2896 free (rev2_symlink);
2897 if (rev1_hardlinks != NULL)
2898 dellist (&rev1_hardlinks);
2899 if (rev2_hardlinks != NULL)
2900 dellist (&rev2_hardlinks);
2902 return result;
2903 #else
2904 return 0;
2905 #endif
2911 joining (void)
2913 return join_rev1 || join_date1;