File: | src/usr.bin/cvs/commit.c |
Warning: | line 561, column 20 Access to field 'rf_head' results in a dereference of a null pointer (loaded from field 'file_rcs') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: commit.c,v 1.160 2019/06/28 13:35:00 deraadt Exp $ */ | |||
2 | /* | |||
3 | * Copyright (c) 2006 Joris Vink <joris@openbsd.org> | |||
4 | * Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org> | |||
5 | * | |||
6 | * Permission to use, copy, modify, and distribute this software for any | |||
7 | * purpose with or without fee is hereby granted, provided that the above | |||
8 | * copyright notice and this permission notice appear in all copies. | |||
9 | * | |||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
17 | */ | |||
18 | ||||
19 | #include <sys/stat.h> | |||
20 | ||||
21 | #include <errno(*__errno()).h> | |||
22 | #include <fcntl.h> | |||
23 | #include <stdlib.h> | |||
24 | #include <string.h> | |||
25 | #include <unistd.h> | |||
26 | ||||
27 | #include "cvs.h" | |||
28 | #include "diff.h" | |||
29 | #include "remote.h" | |||
30 | ||||
31 | void cvs_commit_local(struct cvs_file *); | |||
32 | void cvs_commit_check_files(struct cvs_file *); | |||
33 | void cvs_commit_loginfo(char *); | |||
34 | void cvs_commit_lock_dirs(struct cvs_file *); | |||
35 | ||||
36 | static BUF *commit_diff(struct cvs_file *, RCSNUM *, int); | |||
37 | static void commit_desc_set(struct cvs_file *); | |||
38 | ||||
39 | struct file_info_list files_info; | |||
40 | struct trigger_list *line_list; | |||
41 | ||||
42 | struct cvs_flisthead files_affected; | |||
43 | struct cvs_flisthead files_added; | |||
44 | struct cvs_flisthead files_removed; | |||
45 | struct cvs_flisthead files_modified; | |||
46 | ||||
47 | char *logmsg = NULL((void *)0); | |||
48 | char *loginfo = NULL((void *)0); | |||
49 | ||||
50 | static int conflicts_found; | |||
51 | ||||
52 | struct cvs_cmd cvs_cmd_commit = { | |||
53 | CVS_OP_COMMIT5, CVS_USE_WDIR0x01, "commit", | |||
54 | { "ci", "com" }, | |||
55 | "Check files into the repository", | |||
56 | "[-flR] [-F logfile | -m msg] [-r rev] ...", | |||
57 | "F:flm:Rr:", | |||
58 | NULL((void *)0), | |||
59 | cvs_commit | |||
60 | }; | |||
61 | ||||
62 | int | |||
63 | cvs_commit(int argc, char **argv) | |||
64 | { | |||
65 | int flags; | |||
66 | int ch, Fflag, mflag; | |||
67 | struct module_checkout *mc; | |||
68 | struct cvs_recursion cr; | |||
69 | struct cvs_filelist *l; | |||
70 | struct file_info *fi; | |||
71 | char *arg = ".", repo[PATH_MAX1024]; | |||
72 | ||||
73 | flags = CR_RECURSE_DIRS0x01; | |||
74 | Fflag = mflag = 0; | |||
75 | ||||
76 | while ((ch = getopt(argc, argv, cvs_cmd_commit.cmd_opts)) != -1) { | |||
77 | switch (ch) { | |||
78 | case 'F': | |||
79 | /* free previously assigned value */ | |||
80 | free(logmsg); | |||
81 | logmsg = cvs_logmsg_read(optarg); | |||
82 | Fflag = 1; | |||
83 | break; | |||
84 | case 'f': | |||
85 | break; | |||
86 | case 'l': | |||
87 | flags &= ~CR_RECURSE_DIRS0x01; | |||
88 | break; | |||
89 | case 'm': | |||
90 | /* free previously assigned value */ | |||
91 | free(logmsg); | |||
92 | logmsg = xstrdup(optarg); | |||
93 | mflag = 1; | |||
94 | break; | |||
95 | case 'R': | |||
96 | flags |= CR_RECURSE_DIRS0x01; | |||
97 | break; | |||
98 | case 'r': | |||
99 | break; | |||
100 | default: | |||
101 | fatal("%s", cvs_cmd_commit.cmd_synopsis); | |||
102 | } | |||
103 | } | |||
104 | ||||
105 | argc -= optind; | |||
106 | argv += optind; | |||
107 | ||||
108 | /* -F and -m are mutually exclusive */ | |||
109 | if (Fflag && mflag) | |||
110 | fatal("cannot specify both a log file and a message"); | |||
111 | ||||
112 | RB_INIT(&files_affected)do { (&files_affected)->rbh_root = ((void *)0); } while (0); | |||
113 | RB_INIT(&files_added)do { (&files_added)->rbh_root = ((void *)0); } while ( 0); | |||
114 | RB_INIT(&files_removed)do { (&files_removed)->rbh_root = ((void *)0); } while (0); | |||
115 | RB_INIT(&files_modified)do { (&files_modified)->rbh_root = ((void *)0); } while (0); | |||
116 | ||||
117 | TAILQ_INIT(&files_info)do { (&files_info)->tqh_first = ((void *)0); (&files_info )->tqh_last = &(&files_info)->tqh_first; } while (0); | |||
118 | conflicts_found = 0; | |||
119 | ||||
120 | cr.enterdir = NULL((void *)0); | |||
121 | cr.leavedir = NULL((void *)0); | |||
122 | cr.fileproc = cvs_commit_check_files; | |||
123 | cr.flags = flags; | |||
124 | ||||
125 | if (argc > 0) | |||
126 | cvs_file_run(argc, argv, &cr); | |||
127 | else | |||
128 | cvs_file_run(1, &arg, &cr); | |||
129 | ||||
130 | if (conflicts_found != 0) | |||
131 | fatal("%d conflicts found, please correct these first", | |||
132 | conflicts_found); | |||
133 | ||||
134 | if (RB_EMPTY(&files_affected)((&files_affected)->rbh_root == ((void *)0))) | |||
135 | return (0); | |||
136 | ||||
137 | if (cvsroot_is_remote()) { | |||
138 | if (logmsg == NULL((void *)0)) { | |||
139 | logmsg = cvs_logmsg_create(NULL((void *)0), &files_added, | |||
140 | &files_removed, &files_modified); | |||
141 | if (logmsg == NULL((void *)0)) | |||
142 | fatal("This shouldnt happen, honestly!"); | |||
143 | } | |||
144 | cvs_client_connect_to_server(); | |||
145 | cr.fileproc = cvs_client_sendfile; | |||
146 | ||||
147 | if (argc > 0) | |||
148 | cvs_file_run(argc, argv, &cr); | |||
149 | else | |||
150 | cvs_file_run(1, &arg, &cr); | |||
151 | ||||
152 | if (!(flags & CR_RECURSE_DIRS0x01)) | |||
153 | cvs_client_send_request("Argument -l"); | |||
154 | ||||
155 | cvs_client_send_logmsg(logmsg); | |||
156 | cvs_client_send_files(argv, argc); | |||
157 | cvs_client_senddir("."); | |||
158 | cvs_client_send_request("ci"); | |||
159 | cvs_client_get_responses(); | |||
160 | } else { | |||
161 | cvs_get_repository_name(".", repo, PATH_MAX1024); | |||
162 | ||||
163 | line_list = cvs_trigger_getlines(CVS_PATH_COMMITINFO"CVSROOT" "/commitinfo", repo); | |||
164 | if (line_list != NULL((void *)0)) { | |||
165 | RB_FOREACH(l, cvs_flisthead, &files_affected)for ((l) = cvs_flisthead_RB_MINMAX(&files_affected, -1); ( l) != ((void *)0); (l) = cvs_flisthead_RB_NEXT(l)) { | |||
166 | fi = xcalloc(1, sizeof(*fi)); | |||
167 | fi->file_path = xstrdup(l->file_path); | |||
168 | TAILQ_INSERT_TAIL(&files_info, fi,do { (fi)->flist.tqe_next = ((void *)0); (fi)->flist.tqe_prev = (&files_info)->tqh_last; *(&files_info)->tqh_last = (fi); (&files_info)->tqh_last = &(fi)->flist .tqe_next; } while (0) | |||
169 | flist)do { (fi)->flist.tqe_next = ((void *)0); (fi)->flist.tqe_prev = (&files_info)->tqh_last; *(&files_info)->tqh_last = (fi); (&files_info)->tqh_last = &(fi)->flist .tqe_next; } while (0); | |||
170 | } | |||
171 | ||||
172 | if (cvs_trigger_handle(CVS_TRIGGER_COMMITINFO1, | |||
173 | repo, NULL((void *)0), line_list, &files_info)) { | |||
174 | cvs_log(LP_ERR1, | |||
175 | "Pre-commit check failed"); | |||
176 | cvs_trigger_freelist(line_list); | |||
177 | goto end; | |||
178 | } | |||
179 | ||||
180 | cvs_trigger_freelist(line_list); | |||
181 | cvs_trigger_freeinfo(&files_info); | |||
182 | } | |||
183 | ||||
184 | if (cvs_server_active) { | |||
185 | if (logmsg == NULL((void *)0)) | |||
186 | fatal("no log message specified"); | |||
187 | } else if (logmsg == NULL((void *)0)) { | |||
188 | logmsg = cvs_logmsg_create(NULL((void *)0), &files_added, | |||
189 | &files_removed, &files_modified); | |||
190 | if (logmsg == NULL((void *)0)) | |||
191 | fatal("This shouldnt happen, honestly!"); | |||
192 | } | |||
193 | ||||
194 | if (cvs_logmsg_verify(logmsg)) | |||
195 | goto end; | |||
196 | ||||
197 | cr.fileproc = cvs_commit_lock_dirs; | |||
198 | cvs_file_walklist(&files_affected, &cr); | |||
199 | ||||
200 | line_list = cvs_trigger_getlines(CVS_PATH_LOGINFO"CVSROOT" "/loginfo", repo); | |||
201 | ||||
202 | cr.fileproc = cvs_commit_local; | |||
203 | cvs_file_walklist(&files_affected, &cr); | |||
204 | ||||
205 | if (line_list != NULL((void *)0)) { | |||
206 | cvs_commit_loginfo(repo); | |||
207 | ||||
208 | cvs_trigger_handle(CVS_TRIGGER_LOGINFO2, repo, | |||
209 | loginfo, line_list, &files_info); | |||
210 | ||||
211 | free(loginfo); | |||
212 | cvs_trigger_freelist(line_list); | |||
213 | cvs_trigger_freeinfo(&files_info); | |||
214 | } | |||
215 | ||||
216 | mc = cvs_module_lookup(repo); | |||
217 | if (mc->mc_prog != NULL((void *)0) && | |||
218 | (mc->mc_flags & MODULE_RUN_ON_COMMIT0x08)) | |||
219 | cvs_exec(mc->mc_prog, NULL((void *)0), 0); | |||
220 | } | |||
221 | ||||
222 | end: | |||
223 | cvs_trigger_freeinfo(&files_info); | |||
224 | free(logmsg); | |||
225 | return (0); | |||
226 | } | |||
227 | ||||
228 | void | |||
229 | cvs_commit_loginfo(char *repo) | |||
230 | { | |||
231 | BUF *buf; | |||
232 | char pwd[PATH_MAX1024]; | |||
233 | struct cvs_filelist *cf; | |||
234 | ||||
235 | if (getcwd(pwd, sizeof(pwd)) == NULL((void *)0)) | |||
236 | fatal("Can't get working directory"); | |||
237 | ||||
238 | buf = buf_alloc(1024); | |||
239 | ||||
240 | cvs_trigger_loginfo_header(buf, repo); | |||
241 | ||||
242 | if (!RB_EMPTY(&files_added)((&files_added)->rbh_root == ((void *)0))) { | |||
243 | buf_puts(buf, "Added Files:"); | |||
244 | ||||
245 | RB_FOREACH(cf, cvs_flisthead, &files_added)for ((cf) = cvs_flisthead_RB_MINMAX(&files_added, -1); (cf ) != ((void *)0); (cf) = cvs_flisthead_RB_NEXT(cf)) { | |||
246 | buf_putc(buf, '\n'); | |||
247 | buf_putc(buf, '\t'); | |||
248 | buf_puts(buf, cf->file_path); | |||
249 | } | |||
250 | ||||
251 | buf_putc(buf, '\n'); | |||
252 | } | |||
253 | ||||
254 | if (!RB_EMPTY(&files_modified)((&files_modified)->rbh_root == ((void *)0))) { | |||
255 | buf_puts(buf, "Modified Files:"); | |||
256 | ||||
257 | RB_FOREACH(cf, cvs_flisthead, &files_modified)for ((cf) = cvs_flisthead_RB_MINMAX(&files_modified, -1); (cf) != ((void *)0); (cf) = cvs_flisthead_RB_NEXT(cf)) { | |||
258 | buf_putc(buf, '\n'); | |||
259 | buf_putc(buf, '\t'); | |||
260 | buf_puts(buf, cf->file_path); | |||
261 | } | |||
262 | ||||
263 | buf_putc(buf, '\n'); | |||
264 | } | |||
265 | ||||
266 | if (!RB_EMPTY(&files_removed)((&files_removed)->rbh_root == ((void *)0))) { | |||
267 | buf_puts(buf, "Removed Files:"); | |||
268 | ||||
269 | RB_FOREACH(cf, cvs_flisthead, &files_removed)for ((cf) = cvs_flisthead_RB_MINMAX(&files_removed, -1); ( cf) != ((void *)0); (cf) = cvs_flisthead_RB_NEXT(cf)) { | |||
270 | buf_putc(buf, '\n'); | |||
271 | buf_putc(buf, '\t'); | |||
272 | buf_puts(buf, cf->file_path); | |||
273 | } | |||
274 | ||||
275 | buf_putc(buf, '\n'); | |||
276 | } | |||
277 | ||||
278 | buf_puts(buf, "Log Message:\n"); | |||
279 | ||||
280 | buf_puts(buf, logmsg); | |||
281 | ||||
282 | buf_putc(buf, '\n'); | |||
283 | buf_putc(buf, '\0'); | |||
284 | ||||
285 | loginfo = buf_release(buf); | |||
286 | } | |||
287 | ||||
288 | void | |||
289 | cvs_commit_lock_dirs(struct cvs_file *cf) | |||
290 | { | |||
291 | char repo[PATH_MAX1024]; | |||
292 | ||||
293 | cvs_get_repository_path(cf->file_wd, repo, sizeof(repo)); | |||
294 | cvs_log(LP_TRACE4, "cvs_commit_lock_dirs: %s", repo); | |||
295 | ||||
296 | /* locks stay in place until we are fully done and exit */ | |||
297 | cvs_repository_lock(repo, 1); | |||
298 | } | |||
299 | ||||
300 | void | |||
301 | cvs_commit_check_files(struct cvs_file *cf) | |||
302 | { | |||
303 | char *tag; | |||
304 | RCSNUM *branch, *brev; | |||
305 | ||||
306 | branch = brev = NULL((void *)0); | |||
307 | ||||
308 | cvs_log(LP_TRACE4, "cvs_commit_check_files(%s)", cf->file_path); | |||
309 | ||||
310 | if (cvsroot_is_remote()) | |||
311 | cvs_remote_classify_file(cf); | |||
312 | else | |||
313 | cvs_file_classify(cf, cvs_directory_tag); | |||
314 | ||||
315 | if (cf->file_type == CVS_DIR1) { | |||
316 | if (verbosity > 1) | |||
317 | cvs_log(LP_NOTICE0, "Examining %s", cf->file_path); | |||
318 | return; | |||
319 | } | |||
320 | ||||
321 | if (cf->file_status == FILE_UPTODATE4) | |||
322 | return; | |||
323 | ||||
324 | if (cf->file_status == FILE_MERGE7 || | |||
325 | cf->file_status == FILE_PATCH8 || | |||
326 | cf->file_status == FILE_CHECKOUT6 || | |||
327 | cf->file_status == FILE_LOST5 || | |||
328 | cf->file_status == FILE_UNLINK11) { | |||
329 | cvs_log(LP_ERR1, "conflict: %s is not up-to-date", | |||
330 | cf->file_path); | |||
331 | conflicts_found++; | |||
332 | return; | |||
333 | } | |||
334 | ||||
335 | if (cf->file_status == FILE_CONFLICT10 && | |||
336 | cf->file_ent->ce_conflict != NULL((void *)0)) { | |||
337 | cvs_log(LP_ERR1, "conflict: unresolved conflicts in %s from " | |||
338 | "merging, please fix these first", cf->file_path); | |||
339 | conflicts_found++; | |||
340 | return; | |||
341 | } | |||
342 | ||||
343 | if (cf->file_status == FILE_MODIFIED3 && | |||
344 | cf->file_ent->ce_conflict != NULL((void *)0) && | |||
345 | update_has_conflict_markers(cf)) { | |||
346 | cvs_log(LP_ERR1, "warning: file %s seems to still contain " | |||
347 | "conflict indicators", cf->file_path); | |||
348 | } | |||
349 | ||||
350 | if (cf->file_ent != NULL((void *)0) && cf->file_ent->ce_date != -1) { | |||
351 | cvs_log(LP_ERR1, "conflict: cannot commit to sticky date for %s", | |||
352 | cf->file_path); | |||
353 | conflicts_found++; | |||
354 | return; | |||
355 | } | |||
356 | ||||
357 | if (cvsroot_is_local()) { | |||
358 | tag = cvs_directory_tag; | |||
359 | if (cf->file_ent != NULL((void *)0)) | |||
360 | tag = cf->file_ent->ce_tag; | |||
361 | ||||
362 | if (tag != NULL((void *)0) && cf->file_rcs != NULL((void *)0)) { | |||
363 | brev = rcs_sym_getrev(cf->file_rcs, tag); | |||
364 | if (brev != NULL((void *)0)) { | |||
365 | if (!RCSNUM_ISBRANCH(brev)((brev)->rn_len % 2)) { | |||
366 | cvs_log(LP_ERR1, "sticky tag %s is not " | |||
367 | "a branch for file %s", tag, | |||
368 | cf->file_path); | |||
369 | conflicts_found++; | |||
370 | } | |||
371 | } | |||
372 | } | |||
373 | } | |||
374 | ||||
375 | free(branch); | |||
376 | free(brev); | |||
377 | ||||
378 | if (cf->file_status != FILE_ADDED1 && | |||
379 | cf->file_status != FILE_REMOVED2 && | |||
380 | cf->file_status != FILE_MODIFIED3) | |||
381 | return; | |||
382 | ||||
383 | cvs_file_get(cf->file_path, 0, &files_affected, CVS_FILE2); | |||
384 | ||||
385 | switch (cf->file_status) { | |||
386 | case FILE_ADDED1: | |||
387 | cvs_file_get(cf->file_path, 0, &files_added, CVS_FILE2); | |||
388 | break; | |||
389 | case FILE_REMOVED2: | |||
390 | cvs_file_get(cf->file_path, 0, &files_removed, CVS_FILE2); | |||
391 | break; | |||
392 | case FILE_MODIFIED3: | |||
393 | cvs_file_get(cf->file_path, 0, &files_modified, CVS_FILE2); | |||
394 | break; | |||
395 | } | |||
396 | } | |||
397 | ||||
398 | void | |||
399 | cvs_commit_local(struct cvs_file *cf) | |||
400 | { | |||
401 | char *tag; | |||
402 | BUF *b, *d; | |||
403 | int onbranch, isnew, histtype, branchadded; | |||
404 | RCSNUM *nrev, *crev, *rrev, *brev; | |||
405 | int openflags, rcsflags; | |||
406 | char rbuf[CVS_REV_BUFSZ32], nbuf[CVS_REV_BUFSZ32]; | |||
407 | CVSENTRIES *entlist; | |||
408 | char attic[PATH_MAX1024], repo[PATH_MAX1024], rcsfile[PATH_MAX1024]; | |||
409 | struct file_info *fi; | |||
410 | ||||
411 | cvs_log(LP_TRACE4, "cvs_commit_local(%s)", cf->file_path); | |||
412 | cvs_file_classify(cf, cvs_directory_tag); | |||
413 | ||||
414 | if (cvs_noexec == 1) | |||
| ||||
415 | return; | |||
416 | ||||
417 | if (cf->file_type != CVS_FILE2) | |||
418 | fatal("cvs_commit_local: '%s' is not a file", cf->file_path); | |||
419 | ||||
420 | tag = cvs_directory_tag; | |||
421 | if (cf->file_ent != NULL((void *)0) && cf->file_ent->ce_tag != NULL((void *)0)) | |||
422 | tag = cf->file_ent->ce_tag; | |||
423 | ||||
424 | branchadded = 0; | |||
425 | switch (cf->file_status) { | |||
426 | case FILE_ADDED1: | |||
427 | if (cf->file_rcs == NULL((void *)0) && tag != NULL((void *)0)) { | |||
428 | branchadded = 1; | |||
429 | cvs_add_tobranch(cf, tag); | |||
430 | } | |||
431 | break; | |||
432 | case FILE_MODIFIED3: | |||
433 | case FILE_REMOVED2: | |||
434 | if (cf->file_rcs == NULL((void *)0)) { | |||
435 | cvs_log(LP_ERR1, "RCS file for %s got lost", | |||
436 | cf->file_path); | |||
437 | return; | |||
438 | } | |||
439 | break; | |||
440 | default: | |||
441 | cvs_log(LP_ERR1, "skipping bogus file `%s'", cf->file_path); | |||
442 | return; | |||
443 | } | |||
444 | ||||
445 | onbranch = 0; | |||
446 | nrev = RCS_HEAD_REV((RCSNUM *)(-1)); | |||
447 | crev = NULL((void *)0); | |||
448 | rrev = NULL((void *)0); | |||
449 | d = NULL((void *)0); | |||
450 | ||||
451 | if (cf->file_rcs != NULL((void *)0) && cf->file_rcs->rf_branch != NULL((void *)0)) { | |||
452 | free(cf->file_rcs->rf_branch); | |||
453 | cf->file_rcs->rf_branch = NULL((void *)0); | |||
454 | } | |||
455 | ||||
456 | if (cf->file_rcs
| |||
457 | rrev = rcs_head_get(cf->file_rcs); | |||
458 | crev = rcs_head_get(cf->file_rcs); | |||
459 | if (crev == NULL((void *)0) || rrev == NULL((void *)0)) | |||
460 | fatal("no head revision in RCS file for %s", | |||
461 | cf->file_path); | |||
462 | ||||
463 | if (tag != NULL((void *)0)) { | |||
464 | free(crev); | |||
465 | free(rrev); | |||
466 | brev = rcs_sym_getrev(cf->file_rcs, tag); | |||
467 | crev = rcs_translate_tag(tag, cf->file_rcs); | |||
468 | if (brev == NULL((void *)0) || crev == NULL((void *)0)) { | |||
469 | fatal("failed to resolve existing tag: %s", | |||
470 | tag); | |||
471 | } | |||
472 | ||||
473 | rrev = rcsnum_alloc(); | |||
474 | rcsnum_cpy(brev, rrev, brev->rn_len - 1); | |||
475 | ||||
476 | if (RCSNUM_ISBRANCHREV(crev)(!((crev)->rn_len % 2) && ((crev)->rn_len >= 4)) && | |||
477 | rcsnum_cmp(crev, rrev, 0)) { | |||
478 | nrev = rcsnum_alloc(); | |||
479 | rcsnum_cpy(crev, nrev, 0); | |||
480 | rcsnum_inc(nrev); | |||
481 | } else if (!RCSNUM_ISBRANCH(crev)((crev)->rn_len % 2)) { | |||
482 | nrev = rcsnum_brtorev(brev); | |||
483 | if (nrev == NULL((void *)0)) | |||
484 | fatal("failed to create branch rev"); | |||
485 | } else { | |||
486 | fatal("this isnt suppose to happen, honestly"); | |||
487 | } | |||
488 | ||||
489 | free(brev); | |||
490 | free(rrev); | |||
491 | rrev = rcsnum_branch_root(nrev); | |||
492 | ||||
493 | /* branch stuff was checked in cvs_commit_check_files */ | |||
494 | onbranch = 1; | |||
495 | } | |||
496 | ||||
497 | rcsnum_tostr(crev, rbuf, sizeof(rbuf)); | |||
498 | } else { | |||
499 | strlcpy(rbuf, "Non-existent", sizeof(rbuf)); | |||
500 | } | |||
501 | ||||
502 | free(rrev); | |||
503 | isnew = 0; | |||
504 | if (cf->file_status == FILE_ADDED1) { | |||
505 | isnew = 1; | |||
506 | rcsflags = RCS_CREATE(1<<2); | |||
507 | openflags = O_CREAT0x0200 | O_RDONLY0x0000; | |||
508 | if (cf->file_rcs != NULL((void *)0)) { | |||
509 | if (!onbranch) { | |||
510 | if (cf->in_attic == 0) | |||
511 | cvs_log(LP_ERR1, "warning: expected %s " | |||
512 | "to be in the Attic", | |||
513 | cf->file_path); | |||
514 | ||||
515 | if (cf->file_rcs->rf_dead == 0) | |||
516 | cvs_log(LP_ERR1, "warning: expected %s " | |||
517 | "to be dead", cf->file_path); | |||
518 | ||||
519 | cvs_get_repository_path(cf->file_wd, repo, | |||
520 | PATH_MAX1024); | |||
521 | (void)xsnprintf(rcsfile, PATH_MAX1024, "%s/%s%s", | |||
522 | repo, cf->file_name, RCS_FILE_EXT",v"); | |||
523 | ||||
524 | if (rename(cf->file_rpath, rcsfile) == -1) | |||
525 | fatal("cvs_commit_local: failed to " | |||
526 | "move %s outside the Attic: %s", | |||
527 | cf->file_path, strerror(errno(*__errno()))); | |||
528 | ||||
529 | free(cf->file_rpath); | |||
530 | cf->file_rpath = xstrdup(rcsfile); | |||
531 | isnew = 0; | |||
532 | } | |||
533 | ||||
534 | rcsflags = RCS_READ(1<<0) | RCS_PARSE_FULLY(1<<3); | |||
535 | openflags = O_RDONLY0x0000; | |||
536 | rcs_close(cf->file_rcs); | |||
537 | } | |||
538 | ||||
539 | cf->repo_fd = open(cf->file_rpath, openflags); | |||
540 | if (cf->repo_fd == -1) | |||
541 | fatal("cvs_commit_local: %s", strerror(errno(*__errno()))); | |||
542 | ||||
543 | cf->file_rcs = rcs_open(cf->file_rpath, cf->repo_fd, | |||
544 | rcsflags, 0444); | |||
545 | if (cf->file_rcs == NULL((void *)0)) | |||
546 | fatal("cvs_commit_local: failed to create RCS file " | |||
547 | "for %s", cf->file_path); | |||
548 | ||||
549 | commit_desc_set(cf); | |||
550 | ||||
551 | if (branchadded) | |||
552 | strlcpy(rbuf, "Non-existent", sizeof(rbuf)); | |||
553 | } | |||
554 | ||||
555 | if (verbosity > 1) { | |||
556 | cvs_printf("Checking in %s:\n", cf->file_path); | |||
557 | cvs_printf("%s <- %s\n", cf->file_rpath, cf->file_path); | |||
558 | cvs_printf("old revision: %s; ", rbuf); | |||
559 | } | |||
560 | ||||
561 | if (isnew
| |||
| ||||
562 | fatal("no head revision in RCS file for %s", cf->file_path); | |||
563 | ||||
564 | if (isnew == 0 && onbranch == 0) | |||
565 | d = commit_diff(cf, cf->file_rcs->rf_head, 0); | |||
566 | ||||
567 | if (cf->file_status == FILE_REMOVED2) { | |||
568 | b = rcs_rev_getbuf(cf->file_rcs, crev, 0); | |||
569 | } else if (onbranch == 1) { | |||
570 | b = commit_diff(cf, crev, 1); | |||
571 | } else { | |||
572 | b = buf_load_fd(cf->fd); | |||
573 | } | |||
574 | ||||
575 | if (isnew == 0 && onbranch == 0) { | |||
576 | if (rcs_deltatext_set(cf->file_rcs, crev, d) == -1) | |||
577 | fatal("cvs_commit_local: failed to set delta"); | |||
578 | } | |||
579 | ||||
580 | if (rcs_rev_add(cf->file_rcs, nrev, logmsg, -1, NULL((void *)0)) == -1) | |||
581 | fatal("cvs_commit_local: failed to add new revision"); | |||
582 | ||||
583 | if (nrev == RCS_HEAD_REV((RCSNUM *)(-1))) | |||
584 | nrev = cf->file_rcs->rf_head; | |||
585 | ||||
586 | if (rcs_deltatext_set(cf->file_rcs, nrev, b) == -1) | |||
587 | fatal("cvs_commit_local: failed to set new HEAD delta"); | |||
588 | ||||
589 | if (cf->file_status == FILE_REMOVED2) { | |||
590 | if (rcs_state_set(cf->file_rcs, nrev, RCS_STATE_DEAD"dead") == -1) | |||
591 | fatal("cvs_commit_local: failed to set state"); | |||
592 | } | |||
593 | ||||
594 | if (cf->file_status == FILE_ADDED1 && cf->file_ent->ce_opts != NULL((void *)0)) { | |||
595 | int cf_kflag; | |||
596 | ||||
597 | cf_kflag = rcs_kflag_get(cf->file_ent->ce_opts + 2); | |||
598 | rcs_kwexp_set(cf->file_rcs, cf_kflag); | |||
599 | } | |||
600 | ||||
601 | rcs_write(cf->file_rcs); | |||
602 | ||||
603 | if (cf->file_status == FILE_REMOVED2) { | |||
604 | strlcpy(nbuf, "Removed", sizeof(nbuf)); | |||
605 | } else if (cf->file_status == FILE_ADDED1) { | |||
606 | if (cf->file_rcs->rf_dead == 1) | |||
607 | strlcpy(nbuf, "Initial Revision", sizeof(nbuf)); | |||
608 | else | |||
609 | rcsnum_tostr(nrev, nbuf, sizeof(nbuf)); | |||
610 | } else if (cf->file_status == FILE_MODIFIED3) { | |||
611 | rcsnum_tostr(nrev, nbuf, sizeof(nbuf)); | |||
612 | } | |||
613 | ||||
614 | if (verbosity > 1) | |||
615 | cvs_printf("new revision: %s\n", nbuf); | |||
616 | ||||
617 | (void)unlink(cf->file_path); | |||
618 | (void)close(cf->fd); | |||
619 | cf->fd = -1; | |||
620 | ||||
621 | if (cf->file_status != FILE_REMOVED2) { | |||
622 | cvs_checkout_file(cf, nrev, NULL((void *)0), CO_COMMIT0x08); | |||
623 | } else { | |||
624 | entlist = cvs_ent_open(cf->file_wd); | |||
625 | cvs_ent_remove(entlist, cf->file_name); | |||
626 | ||||
627 | cvs_get_repository_path(cf->file_wd, repo, PATH_MAX1024); | |||
628 | ||||
629 | (void)xsnprintf(attic, PATH_MAX1024, "%s/%s", | |||
630 | repo, CVS_PATH_ATTIC"Attic"); | |||
631 | ||||
632 | if (mkdir(attic, 0755) == -1 && errno(*__errno()) != EEXIST17) | |||
633 | fatal("cvs_commit_local: failed to create Attic"); | |||
634 | ||||
635 | (void)xsnprintf(attic, PATH_MAX1024, "%s/%s/%s%s", repo, | |||
636 | CVS_PATH_ATTIC"Attic", cf->file_name, RCS_FILE_EXT",v"); | |||
637 | ||||
638 | if (rename(cf->file_rpath, attic) == -1) | |||
639 | fatal("cvs_commit_local: failed to move %s to Attic", | |||
640 | cf->file_path); | |||
641 | ||||
642 | if (cvs_server_active == 1) | |||
643 | cvs_server_update_entry("Remove-entry", cf); | |||
644 | } | |||
645 | ||||
646 | if (verbosity > 1) | |||
647 | cvs_printf("done\n"); | |||
648 | else { | |||
649 | cvs_log(LP_NOTICE0, "checking in '%s'; revision %s -> %s", | |||
650 | cf->file_path, rbuf, nbuf); | |||
651 | } | |||
652 | ||||
653 | if (line_list != NULL((void *)0)) { | |||
654 | fi = xcalloc(1, sizeof(*fi)); | |||
655 | fi->file_path = xstrdup(cf->file_path); | |||
656 | fi->crevstr = xstrdup(rbuf); | |||
657 | fi->nrevstr = xstrdup(nbuf); | |||
658 | if (tag != NULL((void *)0)) | |||
659 | fi->tag_new = xstrdup(tag); | |||
660 | TAILQ_INSERT_TAIL(&files_info, fi, flist)do { (fi)->flist.tqe_next = ((void *)0); (fi)->flist.tqe_prev = (&files_info)->tqh_last; *(&files_info)->tqh_last = (fi); (&files_info)->tqh_last = &(fi)->flist .tqe_next; } while (0); | |||
661 | } | |||
662 | ||||
663 | switch (cf->file_status) { | |||
664 | case FILE_MODIFIED3: | |||
665 | histtype = CVS_HISTORY_COMMIT_MODIFIED8; | |||
666 | break; | |||
667 | case FILE_ADDED1: | |||
668 | histtype = CVS_HISTORY_COMMIT_ADDED9; | |||
669 | break; | |||
670 | case FILE_REMOVED2: | |||
671 | histtype = CVS_HISTORY_COMMIT_REMOVED10; | |||
672 | break; | |||
673 | default: | |||
674 | histtype = -1; | |||
675 | break; | |||
676 | } | |||
677 | ||||
678 | free(crev); | |||
679 | ||||
680 | if (histtype != -1) | |||
681 | cvs_history_add(histtype, cf, NULL((void *)0)); | |||
682 | else | |||
683 | cvs_log(LP_NOTICE0, "histtype was -1 for %s", cf->file_path); | |||
684 | } | |||
685 | ||||
686 | static BUF * | |||
687 | commit_diff(struct cvs_file *cf, RCSNUM *rev, int reverse) | |||
688 | { | |||
689 | int fd1, fd2, d; | |||
690 | char *p1, *p2; | |||
691 | BUF *b; | |||
692 | ||||
693 | (void)xasprintf(&p1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir); | |||
694 | ||||
695 | if (cf->file_status == FILE_MODIFIED3 || | |||
696 | cf->file_status == FILE_ADDED1) { | |||
697 | b = buf_load_fd(cf->fd); | |||
698 | fd1 = buf_write_stmp(b, p1, NULL((void *)0)); | |||
699 | buf_free(b); | |||
700 | } else { | |||
701 | fd1 = rcs_rev_write_stmp(cf->file_rcs, rev, p1, 0); | |||
702 | } | |||
703 | ||||
704 | (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir); | |||
705 | fd2 = rcs_rev_write_stmp(cf->file_rcs, rev, p2, RCS_KWEXP_NONE0x01); | |||
706 | ||||
707 | b = buf_alloc(128); | |||
708 | ||||
709 | diff_format = D_RCSDIFF5; | |||
710 | ||||
711 | if (reverse == 1) | |||
712 | d = diffreg(p2, p1, fd2, fd1, b, D_FORCEASCII0x01); | |||
713 | else | |||
714 | d = diffreg(p1, p2, fd1, fd2, b, D_FORCEASCII0x01); | |||
715 | if (d == D_ERROR7) | |||
716 | fatal("commit_diff: failed to get RCS patch"); | |||
717 | ||||
718 | close(fd1); | |||
719 | close(fd2); | |||
720 | ||||
721 | free(p1); | |||
722 | free(p2); | |||
723 | ||||
724 | return (b); | |||
725 | } | |||
726 | ||||
727 | static void | |||
728 | commit_desc_set(struct cvs_file *cf) | |||
729 | { | |||
730 | BUF *bp; | |||
731 | int fd; | |||
732 | char desc_path[PATH_MAX1024], *desc; | |||
733 | ||||
734 | (void)xsnprintf(desc_path, PATH_MAX1024, "%s/%s/%s%s", | |||
735 | cf->file_wd, CVS_PATH_CVSDIR"CVS", cf->file_name, CVS_DESCR_FILE_EXT",t"); | |||
736 | ||||
737 | if ((fd = open(desc_path, O_RDONLY0x0000)) == -1) | |||
738 | return; | |||
739 | ||||
740 | bp = buf_load_fd(fd); | |||
741 | buf_putc(bp, '\0'); | |||
742 | desc = buf_release(bp); | |||
743 | ||||
744 | rcs_desc_set(cf->file_rcs, desc); | |||
745 | ||||
746 | (void)close(fd); | |||
747 | (void)cvs_unlink(desc_path); | |||
748 | ||||
749 | free(desc); | |||
750 | } |