1 /* 2 * Copyright (C) 1986-2005 The Free Software Foundation, Inc. 3 * 4 * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, 5 * and others. 6 * 7 * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk 8 * Portions Copyright (C) 1989-1992, Brian Berliner 9 * 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. 12 * 13 * Check In 14 * 15 * Does a very careful checkin of the file "user", and tries not to spoil its 16 * modification time (to avoid needless recompilations). When RCS ID keywords 17 * get expanded on checkout, however, the modification time is updated and 18 * there is no good way to get around this. 19 * 20 * Returns non-zero on error. 21 */ 22 #include <sys/cdefs.h> 23 __RCSID("$NetBSD: checkin.c,v 1.2 2016/05/17 14:00:09 christos Exp $"); 24 25 #include "cvs.h" 26 #include "fileattr.h" 27 #include "edit.h" 28 29 int 30 Checkin (int type, struct file_info *finfo, char *rev, char *tag, 31 char *options, char *message) 32 { 33 Vers_TS *vers; 34 int set_time; 35 char *tocvsPath = NULL; 36 37 tocvsPath = wrap_tocvs_process_file (finfo->file); 38 if (!noexec) 39 { 40 if (tocvsPath) 41 { 42 if (unlink_file_dir (finfo->file) < 0) 43 if (! existence_error (errno)) 44 error (1, errno, "cannot remove %s", finfo->fullname); 45 rename_file (tocvsPath, finfo->file); 46 } 47 } 48 49 /* There use to be a check for finfo->rcs == NULL here and then a 50 * call to RCS_parse when necessary, but Checkin() isn't called 51 * if the RCS file hasn't already been parsed in one of the 52 * check functions. 53 */ 54 assert (finfo->rcs != NULL); 55 56 switch (RCS_checkin (finfo->rcs, finfo->update_dir, finfo->file, message, 57 rev, 0, RCS_FLAGS_KEEPFILE)) 58 { 59 case 0: /* everything normal */ 60 61 /* The checkin succeeded. If checking the file out again 62 would not cause any changes, we are done. Otherwise, 63 we need to check out the file, which will change the 64 modification time of the file. 65 66 The only way checking out the file could cause any 67 changes is if the file contains RCS keywords. So we if 68 we are not expanding RCS keywords, we are done. */ 69 70 if (strcmp (options, "-V4") == 0) /* upgrade to V5 now */ 71 options[0] = '\0'; 72 73 /* FIXME: If PreservePermissions is on, RCS_cmp_file is 74 going to call RCS_checkout into a temporary file 75 anyhow. In that case, it would be more efficient to 76 call RCS_checkout here, compare the resulting files 77 using xcmp, and rename if necessary. I think this 78 should be fixed in RCS_cmp_file. */ 79 if ((1 80 #ifdef PRESERVE_PERMISSIONS_SUPPORT 81 !config->preserve_perms 82 #endif /* PRESERVE_PERMISSIONS_SUPPORT */ 83 && options 84 && (!strcmp (options, "-ko") || !strcmp (options, "-kb"))) 85 || !RCS_cmp_file (finfo->rcs, rev, NULL, NULL, 86 options, finfo->file)) 87 { 88 /* The existing file is correct. We don't have to do 89 anything. */ 90 set_time = 0; 91 } 92 else 93 { 94 /* The existing file is incorrect. We need to check 95 out the correct file contents. */ 96 if (RCS_checkout (finfo->rcs, finfo->file, rev, NULL, 97 options, RUN_TTY, NULL, NULL) != 0) 98 error (1, 0, "failed when checking out new copy of %s", 99 finfo->fullname); 100 xchmod (finfo->file, 1); 101 set_time = 1; 102 } 103 104 wrap_fromcvs_process_file (finfo->file); 105 106 /* 107 * If we want read-only files, muck the permissions here, before 108 * getting the file time-stamp. 109 */ 110 if (!cvswrite || fileattr_get (finfo->file, "_watched")) 111 xchmod (finfo->file, 0); 112 113 /* Re-register with the new data. */ 114 vers = Version_TS (finfo, NULL, tag, NULL, 1, set_time); 115 if (strcmp (vers->options, "-V4") == 0) 116 vers->options[0] = '\0'; 117 Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_user, 118 vers->options, vers->tag, vers->date, NULL); 119 history_write (type, NULL, vers->vn_rcs, 120 finfo->file, finfo->repository); 121 122 if (tocvsPath) 123 if (unlink_file_dir (tocvsPath) < 0) 124 error (0, errno, "cannot remove %s", tocvsPath); 125 126 break; 127 128 case -1: /* fork failed */ 129 if (tocvsPath) 130 if (unlink_file_dir (tocvsPath) < 0) 131 error (0, errno, "cannot remove %s", tocvsPath); 132 133 if (!noexec) 134 error (1, errno, "could not check in %s -- fork failed", 135 finfo->fullname); 136 return (1); 137 138 default: /* ci failed */ 139 140 /* The checkin failed, for some unknown reason, so we 141 print an error, and return an error. We assume that 142 the original file has not been touched. */ 143 if (tocvsPath) 144 if (unlink_file_dir (tocvsPath) < 0) 145 error (0, errno, "cannot remove %s", tocvsPath); 146 147 if (!noexec) 148 error (0, 0, "could not check in %s", finfo->fullname); 149 return (1); 150 } 151 152 /* 153 * When checking in a specific revision, we may have locked the wrong 154 * branch, so to be sure, we do an extra unlock here before 155 * returning. 156 */ 157 if (rev) 158 { 159 (void) RCS_unlock (finfo->rcs, NULL, 1); 160 RCS_rewrite (finfo->rcs, NULL, NULL); 161 } 162 163 #ifdef SERVER_SUPPORT 164 if (server_active) 165 { 166 if (set_time) 167 /* Need to update the checked out file on the client side. */ 168 server_updated (finfo, vers, SERVER_UPDATED, 169 (mode_t) -1, NULL, NULL); 170 else 171 server_checked_in (finfo->file, finfo->update_dir, 172 finfo->repository); 173 } 174 else 175 #endif 176 mark_up_to_date (finfo->file); 177 178 freevers_ts (&vers); 179 return 0; 180 } 181