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