]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/cvs/src/checkin.c
Import of slightly trimmed cvs-1.8 distribution. Generated files
[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 1.4 kit.
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 (type, file, update_dir, repository,
24          rcs, rev, tag, options, message, entries)
25     int type;
26     char *file;
27     char *update_dir;
28     char *repository;
29     char *rcs;
30     char *rev;
31     char *tag;
32     char *options;
33     char *message;
34     List *entries;
35 {
36     char fname[PATH_MAX];
37     Vers_TS *vers;
38     int set_time;
39     char *fullname;
40
41     char *tocvsPath = NULL;
42
43     fullname = xmalloc (strlen (update_dir) + strlen (file) + 10);
44     if (update_dir[0] == '\0')
45         strcpy (fullname, file);
46     else
47         sprintf (fullname, "%s/%s", update_dir, file);
48
49     (void) printf ("Checking in %s;\n", fullname);
50     (void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
51
52     /*
53      * Move the user file to a backup file, so as to preserve its
54      * modification times, then place a copy back in the original file name
55      * for the checkin and checkout.
56      */
57
58     tocvsPath = wrap_tocvs_process_file (fullname);
59
60     if (!noexec)
61     {
62         if (tocvsPath)
63         {
64             copy_file (tocvsPath, fname);
65             if (unlink_file_dir (file) < 0)
66                 if (! existence_error (errno))
67                     error (1, errno, "cannot remove %s", file);
68             copy_file (tocvsPath, file);
69         }
70         else
71         {
72             copy_file (file, fname);
73         }
74     }
75
76     switch (RCS_checkin (rcs, NULL, message, rev, 0, 0))
77     {
78         case 0:                 /* everything normal */
79
80             /*
81              * The checkin succeeded, so now check the new file back out and
82              * see if it matches exactly with the one we checked in. If it
83              * does, just move the original user file back, thus preserving
84              * the modes; otherwise, we have no recourse but to leave the
85              * newly checkout file as the user file and remove the old
86              * original user file.
87              */
88
89             if (strcmp (options, "-V4") == 0) /* upgrade to V5 now */
90                 options[0] = '\0';
91
92             /* FIXME: should be checking for errors.  */
93             (void) RCS_checkout (rcs, "", rev, options, RUN_TTY, 0, 0);
94
95             xchmod (file, 1);
96             if (xcmp (file, fname) == 0)
97             {
98                 rename_file (fname, file);
99                 /* the time was correct, so leave it alone */
100                 set_time = 0;
101             }
102             else
103             {
104                 if (unlink_file (fname) < 0)
105                     error (0, errno, "cannot remove %s", fname);
106                 /* sync up with the time from the RCS file */
107                 set_time = 1;
108             }
109
110             wrap_fromcvs_process_file (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 == FALSE || fileattr_get (file, "_watched"))
117                 xchmod (file, 0);
118
119             /* re-register with the new data */
120             vers = Version_TS (repository, (char *) NULL, tag, (char *) NULL,
121                                file, 1, set_time, entries, (RCSNode *) NULL);
122             if (strcmp (vers->options, "-V4") == 0)
123                 vers->options[0] = '\0';
124             Register (entries, file, vers->vn_rcs, vers->ts_user,
125                       vers->options, vers->tag, vers->date, (char *) 0);
126             history_write (type, (char *) 0, vers->vn_rcs, file, repository);
127             freevers_ts (&vers);
128
129             if (tocvsPath)
130                 if (unlink_file_dir (tocvsPath) < 0)
131                     error (0, errno, "cannot remove %s", tocvsPath);
132
133             break;
134
135         case -1:                        /* fork failed */
136             if (tocvsPath)
137                 if (unlink_file_dir (tocvsPath) < 0)
138                     error (0, errno, "cannot remove %s", tocvsPath);
139
140             if (!noexec)
141                 error (1, errno, "could not check in %s -- fork failed",
142                        fullname);
143             return (1);
144
145         default:                        /* ci failed */
146
147             /*
148              * The checkin failed, for some unknown reason, so we restore the
149              * original user file, print an error, and return an error
150              */
151             if (tocvsPath)
152                 if (unlink_file_dir (tocvsPath) < 0)
153                     error (0, errno, "cannot remove %s", tocvsPath);
154
155             if (!noexec)
156             {
157                 rename_file (fname, file);
158                 error (0, 0, "could not check in %s", fullname);
159             }
160             return (1);
161     }
162
163     /*
164      * When checking in a specific revision, we may have locked the wrong
165      * branch, so to be sure, we do an extra unlock here before
166      * returning.
167      */
168     if (rev)
169     {
170         (void) RCS_unlock (rcs, NULL, 1);
171     }
172
173 #ifdef SERVER_SUPPORT
174     if (server_active)
175     {
176         if (set_time)
177             /* Need to update the checked out file on the client side.  */
178             server_updated (file, update_dir, repository, SERVER_UPDATED,
179                             NULL, NULL);
180         else
181             server_checked_in (file, update_dir, repository);
182     }
183     else
184 #endif
185         mark_up_to_date (file);
186
187     return (0);
188 }