2 * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
4 * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
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
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
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
54 static int checkout_file (struct file_info *finfo, Vers_TS *vers_ts,
55 int adding, int merging, int update_server);
57 static void checkout_to_buffer (void *, const char *, size_t);
58 static int patch_file (struct file_info *finfo,
60 int *docheckout, struct stat *file_info,
61 unsigned char *checksum);
62 static void patch_file_write (void *, const char *, size_t);
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,
70 static int update_dirleave_proc (void *callerdat, const char *dir,
71 int err, const char *update_dir,
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 * );
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;
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;
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",
140 * update is the argv,argc based front end for arg parsing
143 update (int argc, char **argv)
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;
153 usage (update_usage);
155 xjoin_rev1 = xjoin_date1 = xjoin_rev2 = xjoin_date2 = join_orig1 =
163 while ((c = getopt (argc, argv, "+ApCPflRQqduk:r:D:j:I:W:")) != -1)
171 toss_local_changes = 1;
177 wrap_add (optarg, 0);
182 options = RCS_check_kflag (optarg);
192 #ifdef SERVER_SUPPORT
193 /* The CVS 1.5 client sends these options (in addition to
194 Global_option requests), so we must ignore them. */
198 "-q or -Q must be specified before \"%s\"",
202 update_build_dirs = 1;
208 parse_tagdate (&tag, &date, optarg);
211 if (date) free (date);
212 date = Make_Date (optarg);
215 update_prune_dirs = 1;
219 noexec = 1; /* so no locks will be created */
223 error (1, 0, "only two -j options can be specified");
226 join_orig2 = xstrdup (optarg);
227 parse_tagdate (&xjoin_rev2, &xjoin_date2, optarg);
231 join_orig1 = xstrdup (optarg);
232 parse_tagdate (&xjoin_rev1, &xjoin_date1, optarg);
236 #ifdef SERVER_SUPPORT
240 rcs_diff_patches = server_use_rcs_diff ();
244 usage (update_usage);
248 usage (update_usage);
255 #ifdef CLIENT_SUPPORT
256 if (current_parsed_root->isremote)
260 /* The first pass does the regular update. If we receive at least
261 one patch which failed, we do a second pass and just fetch
262 those files whose patches failed. */
272 if (update_build_dirs)
276 if (!force_tag_match)
280 if (toss_local_changes)
282 if (update_prune_dirs)
284 client_prune_dirs = update_prune_dirs;
285 option_with_arg ("-r", tag);
286 if (options && options[0] != '\0')
289 client_senddate (date);
291 option_with_arg ("-j", join_orig1);
293 option_with_arg ("-j", join_orig2);
296 if (failed_patches_count == 0)
298 unsigned int flags = 0;
300 /* If the server supports the command "update-patches", that
301 means that it knows how to handle the -u argument to update,
302 which means to send patches instead of complete files.
304 We don't send -u if failed_patches != NULL, so that the
305 server doesn't try to send patches which will just fail
306 again. At least currently, the client also clobbers the
307 file and tells the server it is lost, which also will get
308 a full file instead of a patch, but it seems clean to omit
310 if (supported_request ("update-patches"))
315 if (update_build_dirs)
316 flags |= SEND_BUILD_DIRS;
318 if (toss_local_changes) {
319 flags |= SEND_NO_CONTENTS;
320 flags |= BACKUP_MODIFIED_FILES;
323 /* If noexec, probably could be setting SEND_NO_CONTENTS.
324 Same caveats as for "cvs status" apply. */
326 send_files (argc, argv, local, aflag, flags);
327 send_file_names (argc, argv, SEND_EXPAND_WILD);
333 (void) printf ("%s client: refetching unpatchable files\n",
336 if (toplevel_wd != NULL
337 && CVS_CHDIR (toplevel_wd) < 0)
339 error (1, errno, "could not chdir to %s", toplevel_wd);
344 for (i = 0; i < failed_patches_count; i++)
345 if (unlink_file (failed_patches[i]) < 0
346 && !existence_error (errno))
347 error (0, errno, "cannot remove %s",
349 send_files (failed_patches_count, failed_patches, local,
350 aflag, update_build_dirs ? SEND_BUILD_DIRS : 0);
351 send_file_names (failed_patches_count, failed_patches, 0);
352 free_names (&failed_patches_count, failed_patches);
355 send_to_server ("update\012", 0);
357 status = get_responses_and_close ();
359 /* If there are any conflicts, the server will return a
360 non-zero exit status. If any patches failed, we still
361 want to run the update again. We use a pass count to
362 avoid an endless loop. */
364 /* Notes: (1) assuming that status != 0 implies a
365 potential conflict is the best we can cleanly do given
366 the current protocol. I suppose that trying to
367 re-fetch in cases where there was a more serious error
368 is probably more or less harmless, but it isn't really
369 ideal. (2) it would be nice to have a testsuite case for the
370 conflict-and-patch-failed case. */
373 && (failed_patches_count == 0 || pass > 1))
375 if (failed_patches_count > 0)
376 free_names (&failed_patches_count, failed_patches);
381 } while (failed_patches_count > 0);
388 tag_check_valid (tag, argc, argv, local, aflag, "", false);
389 if (join_rev1 != NULL)
390 tag_check_valid (xjoin_rev1, argc, argv, local, aflag, "", false);
391 if (join_rev2 != NULL)
392 tag_check_valid (xjoin_rev2, argc, argv, local, aflag, "", false);
395 * If we are updating the entire directory (for real) and building dirs
396 * as we go, we make sure there is no static entries file and write the
397 * tag file as appropriate
399 if (argc <= 0 && !pipeout)
401 if (update_build_dirs)
403 if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno))
404 error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
405 #ifdef SERVER_SUPPORT
408 char *repos = Name_Repository (NULL, NULL);
409 server_clear_entstat (".", repos);
415 /* keep the CVS/Tag file current with the specified arguments */
416 if (aflag || tag || date)
418 char *repos = Name_Repository (NULL, NULL);
419 WriteTag (NULL, tag, date, 0, ".", repos);
427 /* look for files/dirs locally and in the repository */
428 which = W_LOCAL | W_REPOS;
430 /* look in the attic too if a tag or date is specified */
431 if (tag || date || join_orig1)
433 TRACE (TRACE_DATA, "update: searching attic");
437 /* call the command line interface */
438 err = do_update (argc, argv, options, tag, date, force_tag_match,
439 local, update_build_dirs, aflag, update_prune_dirs,
440 pipeout, which, xjoin_rev1, xjoin_date1, xjoin_rev2,
441 xjoin_date2, NULL, 1, NULL);
443 /* Free the space allocated for tags and dates, if necessary. */
445 if (date) free (date);
453 * Command line interface to update (used by checkout)
455 * repository = cvsroot->repository + update_dir. This is necessary for
456 * checkout so that start_recursion can determine our repository. In the
457 * update case, start_recursion can use the CVS/Root & CVS/Repository file
458 * to determine this value.
461 do_update (int argc, char **argv, char *xoptions, char *xtag, char *xdate,
462 int xforce, int local, int xbuild, int xaflag, int xprune,
463 int xpipeout, int which, char *xjoin_rev1, char *xjoin_date1,
464 char *xjoin_rev2, char *xjoin_date2,
465 char *preload_update_dir, int xdotemplate, char *repository)
469 TRACE (TRACE_FUNCTION,
470 "do_update (%s, %s, %s, %d, %d, %d, %d, %d, %d, %d, %s, %s, %s, %s, %s, %d, %s)",
471 xoptions ? xoptions : "(null)", xtag ? xtag : "(null)",
472 xdate ? xdate : "(null)", xforce, local, xbuild, xaflag, xprune,
473 xpipeout, which, xjoin_rev1 ? xjoin_rev1 : "(null)",
474 xjoin_date1 ? xjoin_date1 : "(null)",
475 xjoin_rev2 ? xjoin_rev2 : "(null)",
476 xjoin_date2 ? xjoin_date2 : "(null)",
477 preload_update_dir ? preload_update_dir : "(null)", xdotemplate,
478 repository ? repository : "(null)");
480 /* fill in the statics */
484 force_tag_match = xforce;
485 update_build_dirs = xbuild;
487 update_prune_dirs = xprune;
489 dotemplate = xdotemplate;
491 /* setup the join support */
492 join_rev1 = xjoin_rev1;
493 join_date1 = xjoin_date1;
494 join_rev2 = xjoin_rev2;
495 join_date2 = xjoin_date2;
497 #ifdef PRESERVE_PERMISSIONS_SUPPORT
500 /* We need to do an extra recursion, bleah. It's to make sure
501 that we know as much as possible about file linkage. */
502 hardlist = getlist();
503 working_dir = xgetcwd (); /* save top-level working dir */
505 /* FIXME-twp: the arguments to start_recursion make me dizzy. This
506 function call was copied from the update_fileproc call that
507 follows it; someone should make sure that I did it right. */
508 err = start_recursion
509 (get_linkinfo_proc, NULL, NULL, NULL, NULL,
510 argc, argv, local, which, aflag, CVS_LOCK_READ,
511 preload_update_dir, 1, NULL);
515 /* FIXME-twp: at this point we should walk the hardlist
516 and update the `links' field of each hardlink_info struct
517 to list the files that are linked on dist. That would make
518 it easier & more efficient to compare the disk linkage with
519 the repository linkage (a simple strcmp). */
523 /* call the recursion processor */
524 err = start_recursion (update_fileproc, update_filesdone_proc,
525 update_dirent_proc, update_dirleave_proc, NULL,
526 argc, argv, local, which, aflag, CVS_LOCK_READ,
527 preload_update_dir, 1, repository);
529 #ifdef SERVER_SUPPORT
534 /* see if we need to sleep before returning to avoid time-stamp races */
535 if (last_register_time)
537 sleep_past (last_register_time);
545 #ifdef PRESERVE_PERMISSIONS_SUPPORT
547 * The get_linkinfo_proc callback adds each file to the hardlist
552 get_linkinfo_proc (void *callerdat, struct file_info *finfo)
556 struct hardlink_info *hlinfo;
558 /* Get the full pathname of the current file. */
559 fullpath = Xasprintf ("%s/%s", working_dir, finfo->fullname);
561 /* To permit recursing into subdirectories, files
562 are keyed on the full pathname and not on the basename. */
563 linkp = lookup_file_by_inode (fullpath);
566 /* The file isn't on disk; we are probably restoring
567 a file that was removed. */
571 /* Create a new, empty hardlink_info node. */
572 hlinfo = xmalloc (sizeof (struct hardlink_info));
574 hlinfo->status = (Ctype) 0; /* is this dumb? */
575 hlinfo->checked_out = 0;
577 linkp->data = hlinfo;
586 * This is the callback proc for update. It is called for each file in each
587 * directory by the recursion code. The current directory is the local
588 * instantiation. file is the file name we are to operate on. update_dir is
589 * set to the path relative to where we started (for pretty printing).
590 * repository is the repository. entries and srcfiles are the pre-parsed
591 * entries and source control files.
593 * This routine decides what needs to be done for each file and does the
594 * appropriate magic for checkout
597 update_fileproc (void *callerdat, struct file_info *finfo)
603 status = Classify_File (finfo, tag, date, options, force_tag_match,
604 aflag, &vers, pipeout);
606 /* Keep track of whether TAG is a branch tag.
607 Note that if it is a branch tag in some files and a nonbranch tag
608 in others, treat it as a nonbranch tag. */
611 && finfo->rcs != NULL)
613 char *rev = RCS_getversion (finfo->rcs, tag, NULL, 1, NULL);
615 && nonbranch != (nb = !RCS_nodeisbranch (finfo->rcs, tag)))
617 if (nonbranch >= 0 && !warned && !quiet)
620 "warning: %s is a branch tag in some files and a revision tag in others.",
624 if (nonbranch < nb) nonbranch = nb;
633 * We just return success without doing anything if any of the really
636 * If there is still a valid RCS file, do a regular checkout type
641 case T_UNKNOWN: /* unknown file was explicitly asked
643 case T_REMOVE_ENTRY: /* needs to be un-registered */
644 case T_ADDED: /* added but not committed */
647 case T_CONFLICT: /* old punt-type errors */
650 case T_UPTODATE: /* file was already up-to-date */
651 case T_NEEDS_MERGE: /* needs merging */
652 case T_MODIFIED: /* locally modified */
653 case T_REMOVED: /* removed but not committed */
654 case T_CHECKOUT: /* needs checkout */
655 case T_PATCH: /* needs patch */
656 retval = checkout_file (finfo, vers, 0, 0, 0);
659 default: /* can't ever happen :-) */
661 "unknown file status %d for file %s", status, finfo->file);
670 case T_UNKNOWN: /* unknown file was explicitly asked
672 case T_UPTODATE: /* file was already up-to-date */
675 case T_CONFLICT: /* old punt-type errors */
677 write_letter (finfo, 'C');
679 case T_NEEDS_MERGE: /* needs merging */
680 if (! toss_local_changes)
682 retval = merge_file (finfo, vers);
685 /* else FALL THROUGH */
686 case T_MODIFIED: /* locally modified */
688 if (toss_local_changes)
691 bakname = backup_file (finfo->file, vers->vn_user);
692 /* This behavior is sufficiently unexpected to
693 justify overinformativeness, I think. */
694 #ifdef SERVER_SUPPORT
695 if ((! really_quiet) && (! server_active))
696 #else /* ! SERVER_SUPPORT */
698 #endif /* SERVER_SUPPORT */
699 (void) printf ("(Locally modified %s moved to %s)\n",
700 finfo->file, bakname);
703 /* The locally modified file is still present, but
704 it will be overwritten by the repository copy
707 retval = checkout_file (finfo, vers, 0, 0, 1);
711 if (vers->ts_conflict)
713 if (file_has_conflict (finfo, vers->ts_conflict)
714 || file_has_markers (finfo))
716 write_letter (finfo, 'C');
721 /* Reregister to clear conflict flag. */
722 Register (finfo->entries, finfo->file,
723 vers->vn_rcs, vers->ts_rcs,
724 vers->options, vers->tag,
729 write_letter (finfo, 'M');
732 case T_PATCH: /* needs patch */
733 #ifdef SERVER_SUPPORT
737 struct stat file_info;
738 unsigned char checksum[16];
740 retval = patch_file (finfo,
742 &file_info, checksum);
745 if (server_active && retval == 0)
746 server_updated (finfo, vers,
750 file_info.st_mode, checksum,
756 /* If we're not running as a server, just check the
757 file out. It's simpler and faster than producing
758 and applying patches. */
760 case T_CHECKOUT: /* needs checkout */
761 retval = checkout_file (finfo, vers, 0, 0, 1);
763 case T_ADDED: /* added but not committed */
764 write_letter (finfo, 'A');
767 case T_REMOVED: /* removed but not committed */
768 write_letter (finfo, 'R');
771 case T_REMOVE_ENTRY: /* needs to be un-registered */
772 retval = scratch_file (finfo, vers);
774 default: /* can't ever happen :-) */
776 "unknown file status %d for file %s", status, finfo->file);
782 /* only try to join if things have gone well thus far */
783 if (retval == 0 && join_rev1)
784 join_file (finfo, vers);
786 /* if this directory has an ignore list, add this file to it */
787 if (ignlist && (status != T_UNKNOWN || vers->ts_user == NULL))
793 p->key = xstrdup (finfo->file);
794 if (addnode (ignlist, p) != 0)
805 update_ignproc (const char *file, const char *dir)
807 struct file_info finfo;
810 memset (&finfo, 0, sizeof (finfo));
812 finfo.update_dir = dir;
814 finfo.fullname = tmp = Xasprintf ("%s%s%s",
815 dir[0] == '\0' ? "" : dir,
816 dir[0] == '\0' ? "" : "/",
818 write_letter (&finfo, '?');
826 update_filesdone_proc (void *callerdat, int err, const char *repository,
827 const char *update_dir, List *entries)
829 if (nonbranch < 0) nonbranch = 0;
832 WriteTag (NULL, tag, date, nonbranch, update_dir, repository);
836 /* if this directory has an ignore list, process it then free it */
839 ignore_files (ignlist, entries, update_dir, update_ignproc);
843 /* Clean up CVS admin dirs if we are export */
844 if (strcmp (cvs_cmd_name, "export") == 0)
846 /* I'm not sure the existence_error is actually possible (except
847 in cases where we really should print a message), but since
848 this code used to ignore all errors, I'll play it safe. */
849 if (unlink_file_dir (CVSADM) < 0 && !existence_error (errno))
850 error (0, errno, "cannot remove %s directory", CVSADM);
852 #ifdef SERVER_SUPPORT
853 else if (!server_active && !pipeout)
856 #endif /* SERVER_SUPPORT */
858 /* If there is no CVS/Root file, add one */
859 if (!isfile (CVSADM_ROOT))
860 Create_Root (NULL, original_parsed_root->original);
869 * update_dirent_proc () is called back by the recursion processor before a
870 * sub-directory is processed for update. In this case, update_dirent proc
871 * will probably create the directory unless -d isn't specified and this is a
872 * new directory. A return code of 0 indicates the directory should be
873 * processed by the recursion code. A return of non-zero indicates the
874 * recursion code should skip this directory.
877 update_dirent_proc (void *callerdat, const char *dir, const char *repository,
878 const char *update_dir, List *entries)
880 if (ignore_directory (update_dir))
882 /* print the warm fuzzy message */
884 error (0, 0, "Ignoring %s", update_dir);
890 /* if we aren't building dirs, blow it off */
891 if (!update_build_dirs)
894 /* Various CVS administrators are in the habit of removing
895 the repository directory for things they don't want any
896 more. I've even been known to do it myself (on rare
897 occasions). Not the usual recommended practice, but we
898 want to try to come up with some kind of
899 reasonable/documented/sensible behavior. Generally
900 the behavior is to just skip over that directory (see
901 dirs test in sanity.sh; the case which reaches here
902 is when update -d is specified, and the working directory
903 is gone but the subdirectory is still mentioned in
906 #ifdef SERVER_SUPPORT
907 /* In the remote case, the client should refrain from
908 sending us the directory in the first place. So we
909 want to continue to give an error, so clients make
913 && !isdir (repository))
918 /* ignore the missing dir if -n is specified */
919 error (0, 0, "New directory `%s' -- ignored", update_dir);
924 /* otherwise, create the dir and appropriate adm files */
926 /* If no tag or date were specified on the command line,
927 and we're not using -A, we want the subdirectory to use
928 the tag and date, if any, of the current directory.
929 That way, update -d will work correctly when working on
932 We use TAG_UPDATE_DIR to undo the tag setting in
933 update_dirleave_proc. If we did not do this, we would
934 not correctly handle a working directory with multiple
935 tags (and maybe we should prohibit such working
936 directories, but they work now and we shouldn't make
937 them stop working without more thought). */
938 if ((tag == NULL && date == NULL) && ! aflag)
940 ParseTag (&tag, &date, &nonbranch);
941 if (tag != NULL || date != NULL)
942 tag_update_dir = xstrdup (update_dir);
945 make_directory (dir);
946 Create_Admin (dir, update_dir, repository, tag, date,
947 /* This is a guess. We will rewrite it later
955 Subdir_Register (entries, NULL, dir);
958 /* Do we need to check noexec here? */
963 /* The directory exists. Check to see if it has a CVS
966 cvsadmdir = Xasprintf ("%s/%s", dir, CVSADM);
968 if (!isdir (cvsadmdir))
970 /* We cannot successfully recurse into a directory without a CVS
971 subdirectory. Generally we will have already printed
980 * If we are building dirs and not going to stdout, we make sure there is
981 * no static entries file and write the tag file as appropriate
985 if (update_build_dirs)
987 char *tmp = Xasprintf ("%s/%s", dir, CVSADM_ENTSTAT);
989 if (unlink_file (tmp) < 0 && ! existence_error (errno))
990 error (1, errno, "cannot remove file %s", tmp);
991 #ifdef SERVER_SUPPORT
993 server_clear_entstat (update_dir, repository);
998 /* keep the CVS/Tag file current with the specified arguments */
999 if (aflag || tag || date)
1001 WriteTag (dir, tag, date, 0, update_dir, repository);
1007 WriteTemplate (update_dir, dotemplate, repository);
1009 /* initialize the ignore list for this directory */
1010 ignlist = getlist ();
1013 /* print the warm fuzzy message */
1015 error (0, 0, "Updating %s", update_dir);
1023 * update_dirleave_proc () is called back by the recursion code upon leaving
1024 * a directory. It will prune empty directories if needed and will execute
1025 * any appropriate update programs.
1029 update_dirleave_proc (void *callerdat, const char *dir, int err,
1030 const char *update_dir, List *entries)
1032 /* Delete the ignore list if it hasn't already been done. */
1036 /* If we set the tag or date for a new subdirectory in
1037 update_dirent_proc, and we're now done with that subdirectory,
1038 undo the tag/date setting. Note that we know that the tag and
1039 date were both originally NULL in this case. */
1040 if (tag_update_dir != NULL && strcmp (update_dir, tag_update_dir) == 0)
1054 free (tag_update_dir);
1055 tag_update_dir = NULL;
1058 if (strchr (dir, '/') == NULL)
1060 /* FIXME: chdir ("..") loses with symlinks. */
1061 /* Prune empty dirs on the way out - if necessary */
1062 (void) CVS_CHDIR ("..");
1063 if (update_prune_dirs && isemptydir (dir, 0))
1065 /* I'm not sure the existence_error is actually possible (except
1066 in cases where we really should print a message), but since
1067 this code used to ignore all errors, I'll play it safe. */
1068 if (unlink_file_dir (dir) < 0 && !existence_error (errno))
1069 error (0, errno, "cannot remove %s directory", dir);
1070 Subdir_Deregister (entries, NULL, dir);
1079 /* Returns 1 if the file indicated by node has been removed. */
1081 isremoved (Node *node, void *closure)
1083 Entnode *entdata = node->data;
1085 /* If the first character of the version is a '-', the file has been
1087 return (entdata->version && entdata->version[0] == '-') ? 1 : 0;
1092 /* Returns 1 if the argument directory is completely empty, other than the
1093 existence of the CVS directory entry. Zero otherwise. If MIGHT_NOT_EXIST
1094 and the directory doesn't exist, then just return 0. */
1096 isemptydir (const char *dir, int might_not_exist)
1101 if ((dirp = CVS_OPENDIR (dir)) == NULL)
1103 if (might_not_exist && existence_error (errno))
1105 error (0, errno, "cannot open directory %s for empty check", dir);
1109 while ((dp = CVS_READDIR (dirp)) != NULL)
1111 if (strcmp (dp->d_name, ".") != 0
1112 && strcmp (dp->d_name, "..") != 0)
1114 if (strcmp (dp->d_name, CVSADM) != 0)
1116 /* An entry other than the CVS directory. The directory
1117 is certainly not empty. */
1118 (void) CVS_CLOSEDIR (dirp);
1123 /* The CVS directory entry. We don't have to worry about
1124 this unless the Entries file indicates that files have
1125 been removed, but not committed, in this directory.
1126 (Removing the directory would prevent people from
1127 comitting the fact that they removed the files!) */
1130 struct saved_cwd cwd;
1132 if (save_cwd (&cwd))
1133 error (1, errno, "Failed to save current directory.");
1135 if (CVS_CHDIR (dir) < 0)
1136 error (1, errno, "cannot change directory to %s", dir);
1137 l = Entries_Open (0, NULL);
1138 files_removed = walklist (l, isremoved, 0);
1141 if (restore_cwd (&cwd))
1143 "Failed to restore current directory, `%s'.",
1147 if (files_removed != 0)
1149 /* There are files that have been removed, but not
1150 committed! Do not consider the directory empty. */
1151 (void) CVS_CLOSEDIR (dirp);
1160 error (0, errno, "cannot read directory %s", dir);
1161 (void) CVS_CLOSEDIR (dirp);
1164 (void) CVS_CLOSEDIR (dirp);
1171 * scratch the Entries file entry associated with a file
1174 scratch_file (struct file_info *finfo, Vers_TS *vers)
1176 history_write ('W', finfo->update_dir, "", finfo->file, finfo->repository);
1177 Scratch_Entry (finfo->entries, finfo->file);
1178 #ifdef SERVER_SUPPORT
1181 if (vers->ts_user == NULL)
1182 server_scratch_entry_only ();
1183 server_updated (finfo, vers, SERVER_UPDATED, (mode_t) -1, NULL, NULL);
1186 if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1187 error (0, errno, "unable to remove %s", finfo->fullname);
1189 #ifdef SERVER_SUPPORT
1190 /* skip this step when the server is running since
1191 * server_updated should have handled it */
1195 /* keep the vers structure up to date in case we do a join
1196 * - if there isn't a file, it can't very well have a version number, can it?
1198 if (vers->vn_user != NULL)
1200 free (vers->vn_user);
1201 vers->vn_user = NULL;
1203 if (vers->ts_user != NULL)
1205 free (vers->ts_user);
1206 vers->ts_user = NULL;
1218 checkout_file (struct file_info *finfo, Vers_TS *vers_ts, int adding,
1219 int merging, int update_server)
1222 int set_time, retval = 0;
1225 struct buffer *revbuf;
1230 /* Don't screw with backup files if we're going to stdout, or if
1231 we are the server. */
1233 #ifdef SERVER_SUPPORT
1238 backup = Xasprintf ("%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
1239 if (isfile (finfo->file))
1240 rename_file (finfo->file, backup);
1243 /* If -f/-t wrappers are being used to wrap up a directory,
1244 then backup might be a directory instead of just a file. */
1245 if (unlink_file_dir (backup) < 0)
1247 /* Not sure if the existence_error check is needed here. */
1248 if (!existence_error (errno))
1249 /* FIXME: should include update_dir in message. */
1250 error (0, errno, "error removing %s", backup);
1257 file_is_dead = RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs);
1262 * if we are checking out to stdout, print a nice message to
1263 * stderr, and add the -p flag to the command */
1269 ===================================================================\n\
1271 cvs_outerr (finfo->fullname, 0);
1274 cvs_outerr (vers_ts->srcfile->print_path, 0);
1277 cvs_outerr (vers_ts->vn_rcs, 0);
1278 cvs_outerr ("\n***************\n", 0);
1282 #ifdef SERVER_SUPPORT
1286 && ! file_gzip_level
1288 && ! wrap_name_has (finfo->file, WRAP_FROMCVS))
1290 revbuf = buf_nonio_initialize (NULL);
1291 status = RCS_checkout (vers_ts->srcfile, NULL,
1292 vers_ts->vn_rcs, vers_ts->tag,
1293 vers_ts->options, RUN_TTY,
1294 checkout_to_buffer, revbuf);
1298 status = RCS_checkout (vers_ts->srcfile,
1299 pipeout ? NULL : finfo->file,
1300 vers_ts->vn_rcs, vers_ts->tag,
1301 vers_ts->options, RUN_TTY, NULL, NULL);
1303 if (file_is_dead || status == 0)
1313 if (revbuf != NULL && !noexec)
1317 /* FIXME: We should have RCS_checkout return the mode.
1318 That would also fix the kludge with noexec, above, which
1319 is here only because noexec doesn't write srcfile->path
1321 if( CVS_STAT( vers_ts->srcfile->path, &sb ) < 0 )
1323 #if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
1325 #endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
1326 error (1, errno, "cannot stat %s",
1327 vers_ts->srcfile->path);
1329 mode = sb.st_mode &~ (S_IWRITE | S_IWGRP | S_IWOTH);
1334 && !fileattr_get (finfo->file, "_watched"))
1337 xchmod (finfo->file, 1);
1340 /* We know that we are the server here, so
1341 although xchmod checks umask, we don't bother. */
1342 mode |= (((mode & S_IRUSR) ? S_IWUSR : 0)
1343 | ((mode & S_IRGRP) ? S_IWGRP : 0)
1344 | ((mode & S_IROTH) ? S_IWOTH : 0));
1349 /* A newly checked out file is never under the spell
1350 of "cvs edit". If we think we were editing it
1351 from a previous life, clean up. Would be better to
1352 check for same the working directory instead of
1353 same user, but that is hairy. */
1355 struct addremove_args args;
1357 editor_set (finfo->file, getcaller (), NULL);
1359 memset (&args, 0, sizeof args);
1360 args.remove_temp = 1;
1361 watch_modify_watchers (finfo->file, &args);
1364 /* set the time from the RCS file iff it was unknown before */
1367 && (vers_ts->vn_user == NULL ||
1368 strncmp (vers_ts->ts_rcs, "Initial", 7) == 0)
1371 wrap_fromcvs_process_file (finfo->file);
1373 xvers_ts = Version_TS (finfo, options, tag, date,
1374 force_tag_match, set_time);
1375 if (strcmp (xvers_ts->options, "-V4") == 0)
1376 xvers_ts->options[0] = '\0';
1380 /* If we stored the file data into a buffer, then we
1381 didn't create a file at all, so xvers_ts->ts_user
1382 is wrong. The correct value is to have it be the
1383 same as xvers_ts->ts_rcs, meaning that the working
1384 file is unchanged from the RCS file.
1386 FIXME: We should tell Version_TS not to waste time
1387 statting the nonexistent file.
1389 FIXME: Actually, I don't think the ts_user value
1390 matters at all here. The only use I know of is
1391 that it is printed in a trace message by
1394 if (xvers_ts->ts_user != NULL)
1395 free (xvers_ts->ts_user);
1396 xvers_ts->ts_user = xstrdup (xvers_ts->ts_rcs);
1399 (void) time (&last_register_time);
1403 if (xvers_ts->vn_user != NULL)
1406 "warning: %s is not (any longer) pertinent",
1409 Scratch_Entry (finfo->entries, finfo->file);
1410 #ifdef SERVER_SUPPORT
1411 if (server_active && xvers_ts->ts_user == NULL)
1412 server_scratch_entry_only ();
1414 /* FIXME: Rather than always unlink'ing, and ignoring the
1415 existence_error, we should do the unlink only if
1416 vers_ts->ts_user is non-NULL. Then there would be no
1417 need to ignore an existence_error (for example, if the
1418 user removes the file while we are running). */
1419 if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1421 error (0, errno, "cannot remove %s", finfo->fullname);
1425 Register (finfo->entries, finfo->file,
1426 adding ? "0" : xvers_ts->vn_rcs,
1427 xvers_ts->ts_user, xvers_ts->options,
1428 xvers_ts->tag, xvers_ts->date,
1429 NULL); /* Clear conflict flag on fresh checkout */
1431 /* fix up the vers structure, in case it is used by join */
1434 /* FIXME: Throwing away the original revision info is almost
1435 certainly wrong -- what if join_rev1 is "BASE"? */
1436 if (vers_ts->vn_user != NULL)
1437 free (vers_ts->vn_user);
1438 if (vers_ts->vn_rcs != NULL)
1439 free (vers_ts->vn_rcs);
1440 vers_ts->vn_user = xstrdup (xvers_ts->vn_rcs);
1441 vers_ts->vn_rcs = xstrdup (xvers_ts->vn_rcs);
1444 /* If this is really Update and not Checkout, recode history */
1445 if (strcmp (cvs_cmd_name, "update") == 0)
1446 history_write ('U', finfo->update_dir, xvers_ts->vn_rcs, finfo->file,
1449 freevers_ts (&xvers_ts);
1451 if (!really_quiet && !file_is_dead)
1453 write_letter (finfo, 'U');
1457 #ifdef SERVER_SUPPORT
1458 if (update_server && server_active)
1459 server_updated (finfo, vers_ts,
1460 merging ? SERVER_MERGED : SERVER_UPDATED,
1461 mode, NULL, revbuf);
1468 rename_file (backup, finfo->file);
1473 error (0, 0, "could not check out %s", finfo->fullname);
1480 /* If -f/-t wrappers are being used to wrap up a directory,
1481 then backup might be a directory instead of just a file. */
1482 if (unlink_file_dir (backup) < 0)
1484 /* Not sure if the existence_error check is needed here. */
1485 if (!existence_error (errno))
1486 /* FIXME: should include update_dir in message. */
1487 error (0, errno, "error removing %s", backup);
1492 #if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
1495 #endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
1501 #ifdef SERVER_SUPPORT
1503 /* This function is used to write data from a file being checked out
1507 checkout_to_buffer (void *callerdat, const char *data, size_t len)
1509 struct buffer *buf = (struct buffer *) callerdat;
1511 buf_output (buf, data, len);
1514 #endif /* SERVER_SUPPORT */
1516 #ifdef SERVER_SUPPORT
1518 /* This structure is used to pass information between patch_file and
1519 patch_file_write. */
1521 struct patch_file_data
1523 /* File name, for error messages. */
1524 const char *filename;
1525 /* File to which to write. */
1527 /* Whether to compute the MD5 checksum. */
1528 int compute_checksum;
1529 /* Data structure for computing the MD5 checksum. */
1530 struct md5_ctx context;
1531 /* Set if the file has a final newline. */
1535 /* Patch a file. Runs diff. This is only done when running as the
1536 * server. The hope is that the diff will be smaller than the file
1540 patch_file (struct file_info *finfo, Vers_TS *vers_ts, int *docheckout,
1541 struct stat *file_info, unsigned char *checksum)
1550 struct patch_file_data data;
1554 if (noexec || pipeout || joining ())
1560 /* If this file has been marked as being binary, then never send a
1562 if (strcmp (vers_ts->options, "-kb") == 0)
1568 /* First check that the first revision exists. If it has been nuked
1569 by cvs admin -o, then just fall back to checking out entire
1570 revisions. In some sense maybe we don't have to do this; after
1571 all cvs.texinfo says "Make sure that no-one has checked out a
1572 copy of the revision you outdate" but then again, that advice
1573 doesn't really make complete sense, because "cvs admin" operates
1574 on a working directory and so _someone_ will almost always have
1575 _some_ revision checked out. */
1579 rev = RCS_gettag (finfo->rcs, vers_ts->vn_user, 1, NULL);
1589 /* If the revision is dead, let checkout_file handle it rather
1590 than duplicating the processing here. */
1591 if (RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs))
1597 backup = Xasprintf ("%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
1598 if (isfile (finfo->file))
1599 rename_file (finfo->file, backup);
1602 if (unlink_file (backup) < 0
1603 && !existence_error (errno))
1604 error (0, errno, "cannot remove %s", backup);
1607 file1 = Xasprintf ("%s/%s%s-1", CVSADM, CVSPREFIX, finfo->file);
1608 file2 = Xasprintf ("%s/%s%s-2", CVSADM, CVSPREFIX, finfo->file);
1612 /* We need to check out both revisions first, to see if either one
1613 has a trailing newline. Because of this, we don't use rcsdiff,
1614 but just use diff. */
1616 e = CVS_FOPEN (file1, "w");
1618 error (1, errno, "cannot open %s", file1);
1620 data.filename = file1;
1623 data.compute_checksum = 0;
1625 /* FIXME - Passing vers_ts->tag here is wrong in the least number
1626 * of cases. Since we don't know whether vn_user was checked out
1627 * using a tag, we pass vers_ts->tag, which, assuming the user did
1628 * not specify a new TAG to -r, will be the branch we are on.
1630 * The only thing it is used for is to substitute in for the Name
1631 * RCS keyword, so in the error case, the patch fails to apply on
1632 * the client end and we end up resending the whole file.
1634 * At least, if we are keeping track of the tag vn_user came from,
1635 * I don't know where yet. -DRP
1637 retcode = RCS_checkout (vers_ts->srcfile, NULL,
1638 vers_ts->vn_user, vers_ts->tag,
1639 vers_ts->options, RUN_TTY,
1640 patch_file_write, (void *) &data);
1643 error (1, errno, "cannot close %s", file1);
1645 if (retcode != 0 || ! data.final_nl)
1650 e = CVS_FOPEN (file2, "w");
1652 error (1, errno, "cannot open %s", file2);
1654 data.filename = file2;
1657 data.compute_checksum = 1;
1658 md5_init_ctx (&data.context);
1660 retcode = RCS_checkout (vers_ts->srcfile, NULL,
1661 vers_ts->vn_rcs, vers_ts->tag,
1662 vers_ts->options, RUN_TTY,
1663 patch_file_write, (void *) &data);
1666 error (1, errno, "cannot close %s", file2);
1668 if (retcode != 0 || ! data.final_nl)
1671 md5_finish_ctx (&data.context, checksum);
1679 /* If the client does not support the Rcs-diff command, we
1680 send a context diff, and the client must invoke patch.
1681 That approach was problematical for various reasons. The
1682 new approach only requires running diff in the server; the
1683 client can handle everything without invoking an external
1685 if (! rcs_diff_patches)
1687 /* We use -c, not -u, because that is what CVS has
1688 traditionally used. Kind of a moot point, now that
1689 Rcs-diff is preferred, so there is no point in making
1690 the compatibility issues worse. */
1691 diff_options = "-c";
1695 /* Now that diff is librarified, we could be passing -a if
1696 we wanted to. However, it is unclear to me whether we
1697 would want to. Does diff -a, in any significant
1698 percentage of cases, produce patches which are smaller
1699 than the files it is patching? I guess maybe text
1700 files with character sets which diff regards as
1701 'binary'. Conversely, do they tend to be much larger
1702 in the bad cases? This needs some more
1703 thought/investigation, I suspect. */
1705 diff_options = "-n";
1707 retcode = diff_exec (file1, file2, NULL, NULL, diff_options, finfo->file);
1709 /* A retcode of 0 means no differences. 1 means some differences. */
1719 struct stat file2_info;
1721 /* Check to make sure the patch is really shorter */
1722 if (CVS_STAT (file2, &file2_info) < 0)
1723 error (1, errno, "could not stat %s", file2);
1724 if (CVS_STAT (finfo->file, file_info) < 0)
1725 error (1, errno, "could not stat %s", finfo->file);
1726 if (file2_info.st_size <= file_info->st_size)
1732 # define BINARY "Binary"
1733 char buf[sizeof BINARY];
1736 /* Check the diff output to make sure patch will be handle it. */
1737 e = CVS_FOPEN (finfo->file, "r");
1739 error (1, errno, "could not open diff output file %s",
1741 c = fread (buf, 1, sizeof BINARY - 1, e);
1743 if (strcmp (buf, BINARY) == 0)
1745 /* These are binary files. We could use diff -a, but
1746 patch can't handle that. */
1756 /* Stat the original RCS file, and then adjust it the way
1757 that RCS_checkout would. FIXME: This is an abstraction
1759 if (CVS_STAT (vers_ts->srcfile->path, file_info) < 0)
1760 error (1, errno, "could not stat %s", vers_ts->srcfile->path);
1761 if (chmod (finfo->file,
1762 file_info->st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH))
1764 error (0, errno, "cannot change mode of file %s", finfo->file);
1766 && !fileattr_get (finfo->file, "_watched"))
1767 xchmod (finfo->file, 1);
1769 /* This stuff is just copied blindly from checkout_file. I
1770 don't really know what it does. */
1771 xvers_ts = Version_TS (finfo, options, tag, date,
1772 force_tag_match, 0);
1773 if (strcmp (xvers_ts->options, "-V4") == 0)
1774 xvers_ts->options[0] = '\0';
1776 Register (finfo->entries, finfo->file, xvers_ts->vn_rcs,
1777 xvers_ts->ts_user, xvers_ts->options,
1778 xvers_ts->tag, xvers_ts->date, NULL);
1780 if (CVS_STAT (finfo->file, file_info) < 0)
1781 error (1, errno, "could not stat %s", finfo->file);
1783 /* If this is really Update and not Checkout, record history. */
1784 if (strcmp (cvs_cmd_name, "update") == 0)
1785 history_write ('P', finfo->update_dir, xvers_ts->vn_rcs,
1786 finfo->file, finfo->repository);
1788 freevers_ts (&xvers_ts);
1792 write_letter (finfo, 'P');
1797 int old_errno = errno; /* save errno value over the rename */
1799 if (isfile (backup))
1800 rename_file (backup, finfo->file);
1802 if (retcode != 0 && retcode != 1)
1803 error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0,
1804 "could not diff %s", finfo->fullname);
1810 if (unlink_file (backup) < 0
1811 && !existence_error (errno))
1812 error (0, errno, "cannot remove %s", backup);
1813 if (unlink_file (file1) < 0
1814 && !existence_error (errno))
1815 error (0, errno, "cannot remove %s", file1);
1816 if (unlink_file (file2) < 0
1817 && !existence_error (errno))
1818 error (0, errno, "cannot remove %s", file2);
1828 /* Write data to a file. Record whether the last byte written was a
1829 newline. Optionally compute a checksum. This is called by
1830 patch_file via RCS_checkout. */
1833 patch_file_write (void *callerdat, const char *buffer, size_t len)
1835 struct patch_file_data *data = (struct patch_file_data *) callerdat;
1837 if (fwrite (buffer, 1, len, data->fp) != len)
1838 error (1, errno, "cannot write %s", data->filename);
1840 data->final_nl = (buffer[len - 1] == '\n');
1842 if (data->compute_checksum)
1843 md5_process_bytes (buffer, len, &data->context);
1846 #endif /* SERVER_SUPPORT */
1849 * Several of the types we process only print a bit of information consisting
1850 * of a single letter and the name.
1853 write_letter (struct file_info *finfo, int letter)
1858 /* Big enough for "+updated" or any of its ilk. */
1867 /* We don't yet support tagged output except for "U". */
1873 sprintf (buf, "+%s", tag);
1874 cvs_output_tagged (buf, NULL);
1879 cvs_output_tagged ("text", buf);
1880 cvs_output_tagged ("fname", finfo->fullname);
1881 cvs_output_tagged ("newline", NULL);
1884 sprintf (buf, "-%s", tag);
1885 cvs_output_tagged (buf, NULL);
1894 * Do all the magic associated with a file which needs to be merged
1897 merge_file (struct file_info *finfo, Vers_TS *vers)
1903 assert (vers->vn_user);
1906 * The users currently modified file is moved to a backup file name
1907 * ".#filename.version", so that it will stay around for a few days
1908 * before being automatically removed by some cron daemon. The "version"
1909 * is the version of the file that the user was most up-to-date with
1912 backup = Xasprintf ("%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
1914 if (unlink_file (backup) && !existence_error (errno))
1915 error (0, errno, "unable to remove %s", backup);
1916 copy_file (finfo->file, backup);
1917 xchmod (finfo->file, 1);
1919 if (strcmp (vers->options, "-kb") == 0
1920 || wrap_merge_is_copy (finfo->file)
1921 || special_file_mismatch (finfo, NULL, vers->vn_rcs))
1923 /* For binary files, a merge is always a conflict. Same for
1924 files whose permissions or linkage do not match. We give the
1925 user the two files, and let them resolve it. It is possible
1926 that we should require a "touch foo" or similar step before
1927 we allow a checkin. */
1929 /* TODO: it may not always be necessary to regard a permission
1930 mismatch as a conflict. The working file and the RCS file
1931 have a common ancestor `A'; if the working file's permissions
1932 match A's, then it's probably safe to overwrite them with the
1933 RCS permissions. Only if the working file, the RCS file, and
1934 A all disagree should this be considered a conflict. But more
1935 thought needs to go into this, and in the meantime it is safe
1936 to treat any such mismatch as an automatic conflict. -twp */
1938 #ifdef SERVER_SUPPORT
1940 server_copy_file (finfo->file, finfo->update_dir,
1941 finfo->repository, backup);
1944 status = checkout_file (finfo, vers, 0, 1, 1);
1946 /* Is there a better term than "nonmergeable file"? What we
1947 really mean is, not something that CVS cannot or does not
1948 want to merge (there might be an external manual or
1949 automatic merge process). */
1950 error (0, 0, "nonmergeable file needs merge");
1951 error (0, 0, "revision %s from repository is now in %s",
1952 vers->vn_rcs, finfo->fullname);
1953 error (0, 0, "file from working directory is now in %s", backup);
1954 write_letter (finfo, 'C');
1956 history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file,
1962 status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
1963 vers->options, vers->vn_user, vers->vn_rcs);
1964 if (status != 0 && status != 1)
1966 error (0, status == -1 ? errno : 0,
1967 "could not merge revision %s of %s", vers->vn_user, finfo->fullname);
1968 error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
1969 finfo->fullname, backup);
1970 rename_file (backup, finfo->file);
1975 if (strcmp (vers->options, "-V4") == 0)
1976 vers->options[0] = '\0';
1978 /* This file is the result of a merge, which means that it has
1979 been modified. We use a special timestamp string which will
1980 not compare equal to any actual timestamp. */
1986 (void) time (&last_register_time);
1987 cp = time_stamp (finfo->file);
1989 Register (finfo->entries, finfo->file, vers->vn_rcs,
1990 "Result of merge", vers->options, vers->tag,
1996 /* fix up the vers structure, in case it is used by join */
1999 /* FIXME: Throwing away the original revision info is almost
2000 certainly wrong -- what if join_rev1 is "BASE"? */
2001 if (vers->vn_user != NULL)
2002 free (vers->vn_user);
2003 vers->vn_user = xstrdup (vers->vn_rcs);
2006 #ifdef SERVER_SUPPORT
2007 /* Send the new contents of the file before the message. If we
2008 wanted to be totally correct, we would have the client write
2009 the message only after the file has safely been written. */
2012 server_copy_file (finfo->file, finfo->update_dir, finfo->repository,
2014 server_updated (finfo, vers, SERVER_MERGED, (mode_t) -1, NULL, NULL);
2020 error (0, 0, "conflicts found in %s", finfo->fullname);
2022 write_letter (finfo, 'C');
2024 history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file,
2028 else /* status == 0 */
2030 history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file,
2033 /* FIXME: the noexec case is broken. RCS_merge could be doing the
2034 xcmp on the temporary files without much hassle, I think. */
2035 if (!noexec && !xcmp (backup, finfo->file))
2037 cvs_output (finfo->fullname, 0);
2038 cvs_output (" already contains the differences between ", 0);
2039 cvs_output (vers->vn_user, 0);
2040 cvs_output (" and ", 0);
2041 cvs_output (vers->vn_rcs, 0);
2042 cvs_output ("\n", 1);
2048 write_letter (finfo, 'M');
2059 * Do all the magic associated with a file which needs to be joined
2060 * (reached via the -j option to checkout or update).
2063 * finfo File information about the destination file.
2064 * vers The Vers_TS structure for finfo.
2067 * join_rev1 From the command line.
2068 * join_rev2 From the command line.
2069 * server_active Natch.
2072 * 1. Is not called in client mode.
2075 join_file (struct file_info *finfo, Vers_TS *vers)
2088 TRACE (TRACE_FUNCTION, "join_file(%s, %s%s%s%s, %s, %s)",
2090 vers->tag ? vers->tag : "",
2091 vers->tag ? " (" : "",
2092 vers->vn_rcs ? vers->vn_rcs : "",
2093 vers->tag ? ")" : "",
2094 join_rev1 ? join_rev1 : "",
2095 join_rev2 ? join_rev2 : "");
2099 jdate1 = join_date1;
2100 jdate2 = join_date2;
2102 /* Determine if we need to do anything at all. */
2103 if (vers->srcfile == NULL ||
2104 vers->srcfile->path == NULL)
2109 /* If only one join revision is specified, it becomes the second
2119 /* FIXME: Need to handle "BASE" for jrev1 and/or jrev2. Note caveat
2120 below about vn_user. */
2122 /* Convert the second revision, walking branches and dates. */
2123 rev2 = RCS_getversion (vers->srcfile, jrev2, jdate2, 1, NULL);
2125 /* If this is a merge of two revisions, get the first revision.
2126 If only one join tag was specified, then the first revision is
2127 the greatest common ancestor of the second revision and the
2130 rev1 = RCS_getversion (vers->srcfile, jrev1, jdate1, 1, NULL);
2133 /* Note that we use vn_rcs here, since vn_user may contain a
2134 special string such as "-nn". */
2135 if (vers->vn_rcs == NULL)
2137 else if (rev2 == NULL)
2139 /* This means that the file never existed on the branch.
2140 It does not mean that the file was removed on the
2141 branch: that case is represented by a dead rev2. If
2142 the file never existed on the branch, then we have
2143 nothing to merge, so we just return. */
2147 rev1 = gca (vers->vn_rcs, rev2);
2150 /* Handle a nonexistent or dead merge target. */
2151 if (rev2 == NULL || RCS_isdead (vers->srcfile, rev2))
2158 /* If the first revision doesn't exist either, then there is
2159 no change between the two revisions, so we don't do
2161 if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
2168 /* If we are merging two revisions, then the file was removed
2169 between the first revision and the second one. In this
2170 case we want to mark the file for removal.
2172 If we are merging one revision, then the file has been
2173 removed between the greatest common ancestor and the merge
2174 revision. From the perspective of the branch on to which
2175 we ar emerging, which may be the trunk, either 1) the file
2176 does not currently exist on the target, or 2) the file has
2177 not been modified on the target branch since the greatest
2178 common ancestor, or 3) the file has been modified on the
2179 target branch since the greatest common ancestor. In case
2180 1 there is nothing to do. In case 2 we mark the file for
2181 removal. In case 3 we have a conflict.
2183 Note that the handling is slightly different depending upon
2184 whether one or two join targets were specified. If two
2185 join targets were specified, we don't check whether the
2186 file was modified since a given point. My reasoning is
2187 that if you ask for an explicit merge between two tags,
2188 then you want to merge in whatever was changed between
2189 those two tags. If a file was removed between the two
2190 tags, then you want it to be removed. However, if you ask
2191 for a merge of a branch, then you want to merge in all
2192 changes which were made on the branch. If a file was
2193 removed on the branch, that is a change to the file. If
2194 the file was also changed on the main line, then that is
2195 also a change. These two changes--the file removal and the
2196 modification--must be merged. This is a conflict. */
2198 /* If the user file is dead, or does not exist, or has been
2199 marked for removal, then there is nothing to do. */
2200 if (vers->vn_user == NULL
2201 || vers->vn_user[0] == '-'
2202 || RCS_isdead (vers->srcfile, vers->vn_user))
2209 /* If the user file has been marked for addition, or has been
2210 locally modified, then we have a conflict which we can not
2211 resolve. No_Difference will already have been called in
2212 this case, so comparing the timestamps is sufficient to
2213 determine whether the file is locally modified. */
2214 if (strcmp (vers->vn_user, "0") == 0
2215 || (vers->ts_user != NULL
2216 && strcmp (vers->ts_user, vers->ts_rcs) != 0))
2220 "file %s is locally modified, but has been removed in revision %s as of %s",
2221 finfo->fullname, jrev2, jdate2);
2224 "file %s is locally modified, but has been removed in revision %s",
2225 finfo->fullname, jrev2);
2227 /* FIXME: Should we arrange to return a non-zero exit
2236 /* If only one join tag was specified, and the user file has
2237 been changed since the greatest common ancestor (rev1),
2238 then there is a conflict we can not resolve. See above for
2240 if (join_rev2 == NULL
2241 && strcmp (rev1, vers->vn_user) != 0)
2245 "file %s has been modified, but has been removed in revision %s as of %s",
2246 finfo->fullname, jrev2, jdate2);
2249 "file %s has been modified, but has been removed in revision %s",
2250 finfo->fullname, jrev2);
2252 /* FIXME: Should we arrange to return a non-zero exit
2264 /* The user file exists and has not been modified. Mark it
2265 for removal. FIXME: If we are doing a checkout, this has
2266 the effect of first checking out the file, and then
2267 removing it. It would be better to just register the
2270 The same goes for a removal then an add. e.g.
2271 cvs up -rbr -jbr2 could remove and readd the same file
2273 /* save the rev since server_updated might invalidate it */
2274 mrev = Xasprintf ("-%s", vers->vn_user);
2275 #ifdef SERVER_SUPPORT
2278 server_scratch (finfo->file);
2279 server_updated (finfo, vers, SERVER_UPDATED, (mode_t) -1,
2283 Register (finfo->entries, finfo->file, mrev, vers->ts_rcs,
2284 vers->options, vers->tag, vers->date, vers->ts_conflict);
2286 /* We need to check existence_error here because if we are
2287 running as the server, and the file is up to date in the
2288 working directory, the client will not have sent us a copy. */
2289 if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
2290 error (0, errno, "cannot remove file %s", finfo->fullname);
2291 #ifdef SERVER_SUPPORT
2293 server_checked_in (finfo->file, finfo->update_dir,
2297 error (0, 0, "scheduling `%s' for removal", finfo->fullname);
2302 /* If the two merge revisions are the same, then there is nothing
2303 * to do. This needs to be checked before the rev2 == up-to-date base
2304 * revision check tha comes next. Otherwise, rev1 can == rev2 and get an
2305 * "already contains the changes between <rev1> and <rev1>" message.
2307 if (rev1 && strcmp (rev1, rev2) == 0)
2314 /* If we know that the user file is up-to-date, then it becomes an
2315 * optimization to skip the merge when rev2 is the same as the base
2316 * revision. i.e. we know that diff3(file2,file1,file2) will produce
2319 if (vers->vn_user != NULL && vers->ts_user != NULL
2320 && strcmp (vers->ts_user, vers->ts_rcs) == 0
2321 && strcmp (rev2, vers->vn_user) == 0)
2325 cvs_output (finfo->fullname, 0);
2326 cvs_output (" already contains the differences between ", 0);
2327 cvs_output (rev1 ? rev1 : "creation", 0);
2328 cvs_output (" and ", 0);
2329 cvs_output (rev2, 0);
2330 cvs_output ("\n", 1);
2340 /* If rev1 is dead or does not exist, then the file was added
2341 between rev1 and rev2. */
2342 if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
2348 /* If the file does not exist in the working directory, then
2349 we can just check out the new revision and mark it for
2351 if (vers->vn_user == NULL)
2353 char *saved_options = options;
2356 xvers = Version_TS (finfo, vers->options, jrev2, jdate2, 1, 0);
2358 /* Reset any keyword expansion option. Otherwise, when a
2359 command like `cvs update -kk -jT1 -jT2' creates a new file
2360 (because a file had the T2 tag, but not T1), the subsequent
2361 commit of that just-added file effectively would set the
2362 admin `-kk' option for that file in the repository. */
2365 /* FIXME: If checkout_file fails, we should arrange to
2366 return a non-zero exit status. */
2367 status = checkout_file (finfo, xvers, 1, 0, 1);
2368 options = saved_options;
2370 freevers_ts (&xvers);
2375 /* The file currently exists in the working directory, so we
2376 have a conflict which we can not resolve. Note that this
2377 is true even if the file is marked for addition or removal. */
2381 "file %s exists, but has been added in revision %s as of %s",
2382 finfo->fullname, jrev2, jdate2);
2385 "file %s exists, but has been added in revision %s",
2386 finfo->fullname, jrev2);
2391 /* If there is no working file, then we can't do the merge. */
2392 if (vers->vn_user == NULL || vers->vn_user[0] == '-')
2399 "file %s does not exist, but is present in revision %s as of %s",
2400 finfo->fullname, jrev2, jdate2);
2403 "file %s does not exist, but is present in revision %s",
2404 finfo->fullname, jrev2);
2406 /* FIXME: Should we arrange to return a non-zero exit status? */
2411 #ifdef SERVER_SUPPORT
2412 if (server_active && !isreadable (finfo->file))
2415 /* The file is up to date. Need to check out the current contents. */
2416 /* FIXME - see the FIXME comment above the call to RCS_checkout in the
2417 * patch_file function.
2419 retcode = RCS_checkout (vers->srcfile, finfo->file,
2420 vers->vn_user, vers->tag,
2421 NULL, RUN_TTY, NULL, NULL);
2424 "failed to check out %s file", finfo->fullname);
2429 * The users currently modified file is moved to a backup file name
2430 * ".#filename.version", so that it will stay around for a few days
2431 * before being automatically removed by some cron daemon. The "version"
2432 * is the version of the file that the user was most up-to-date with
2435 backup = Xasprintf ("%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
2437 if (unlink_file (backup) < 0
2438 && !existence_error (errno))
2439 error (0, errno, "cannot remove %s", backup);
2440 copy_file (finfo->file, backup);
2441 xchmod (finfo->file, 1);
2443 t_options = vers->options;
2445 if (*t_options == '\0')
2446 t_options = "-kk"; /* to ignore keyword expansions */
2449 /* If the source of the merge is the same as the working file
2450 revision, then we can just RCS_checkout the target (no merging
2451 as such). In the text file case, this is probably quite
2452 similar to the RCS_merge, but in the binary file case,
2453 RCS_merge gives all kinds of trouble. */
2454 if (vers->vn_user != NULL
2455 && strcmp (rev1, vers->vn_user) == 0
2456 /* See comments above about how No_Difference has already been
2458 && vers->ts_user != NULL
2459 && strcmp (vers->ts_user, vers->ts_rcs) == 0
2461 /* Avoid this in the text file case. See below for why.
2463 && (strcmp (t_options, "-kb") == 0
2464 || wrap_merge_is_copy (finfo->file)))
2466 /* FIXME: Verify my comment below:
2468 * RCS_merge does nothing with keywords. It merges the changes between
2469 * two revisions without expanding the keywords (it might expand in
2470 * -kk mode before computing the diff between rev1 and rev2 - I'm not
2471 * sure). In other words, the keyword lines in the current work file
2474 * Therfore, checking out the destination revision (rev2) is probably
2475 * incorrect in the text case since we should see the keywords that were
2476 * substituted into the original file at the time it was checked out
2477 * and not the keywords from rev2.
2479 * Also, it is safe to pass in NULL for nametag since we know no
2480 * substitution is happening during the binary mode checkout.
2482 if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, t_options,
2483 RUN_TTY, NULL, NULL) != 0)
2488 /* OK, this is really stupid. RCS_checkout carefully removes
2489 write permissions, and we carefully put them back. But
2490 until someone gets around to fixing it, that seems like the
2491 easiest way to get what would seem to be the right mode.
2492 I don't check CVSWRITE or _watched; I haven't thought about
2493 that in great detail, but it seems like a watched file should
2494 be checked out (writable) after a merge. */
2495 xchmod (finfo->file, 1);
2497 /* Traditionally, the text file case prints a whole bunch of
2498 scary looking and verbose output which fails to tell the user
2499 what is really going on (it gives them rev1 and rev2 but doesn't
2500 indicate in any way that rev1 == vn_user). I think just a
2501 simple "U foo" is good here; it seems analogous to the case in
2502 which the file was added on the branch in terms of what to
2504 write_letter (finfo, 'U');
2506 else if (strcmp (t_options, "-kb") == 0
2507 || wrap_merge_is_copy (finfo->file)
2508 || special_file_mismatch (finfo, rev1, rev2))
2510 /* We are dealing with binary files, or files with a
2511 permission/linkage mismatch (this second case only occurs when
2512 PRESERVE_PERMISSIONS_SUPPORT is enabled), and real merging would
2513 need to take place. This is a conflict. We give the user
2514 the two files, and let them resolve it. It is possible
2515 that we should require a "touch foo" or similar step before
2516 we allow a checkin. */
2517 if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL,
2518 t_options, RUN_TTY, NULL, NULL) != 0)
2523 /* OK, this is really stupid. RCS_checkout carefully removes
2524 write permissions, and we carefully put them back. But
2525 until someone gets around to fixing it, that seems like the
2526 easiest way to get what would seem to be the right mode.
2527 I don't check CVSWRITE or _watched; I haven't thought about
2528 that in great detail, but it seems like a watched file should
2529 be checked out (writable) after a merge. */
2530 xchmod (finfo->file, 1);
2532 /* Hmm. We don't give them REV1 anywhere. I guess most people
2533 probably don't have a 3-way merge tool for the file type in
2534 question, and might just get confused if we tried to either
2535 provide them with a copy of the file from REV1, or even just
2536 told them what REV1 is so they can get it themself, but it
2537 might be worth thinking about. */
2538 /* See comment in merge_file about the "nonmergeable file"
2540 error (0, 0, "nonmergeable file needs merge");
2541 error (0, 0, "revision %s from repository is now in %s",
2542 rev2, finfo->fullname);
2543 error (0, 0, "file from working directory is now in %s", backup);
2544 write_letter (finfo, 'C');
2547 status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
2548 t_options, rev1, rev2);
2554 error (0, status == -1 ? errno : 0,
2555 "could not merge revision %s of %s", rev2, finfo->fullname);
2556 error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
2557 finfo->fullname, backup);
2558 rename_file (backup, finfo->file);
2561 else /* status == 0 */
2563 /* FIXME: the noexec case is broken. RCS_merge could be doing the
2564 xcmp on the temporary files without much hassle, I think. */
2565 if (!noexec && !xcmp (backup, finfo->file))
2569 cvs_output (finfo->fullname, 0);
2570 cvs_output (" already contains the differences between ", 0);
2571 cvs_output (rev1, 0);
2572 cvs_output (" and ", 0);
2573 cvs_output (rev2, 0);
2574 cvs_output ("\n", 1);
2577 /* and skip the registering and sending the new file since it
2578 * hasn't been updated.
2584 /* The file has changed, but if we just checked it out it may
2585 still have the same timestamp it did when it was first
2586 registered above in checkout_file. We register it again with a
2587 dummy timestamp to make sure that later runs of CVS will
2588 recognize that it has changed.
2590 We don't actually need to register again if we called
2591 RCS_checkout above, and we aren't running as the server.
2592 However, that is not the normal case, and calling Register
2593 again won't cost much in that case. */
2599 (void) time (&last_register_time);
2600 cp = time_stamp (finfo->file);
2602 Register (finfo->entries, finfo->file,
2603 vers->vn_rcs ? vers->vn_rcs : "0", "Result of merge",
2604 vers->options, vers->tag, vers->date, cp);
2609 #ifdef SERVER_SUPPORT
2612 server_copy_file (finfo->file, finfo->update_dir, finfo->repository,
2614 server_updated (finfo, vers, SERVER_MERGED, (mode_t) -1, NULL, NULL);
2627 * Report whether revisions REV1 and REV2 of FINFO agree on:
2630 * . major and minor device numbers
2634 * If either REV1 or REV2 is NULL, the working copy is used instead.
2636 * Return 1 if the files differ on these data.
2640 special_file_mismatch (struct file_info *finfo, char *rev1, char *rev2)
2642 #ifdef PRESERVE_PERMISSIONS_SUPPORT
2646 uid_t rev1_uid, rev2_uid;
2647 gid_t rev1_gid, rev2_gid;
2648 mode_t rev1_mode, rev2_mode;
2649 unsigned long dev_long;
2650 dev_t rev1_dev, rev2_dev;
2651 char *rev1_symlink = NULL;
2652 char *rev2_symlink = NULL;
2653 List *rev1_hardlinks = NULL;
2654 List *rev2_hardlinks = NULL;
2655 int check_uids, check_gids, check_modes;
2658 /* If we don't care about special file info, then
2659 don't report a mismatch in any case. */
2660 if (!preserve_perms)
2663 /* When special_file_mismatch is called from No_Difference, the
2664 RCS file has been only partially parsed. We must read the
2665 delta tree in order to compare special file info recorded in
2666 the delta nodes. (I think this is safe. -twp) */
2667 if (finfo->rcs->flags & PARTIAL)
2668 RCS_reparsercsfile (finfo->rcs, NULL, NULL);
2670 check_uids = check_gids = check_modes = 1;
2672 /* Obtain file information for REV1. If this is null, then stat
2673 finfo->file and use that info. */
2674 /* If a revision does not know anything about its status,
2675 then presumably it doesn't matter, and indicates no conflict. */
2681 if ((rsize = islink (finfo->file)) > 0)
2682 rev1_symlink = Xreadlink (finfo->file, rsize);
2685 # ifdef HAVE_STRUCT_STAT_ST_RDEV
2686 if (CVS_LSTAT (finfo->file, &sb) < 0)
2687 error (1, errno, "could not get file information for %s",
2689 rev1_uid = sb.st_uid;
2690 rev1_gid = sb.st_gid;
2691 rev1_mode = sb.st_mode;
2692 if (S_ISBLK (rev1_mode) || S_ISCHR (rev1_mode))
2693 rev1_dev = sb.st_rdev;
2695 error (1, 0, "cannot handle device files on this system (%s)",
2699 rev1_hardlinks = list_linked_files_on_disk (finfo->file);
2703 n = findnode (finfo->rcs->versions, rev1);
2706 n = findnode (vp->other_delta, "symlink");
2708 rev1_symlink = xstrdup (n->data);
2711 n = findnode (vp->other_delta, "owner");
2713 check_uids = 0; /* don't care */
2715 rev1_uid = strtoul (n->data, NULL, 10);
2717 n = findnode (vp->other_delta, "group");
2719 check_gids = 0; /* don't care */
2721 rev1_gid = strtoul (n->data, NULL, 10);
2723 n = findnode (vp->other_delta, "permissions");
2725 check_modes = 0; /* don't care */
2727 rev1_mode = strtoul (n->data, NULL, 8);
2729 n = findnode (vp->other_delta, "special");
2731 rev1_mode |= S_IFREG;
2734 /* If the size of `ftype' changes, fix the sscanf call also */
2736 if (sscanf (n->data, "%15s %lu", ftype,
2738 error (1, 0, "%s:%s has bad `special' newphrase %s",
2739 finfo->file, rev1, (char *)n->data);
2740 rev1_dev = dev_long;
2741 if (strcmp (ftype, "character") == 0)
2742 rev1_mode |= S_IFCHR;
2743 else if (strcmp (ftype, "block") == 0)
2744 rev1_mode |= S_IFBLK;
2746 error (0, 0, "%s:%s unknown file type `%s'",
2747 finfo->file, rev1, ftype);
2750 rev1_hardlinks = vp->hardlinks;
2751 if (rev1_hardlinks == NULL)
2752 rev1_hardlinks = getlist();
2756 /* Obtain file information for REV2. */
2761 if ((rsize = islink (finfo->file)) > 0)
2762 rev2_symlink = Xreadlink (finfo->file, rsize);
2765 # ifdef HAVE_STRUCT_STAT_ST_RDEV
2766 if (CVS_LSTAT (finfo->file, &sb) < 0)
2767 error (1, errno, "could not get file information for %s",
2769 rev2_uid = sb.st_uid;
2770 rev2_gid = sb.st_gid;
2771 rev2_mode = sb.st_mode;
2772 if (S_ISBLK (rev2_mode) || S_ISCHR (rev2_mode))
2773 rev2_dev = sb.st_rdev;
2775 error (1, 0, "cannot handle device files on this system (%s)",
2779 rev2_hardlinks = list_linked_files_on_disk (finfo->file);
2783 n = findnode (finfo->rcs->versions, rev2);
2786 n = findnode (vp->other_delta, "symlink");
2788 rev2_symlink = xstrdup (n->data);
2791 n = findnode (vp->other_delta, "owner");
2793 check_uids = 0; /* don't care */
2795 rev2_uid = strtoul (n->data, NULL, 10);
2797 n = findnode (vp->other_delta, "group");
2799 check_gids = 0; /* don't care */
2801 rev2_gid = strtoul (n->data, NULL, 10);
2803 n = findnode (vp->other_delta, "permissions");
2805 check_modes = 0; /* don't care */
2807 rev2_mode = strtoul (n->data, NULL, 8);
2809 n = findnode (vp->other_delta, "special");
2811 rev2_mode |= S_IFREG;
2814 /* If the size of `ftype' changes, fix the sscanf call also */
2816 if (sscanf (n->data, "%15s %lu", ftype,
2818 error (1, 0, "%s:%s has bad `special' newphrase %s",
2819 finfo->file, rev2, (char *)n->data);
2820 rev2_dev = dev_long;
2821 if (strcmp (ftype, "character") == 0)
2822 rev2_mode |= S_IFCHR;
2823 else if (strcmp (ftype, "block") == 0)
2824 rev2_mode |= S_IFBLK;
2826 error (0, 0, "%s:%s unknown file type `%s'",
2827 finfo->file, rev2, ftype);
2830 rev2_hardlinks = vp->hardlinks;
2831 if (rev2_hardlinks == NULL)
2832 rev2_hardlinks = getlist();
2836 /* Check the user/group ownerships and file permissions, printing
2837 an error for each mismatch found. Return 0 if all characteristics
2838 matched, and 1 otherwise. */
2842 /* Compare symlinks first, since symlinks are simpler (don't have
2843 any other characteristics). */
2844 if (rev1_symlink != NULL && rev2_symlink == NULL)
2846 error (0, 0, "%s is a symbolic link",
2847 (rev1 == NULL ? "working file" : rev1));
2850 else if (rev1_symlink == NULL && rev2_symlink != NULL)
2852 error (0, 0, "%s is a symbolic link",
2853 (rev2 == NULL ? "working file" : rev2));
2856 else if (rev1_symlink != NULL)
2857 result = (strcmp (rev1_symlink, rev2_symlink) == 0);
2860 /* Compare user ownership. */
2861 if (check_uids && rev1_uid != rev2_uid)
2863 error (0, 0, "%s: owner mismatch between %s and %s",
2865 (rev1 == NULL ? "working file" : rev1),
2866 (rev2 == NULL ? "working file" : rev2));
2870 /* Compare group ownership. */
2871 if (check_gids && rev1_gid != rev2_gid)
2873 error (0, 0, "%s: group mismatch between %s and %s",
2875 (rev1 == NULL ? "working file" : rev1),
2876 (rev2 == NULL ? "working file" : rev2));
2880 /* Compare permissions. */
2882 (rev1_mode & 07777) != (rev2_mode & 07777))
2884 error (0, 0, "%s: permission mismatch between %s and %s",
2886 (rev1 == NULL ? "working file" : rev1),
2887 (rev2 == NULL ? "working file" : rev2));
2891 /* Compare device file characteristics. */
2892 if ((rev1_mode & S_IFMT) != (rev2_mode & S_IFMT))
2894 error (0, 0, "%s: %s and %s are different file types",
2896 (rev1 == NULL ? "working file" : rev1),
2897 (rev2 == NULL ? "working file" : rev2));
2900 else if (S_ISBLK (rev1_mode))
2902 if (rev1_dev != rev2_dev)
2904 error (0, 0, "%s: device numbers of %s and %s do not match",
2906 (rev1 == NULL ? "working file" : rev1),
2907 (rev2 == NULL ? "working file" : rev2));
2912 /* Compare hard links. */
2913 if (compare_linkage_lists (rev1_hardlinks, rev2_hardlinks) == 0)
2915 error (0, 0, "%s: hard linkage of %s and %s do not match",
2917 (rev1 == NULL ? "working file" : rev1),
2918 (rev2 == NULL ? "working file" : rev2));
2923 if (rev1_symlink != NULL)
2924 free (rev1_symlink);
2925 if (rev2_symlink != NULL)
2926 free (rev2_symlink);
2927 if (rev1_hardlinks != NULL)
2928 dellist (&rev1_hardlinks);
2929 if (rev2_hardlinks != NULL)
2930 dellist (&rev2_hardlinks);
2943 return join_rev1 || join_date1;