2 * Copyright (c) 1992, Brian Berliner and Jeff Polk
3 * Copyright (c) 1989-1992, Brian Berliner
5 * You may distribute under the terms of the GNU General Public License as
6 * specified in the README file that comes with the CVS source distribution.
8 * "update" updates the version in the present directory with respect to the RCS
9 * repository. The present version must have been created by "checkout". The
10 * user can keep up-to-date by calling "update" whenever he feels like it.
12 * The present version can be committed by "commit", but this keeps the version
15 * Arguments following the options are taken to be file names to be updated,
16 * rather than updating the entire directory.
18 * Modified or non-existent RCS files are checked out and reported as U
21 * Modified user files are reported as M <user_file>. If both the RCS file and
22 * the user file have been modified, the user file is replaced by the result
23 * of rcsmerge, and a backup file is written for the user in .#file.version.
24 * If this throws up irreconcilable differences, the file is reported as C
25 * <user_file>, and as M <user_file> otherwise.
27 * Files added but not yet committed are reported as A <user_file>. Files
28 * removed but not yet committed are reported as R <user_file>.
30 * If the current directory contains subdirectories that hold concurrent
31 * versions, these are updated too. If the -d option was specified, new
32 * directories added to the repository are automatically created and updated
48 static int checkout_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts,
49 int adding, int merging, int update_server));
51 static void checkout_to_buffer PROTO ((void *, const char *, size_t));
52 static int patch_file PROTO ((struct file_info *finfo,
54 int *docheckout, struct stat *file_info,
55 unsigned char *checksum));
56 static void patch_file_write PROTO ((void *, const char *, size_t));
57 #endif /* SERVER_SUPPORT */
58 static int merge_file PROTO ((struct file_info *finfo, Vers_TS *vers));
59 static int scratch_file PROTO((struct file_info *finfo, Vers_TS *vers));
60 static Dtype update_dirent_proc PROTO ((void *callerdat, const char *dir,
61 const char *repository,
62 const char *update_dir,
64 static int update_dirleave_proc PROTO ((void *callerdat, const char *dir,
65 int err, const char *update_dir,
67 static int update_fileproc PROTO ((void *callerdat, struct file_info *));
68 static int update_filesdone_proc PROTO ((void *callerdat, int err,
69 const char *repository,
70 const char *update_dir,
72 #ifdef PRESERVE_PERMISSIONS_SUPPORT
73 static int get_linkinfo_proc PROTO ((void *callerdat, struct file_info *));
75 static void join_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts));
77 static char *options = NULL;
78 static char *tag = NULL;
79 static char *date = NULL;
80 /* This is a bit of a kludge. We call WriteTag at the beginning
81 before we know whether nonbranch is set or not. And then at the
82 end, once we have the right value for nonbranch, we call WriteTag
83 again. I don't know whether the first call is necessary or not.
84 rewrite_tag is nonzero if we are going to have to make that second
86 static int rewrite_tag;
89 /* If we set the tag or date for a subdirectory, we use this to undo
90 the setting. See update_dirent_proc. */
91 static char *tag_update_dir;
93 static char *join_rev1, *date_rev1;
94 static char *join_rev2, *date_rev2;
96 static int toss_local_changes = 0;
97 static int force_tag_match = 1;
98 static int update_build_dirs = 0;
99 static int update_prune_dirs = 0;
100 static int pipeout = 0;
101 static int dotemplate = 0;
102 #ifdef SERVER_SUPPORT
103 static int patches = 0;
104 static int rcs_diff_patches = 0;
106 static List *ignlist = (List *) NULL;
107 static time_t last_register_time;
108 static const char *const update_usage[] =
110 "Usage: %s %s [-APCdflRp] [-k kopt] [-r rev] [-D date] [-j rev]\n",
111 " [-I ign] [-W spec] [files...]\n",
112 "\t-A\tReset any sticky tags/date/kopts.\n",
113 "\t-P\tPrune empty directories.\n",
114 "\t-C\tOverwrite locally modified files with clean repository copies.\n",
115 "\t-d\tBuild directories, like checkout does.\n",
116 "\t-f\tForce a head revision match if tag/date not found.\n",
117 "\t-l\tLocal directory only, no recursion.\n",
118 "\t-R\tProcess directories recursively.\n",
119 "\t-p\tSend updates to standard output (avoids stickiness).\n",
120 "\t-k kopt\tUse RCS kopt -k option on checkout. (is sticky)\n",
121 "\t-r rev\tUpdate using specified revision/tag (is sticky).\n",
122 "\t-D date\tSet date to update from (is sticky).\n",
123 "\t-j rev\tMerge in changes made between current revision and rev.\n",
124 "\t-I ign\tMore files to ignore (! to reset).\n",
125 "\t-W spec\tWrappers specification line.\n",
126 "(Specify the --help global option for a list of other help options)\n",
131 * update is the argv,argc based front end for arg parsing
139 int local = 0; /* recursive by default */
140 int which; /* where to look for files and dirs */
143 usage (update_usage);
150 while ((c = getopt (argc, argv, "+ApCPflRQqduk:r:D:j:I:W:")) != -1)
158 toss_local_changes = 1;
164 wrap_add (optarg, 0);
169 options = RCS_check_kflag (optarg);
179 #ifdef SERVER_SUPPORT
180 /* The CVS 1.5 client sends these options (in addition to
181 Global_option requests), so we must ignore them. */
185 "-q or -Q must be specified before \"%s\"",
189 update_build_dirs = 1;
198 date = Make_Date (optarg);
201 update_prune_dirs = 1;
205 noexec = 1; /* so no locks will be created */
209 error (1, 0, "only two -j options can be specified");
216 #ifdef SERVER_SUPPORT
220 rcs_diff_patches = server_use_rcs_diff ();
224 usage (update_usage);
228 usage (update_usage);
235 #ifdef CLIENT_SUPPORT
236 if (current_parsed_root->isremote)
240 /* The first pass does the regular update. If we receive at least
241 one patch which failed, we do a second pass and just fetch
242 those files whose patches failed. */
252 if (update_build_dirs)
256 if (!force_tag_match)
260 if (toss_local_changes)
262 if (update_prune_dirs)
264 client_prune_dirs = update_prune_dirs;
265 option_with_arg ("-r", tag);
266 if (options && options[0] != '\0')
269 client_senddate (date);
271 option_with_arg ("-j", join_rev1);
273 option_with_arg ("-j", join_rev2);
276 if (failed_patches_count == 0)
278 unsigned int flags = 0;
280 /* If the server supports the command "update-patches", that
281 means that it knows how to handle the -u argument to update,
282 which means to send patches instead of complete files.
284 We don't send -u if failed_patches != NULL, so that the
285 server doesn't try to send patches which will just fail
286 again. At least currently, the client also clobbers the
287 file and tells the server it is lost, which also will get
288 a full file instead of a patch, but it seems clean to omit
290 if (supported_request ("update-patches"))
295 if (update_build_dirs)
296 flags |= SEND_BUILD_DIRS;
298 if (toss_local_changes) {
299 flags |= SEND_NO_CONTENTS;
300 flags |= BACKUP_MODIFIED_FILES;
303 /* If noexec, probably could be setting SEND_NO_CONTENTS.
304 Same caveats as for "cvs status" apply. */
306 send_files (argc, argv, local, aflag, flags);
307 send_file_names (argc, argv, SEND_EXPAND_WILD);
313 (void) printf ("%s client: refetching unpatchable files\n",
316 if (toplevel_wd != NULL
317 && CVS_CHDIR (toplevel_wd) < 0)
319 error (1, errno, "could not chdir to %s", toplevel_wd);
324 for (i = 0; i < failed_patches_count; i++)
325 if (unlink_file (failed_patches[i]) < 0
326 && !existence_error (errno))
327 error (0, errno, "cannot remove %s",
329 send_files (failed_patches_count, failed_patches, local,
330 aflag, update_build_dirs ? SEND_BUILD_DIRS : 0);
331 send_file_names (failed_patches_count, failed_patches, 0);
332 free_names (&failed_patches_count, failed_patches);
335 send_to_server ("update\012", 0);
337 status = get_responses_and_close ();
339 /* If there are any conflicts, the server will return a
340 non-zero exit status. If any patches failed, we still
341 want to run the update again. We use a pass count to
342 avoid an endless loop. */
344 /* Notes: (1) assuming that status != 0 implies a
345 potential conflict is the best we can cleanly do given
346 the current protocol. I suppose that trying to
347 re-fetch in cases where there was a more serious error
348 is probably more or less harmless, but it isn't really
349 ideal. (2) it would be nice to have a testsuite case for the
350 conflict-and-patch-failed case. */
353 && (failed_patches_count == 0 || pass > 1))
355 if (failed_patches_count > 0)
356 free_names (&failed_patches_count, failed_patches);
361 } while (failed_patches_count > 0);
368 tag_check_valid (tag, argc, argv, local, aflag, "");
369 if (join_rev1 != NULL)
370 tag_check_valid_join (join_rev1, argc, argv, local, aflag, "");
371 if (join_rev2 != NULL)
372 tag_check_valid_join (join_rev2, argc, argv, local, aflag, "");
375 * If we are updating the entire directory (for real) and building dirs
376 * as we go, we make sure there is no static entries file and write the
377 * tag file as appropriate
379 if (argc <= 0 && !pipeout)
381 if (update_build_dirs)
383 if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno))
384 error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT);
385 #ifdef SERVER_SUPPORT
388 char *repos = Name_Repository (NULL, NULL);
389 server_clear_entstat (".", repos);
395 /* keep the CVS/Tag file current with the specified arguments */
396 if (aflag || tag || date)
398 char *repos = Name_Repository (NULL, NULL);
399 WriteTag ((char *) NULL, tag, date, 0, ".", repos);
406 /* look for files/dirs locally and in the repository */
407 which = W_LOCAL | W_REPOS;
409 /* look in the attic too if a tag or date is specified */
410 if (tag != NULL || date != NULL || joining())
413 /* call the command line interface */
414 err = do_update (argc, argv, options, tag, date, force_tag_match,
415 local, update_build_dirs, aflag, update_prune_dirs,
416 pipeout, which, join_rev1, join_rev2, (char *) NULL, 1,
419 /* free the space Make_Date allocated if necessary */
429 * Command line interface to update (used by checkout)
432 do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag,
433 xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir,
434 xdotemplate, repository)
449 char *preload_update_dir;
456 /* fill in the statics */
460 force_tag_match = xforce;
461 update_build_dirs = xbuild;
463 update_prune_dirs = xprune;
465 dotemplate = xdotemplate;
467 /* setup the join support */
468 join_rev1 = xjoin_rev1;
469 join_rev2 = xjoin_rev2;
470 if (join_rev1 && (cp = strchr (join_rev1, ':')) != NULL)
473 date_rev1 = Make_Date (cp);
476 date_rev1 = (char *) NULL;
477 if (join_rev2 && (cp = strchr (join_rev2, ':')) != NULL)
480 date_rev2 = Make_Date (cp);
483 date_rev2 = (char *) NULL;
485 #ifdef PRESERVE_PERMISSIONS_SUPPORT
488 /* We need to do an extra recursion, bleah. It's to make sure
489 that we know as much as possible about file linkage. */
490 hardlist = getlist();
491 working_dir = xgetwd(); /* save top-level working dir */
493 /* FIXME-twp: the arguments to start_recursion make me dizzy. This
494 function call was copied from the update_fileproc call that
495 follows it; someone should make sure that I did it right. */
496 err = start_recursion (get_linkinfo_proc, (FILESDONEPROC) NULL,
497 (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
498 argc, argv, local, which, aflag, CVS_LOCK_READ,
499 preload_update_dir, 1, (char *) NULL);
503 /* FIXME-twp: at this point we should walk the hardlist
504 and update the `links' field of each hardlink_info struct
505 to list the files that are linked on dist. That would make
506 it easier & more efficient to compare the disk linkage with
507 the repository linkage (a simple strcmp). */
511 /* call the recursion processor */
512 err = start_recursion (update_fileproc, update_filesdone_proc,
513 update_dirent_proc, update_dirleave_proc, NULL,
514 argc, argv, local, which, aflag, CVS_LOCK_READ,
515 preload_update_dir, 1, repository);
517 #ifdef SERVER_SUPPORT
522 /* see if we need to sleep before returning to avoid time-stamp races */
523 if (last_register_time)
525 sleep_past (last_register_time);
531 #ifdef PRESERVE_PERMISSIONS_SUPPORT
533 * The get_linkinfo_proc callback adds each file to the hardlist
538 get_linkinfo_proc (callerdat, finfo)
540 struct file_info *finfo;
544 struct hardlink_info *hlinfo;
546 /* Get the full pathname of the current file. */
547 fullpath = xmalloc (strlen(working_dir) +
548 strlen(finfo->fullname) + 2);
549 sprintf (fullpath, "%s/%s", working_dir, finfo->fullname);
551 /* To permit recursing into subdirectories, files
552 are keyed on the full pathname and not on the basename. */
553 linkp = lookup_file_by_inode (fullpath);
556 /* The file isn't on disk; we are probably restoring
557 a file that was removed. */
561 /* Create a new, empty hardlink_info node. */
562 hlinfo = (struct hardlink_info *)
563 xmalloc (sizeof (struct hardlink_info));
565 hlinfo->status = (Ctype) 0; /* is this dumb? */
566 hlinfo->checked_out = 0;
568 linkp->data = hlinfo;
577 * This is the callback proc for update. It is called for each file in each
578 * directory by the recursion code. The current directory is the local
579 * instantiation. file is the file name we are to operate on. update_dir is
580 * set to the path relative to where we started (for pretty printing).
581 * repository is the repository. entries and srcfiles are the pre-parsed
582 * entries and source control files.
584 * This routine decides what needs to be done for each file and does the
585 * appropriate magic for checkout
588 update_fileproc (callerdat, finfo)
590 struct file_info *finfo;
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. It is possible that case
602 should elicit a warning or an error. */
605 && finfo->rcs != NULL)
607 char *rev = RCS_getversion (finfo->rcs, tag, NULL, 1, NULL);
609 && !RCS_nodeisbranch (finfo->rcs, tag))
618 * We just return success without doing anything if any of the really
621 * If there is still a valid RCS file, do a regular checkout type
626 case T_UNKNOWN: /* unknown file was explicitly asked
628 case T_REMOVE_ENTRY: /* needs to be un-registered */
629 case T_ADDED: /* added but not committed */
632 case T_CONFLICT: /* old punt-type errors */
635 case T_UPTODATE: /* file was already up-to-date */
636 case T_NEEDS_MERGE: /* needs merging */
637 case T_MODIFIED: /* locally modified */
638 case T_REMOVED: /* removed but not committed */
639 case T_CHECKOUT: /* needs checkout */
640 case T_PATCH: /* needs patch */
641 retval = checkout_file (finfo, vers, 0, 0, 0);
644 default: /* can't ever happen :-) */
646 "unknown file status %d for file %s", status, finfo->file);
655 case T_UNKNOWN: /* unknown file was explicitly asked
657 case T_UPTODATE: /* file was already up-to-date */
660 case T_CONFLICT: /* old punt-type errors */
662 write_letter (finfo, 'C');
664 case T_NEEDS_MERGE: /* needs merging */
665 if (! toss_local_changes)
667 retval = merge_file (finfo, vers);
670 /* else FALL THROUGH */
671 case T_MODIFIED: /* locally modified */
673 if (toss_local_changes)
676 bakname = backup_file (finfo->file, vers->vn_user);
677 /* This behavior is sufficiently unexpected to
678 justify overinformativeness, I think. */
679 #ifdef SERVER_SUPPORT
680 if ((! really_quiet) && (! server_active))
681 #else /* ! SERVER_SUPPORT */
683 #endif /* SERVER_SUPPORT */
684 (void) printf ("(Locally modified %s moved to %s)\n",
685 finfo->file, bakname);
688 /* The locally modified file is still present, but
689 it will be overwritten by the repository copy
692 retval = checkout_file (finfo, vers, 0, 0, 1);
696 if (vers->ts_conflict)
698 if (file_has_conflict (finfo, vers->ts_conflict)
699 || file_has_markers (finfo))
701 write_letter (finfo, 'C');
706 /* Reregister to clear conflict flag. */
707 Register (finfo->entries, finfo->file,
708 vers->vn_rcs, vers->ts_rcs,
709 vers->options, vers->tag,
710 vers->date, (char *)0);
714 write_letter (finfo, 'M');
717 case T_PATCH: /* needs patch */
718 #ifdef SERVER_SUPPORT
722 struct stat file_info;
723 unsigned char checksum[16];
725 retval = patch_file (finfo,
727 &file_info, checksum);
730 if (server_active && retval == 0)
731 server_updated (finfo, vers,
735 file_info.st_mode, checksum,
736 (struct buffer *) NULL);
741 /* If we're not running as a server, just check the
742 file out. It's simpler and faster than producing
743 and applying patches. */
745 case T_CHECKOUT: /* needs checkout */
746 retval = checkout_file (finfo, vers, 0, 0, 1);
748 case T_ADDED: /* added but not committed */
749 write_letter (finfo, 'A');
752 case T_REMOVED: /* removed but not committed */
753 write_letter (finfo, 'R');
756 case T_REMOVE_ENTRY: /* needs to be un-registered */
757 retval = scratch_file (finfo, vers);
759 default: /* can't ever happen :-) */
761 "unknown file status %d for file %s", status, finfo->file);
767 /* only try to join if things have gone well thus far */
768 if (retval == 0 && join_rev1)
769 join_file (finfo, vers);
771 /* if this directory has an ignore list, add this file to it */
772 if (ignlist && (status != T_UNKNOWN || vers->ts_user == NULL))
778 p->key = xstrdup (finfo->file);
779 if (addnode (ignlist, p) != 0)
789 static void update_ignproc PROTO ((const char *, const char *));
792 update_ignproc (file, dir)
796 struct file_info finfo;
799 memset (&finfo, 0, sizeof (finfo));
801 finfo.update_dir = dir;
803 tmp = xstrdup (file);
806 tmp = xmalloc (strlen (file) + strlen (dir) + 10);
812 finfo.fullname = tmp;
813 write_letter (&finfo, '?');
821 update_filesdone_proc (callerdat, err, repository, update_dir, entries)
824 const char *repository;
825 const char *update_dir;
830 WriteTag (NULL, tag, date, nonbranch, update_dir, repository);
834 /* if this directory has an ignore list, process it then free it */
837 ignore_files (ignlist, entries, update_dir, update_ignproc);
841 /* Clean up CVS admin dirs if we are export */
842 if (strcmp (cvs_cmd_name, "export") == 0)
844 /* I'm not sure the existence_error is actually possible (except
845 in cases where we really should print a message), but since
846 this code used to ignore all errors, I'll play it safe. */
847 if (unlink_file_dir (CVSADM) < 0 && !existence_error (errno))
848 error (0, errno, "cannot remove %s directory", CVSADM);
850 #ifdef SERVER_SUPPORT
851 else if (!server_active && !pipeout)
854 #endif /* SERVER_SUPPORT */
856 /* If there is no CVS/Root file, add one */
857 if (!isfile (CVSADM_ROOT))
858 Create_Root ((char *) NULL, current_parsed_root->original);
867 * update_dirent_proc () is called back by the recursion processor before a
868 * sub-directory is processed for update. In this case, update_dirent proc
869 * will probably create the directory unless -d isn't specified and this is a
870 * new directory. A return code of 0 indicates the directory should be
871 * processed by the recursion code. A return of non-zero indicates the
872 * recursion code should skip this directory.
875 update_dirent_proc (callerdat, dir, repository, update_dir, entries)
878 const char *repository;
879 const char *update_dir;
882 if (ignore_directory (update_dir))
884 /* print the warm fuzzy message */
886 error (0, 0, "Ignoring %s", update_dir);
892 /* if we aren't building dirs, blow it off */
893 if (!update_build_dirs)
896 /* Various CVS administrators are in the habit of removing
897 the repository directory for things they don't want any
898 more. I've even been known to do it myself (on rare
899 occasions). Not the usual recommended practice, but we
900 want to try to come up with some kind of
901 reasonable/documented/sensible behavior. Generally
902 the behavior is to just skip over that directory (see
903 dirs test in sanity.sh; the case which reaches here
904 is when update -d is specified, and the working directory
905 is gone but the subdirectory is still mentioned in
908 #ifdef SERVER_SUPPORT
909 /* In the remote case, the client should refrain from
910 sending us the directory in the first place. So we
911 want to continue to give an error, so clients make
915 && !isdir (repository))
920 /* ignore the missing dir if -n is specified */
921 error (0, 0, "New directory `%s' -- ignored", update_dir);
926 /* otherwise, create the dir and appropriate adm files */
928 /* If no tag or date were specified on the command line,
929 and we're not using -A, we want the subdirectory to use
930 the tag and date, if any, of the current directory.
931 That way, update -d will work correctly when working on
934 We use TAG_UPDATE_DIR to undo the tag setting in
935 update_dirleave_proc. If we did not do this, we would
936 not correctly handle a working directory with multiple
937 tags (and maybe we should prohibit such working
938 directories, but they work now and we shouldn't make
939 them stop working without more thought). */
940 if ((tag == NULL && date == NULL) && ! aflag)
942 ParseTag (&tag, &date, &nonbranch);
943 if (tag != NULL || date != NULL)
944 tag_update_dir = xstrdup (update_dir);
947 make_directory (dir);
948 Create_Admin (dir, update_dir, repository, tag, date,
949 /* This is a guess. We will rewrite it later
956 Subdir_Register (entries, (char *) NULL, dir);
959 /* Do we need to check noexec here? */
964 /* The directory exists. Check to see if it has a CVS
967 cvsadmdir = xmalloc (strlen (dir) + 80);
968 strcpy (cvsadmdir, dir);
969 strcat (cvsadmdir, "/");
970 strcat (cvsadmdir, CVSADM);
972 if (!isdir (cvsadmdir))
974 /* We cannot successfully recurse into a directory without a CVS
975 subdirectory. Generally we will have already printed
984 * If we are building dirs and not going to stdout, we make sure there is
985 * no static entries file and write the tag file as appropriate
989 if (update_build_dirs)
993 tmp = xmalloc (strlen (dir) + sizeof (CVSADM_ENTSTAT) + 10);
994 (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENTSTAT);
995 if (unlink_file (tmp) < 0 && ! existence_error (errno))
996 error (1, errno, "cannot remove file %s", tmp);
997 #ifdef SERVER_SUPPORT
999 server_clear_entstat (update_dir, repository);
1004 /* keep the CVS/Tag file current with the specified arguments */
1005 if (aflag || tag || date)
1007 WriteTag (dir, tag, date, 0, update_dir, repository);
1012 /* initialize the ignore list for this directory */
1013 ignlist = getlist ();
1016 /* print the warm fuzzy message */
1018 error (0, 0, "Updating %s", update_dir);
1026 * update_dirleave_proc () is called back by the recursion code upon leaving
1027 * a directory. It will prune empty directories if needed and will execute
1028 * any appropriate update programs.
1032 update_dirleave_proc (callerdat, dir, err, update_dir, entries)
1036 const char *update_dir;
1039 /* Delete the ignore list if it hasn't already been done. */
1043 /* If we set the tag or date for a new subdirectory in
1044 update_dirent_proc, and we're now done with that subdirectory,
1045 undo the tag/date setting. Note that we know that the tag and
1046 date were both originally NULL in this case. */
1047 if (tag_update_dir != NULL && strcmp (update_dir, tag_update_dir) == 0)
1060 free (tag_update_dir);
1061 tag_update_dir = NULL;
1064 if (strchr (dir, '/') == NULL)
1066 /* FIXME: chdir ("..") loses with symlinks. */
1067 /* Prune empty dirs on the way out - if necessary */
1068 (void) CVS_CHDIR ("..");
1069 if (update_prune_dirs && isemptydir (dir, 0))
1071 /* I'm not sure the existence_error is actually possible (except
1072 in cases where we really should print a message), but since
1073 this code used to ignore all errors, I'll play it safe. */
1074 if (unlink_file_dir (dir) < 0 && !existence_error (errno))
1075 error (0, errno, "cannot remove %s directory", dir);
1076 Subdir_Deregister (entries, (char *) NULL, dir);
1085 static int isremoved PROTO ((Node *, void *));
1087 /* Returns 1 if the file indicated by node has been removed. */
1089 isremoved (node, closure)
1093 Entnode *entdata = node->data;
1095 /* If the first character of the version is a '-', the file has been
1097 return (entdata->version && entdata->version[0] == '-') ? 1 : 0;
1102 /* Returns 1 if the argument directory is completely empty, other than the
1103 existence of the CVS directory entry. Zero otherwise. If MIGHT_NOT_EXIST
1104 and the directory doesn't exist, then just return 0. */
1106 isemptydir (dir, might_not_exist)
1108 int might_not_exist;
1113 if ((dirp = CVS_OPENDIR (dir)) == NULL)
1115 if (might_not_exist && existence_error (errno))
1117 error (0, errno, "cannot open directory %s for empty check", dir);
1121 while ((dp = CVS_READDIR (dirp)) != NULL)
1123 if (strcmp (dp->d_name, ".") != 0
1124 && strcmp (dp->d_name, "..") != 0)
1126 if (strcmp (dp->d_name, CVSADM) != 0)
1128 /* An entry other than the CVS directory. The directory
1129 is certainly not empty. */
1130 (void) CVS_CLOSEDIR (dirp);
1135 /* The CVS directory entry. We don't have to worry about
1136 this unless the Entries file indicates that files have
1137 been removed, but not committed, in this directory.
1138 (Removing the directory would prevent people from
1139 comitting the fact that they removed the files!) */
1142 struct saved_cwd cwd;
1144 if (save_cwd (&cwd))
1147 if (CVS_CHDIR (dir) < 0)
1148 error (1, errno, "cannot change directory to %s", dir);
1149 l = Entries_Open (0, NULL);
1150 files_removed = walklist (l, isremoved, 0);
1153 if (restore_cwd (&cwd, NULL))
1157 if (files_removed != 0)
1159 /* There are files that have been removed, but not
1160 committed! Do not consider the directory empty. */
1161 (void) CVS_CLOSEDIR (dirp);
1170 error (0, errno, "cannot read directory %s", dir);
1171 (void) CVS_CLOSEDIR (dirp);
1174 (void) CVS_CLOSEDIR (dirp);
1181 * scratch the Entries file entry associated with a file
1184 scratch_file (finfo, vers)
1185 struct file_info *finfo;
1188 history_write ('W', finfo->update_dir, "", finfo->file, finfo->repository);
1189 Scratch_Entry (finfo->entries, finfo->file);
1190 #ifdef SERVER_SUPPORT
1193 if (vers->ts_user == NULL)
1194 server_scratch_entry_only ();
1195 server_updated (finfo, vers,
1196 SERVER_UPDATED, (mode_t) -1,
1197 (unsigned char *) NULL,
1198 (struct buffer *) NULL);
1201 if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1202 error (0, errno, "unable to remove %s", finfo->fullname);
1204 #ifdef SERVER_SUPPORT
1205 /* skip this step when the server is running since
1206 * server_updated should have handled it */
1210 /* keep the vers structure up to date in case we do a join
1211 * - if there isn't a file, it can't very well have a version number, can it?
1213 if (vers->vn_user != NULL)
1215 free (vers->vn_user);
1216 vers->vn_user = NULL;
1218 if (vers->ts_user != NULL)
1220 free (vers->ts_user);
1221 vers->ts_user = NULL;
1233 checkout_file (finfo, vers_ts, adding, merging, update_server)
1234 struct file_info *finfo;
1241 int set_time, retval = 0;
1244 struct buffer *revbuf;
1249 /* Don't screw with backup files if we're going to stdout, or if
1250 we are the server. */
1252 #ifdef SERVER_SUPPORT
1257 backup = xmalloc (strlen (finfo->file)
1259 + sizeof (CVSPREFIX)
1261 (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
1262 if (isfile (finfo->file))
1263 rename_file (finfo->file, backup);
1266 /* If -f/-t wrappers are being used to wrap up a directory,
1267 then backup might be a directory instead of just a file. */
1268 if (unlink_file_dir (backup) < 0)
1270 /* Not sure if the existence_error check is needed here. */
1271 if (!existence_error (errno))
1272 /* FIXME: should include update_dir in message. */
1273 error (0, errno, "error removing %s", backup);
1280 file_is_dead = RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs);
1285 * if we are checking out to stdout, print a nice message to
1286 * stderr, and add the -p flag to the command */
1292 ===================================================================\n\
1294 cvs_outerr (finfo->fullname, 0);
1297 cvs_outerr (vers_ts->srcfile->path, 0);
1300 cvs_outerr (vers_ts->vn_rcs, 0);
1301 cvs_outerr ("\n***************\n", 0);
1305 #ifdef SERVER_SUPPORT
1309 && ! file_gzip_level
1311 && ! wrap_name_has (finfo->file, WRAP_FROMCVS))
1313 revbuf = buf_nonio_initialize ((BUFMEMERRPROC) NULL);
1314 status = RCS_checkout (vers_ts->srcfile, (char *) NULL,
1315 vers_ts->vn_rcs, vers_ts->tag,
1316 vers_ts->options, RUN_TTY,
1317 checkout_to_buffer, revbuf);
1321 status = RCS_checkout (vers_ts->srcfile,
1322 pipeout ? NULL : finfo->file,
1323 vers_ts->vn_rcs, vers_ts->tag,
1324 vers_ts->options, RUN_TTY,
1325 (RCSCHECKOUTPROC) NULL, (void *) NULL);
1327 if (file_is_dead || status == 0)
1337 if (revbuf != NULL && !noexec)
1341 /* FIXME: We should have RCS_checkout return the mode.
1342 That would also fix the kludge with noexec, above, which
1343 is here only because noexec doesn't write srcfile->path
1345 if (stat (vers_ts->srcfile->path, &sb) < 0)
1348 error (1, errno, "cannot stat %s",
1349 vers_ts->srcfile->path);
1351 mode = sb.st_mode &~ (S_IWRITE | S_IWGRP | S_IWOTH);
1356 && !fileattr_get (finfo->file, "_watched"))
1359 xchmod (finfo->file, 1);
1362 /* We know that we are the server here, so
1363 although xchmod checks umask, we don't bother. */
1364 mode |= (((mode & S_IRUSR) ? S_IWUSR : 0)
1365 | ((mode & S_IRGRP) ? S_IWGRP : 0)
1366 | ((mode & S_IROTH) ? S_IWOTH : 0));
1371 /* A newly checked out file is never under the spell
1372 of "cvs edit". If we think we were editing it
1373 from a previous life, clean up. Would be better to
1374 check for same the working directory instead of
1375 same user, but that is hairy. */
1377 struct addremove_args args;
1379 editor_set (finfo->file, getcaller (), NULL);
1381 memset (&args, 0, sizeof args);
1382 args.remove_temp = 1;
1383 watch_modify_watchers (finfo->file, &args);
1386 /* set the time from the RCS file iff it was unknown before */
1389 && (vers_ts->vn_user == NULL ||
1390 strncmp (vers_ts->ts_rcs, "Initial", 7) == 0)
1393 wrap_fromcvs_process_file (finfo->file);
1395 xvers_ts = Version_TS (finfo, options, tag, date,
1396 force_tag_match, set_time);
1397 if (strcmp (xvers_ts->options, "-V4") == 0)
1398 xvers_ts->options[0] = '\0';
1402 /* If we stored the file data into a buffer, then we
1403 didn't create a file at all, so xvers_ts->ts_user
1404 is wrong. The correct value is to have it be the
1405 same as xvers_ts->ts_rcs, meaning that the working
1406 file is unchanged from the RCS file.
1408 FIXME: We should tell Version_TS not to waste time
1409 statting the nonexistent file.
1411 FIXME: Actually, I don't think the ts_user value
1412 matters at all here. The only use I know of is
1413 that it is printed in a trace message by
1416 if (xvers_ts->ts_user != NULL)
1417 free (xvers_ts->ts_user);
1418 xvers_ts->ts_user = xstrdup (xvers_ts->ts_rcs);
1421 (void) time (&last_register_time);
1425 if (xvers_ts->vn_user != NULL)
1428 "warning: %s is not (any longer) pertinent",
1431 Scratch_Entry (finfo->entries, finfo->file);
1432 #ifdef SERVER_SUPPORT
1433 if (server_active && xvers_ts->ts_user == NULL)
1434 server_scratch_entry_only ();
1436 /* FIXME: Rather than always unlink'ing, and ignoring the
1437 existence_error, we should do the unlink only if
1438 vers_ts->ts_user is non-NULL. Then there would be no
1439 need to ignore an existence_error (for example, if the
1440 user removes the file while we are running). */
1441 if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
1443 error (0, errno, "cannot remove %s", finfo->fullname);
1447 Register (finfo->entries, finfo->file,
1448 adding ? "0" : xvers_ts->vn_rcs,
1449 xvers_ts->ts_user, xvers_ts->options,
1450 xvers_ts->tag, xvers_ts->date,
1451 (char *)0); /* Clear conflict flag on fresh checkout */
1453 /* fix up the vers structure, in case it is used by join */
1456 /* FIXME: Throwing away the original revision info is almost
1457 certainly wrong -- what if join_rev1 is "BASE"? */
1458 if (vers_ts->vn_user != NULL)
1459 free (vers_ts->vn_user);
1460 if (vers_ts->vn_rcs != NULL)
1461 free (vers_ts->vn_rcs);
1462 vers_ts->vn_user = xstrdup (xvers_ts->vn_rcs);
1463 vers_ts->vn_rcs = xstrdup (xvers_ts->vn_rcs);
1466 /* If this is really Update and not Checkout, recode history */
1467 if (strcmp (cvs_cmd_name, "update") == 0)
1468 history_write ('U', finfo->update_dir, xvers_ts->vn_rcs, finfo->file,
1471 freevers_ts (&xvers_ts);
1473 if (!really_quiet && !file_is_dead)
1475 write_letter (finfo, 'U');
1479 #ifdef SERVER_SUPPORT
1480 if (update_server && server_active)
1481 server_updated (finfo, vers_ts,
1482 merging ? SERVER_MERGED : SERVER_UPDATED,
1483 mode, (unsigned char *) NULL, revbuf);
1490 rename_file (backup, finfo->file);
1495 error (0, 0, "could not check out %s", finfo->fullname);
1502 /* If -f/-t wrappers are being used to wrap up a directory,
1503 then backup might be a directory instead of just a file. */
1504 if (unlink_file_dir (backup) < 0)
1506 /* Not sure if the existence_error check is needed here. */
1507 if (!existence_error (errno))
1508 /* FIXME: should include update_dir in message. */
1509 error (0, errno, "error removing %s", backup);
1521 #ifdef SERVER_SUPPORT
1523 /* This function is used to write data from a file being checked out
1527 checkout_to_buffer (callerdat, data, len)
1532 struct buffer *buf = (struct buffer *) callerdat;
1534 buf_output (buf, data, len);
1537 #endif /* SERVER_SUPPORT */
1539 #ifdef SERVER_SUPPORT
1541 /* This structure is used to pass information between patch_file and
1542 patch_file_write. */
1544 struct patch_file_data
1546 /* File name, for error messages. */
1547 const char *filename;
1548 /* File to which to write. */
1550 /* Whether to compute the MD5 checksum. */
1551 int compute_checksum;
1552 /* Data structure for computing the MD5 checksum. */
1553 struct cvs_MD5Context context;
1554 /* Set if the file has a final newline. */
1558 /* Patch a file. Runs diff. This is only done when running as the
1559 * server. The hope is that the diff will be smaller than the file
1563 patch_file (finfo, vers_ts, docheckout, file_info, checksum)
1564 struct file_info *finfo;
1567 struct stat *file_info;
1568 unsigned char *checksum;
1577 struct patch_file_data data;
1581 if (noexec || pipeout || joining ())
1587 /* If this file has been marked as being binary, then never send a
1589 if (strcmp (vers_ts->options, "-kb") == 0)
1595 /* First check that the first revision exists. If it has been nuked
1596 by cvs admin -o, then just fall back to checking out entire
1597 revisions. In some sense maybe we don't have to do this; after
1598 all cvs.texinfo says "Make sure that no-one has checked out a
1599 copy of the revision you outdate" but then again, that advice
1600 doesn't really make complete sense, because "cvs admin" operates
1601 on a working directory and so _someone_ will almost always have
1602 _some_ revision checked out. */
1606 rev = RCS_gettag (finfo->rcs, vers_ts->vn_user, 1, NULL);
1616 /* If the revision is dead, let checkout_file handle it rather
1617 than duplicating the processing here. */
1618 if (RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs))
1624 backup = xmalloc (strlen (finfo->file)
1626 + sizeof (CVSPREFIX)
1628 (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file);
1629 if (isfile (finfo->file))
1630 rename_file (finfo->file, backup);
1633 if (unlink_file (backup) < 0
1634 && !existence_error (errno))
1635 error (0, errno, "cannot remove %s", backup);
1638 file1 = xmalloc (strlen (finfo->file)
1640 + sizeof (CVSPREFIX)
1642 (void) sprintf (file1, "%s/%s%s-1", CVSADM, CVSPREFIX, finfo->file);
1643 file2 = xmalloc (strlen (finfo->file)
1645 + sizeof (CVSPREFIX)
1647 (void) sprintf (file2, "%s/%s%s-2", CVSADM, CVSPREFIX, finfo->file);
1651 /* We need to check out both revisions first, to see if either one
1652 has a trailing newline. Because of this, we don't use rcsdiff,
1653 but just use diff. */
1655 e = CVS_FOPEN (file1, "w");
1657 error (1, errno, "cannot open %s", file1);
1659 data.filename = file1;
1662 data.compute_checksum = 0;
1664 /* FIXME - Passing vers_ts->tag here is wrong in the least number
1665 * of cases. Since we don't know whether vn_user was checked out
1666 * using a tag, we pass vers_ts->tag, which, assuming the user did
1667 * not specify a new TAG to -r, will be the branch we are on.
1669 * The only thing it is used for is to substitute in for the Name
1670 * RCS keyword, so in the error case, the patch fails to apply on
1671 * the client end and we end up resending the whole file.
1673 * At least, if we are keeping track of the tag vn_user came from,
1674 * I don't know where yet. -DRP
1676 retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL,
1677 vers_ts->vn_user, vers_ts->tag,
1678 vers_ts->options, RUN_TTY,
1679 patch_file_write, (void *) &data);
1682 error (1, errno, "cannot close %s", file1);
1684 if (retcode != 0 || ! data.final_nl)
1689 e = CVS_FOPEN (file2, "w");
1691 error (1, errno, "cannot open %s", file2);
1693 data.filename = file2;
1696 data.compute_checksum = 1;
1697 cvs_MD5Init (&data.context);
1699 retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL,
1700 vers_ts->vn_rcs, vers_ts->tag,
1701 vers_ts->options, RUN_TTY,
1702 patch_file_write, (void *) &data);
1705 error (1, errno, "cannot close %s", file2);
1707 if (retcode != 0 || ! data.final_nl)
1710 cvs_MD5Final (checksum, &data.context);
1718 /* If the client does not support the Rcs-diff command, we
1719 send a context diff, and the client must invoke patch.
1720 That approach was problematical for various reasons. The
1721 new approach only requires running diff in the server; the
1722 client can handle everything without invoking an external
1724 if (! rcs_diff_patches)
1726 /* We use -c, not -u, because that is what CVS has
1727 traditionally used. Kind of a moot point, now that
1728 Rcs-diff is preferred, so there is no point in making
1729 the compatibility issues worse. */
1730 diff_options = "-c";
1734 /* Now that diff is librarified, we could be passing -a if
1735 we wanted to. However, it is unclear to me whether we
1736 would want to. Does diff -a, in any significant
1737 percentage of cases, produce patches which are smaller
1738 than the files it is patching? I guess maybe text
1739 files with character sets which diff regards as
1740 'binary'. Conversely, do they tend to be much larger
1741 in the bad cases? This needs some more
1742 thought/investigation, I suspect. */
1744 diff_options = "-n";
1746 retcode = diff_exec (file1, file2, NULL, NULL, diff_options, finfo->file);
1748 /* A retcode of 0 means no differences. 1 means some differences. */
1758 struct stat file2_info;
1760 /* Check to make sure the patch is really shorter */
1761 if (CVS_STAT (file2, &file2_info) < 0)
1762 error (1, errno, "could not stat %s", file2);
1763 if (CVS_STAT (finfo->file, file_info) < 0)
1764 error (1, errno, "could not stat %s", finfo->file);
1765 if (file2_info.st_size <= file_info->st_size)
1771 # define BINARY "Binary"
1772 char buf[sizeof BINARY];
1775 /* Check the diff output to make sure patch will be handle it. */
1776 e = CVS_FOPEN (finfo->file, "r");
1778 error (1, errno, "could not open diff output file %s",
1780 c = fread (buf, 1, sizeof BINARY - 1, e);
1782 if (strcmp (buf, BINARY) == 0)
1784 /* These are binary files. We could use diff -a, but
1785 patch can't handle that. */
1795 /* Stat the original RCS file, and then adjust it the way
1796 that RCS_checkout would. FIXME: This is an abstraction
1798 if (CVS_STAT (vers_ts->srcfile->path, file_info) < 0)
1799 error (1, errno, "could not stat %s", vers_ts->srcfile->path);
1800 if (chmod (finfo->file,
1801 file_info->st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH))
1803 error (0, errno, "cannot change mode of file %s", finfo->file);
1805 && !fileattr_get (finfo->file, "_watched"))
1806 xchmod (finfo->file, 1);
1808 /* This stuff is just copied blindly from checkout_file. I
1809 don't really know what it does. */
1810 xvers_ts = Version_TS (finfo, options, tag, date,
1811 force_tag_match, 0);
1812 if (strcmp (xvers_ts->options, "-V4") == 0)
1813 xvers_ts->options[0] = '\0';
1815 Register (finfo->entries, finfo->file, xvers_ts->vn_rcs,
1816 xvers_ts->ts_user, xvers_ts->options,
1817 xvers_ts->tag, xvers_ts->date, NULL);
1819 if (CVS_STAT (finfo->file, file_info) < 0)
1820 error (1, errno, "could not stat %s", finfo->file);
1822 /* If this is really Update and not Checkout, record history. */
1823 if (strcmp (cvs_cmd_name, "update") == 0)
1824 history_write ('P', finfo->update_dir, xvers_ts->vn_rcs,
1825 finfo->file, finfo->repository);
1827 freevers_ts (&xvers_ts);
1831 write_letter (finfo, 'P');
1836 int old_errno = errno; /* save errno value over the rename */
1838 if (isfile (backup))
1839 rename_file (backup, finfo->file);
1841 if (retcode != 0 && retcode != 1)
1842 error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0,
1843 "could not diff %s", finfo->fullname);
1849 if (unlink_file (backup) < 0
1850 && !existence_error (errno))
1851 error (0, errno, "cannot remove %s", backup);
1852 if (unlink_file (file1) < 0
1853 && !existence_error (errno))
1854 error (0, errno, "cannot remove %s", file1);
1855 if (unlink_file (file2) < 0
1856 && !existence_error (errno))
1857 error (0, errno, "cannot remove %s", file2);
1867 /* Write data to a file. Record whether the last byte written was a
1868 newline. Optionally compute a checksum. This is called by
1869 patch_file via RCS_checkout. */
1872 patch_file_write (callerdat, buffer, len)
1877 struct patch_file_data *data = (struct patch_file_data *) callerdat;
1879 if (fwrite (buffer, 1, len, data->fp) != len)
1880 error (1, errno, "cannot write %s", data->filename);
1882 data->final_nl = (buffer[len - 1] == '\n');
1884 if (data->compute_checksum)
1885 cvs_MD5Update (&data->context, (unsigned char *) buffer, len);
1888 #endif /* SERVER_SUPPORT */
1891 * Several of the types we process only print a bit of information consisting
1892 * of a single letter and the name.
1895 write_letter (finfo, letter)
1896 struct file_info *finfo;
1902 /* Big enough for "+updated" or any of its ilk. */
1911 /* We don't yet support tagged output except for "U". */
1917 sprintf (buf, "+%s", tag);
1918 cvs_output_tagged (buf, NULL);
1923 cvs_output_tagged ("text", buf);
1924 cvs_output_tagged ("fname", finfo->fullname);
1925 cvs_output_tagged ("newline", NULL);
1928 sprintf (buf, "-%s", tag);
1929 cvs_output_tagged (buf, NULL);
1938 * Do all the magic associated with a file which needs to be merged
1941 merge_file (finfo, vers)
1942 struct file_info *finfo;
1951 * The users currently modified file is moved to a backup file name
1952 * ".#filename.version", so that it will stay around for a few days
1953 * before being automatically removed by some cron daemon. The "version"
1954 * is the version of the file that the user was most up-to-date with
1957 backup = xmalloc (strlen (finfo->file)
1958 + strlen (vers->vn_user)
1959 + sizeof (BAKPREFIX)
1961 (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
1963 if (unlink_file (backup) && !existence_error (errno))
1964 error (0, errno, "unable to remove %s", backup);
1965 copy_file (finfo->file, backup);
1966 xchmod (finfo->file, 1);
1968 if (strcmp (vers->options, "-kb") == 0
1969 || wrap_merge_is_copy (finfo->file)
1970 || special_file_mismatch (finfo, NULL, vers->vn_rcs))
1972 /* For binary files, a merge is always a conflict. Same for
1973 files whose permissions or linkage do not match. We give the
1974 user the two files, and let them resolve it. It is possible
1975 that we should require a "touch foo" or similar step before
1976 we allow a checkin. */
1978 /* TODO: it may not always be necessary to regard a permission
1979 mismatch as a conflict. The working file and the RCS file
1980 have a common ancestor `A'; if the working file's permissions
1981 match A's, then it's probably safe to overwrite them with the
1982 RCS permissions. Only if the working file, the RCS file, and
1983 A all disagree should this be considered a conflict. But more
1984 thought needs to go into this, and in the meantime it is safe
1985 to treat any such mismatch as an automatic conflict. -twp */
1987 #ifdef SERVER_SUPPORT
1989 server_copy_file (finfo->file, finfo->update_dir,
1990 finfo->repository, backup);
1993 status = checkout_file (finfo, vers, 0, 1, 1);
1995 /* Is there a better term than "nonmergeable file"? What we
1996 really mean is, not something that CVS cannot or does not
1997 want to merge (there might be an external manual or
1998 automatic merge process). */
1999 error (0, 0, "nonmergeable file needs merge");
2000 error (0, 0, "revision %s from repository is now in %s",
2001 vers->vn_rcs, finfo->fullname);
2002 error (0, 0, "file from working directory is now in %s", backup);
2003 write_letter (finfo, 'C');
2005 history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file,
2011 status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
2012 vers->options, vers->vn_user, vers->vn_rcs);
2013 if (status != 0 && status != 1)
2015 error (0, status == -1 ? errno : 0,
2016 "could not merge revision %s of %s", vers->vn_user, finfo->fullname);
2017 error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
2018 finfo->fullname, backup);
2019 rename_file (backup, finfo->file);
2024 if (strcmp (vers->options, "-V4") == 0)
2025 vers->options[0] = '\0';
2027 /* This file is the result of a merge, which means that it has
2028 been modified. We use a special timestamp string which will
2029 not compare equal to any actual timestamp. */
2035 (void) time (&last_register_time);
2036 cp = time_stamp (finfo->file);
2038 Register (finfo->entries, finfo->file, vers->vn_rcs,
2039 "Result of merge", vers->options, vers->tag,
2045 /* fix up the vers structure, in case it is used by join */
2048 /* FIXME: Throwing away the original revision info is almost
2049 certainly wrong -- what if join_rev1 is "BASE"? */
2050 if (vers->vn_user != NULL)
2051 free (vers->vn_user);
2052 vers->vn_user = xstrdup (vers->vn_rcs);
2055 #ifdef SERVER_SUPPORT
2056 /* Send the new contents of the file before the message. If we
2057 wanted to be totally correct, we would have the client write
2058 the message only after the file has safely been written. */
2061 server_copy_file (finfo->file, finfo->update_dir, finfo->repository,
2063 server_updated (finfo, vers, SERVER_MERGED,
2064 (mode_t) -1, (unsigned char *) NULL,
2065 (struct buffer *) NULL);
2069 /* FIXME: the noexec case is broken. RCS_merge could be doing the
2070 xcmp on the temporary files without much hassle, I think. */
2071 if (!noexec && !xcmp (backup, finfo->file))
2073 cvs_output (finfo->fullname, 0);
2074 cvs_output (" already contains the differences between ", 0);
2075 cvs_output (vers->vn_user, 0);
2076 cvs_output (" and ", 0);
2077 cvs_output (vers->vn_rcs, 0);
2078 cvs_output ("\n", 1);
2080 history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file,
2088 error (0, 0, "conflicts found in %s", finfo->fullname);
2090 write_letter (finfo, 'C');
2092 history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file,
2096 else if (retcode == -1)
2098 error (1, errno, "fork failed while examining update of %s",
2103 write_letter (finfo, 'M');
2104 history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file,
2116 * Do all the magic associated with a file which needs to be joined
2117 * (reached via the -j option to checkout or update).
2120 * finfo File information about the destination file.
2121 * vers The Vers_TS structure for finfo.
2124 * join_rev1 From the command line.
2125 * join_rev2 From the command line.
2126 * server_active Natch.
2129 * 1. Is not called in client mode.
2132 join_file (finfo, vers)
2133 struct file_info *finfo;
2148 fprintf (stderr, "%s-> join_file(%s, %s%s%s%s, %s, %s)\n",
2151 vers->tag ? vers->tag : "",
2152 vers->tag ? " (" : "",
2153 vers->vn_rcs ? vers->vn_rcs : "",
2154 vers->tag ? ")" : "",
2155 join_rev1 ? join_rev1 : "",
2156 join_rev2 ? join_rev2 : "");
2163 /* Determine if we need to do anything at all. */
2164 if (vers->srcfile == NULL ||
2165 vers->srcfile->path == NULL)
2170 /* If only one join revision is specified, it becomes the second
2180 /* FIXME: Need to handle "BASE" for jrev1 and/or jrev2. Note caveat
2181 below about vn_user. */
2183 /* Convert the second revision, walking branches and dates. */
2184 rev2 = RCS_getversion (vers->srcfile, jrev2, jdate2, 1, (int *) NULL);
2186 /* If this is a merge of two revisions, get the first revision.
2187 If only one join tag was specified, then the first revision is
2188 the greatest common ancestor of the second revision and the
2191 rev1 = RCS_getversion (vers->srcfile, jrev1, jdate1, 1, (int *) NULL);
2194 /* Note that we use vn_rcs here, since vn_user may contain a
2195 special string such as "-nn". */
2196 if (vers->vn_rcs == NULL)
2198 else if (rev2 == NULL)
2200 /* This means that the file never existed on the branch.
2201 It does not mean that the file was removed on the
2202 branch: that case is represented by a dead rev2. If
2203 the file never existed on the branch, then we have
2204 nothing to merge, so we just return. */
2208 rev1 = gca (vers->vn_rcs, rev2);
2211 /* Handle a nonexistent or dead merge target. */
2212 if (rev2 == NULL || RCS_isdead (vers->srcfile, rev2))
2219 /* If the first revision doesn't exist either, then there is
2220 no change between the two revisions, so we don't do
2222 if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
2229 /* If we are merging two revisions, then the file was removed
2230 between the first revision and the second one. In this
2231 case we want to mark the file for removal.
2233 If we are merging one revision, then the file has been
2234 removed between the greatest common ancestor and the merge
2235 revision. From the perspective of the branch on to which
2236 we ar emerging, which may be the trunk, either 1) the file
2237 does not currently exist on the target, or 2) the file has
2238 not been modified on the target branch since the greatest
2239 common ancestor, or 3) the file has been modified on the
2240 target branch since the greatest common ancestor. In case
2241 1 there is nothing to do. In case 2 we mark the file for
2242 removal. In case 3 we have a conflict.
2244 Note that the handling is slightly different depending upon
2245 whether one or two join targets were specified. If two
2246 join targets were specified, we don't check whether the
2247 file was modified since a given point. My reasoning is
2248 that if you ask for an explicit merge between two tags,
2249 then you want to merge in whatever was changed between
2250 those two tags. If a file was removed between the two
2251 tags, then you want it to be removed. However, if you ask
2252 for a merge of a branch, then you want to merge in all
2253 changes which were made on the branch. If a file was
2254 removed on the branch, that is a change to the file. If
2255 the file was also changed on the main line, then that is
2256 also a change. These two changes--the file removal and the
2257 modification--must be merged. This is a conflict. */
2259 /* If the user file is dead, or does not exist, or has been
2260 marked for removal, then there is nothing to do. */
2261 if (vers->vn_user == NULL
2262 || vers->vn_user[0] == '-'
2263 || RCS_isdead (vers->srcfile, vers->vn_user))
2270 /* If the user file has been marked for addition, or has been
2271 locally modified, then we have a conflict which we can not
2272 resolve. No_Difference will already have been called in
2273 this case, so comparing the timestamps is sufficient to
2274 determine whether the file is locally modified. */
2275 if (strcmp (vers->vn_user, "0") == 0
2276 || (vers->ts_user != NULL
2277 && strcmp (vers->ts_user, vers->ts_rcs) != 0))
2281 "file %s is locally modified, but has been removed in revision %s as of %s",
2282 finfo->fullname, jrev2, jdate2);
2285 "file %s is locally modified, but has been removed in revision %s",
2286 finfo->fullname, jrev2);
2288 /* FIXME: Should we arrange to return a non-zero exit
2297 /* If only one join tag was specified, and the user file has
2298 been changed since the greatest common ancestor (rev1),
2299 then there is a conflict we can not resolve. See above for
2301 if (join_rev2 == NULL
2302 && strcmp (rev1, vers->vn_user) != 0)
2306 "file %s has been modified, but has been removed in revision %s as of %s",
2307 finfo->fullname, jrev2, jdate2);
2310 "file %s has been modified, but has been removed in revision %s",
2311 finfo->fullname, jrev2);
2313 /* FIXME: Should we arrange to return a non-zero exit
2325 /* The user file exists and has not been modified. Mark it
2326 for removal. FIXME: If we are doing a checkout, this has
2327 the effect of first checking out the file, and then
2328 removing it. It would be better to just register the
2331 The same goes for a removal then an add. e.g.
2332 cvs up -rbr -jbr2 could remove and readd the same file
2334 /* save the rev since server_updated might invalidate it */
2335 mrev = xmalloc (strlen (vers->vn_user) + 2);
2336 sprintf (mrev, "-%s", vers->vn_user);
2337 #ifdef SERVER_SUPPORT
2340 server_scratch (finfo->file);
2341 server_updated (finfo, vers, SERVER_UPDATED, (mode_t) -1,
2342 (unsigned char *) NULL, (struct buffer *) NULL);
2345 Register (finfo->entries, finfo->file, mrev, vers->ts_rcs,
2346 vers->options, vers->tag, vers->date, vers->ts_conflict);
2348 /* We need to check existence_error here because if we are
2349 running as the server, and the file is up to date in the
2350 working directory, the client will not have sent us a copy. */
2351 if (unlink_file (finfo->file) < 0 && ! existence_error (errno))
2352 error (0, errno, "cannot remove file %s", finfo->fullname);
2353 #ifdef SERVER_SUPPORT
2355 server_checked_in (finfo->file, finfo->update_dir,
2359 error (0, 0, "scheduling %s for removal", finfo->fullname);
2364 /* If the two merge revisions are the same, then there is nothing
2365 * to do. This needs to be checked before the rev2 == up-to-date base
2366 * revision check tha comes next. Otherwise, rev1 can == rev2 and get an
2367 * "already contains the changes between <rev1> and <rev1>" message.
2369 if (rev1 && strcmp (rev1, rev2) == 0)
2376 /* If we know that the user file is up-to-date, then it becomes an
2377 * optimization to skip the merge when rev2 is the same as the base
2378 * revision. i.e. we know that diff3(file2,file1,file2) will produce
2381 if (vers->vn_user != NULL && vers->ts_user != NULL
2382 && strcmp (vers->ts_user, vers->ts_rcs) == 0
2383 && strcmp (rev2, vers->vn_user) == 0)
2387 cvs_output (finfo->fullname, 0);
2388 cvs_output (" already contains the differences between ", 0);
2389 cvs_output (rev1 ? rev1 : "creation", 0);
2390 cvs_output (" and ", 0);
2391 cvs_output (rev2, 0);
2392 cvs_output ("\n", 1);
2402 /* If rev1 is dead or does not exist, then the file was added
2403 between rev1 and rev2. */
2404 if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1))
2410 /* If the file does not exist in the working directory, then
2411 we can just check out the new revision and mark it for
2413 if (vers->vn_user == NULL)
2415 char *saved_options = options;
2418 xvers = Version_TS (finfo, vers->options, jrev2, jdate2, 1, 0);
2420 /* Reset any keyword expansion option. Otherwise, when a
2421 command like `cvs update -kk -jT1 -jT2' creates a new file
2422 (because a file had the T2 tag, but not T1), the subsequent
2423 commit of that just-added file effectively would set the
2424 admin `-kk' option for that file in the repository. */
2427 /* FIXME: If checkout_file fails, we should arrange to
2428 return a non-zero exit status. */
2429 status = checkout_file (finfo, xvers, 1, 0, 1);
2430 options = saved_options;
2432 freevers_ts (&xvers);
2437 /* The file currently exists in the working directory, so we
2438 have a conflict which we can not resolve. Note that this
2439 is true even if the file is marked for addition or removal. */
2443 "file %s exists, but has been added in revision %s as of %s",
2444 finfo->fullname, jrev2, jdate2);
2447 "file %s exists, but has been added in revision %s",
2448 finfo->fullname, jrev2);
2453 /* If there is no working file, then we can't do the merge. */
2454 if (vers->vn_user == NULL || vers->vn_user[0] == '-')
2461 "file %s does not exist, but is present in revision %s as of %s",
2462 finfo->fullname, jrev2, jdate2);
2465 "file %s does not exist, but is present in revision %s",
2466 finfo->fullname, jrev2);
2468 /* FIXME: Should we arrange to return a non-zero exit status? */
2473 #ifdef SERVER_SUPPORT
2474 if (server_active && !isreadable (finfo->file))
2477 /* The file is up to date. Need to check out the current contents. */
2478 /* FIXME - see the FIXME comment above the call to RCS_checkout in the
2479 * patch_file function.
2481 retcode = RCS_checkout (vers->srcfile, finfo->file,
2482 vers->vn_user, vers->tag,
2483 (char *) NULL, RUN_TTY,
2484 (RCSCHECKOUTPROC) NULL, (void *) NULL);
2487 "failed to check out %s file", finfo->fullname);
2492 * The users currently modified file is moved to a backup file name
2493 * ".#filename.version", so that it will stay around for a few days
2494 * before being automatically removed by some cron daemon. The "version"
2495 * is the version of the file that the user was most up-to-date with
2498 backup = xmalloc (strlen (finfo->file)
2499 + strlen (vers->vn_user)
2500 + sizeof (BAKPREFIX)
2502 (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user);
2504 if (unlink_file (backup) < 0
2505 && !existence_error (errno))
2506 error (0, errno, "cannot remove %s", backup);
2507 copy_file (finfo->file, backup);
2508 xchmod (finfo->file, 1);
2510 t_options = vers->options;
2512 if (*t_options == '\0')
2513 t_options = "-kk"; /* to ignore keyword expansions */
2516 /* If the source of the merge is the same as the working file
2517 revision, then we can just RCS_checkout the target (no merging
2518 as such). In the text file case, this is probably quite
2519 similar to the RCS_merge, but in the binary file case,
2520 RCS_merge gives all kinds of trouble. */
2521 if (vers->vn_user != NULL
2522 && strcmp (rev1, vers->vn_user) == 0
2523 /* See comments above about how No_Difference has already been
2525 && vers->ts_user != NULL
2526 && strcmp (vers->ts_user, vers->ts_rcs) == 0
2528 /* Avoid this in the text file case. See below for why.
2530 && (strcmp (t_options, "-kb") == 0
2531 || wrap_merge_is_copy (finfo->file)))
2533 /* FIXME: Verify my comment below:
2535 * RCS_merge does nothing with keywords. It merges the changes between
2536 * two revisions without expanding the keywords (it might expand in
2537 * -kk mode before computing the diff between rev1 and rev2 - I'm not
2538 * sure). In other words, the keyword lines in the current work file
2541 * Therfore, checking out the destination revision (rev2) is probably
2542 * incorrect in the text case since we should see the keywords that were
2543 * substituted into the original file at the time it was checked out
2544 * and not the keywords from rev2.
2546 * Also, it is safe to pass in NULL for nametag since we know no
2547 * substitution is happening during the binary mode checkout.
2549 if (RCS_checkout ( finfo->rcs, finfo->file, rev2, (char *)NULL, t_options,
2550 RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0 )
2555 /* OK, this is really stupid. RCS_checkout carefully removes
2556 write permissions, and we carefully put them back. But
2557 until someone gets around to fixing it, that seems like the
2558 easiest way to get what would seem to be the right mode.
2559 I don't check CVSWRITE or _watched; I haven't thought about
2560 that in great detail, but it seems like a watched file should
2561 be checked out (writable) after a merge. */
2562 xchmod (finfo->file, 1);
2564 /* Traditionally, the text file case prints a whole bunch of
2565 scary looking and verbose output which fails to tell the user
2566 what is really going on (it gives them rev1 and rev2 but doesn't
2567 indicate in any way that rev1 == vn_user). I think just a
2568 simple "U foo" is good here; it seems analogous to the case in
2569 which the file was added on the branch in terms of what to
2571 write_letter (finfo, 'U');
2573 else if (strcmp (t_options, "-kb") == 0
2574 || wrap_merge_is_copy (finfo->file)
2575 || special_file_mismatch (finfo, rev1, rev2))
2577 /* We are dealing with binary files, or files with a
2578 permission/linkage mismatch (this second case only occurs when
2579 PRESERVE_PERMISSIONS_SUPPORT is enabled), and real merging would
2580 need to take place. This is a conflict. We give the user
2581 the two files, and let them resolve it. It is possible
2582 that we should require a "touch foo" or similar step before
2583 we allow a checkin. */
2584 if (RCS_checkout ( finfo->rcs, finfo->file, rev2, (char *)NULL,
2585 t_options, RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0)
2590 /* OK, this is really stupid. RCS_checkout carefully removes
2591 write permissions, and we carefully put them back. But
2592 until someone gets around to fixing it, that seems like the
2593 easiest way to get what would seem to be the right mode.
2594 I don't check CVSWRITE or _watched; I haven't thought about
2595 that in great detail, but it seems like a watched file should
2596 be checked out (writable) after a merge. */
2597 xchmod (finfo->file, 1);
2599 /* Hmm. We don't give them REV1 anywhere. I guess most people
2600 probably don't have a 3-way merge tool for the file type in
2601 question, and might just get confused if we tried to either
2602 provide them with a copy of the file from REV1, or even just
2603 told them what REV1 is so they can get it themself, but it
2604 might be worth thinking about. */
2605 /* See comment in merge_file about the "nonmergeable file"
2607 error (0, 0, "nonmergeable file needs merge");
2608 error (0, 0, "revision %s from repository is now in %s",
2609 rev2, finfo->fullname);
2610 error (0, 0, "file from working directory is now in %s", backup);
2611 write_letter (finfo, 'C');
2614 status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
2615 t_options, rev1, rev2);
2621 error (0, status == -1 ? errno : 0,
2622 "could not merge revision %s of %s", rev2, finfo->fullname);
2623 error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s",
2624 finfo->fullname, backup);
2625 rename_file (backup, finfo->file);
2628 else /* status == 0 */
2630 /* FIXME: the noexec case is broken. RCS_merge could be doing the
2631 xcmp on the temporary files without much hassle, I think. */
2632 if (!noexec && !xcmp (backup, finfo->file))
2636 cvs_output (finfo->fullname, 0);
2637 cvs_output (" already contains the differences between ", 0);
2638 cvs_output (rev1, 0);
2639 cvs_output (" and ", 0);
2640 cvs_output (rev2, 0);
2641 cvs_output ("\n", 1);
2644 /* and skip the registering and sending the new file since it
2645 * hasn't been updated.
2651 /* The file has changed, but if we just checked it out it may
2652 still have the same timestamp it did when it was first
2653 registered above in checkout_file. We register it again with a
2654 dummy timestamp to make sure that later runs of CVS will
2655 recognize that it has changed.
2657 We don't actually need to register again if we called
2658 RCS_checkout above, and we aren't running as the server.
2659 However, that is not the normal case, and calling Register
2660 again won't cost much in that case. */
2666 (void) time (&last_register_time);
2667 cp = time_stamp (finfo->file);
2669 Register (finfo->entries, finfo->file,
2670 vers->vn_rcs ? vers->vn_rcs : "0", "Result of merge",
2671 vers->options, vers->tag, vers->date, cp);
2676 #ifdef SERVER_SUPPORT
2679 server_copy_file (finfo->file, finfo->update_dir, finfo->repository,
2681 server_updated (finfo, vers, SERVER_MERGED,
2682 (mode_t) -1, (unsigned char *) NULL,
2683 (struct buffer *) NULL);
2696 * Report whether revisions REV1 and REV2 of FINFO agree on:
2699 * . major and minor device numbers
2703 * If either REV1 or REV2 is NULL, the working copy is used instead.
2705 * Return 1 if the files differ on these data.
2709 special_file_mismatch (finfo, rev1, rev2)
2710 struct file_info *finfo;
2714 #ifdef PRESERVE_PERMISSIONS_SUPPORT
2718 uid_t rev1_uid, rev2_uid;
2719 gid_t rev1_gid, rev2_gid;
2720 mode_t rev1_mode, rev2_mode;
2721 unsigned long dev_long;
2722 dev_t rev1_dev, rev2_dev;
2723 char *rev1_symlink = NULL;
2724 char *rev2_symlink = NULL;
2725 List *rev1_hardlinks = NULL;
2726 List *rev2_hardlinks = NULL;
2727 int check_uids, check_gids, check_modes;
2730 /* If we don't care about special file info, then
2731 don't report a mismatch in any case. */
2732 if (!preserve_perms)
2735 /* When special_file_mismatch is called from No_Difference, the
2736 RCS file has been only partially parsed. We must read the
2737 delta tree in order to compare special file info recorded in
2738 the delta nodes. (I think this is safe. -twp) */
2739 if (finfo->rcs->flags & PARTIAL)
2740 RCS_reparsercsfile (finfo->rcs, NULL, NULL);
2742 check_uids = check_gids = check_modes = 1;
2744 /* Obtain file information for REV1. If this is null, then stat
2745 finfo->file and use that info. */
2746 /* If a revision does not know anything about its status,
2747 then presumably it doesn't matter, and indicates no conflict. */
2751 if (islink (finfo->file))
2752 rev1_symlink = xreadlink (finfo->file);
2755 # ifdef HAVE_STRUCT_STAT_ST_RDEV
2756 if (CVS_LSTAT (finfo->file, &sb) < 0)
2757 error (1, errno, "could not get file information for %s",
2759 rev1_uid = sb.st_uid;
2760 rev1_gid = sb.st_gid;
2761 rev1_mode = sb.st_mode;
2762 if (S_ISBLK (rev1_mode) || S_ISCHR (rev1_mode))
2763 rev1_dev = sb.st_rdev;
2765 error (1, 0, "cannot handle device files on this system (%s)",
2769 rev1_hardlinks = list_linked_files_on_disk (finfo->file);
2773 n = findnode (finfo->rcs->versions, rev1);
2776 n = findnode (vp->other_delta, "symlink");
2778 rev1_symlink = xstrdup (n->data);
2781 n = findnode (vp->other_delta, "owner");
2783 check_uids = 0; /* don't care */
2785 rev1_uid = strtoul (n->data, NULL, 10);
2787 n = findnode (vp->other_delta, "group");
2789 check_gids = 0; /* don't care */
2791 rev1_gid = strtoul (n->data, NULL, 10);
2793 n = findnode (vp->other_delta, "permissions");
2795 check_modes = 0; /* don't care */
2797 rev1_mode = strtoul (n->data, NULL, 8);
2799 n = findnode (vp->other_delta, "special");
2801 rev1_mode |= S_IFREG;
2804 /* If the size of `ftype' changes, fix the sscanf call also */
2806 if (sscanf (n->data, "%15s %lu", ftype,
2808 error (1, 0, "%s:%s has bad `special' newphrase %s",
2809 finfo->file, rev1, (char *)n->data);
2810 rev1_dev = dev_long;
2811 if (strcmp (ftype, "character") == 0)
2812 rev1_mode |= S_IFCHR;
2813 else if (strcmp (ftype, "block") == 0)
2814 rev1_mode |= S_IFBLK;
2816 error (0, 0, "%s:%s unknown file type `%s'",
2817 finfo->file, rev1, ftype);
2820 rev1_hardlinks = vp->hardlinks;
2821 if (rev1_hardlinks == NULL)
2822 rev1_hardlinks = getlist();
2826 /* Obtain file information for REV2. */
2829 if (islink (finfo->file))
2830 rev2_symlink = xreadlink (finfo->file);
2833 # ifdef HAVE_STRUCT_STAT_ST_RDEV
2834 if (CVS_LSTAT (finfo->file, &sb) < 0)
2835 error (1, errno, "could not get file information for %s",
2837 rev2_uid = sb.st_uid;
2838 rev2_gid = sb.st_gid;
2839 rev2_mode = sb.st_mode;
2840 if (S_ISBLK (rev2_mode) || S_ISCHR (rev2_mode))
2841 rev2_dev = sb.st_rdev;
2843 error (1, 0, "cannot handle device files on this system (%s)",
2847 rev2_hardlinks = list_linked_files_on_disk (finfo->file);
2851 n = findnode (finfo->rcs->versions, rev2);
2854 n = findnode (vp->other_delta, "symlink");
2856 rev2_symlink = xstrdup (n->data);
2859 n = findnode (vp->other_delta, "owner");
2861 check_uids = 0; /* don't care */
2863 rev2_uid = strtoul (n->data, NULL, 10);
2865 n = findnode (vp->other_delta, "group");
2867 check_gids = 0; /* don't care */
2869 rev2_gid = strtoul (n->data, NULL, 10);
2871 n = findnode (vp->other_delta, "permissions");
2873 check_modes = 0; /* don't care */
2875 rev2_mode = strtoul (n->data, NULL, 8);
2877 n = findnode (vp->other_delta, "special");
2879 rev2_mode |= S_IFREG;
2882 /* If the size of `ftype' changes, fix the sscanf call also */
2884 if (sscanf (n->data, "%15s %lu", ftype,
2886 error (1, 0, "%s:%s has bad `special' newphrase %s",
2887 finfo->file, rev2, (char *)n->data);
2888 rev2_dev = dev_long;
2889 if (strcmp (ftype, "character") == 0)
2890 rev2_mode |= S_IFCHR;
2891 else if (strcmp (ftype, "block") == 0)
2892 rev2_mode |= S_IFBLK;
2894 error (0, 0, "%s:%s unknown file type `%s'",
2895 finfo->file, rev2, ftype);
2898 rev2_hardlinks = vp->hardlinks;
2899 if (rev2_hardlinks == NULL)
2900 rev2_hardlinks = getlist();
2904 /* Check the user/group ownerships and file permissions, printing
2905 an error for each mismatch found. Return 0 if all characteristics
2906 matched, and 1 otherwise. */
2910 /* Compare symlinks first, since symlinks are simpler (don't have
2911 any other characteristics). */
2912 if (rev1_symlink != NULL && rev2_symlink == NULL)
2914 error (0, 0, "%s is a symbolic link",
2915 (rev1 == NULL ? "working file" : rev1));
2918 else if (rev1_symlink == NULL && rev2_symlink != NULL)
2920 error (0, 0, "%s is a symbolic link",
2921 (rev2 == NULL ? "working file" : rev2));
2924 else if (rev1_symlink != NULL)
2925 result = (strcmp (rev1_symlink, rev2_symlink) == 0);
2928 /* Compare user ownership. */
2929 if (check_uids && rev1_uid != rev2_uid)
2931 error (0, 0, "%s: owner mismatch between %s and %s",
2933 (rev1 == NULL ? "working file" : rev1),
2934 (rev2 == NULL ? "working file" : rev2));
2938 /* Compare group ownership. */
2939 if (check_gids && rev1_gid != rev2_gid)
2941 error (0, 0, "%s: group mismatch between %s and %s",
2943 (rev1 == NULL ? "working file" : rev1),
2944 (rev2 == NULL ? "working file" : rev2));
2948 /* Compare permissions. */
2950 (rev1_mode & 07777) != (rev2_mode & 07777))
2952 error (0, 0, "%s: permission mismatch between %s and %s",
2954 (rev1 == NULL ? "working file" : rev1),
2955 (rev2 == NULL ? "working file" : rev2));
2959 /* Compare device file characteristics. */
2960 if ((rev1_mode & S_IFMT) != (rev2_mode & S_IFMT))
2962 error (0, 0, "%s: %s and %s are different file types",
2964 (rev1 == NULL ? "working file" : rev1),
2965 (rev2 == NULL ? "working file" : rev2));
2968 else if (S_ISBLK (rev1_mode))
2970 if (rev1_dev != rev2_dev)
2972 error (0, 0, "%s: device numbers of %s and %s do not match",
2974 (rev1 == NULL ? "working file" : rev1),
2975 (rev2 == NULL ? "working file" : rev2));
2980 /* Compare hard links. */
2981 if (compare_linkage_lists (rev1_hardlinks, rev2_hardlinks) == 0)
2983 error (0, 0, "%s: hard linkage of %s and %s do not match",
2985 (rev1 == NULL ? "working file" : rev1),
2986 (rev2 == NULL ? "working file" : rev2));
2991 if (rev1_symlink != NULL)
2992 free (rev1_symlink);
2993 if (rev2_symlink != NULL)
2994 free (rev2_symlink);
2995 if (rev1_hardlinks != NULL)
2996 dellist (&rev1_hardlinks);
2997 if (rev2_hardlinks != NULL)
2998 dellist (&rev2_hardlinks);
3011 return join_rev1 != NULL;