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