11e72d8d2Sderaadt /* 21e72d8d2Sderaadt * Copyright (c) 1992, Brian Berliner and Jeff Polk 31e72d8d2Sderaadt * Copyright (c) 1989-1992, Brian Berliner 41e72d8d2Sderaadt * 51e72d8d2Sderaadt * You may distribute under the terms of the GNU General Public License as 61e72d8d2Sderaadt * specified in the README file that comes with the CVS 1.4 kit. 71e72d8d2Sderaadt * 81e72d8d2Sderaadt * Check In 91e72d8d2Sderaadt * 101e72d8d2Sderaadt * Does a very careful checkin of the file "user", and tries not to spoil its 111e72d8d2Sderaadt * modification time (to avoid needless recompilations). When RCS ID keywords 121e72d8d2Sderaadt * get expanded on checkout, however, the modification time is updated and 131e72d8d2Sderaadt * there is no good way to get around this. 141e72d8d2Sderaadt * 151e72d8d2Sderaadt * Returns non-zero on error. 161e72d8d2Sderaadt */ 171e72d8d2Sderaadt 181e72d8d2Sderaadt #include "cvs.h" 1913571821Stholo #include "fileattr.h" 2013571821Stholo #include "edit.h" 211e72d8d2Sderaadt 221e72d8d2Sderaadt int 23*50bf276cStholo Checkin (type, finfo, rcs, rev, tag, options, message) 241e72d8d2Sderaadt int type; 25*50bf276cStholo struct file_info *finfo; 261e72d8d2Sderaadt char *rcs; 271e72d8d2Sderaadt char *rev; 281e72d8d2Sderaadt char *tag; 291e72d8d2Sderaadt char *options; 301e72d8d2Sderaadt char *message; 311e72d8d2Sderaadt { 321e72d8d2Sderaadt char fname[PATH_MAX]; 331e72d8d2Sderaadt Vers_TS *vers; 341e72d8d2Sderaadt int set_time; 351e72d8d2Sderaadt char *tocvsPath = NULL; 361e72d8d2Sderaadt 37*50bf276cStholo (void) printf ("Checking in %s;\n", finfo->fullname); 38*50bf276cStholo (void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file); 391e72d8d2Sderaadt 401e72d8d2Sderaadt /* 411e72d8d2Sderaadt * Move the user file to a backup file, so as to preserve its 421e72d8d2Sderaadt * modification times, then place a copy back in the original file name 431e72d8d2Sderaadt * for the checkin and checkout. 441e72d8d2Sderaadt */ 451e72d8d2Sderaadt 46*50bf276cStholo tocvsPath = wrap_tocvs_process_file (finfo->fullname); 471e72d8d2Sderaadt 481e72d8d2Sderaadt if (!noexec) 491e72d8d2Sderaadt { 501e72d8d2Sderaadt if (tocvsPath) 511e72d8d2Sderaadt { 521e72d8d2Sderaadt copy_file (tocvsPath, fname); 53*50bf276cStholo if (unlink_file_dir (finfo->file) < 0) 5413571821Stholo if (! existence_error (errno)) 55*50bf276cStholo error (1, errno, "cannot remove %s", finfo->fullname); 56*50bf276cStholo copy_file (tocvsPath, finfo->file); 571e72d8d2Sderaadt } 581e72d8d2Sderaadt else 591e72d8d2Sderaadt { 60*50bf276cStholo copy_file (finfo->file, fname); 611e72d8d2Sderaadt } 621e72d8d2Sderaadt } 631e72d8d2Sderaadt 64*50bf276cStholo switch (RCS_checkin (rcs, NULL, message, rev, 0)) 651e72d8d2Sderaadt { 661e72d8d2Sderaadt case 0: /* everything normal */ 671e72d8d2Sderaadt 681e72d8d2Sderaadt /* 691e72d8d2Sderaadt * The checkin succeeded, so now check the new file back out and 701e72d8d2Sderaadt * see if it matches exactly with the one we checked in. If it 711e72d8d2Sderaadt * does, just move the original user file back, thus preserving 721e72d8d2Sderaadt * the modes; otherwise, we have no recourse but to leave the 731e72d8d2Sderaadt * newly checkout file as the user file and remove the old 741e72d8d2Sderaadt * original user file. 751e72d8d2Sderaadt */ 761e72d8d2Sderaadt 771e72d8d2Sderaadt if (strcmp (options, "-V4") == 0) /* upgrade to V5 now */ 781e72d8d2Sderaadt options[0] = '\0'; 79c26070a5Stholo 80*50bf276cStholo /* Reparse the RCS file, so that we can safely call 81*50bf276cStholo RCS_checkout. FIXME: We could probably calculate 82*50bf276cStholo all the changes. */ 83*50bf276cStholo freercsnode (&finfo->rcs); 84*50bf276cStholo finfo->rcs = RCS_parse (finfo->file, finfo->repository); 85c26070a5Stholo 86*50bf276cStholo /* FIXME: should be checking for errors. */ 87*50bf276cStholo (void) RCS_checkout (finfo->rcs, finfo->file, rev, 88*50bf276cStholo (char *) NULL, options, RUN_TTY); 89*50bf276cStholo 90*50bf276cStholo xchmod (finfo->file, 1); 91*50bf276cStholo if (xcmp (finfo->file, fname) == 0) 921e72d8d2Sderaadt { 93*50bf276cStholo rename_file (fname, finfo->file); 941e72d8d2Sderaadt /* the time was correct, so leave it alone */ 951e72d8d2Sderaadt set_time = 0; 961e72d8d2Sderaadt } 971e72d8d2Sderaadt else 981e72d8d2Sderaadt { 991e72d8d2Sderaadt if (unlink_file (fname) < 0) 1001e72d8d2Sderaadt error (0, errno, "cannot remove %s", fname); 1011e72d8d2Sderaadt /* sync up with the time from the RCS file */ 1021e72d8d2Sderaadt set_time = 1; 1031e72d8d2Sderaadt } 1041e72d8d2Sderaadt 105*50bf276cStholo wrap_fromcvs_process_file (finfo->file); 1061e72d8d2Sderaadt 1071e72d8d2Sderaadt /* 1081e72d8d2Sderaadt * If we want read-only files, muck the permissions here, before 1091e72d8d2Sderaadt * getting the file time-stamp. 1101e72d8d2Sderaadt */ 111*50bf276cStholo if (cvswrite == FALSE || fileattr_get (finfo->file, "_watched")) 112*50bf276cStholo xchmod (finfo->file, 0); 1131e72d8d2Sderaadt 114*50bf276cStholo /* Re-register with the new data. */ 115*50bf276cStholo vers = Version_TS (finfo, NULL, tag, NULL, 1, set_time); 1161e72d8d2Sderaadt if (strcmp (vers->options, "-V4") == 0) 1171e72d8d2Sderaadt vers->options[0] = '\0'; 118*50bf276cStholo Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_user, 1191e72d8d2Sderaadt vers->options, vers->tag, vers->date, (char *) 0); 120*50bf276cStholo history_write (type, NULL, vers->vn_rcs, 121*50bf276cStholo finfo->file, finfo->repository); 1221e72d8d2Sderaadt 1231e72d8d2Sderaadt if (tocvsPath) 1241e72d8d2Sderaadt if (unlink_file_dir (tocvsPath) < 0) 1251e72d8d2Sderaadt error (0, errno, "cannot remove %s", tocvsPath); 1261e72d8d2Sderaadt 1271e72d8d2Sderaadt break; 1281e72d8d2Sderaadt 1291e72d8d2Sderaadt case -1: /* fork failed */ 1301e72d8d2Sderaadt if (tocvsPath) 1311e72d8d2Sderaadt if (unlink_file_dir (tocvsPath) < 0) 1321e72d8d2Sderaadt error (0, errno, "cannot remove %s", tocvsPath); 1331e72d8d2Sderaadt 1341e72d8d2Sderaadt if (!noexec) 1351e72d8d2Sderaadt error (1, errno, "could not check in %s -- fork failed", 136*50bf276cStholo finfo->fullname); 1371e72d8d2Sderaadt return (1); 1381e72d8d2Sderaadt 1391e72d8d2Sderaadt default: /* ci failed */ 1401e72d8d2Sderaadt 1411e72d8d2Sderaadt /* 1421e72d8d2Sderaadt * The checkin failed, for some unknown reason, so we restore the 1431e72d8d2Sderaadt * original user file, print an error, and return an error 1441e72d8d2Sderaadt */ 1451e72d8d2Sderaadt if (tocvsPath) 1461e72d8d2Sderaadt if (unlink_file_dir (tocvsPath) < 0) 1471e72d8d2Sderaadt error (0, errno, "cannot remove %s", tocvsPath); 1481e72d8d2Sderaadt 1491e72d8d2Sderaadt if (!noexec) 1501e72d8d2Sderaadt { 151*50bf276cStholo rename_file (fname, finfo->file); 152*50bf276cStholo error (0, 0, "could not check in %s", finfo->fullname); 1531e72d8d2Sderaadt } 1541e72d8d2Sderaadt return (1); 1551e72d8d2Sderaadt } 1561e72d8d2Sderaadt 1571e72d8d2Sderaadt /* 1581e72d8d2Sderaadt * When checking in a specific revision, we may have locked the wrong 1591e72d8d2Sderaadt * branch, so to be sure, we do an extra unlock here before 1601e72d8d2Sderaadt * returning. 1611e72d8d2Sderaadt */ 1621e72d8d2Sderaadt if (rev) 1631e72d8d2Sderaadt { 164*50bf276cStholo (void) RCS_unlock (finfo->rcs, NULL, 1); 1651e72d8d2Sderaadt } 1661e72d8d2Sderaadt 1671e72d8d2Sderaadt #ifdef SERVER_SUPPORT 1681e72d8d2Sderaadt if (server_active) 1691e72d8d2Sderaadt { 1701e72d8d2Sderaadt if (set_time) 1711e72d8d2Sderaadt /* Need to update the checked out file on the client side. */ 172*50bf276cStholo server_updated (finfo, vers, SERVER_UPDATED, 1731e72d8d2Sderaadt NULL, NULL); 1741e72d8d2Sderaadt else 175*50bf276cStholo server_checked_in (finfo->file, finfo->update_dir, finfo->repository); 1761e72d8d2Sderaadt } 17713571821Stholo else 1781e72d8d2Sderaadt #endif 179*50bf276cStholo mark_up_to_date (finfo->file); 1801e72d8d2Sderaadt 181*50bf276cStholo freevers_ts (&vers); 1821e72d8d2Sderaadt return (0); 1831e72d8d2Sderaadt } 184