]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/cvs/src/checkin.c
This commit was generated by cvs2svn to compensate for changes in r169942,
[FreeBSD/FreeBSD.git] / contrib / cvs / 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 <assert.h>
19 #include "cvs.h"
20 #include "fileattr.h"
21 #include "edit.h"
22
23 int
24 Checkin (type, finfo, rev, tag, options, message)
25     int type;
26     struct file_info *finfo;
27     char *rev;
28     char *tag;
29     char *options;
30     char *message;
31 {
32     Vers_TS *vers;
33     int set_time;
34     char *tocvsPath = NULL;
35
36     /* Hmm.  This message goes to stdout and the "foo,v  <--  foo"
37        message from "ci" goes to stderr.  This doesn't make a whole
38        lot of sense, but making everything go to stdout can only be
39        gracefully achieved once RCS_checkin is librarified.  */
40     cvs_output ("Checking in ", 0);
41     cvs_output (finfo->fullname, 0);
42     cvs_output (";\n", 0);
43
44     tocvsPath = wrap_tocvs_process_file (finfo->file);
45     if (!noexec)
46     {
47         if (tocvsPath)
48         {
49             if (unlink_file_dir (finfo->file) < 0)
50                 if (! existence_error (errno))
51                     error (1, errno, "cannot remove %s", finfo->fullname);
52             rename_file (tocvsPath, finfo->file);
53         }
54     }
55
56     /* There use to be a check for finfo->rcs == NULL here and then a
57      * call to RCS_parse when necessary, but Checkin() isn't called
58      * if the RCS file hasn't already been parsed in one of the
59      * check functions.
60      */
61     assert (finfo->rcs != NULL);
62
63     switch (RCS_checkin (finfo->rcs, finfo->file, message, rev,
64                          RCS_FLAGS_KEEPFILE))
65     {
66         case 0:                 /* everything normal */
67
68             /* The checkin succeeded.  If checking the file out again
69                would not cause any changes, we are done.  Otherwise,
70                we need to check out the file, which will change the
71                modification time of the file.
72
73                The only way checking out the file could cause any
74                changes is if the file contains RCS keywords.  So we if
75                we are not expanding RCS keywords, we are done.  */
76
77             if (strcmp (options, "-V4") == 0) /* upgrade to V5 now */
78                 options[0] = '\0';
79
80             /* FIXME: If PreservePermissions is on, RCS_cmp_file is
81                going to call RCS_checkout into a temporary file
82                anyhow.  In that case, it would be more efficient to
83                call RCS_checkout here, compare the resulting files
84                using xcmp, and rename if necessary.  I think this
85                should be fixed in RCS_cmp_file.  */
86             if( ( ! preserve_perms
87                   && options != NULL
88                   && ( strcmp( options, "-ko" ) == 0
89                        || strcmp( options, "-kb" ) == 0 ) )
90                 || RCS_cmp_file( finfo->rcs, rev, (char **)NULL, (char *)NULL,
91                                  options, finfo->file ) == 0 )
92             {
93                 /* The existing file is correct.  We don't have to do
94                    anything.  */
95                 set_time = 0;
96             }
97             else
98             {
99                 /* The existing file is incorrect.  We need to check
100                    out the correct file contents.  */
101                 if (RCS_checkout (finfo->rcs, finfo->file, rev, (char *) NULL,
102                                   options, RUN_TTY, (RCSCHECKOUTPROC) NULL,
103                                   (void *) NULL) != 0)
104                     error (1, 0, "failed when checking out new copy of %s",
105                            finfo->fullname);
106                 xchmod (finfo->file, 1);
107                 set_time = 1;
108             }
109
110             wrap_fromcvs_process_file (finfo->file);
111
112             /*
113              * If we want read-only files, muck the permissions here, before
114              * getting the file time-stamp.
115              */
116             if (!cvswrite || fileattr_get (finfo->file, "_watched"))
117                 xchmod (finfo->file, 0);
118
119             /* Re-register with the new data.  */
120             vers = Version_TS (finfo, NULL, tag, NULL, 1, set_time);
121             if (strcmp (vers->options, "-V4") == 0)
122                 vers->options[0] = '\0';
123             Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_user,
124                       vers->options, vers->tag, vers->date, (char *) 0);
125             history_write (type, NULL, vers->vn_rcs,
126                            finfo->file, finfo->repository);
127
128             if (tocvsPath)
129                 if (unlink_file_dir (tocvsPath) < 0)
130                     error (0, errno, "cannot remove %s", tocvsPath);
131
132             break;
133
134         case -1:                        /* fork failed */
135             if (tocvsPath)
136                 if (unlink_file_dir (tocvsPath) < 0)
137                     error (0, errno, "cannot remove %s", tocvsPath);
138
139             if (!noexec)
140                 error (1, errno, "could not check in %s -- fork failed",
141                        finfo->fullname);
142             return (1);
143
144         default:                        /* ci failed */
145
146             /* The checkin failed, for some unknown reason, so we
147                print an error, and return an error.  We assume that
148                the original file has not been touched.  */
149             if (tocvsPath)
150                 if (unlink_file_dir (tocvsPath) < 0)
151                     error (0, errno, "cannot remove %s", tocvsPath);
152
153             if (!noexec)
154                 error (0, 0, "could not check in %s", finfo->fullname);
155             return (1);
156     }
157
158     /*
159      * When checking in a specific revision, we may have locked the wrong
160      * branch, so to be sure, we do an extra unlock here before
161      * returning.
162      */
163     if (rev)
164     {
165         (void) RCS_unlock (finfo->rcs, NULL, 1);
166         RCS_rewrite (finfo->rcs, NULL, NULL);
167     }
168
169 #ifdef SERVER_SUPPORT
170     if (server_active)
171     {
172         if (set_time)
173             /* Need to update the checked out file on the client side.  */
174             server_updated (finfo, vers, SERVER_UPDATED,
175                             (mode_t) -1, (unsigned char *) NULL,
176                             (struct buffer *) NULL);
177         else
178             server_checked_in (finfo->file, finfo->update_dir, finfo->repository);
179     }
180     else
181 #endif
182         mark_up_to_date (finfo->file);
183
184     freevers_ts (&vers);
185     return 0;
186 }