xref: /openbsd/gnu/usr.bin/cvs/src/checkin.c (revision 50bf276c)
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