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