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