Annotation of src/usr.bin/cvs/commit.c, Revision 1.160
1.160 ! deraadt 1: /* $OpenBSD: commit.c,v 1.159 2018/12/30 23:09:58 guenther Exp $ */
1.1 jfb 2: /*
1.55 joris 3: * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
1.71 xsa 4: * Copyright (c) 2006 Xavier Santolaria <xsa@openbsd.org>
1.1 jfb 5: *
1.55 joris 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.
1.1 jfb 9: *
1.55 joris 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.
1.1 jfb 17: */
18:
1.105 otto 19: #include <sys/stat.h>
20:
21: #include <errno.h>
22: #include <fcntl.h>
1.154 nicm 23: #include <stdlib.h>
1.105 otto 24: #include <string.h>
25: #include <unistd.h>
1.1 jfb 26:
27: #include "cvs.h"
1.55 joris 28: #include "diff.h"
1.80 joris 29: #include "remote.h"
1.1 jfb 30:
1.135 tobias 31: void cvs_commit_local(struct cvs_file *);
32: void cvs_commit_check_files(struct cvs_file *);
1.139 joris 33: void cvs_commit_loginfo(char *);
1.135 tobias 34: void cvs_commit_lock_dirs(struct cvs_file *);
35:
1.112 joris 36: static BUF *commit_diff(struct cvs_file *, RCSNUM *, int);
1.71 xsa 37: static void commit_desc_set(struct cvs_file *);
1.55 joris 38:
1.137 joris 39: struct file_info_list files_info;
40: struct trigger_list *line_list;
1.86 joris 41:
1.139 joris 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:
1.86 joris 47: char *logmsg = NULL;
1.137 joris 48: char *loginfo = NULL;
1.152 nicm 49:
50: static int conflicts_found;
1.34 jfb 51:
52: struct cvs_cmd cvs_cmd_commit = {
1.157 joris 53: CVS_OP_COMMIT, CVS_USE_WDIR, "commit",
1.55 joris 54: { "ci", "com" },
1.34 jfb 55: "Check files into the repository",
56: "[-flR] [-F logfile | -m msg] [-r rev] ...",
57: "F:flm:Rr:",
1.18 joris 58: NULL,
1.55 joris 59: cvs_commit
1.18 joris 60: };
1.1 jfb 61:
1.55 joris 62: int
63: cvs_commit(int argc, char **argv)
1.1 jfb 64: {
1.127 joris 65: int flags;
1.121 tobias 66: int ch, Fflag, mflag;
1.127 joris 67: struct module_checkout *mc;
1.55 joris 68: struct cvs_recursion cr;
1.137 joris 69: struct cvs_filelist *l;
70: struct file_info *fi;
1.153 deraadt 71: char *arg = ".", repo[PATH_MAX];
1.3 krapht 72:
1.58 joris 73: flags = CR_RECURSE_DIRS;
1.121 tobias 74: Fflag = mflag = 0;
1.58 joris 75:
1.55 joris 76: while ((ch = getopt(argc, argv, cvs_cmd_commit.cmd_opts)) != -1) {
1.1 jfb 77: switch (ch) {
78: case 'F':
1.121 tobias 79: /* free previously assigned value */
1.154 nicm 80: free(logmsg);
1.88 joris 81: logmsg = cvs_logmsg_read(optarg);
1.121 tobias 82: Fflag = 1;
1.1 jfb 83: break;
1.82 xsa 84: case 'f':
85: break;
1.1 jfb 86: case 'l':
1.58 joris 87: flags &= ~CR_RECURSE_DIRS;
1.1 jfb 88: break;
89: case 'm':
1.121 tobias 90: /* free previously assigned value */
1.154 nicm 91: free(logmsg);
1.55 joris 92: logmsg = xstrdup(optarg);
1.121 tobias 93: mflag = 1;
1.55 joris 94: break;
1.82 xsa 95: case 'R':
1.120 tobias 96: flags |= CR_RECURSE_DIRS;
1.82 xsa 97: break;
1.55 joris 98: case 'r':
1.1 jfb 99: break;
100: default:
1.55 joris 101: fatal("%s", cvs_cmd_commit.cmd_synopsis);
1.1 jfb 102: }
103: }
104:
1.55 joris 105: argc -= optind;
106: argv += optind;
1.121 tobias 107:
108: /* -F and -m are mutually exclusive */
109: if (Fflag && mflag)
110: fatal("cannot specify both a log file and a message");
1.1 jfb 111:
1.146 joris 112: RB_INIT(&files_affected);
113: RB_INIT(&files_added);
114: RB_INIT(&files_removed);
115: RB_INIT(&files_modified);
1.139 joris 116:
1.137 joris 117: TAILQ_INIT(&files_info);
1.86 joris 118: conflicts_found = 0;
119:
120: cr.enterdir = NULL;
121: cr.leavedir = NULL;
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);
1.92 joris 133:
1.146 joris 134: if (RB_EMPTY(&files_affected))
1.92 joris 135: return (0);
1.86 joris 136:
1.158 joris 137: if (cvsroot_is_remote()) {
1.145 tobias 138: if (logmsg == NULL) {
139: logmsg = cvs_logmsg_create(NULL, &files_added,
140: &files_removed, &files_modified);
141: if (logmsg == NULL)
142: fatal("This shouldnt happen, honestly!");
143: }
1.89 joris 144: cvs_client_connect_to_server();
1.80 joris 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);
1.99 xsa 151:
152: if (!(flags & CR_RECURSE_DIRS))
153: cvs_client_send_request("Argument -l");
1.80 joris 154:
1.123 tobias 155: cvs_client_send_logmsg(logmsg);
1.80 joris 156: cvs_client_send_files(argv, argc);
157: cvs_client_senddir(".");
158: cvs_client_send_request("ci");
159: cvs_client_get_responses();
1.86 joris 160: } else {
1.153 deraadt 161: cvs_get_repository_name(".", repo, PATH_MAX);
1.139 joris 162:
163: line_list = cvs_trigger_getlines(CVS_PATH_COMMITINFO, repo);
164: if (line_list != NULL) {
1.146 joris 165: RB_FOREACH(l, cvs_flisthead, &files_affected) {
1.139 joris 166: fi = xcalloc(1, sizeof(*fi));
167: fi->file_path = xstrdup(l->file_path);
168: TAILQ_INSERT_TAIL(&files_info, fi,
169: flist);
1.135 tobias 170: }
1.132 joris 171:
1.139 joris 172: if (cvs_trigger_handle(CVS_TRIGGER_COMMITINFO,
173: repo, NULL, line_list, &files_info)) {
174: cvs_log(LP_ERR,
175: "Pre-commit check failed");
1.137 joris 176: cvs_trigger_freelist(line_list);
1.139 joris 177: goto end;
1.137 joris 178: }
1.138 joris 179:
1.139 joris 180: cvs_trigger_freelist(line_list);
181: cvs_trigger_freeinfo(&files_info);
182: }
1.137 joris 183:
1.145 tobias 184: if (cvs_server_active) {
185: if (logmsg == NULL)
186: fatal("no log message specified");
187: } else if (logmsg == NULL) {
188: logmsg = cvs_logmsg_create(NULL, &files_added,
1.151 nicm 189: &files_removed, &files_modified);
1.145 tobias 190: if (logmsg == NULL)
191: fatal("This shouldnt happen, honestly!");
192: }
193:
1.139 joris 194: if (cvs_logmsg_verify(logmsg))
195: goto end;
1.127 joris 196:
1.139 joris 197: cr.fileproc = cvs_commit_lock_dirs;
198: cvs_file_walklist(&files_affected, &cr);
1.137 joris 199:
1.139 joris 200: line_list = cvs_trigger_getlines(CVS_PATH_LOGINFO, repo);
1.135 tobias 201:
1.139 joris 202: cr.fileproc = cvs_commit_local;
203: cvs_file_walklist(&files_affected, &cr);
1.138 joris 204:
1.139 joris 205: if (line_list != NULL) {
206: cvs_commit_loginfo(repo);
1.138 joris 207:
1.139 joris 208: cvs_trigger_handle(CVS_TRIGGER_LOGINFO, repo,
209: loginfo, line_list, &files_info);
1.137 joris 210:
1.154 nicm 211: free(loginfo);
1.139 joris 212: cvs_trigger_freelist(line_list);
213: cvs_trigger_freeinfo(&files_info);
1.135 tobias 214: }
1.139 joris 215:
216: mc = cvs_module_lookup(repo);
217: if (mc->mc_prog != NULL &&
218: (mc->mc_flags & MODULE_RUN_ON_COMMIT))
219: cvs_exec(mc->mc_prog, NULL, 0);
1.80 joris 220: }
1.1 jfb 221:
1.137 joris 222: end:
223: cvs_trigger_freeinfo(&files_info);
1.154 nicm 224: free(logmsg);
1.18 joris 225: return (0);
1.132 joris 226: }
227:
228: void
1.139 joris 229: cvs_commit_loginfo(char *repo)
1.137 joris 230: {
231: BUF *buf;
1.153 deraadt 232: char pwd[PATH_MAX];
1.137 joris 233: struct cvs_filelist *cf;
234:
235: if (getcwd(pwd, sizeof(pwd)) == NULL)
236: fatal("Can't get working directory");
237:
1.150 ray 238: buf = buf_alloc(1024);
1.137 joris 239:
240: cvs_trigger_loginfo_header(buf, repo);
241:
1.146 joris 242: if (!RB_EMPTY(&files_added)) {
1.150 ray 243: buf_puts(buf, "Added Files:");
1.137 joris 244:
1.146 joris 245: RB_FOREACH(cf, cvs_flisthead, &files_added) {
1.150 ray 246: buf_putc(buf, '\n');
247: buf_putc(buf, '\t');
248: buf_puts(buf, cf->file_path);
1.137 joris 249: }
250:
1.150 ray 251: buf_putc(buf, '\n');
1.137 joris 252: }
253:
1.146 joris 254: if (!RB_EMPTY(&files_modified)) {
1.150 ray 255: buf_puts(buf, "Modified Files:");
1.137 joris 256:
1.146 joris 257: RB_FOREACH(cf, cvs_flisthead, &files_modified) {
1.150 ray 258: buf_putc(buf, '\n');
259: buf_putc(buf, '\t');
260: buf_puts(buf, cf->file_path);
1.137 joris 261: }
262:
1.150 ray 263: buf_putc(buf, '\n');
1.137 joris 264: }
265:
1.146 joris 266: if (!RB_EMPTY(&files_removed)) {
1.150 ray 267: buf_puts(buf, "Removed Files:");
1.137 joris 268:
1.146 joris 269: RB_FOREACH(cf, cvs_flisthead, &files_removed) {
1.150 ray 270: buf_putc(buf, '\n');
271: buf_putc(buf, '\t');
272: buf_puts(buf, cf->file_path);
1.137 joris 273: }
274:
1.150 ray 275: buf_putc(buf, '\n');
1.137 joris 276: }
277:
1.150 ray 278: buf_puts(buf, "Log Message:\n");
1.137 joris 279:
1.150 ray 280: buf_puts(buf, logmsg);
1.137 joris 281:
1.150 ray 282: buf_putc(buf, '\n');
283: buf_putc(buf, '\0');
1.137 joris 284:
1.150 ray 285: loginfo = buf_release(buf);
1.137 joris 286: }
287:
288: void
1.132 joris 289: cvs_commit_lock_dirs(struct cvs_file *cf)
290: {
1.153 deraadt 291: char repo[PATH_MAX];
1.132 joris 292:
293: cvs_get_repository_path(cf->file_wd, repo, sizeof(repo));
294: cvs_log(LP_TRACE, "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);
1.18 joris 298: }
1.1 jfb 299:
1.55 joris 300: void
1.86 joris 301: cvs_commit_check_files(struct cvs_file *cf)
1.18 joris 302: {
1.112 joris 303: char *tag;
304: RCSNUM *branch, *brev;
305:
1.123 tobias 306: branch = brev = NULL;
307:
1.86 joris 308: cvs_log(LP_TRACE, "cvs_commit_check_files(%s)", cf->file_path);
1.44 joris 309:
1.158 joris 310: if (cvsroot_is_remote())
1.108 joris 311: cvs_remote_classify_file(cf);
312: else
1.110 joris 313: cvs_file_classify(cf, cvs_directory_tag);
1.59 joris 314:
315: if (cf->file_type == CVS_DIR) {
316: if (verbosity > 1)
317: cvs_log(LP_NOTICE, "Examining %s", cf->file_path);
318: return;
319: }
1.32 joris 320:
1.136 tobias 321: if (cf->file_status == FILE_UPTODATE)
322: return;
323:
324: if (cf->file_status == FILE_MERGE ||
325: cf->file_status == FILE_PATCH ||
326: cf->file_status == FILE_CHECKOUT ||
327: cf->file_status == FILE_LOST ||
1.79 joris 328: cf->file_status == FILE_UNLINK) {
1.136 tobias 329: cvs_log(LP_ERR, "conflict: %s is not up-to-date",
330: cf->file_path);
1.55 joris 331: conflicts_found++;
1.79 joris 332: return;
333: }
1.57 joris 334:
1.136 tobias 335: if (cf->file_status == FILE_CONFLICT &&
336: cf->file_ent->ce_conflict != NULL) {
1.60 joris 337: cvs_log(LP_ERR, "conflict: unresolved conflicts in %s from "
338: "merging, please fix these first", cf->file_path);
339: conflicts_found++;
1.79 joris 340: return;
1.60 joris 341: }
342:
1.136 tobias 343: if (cf->file_status == FILE_MODIFIED &&
344: cf->file_ent->ce_conflict != NULL &&
345: update_has_conflict_markers(cf)) {
346: cvs_log(LP_ERR, "warning: file %s seems to still contain "
347: "conflict indicators", cf->file_path);
1.128 joris 348: }
349:
350: if (cf->file_ent != NULL && cf->file_ent->ce_date != -1) {
351: cvs_log(LP_ERR, "conflict: cannot commit to sticky date for %s",
1.57 joris 352: cf->file_path);
353: conflicts_found++;
1.79 joris 354: return;
1.57 joris 355: }
1.55 joris 356:
1.158 joris 357: if (cvsroot_is_local()) {
1.112 joris 358: tag = cvs_directory_tag;
359: if (cf->file_ent != NULL)
360: tag = cf->file_ent->ce_tag;
361:
362: if (tag != NULL && cf->file_rcs != NULL) {
363: brev = rcs_sym_getrev(cf->file_rcs, tag);
364: if (brev != NULL) {
1.156 joris 365: if (!RCSNUM_ISBRANCH(brev)) {
366: cvs_log(LP_ERR, "sticky tag %s is not "
367: "a branch for file %s", tag,
368: cf->file_path);
369: conflicts_found++;
370: }
1.112 joris 371: }
372: }
373: }
374:
1.155 fcambus 375: free(branch);
376: free(brev);
1.123 tobias 377:
1.135 tobias 378: if (cf->file_status != FILE_ADDED &&
379: cf->file_status != FILE_REMOVED &&
380: cf->file_status != FILE_MODIFIED)
381: return;
1.86 joris 382:
1.147 joris 383: cvs_file_get(cf->file_path, 0, &files_affected, CVS_FILE);
1.135 tobias 384:
1.86 joris 385: switch (cf->file_status) {
386: case FILE_ADDED:
1.147 joris 387: cvs_file_get(cf->file_path, 0, &files_added, CVS_FILE);
1.86 joris 388: break;
389: case FILE_REMOVED:
1.147 joris 390: cvs_file_get(cf->file_path, 0, &files_removed, CVS_FILE);
1.86 joris 391: break;
392: case FILE_MODIFIED:
1.147 joris 393: cvs_file_get(cf->file_path, 0, &files_modified, CVS_FILE);
1.86 joris 394: break;
395: }
1.55 joris 396: }
1.1 jfb 397:
1.55 joris 398: void
399: cvs_commit_local(struct cvs_file *cf)
400: {
1.112 joris 401: char *tag;
1.91 joris 402: BUF *b, *d;
1.143 tobias 403: int onbranch, isnew, histtype, branchadded;
1.112 joris 404: RCSNUM *nrev, *crev, *rrev, *brev;
1.102 xsa 405: int openflags, rcsflags;
1.119 tobias 406: char rbuf[CVS_REV_BUFSZ], nbuf[CVS_REV_BUFSZ];
1.56 joris 407: CVSENTRIES *entlist;
1.153 deraadt 408: char attic[PATH_MAX], repo[PATH_MAX], rcsfile[PATH_MAX];
1.137 joris 409: struct file_info *fi;
1.17 joris 410:
1.55 joris 411: cvs_log(LP_TRACE, "cvs_commit_local(%s)", cf->file_path);
1.110 joris 412: cvs_file_classify(cf, cvs_directory_tag);
1.69 joris 413:
414: if (cvs_noexec == 1)
415: return;
1.35 xsa 416:
1.64 joris 417: if (cf->file_type != CVS_FILE)
418: fatal("cvs_commit_local: '%s' is not a file", cf->file_path);
419:
1.143 tobias 420: tag = cvs_directory_tag;
421: if (cf->file_ent != NULL && cf->file_ent->ce_tag != NULL)
422: tag = cf->file_ent->ce_tag;
423:
424: branchadded = 0;
425: switch (cf->file_status) {
426: case FILE_ADDED:
427: if (cf->file_rcs == NULL && tag != NULL) {
428: branchadded = 1;
429: cvs_add_tobranch(cf, tag);
430: }
431: break;
432: case FILE_MODIFIED:
433: case FILE_REMOVED:
434: if (cf->file_rcs == NULL) {
435: cvs_log(LP_ERR, "RCS file for %s got lost",
436: cf->file_path);
437: return;
438: }
439: break;
440: default:
1.107 joris 441: cvs_log(LP_ERR, "skipping bogus file `%s'", cf->file_path);
442: return;
443: }
444:
1.112 joris 445: onbranch = 0;
446: nrev = RCS_HEAD_REV;
447: crev = NULL;
448: rrev = NULL;
1.144 joris 449: d = NULL;
1.112 joris 450:
1.115 joris 451: if (cf->file_rcs != NULL && cf->file_rcs->rf_branch != NULL) {
1.155 fcambus 452: free(cf->file_rcs->rf_branch);
1.114 joris 453: cf->file_rcs->rf_branch = NULL;
454: }
455:
1.143 tobias 456: if (cf->file_rcs != NULL) {
1.112 joris 457: rrev = rcs_head_get(cf->file_rcs);
458: crev = rcs_head_get(cf->file_rcs);
1.116 tobias 459: if (crev == NULL || rrev == NULL)
1.142 tobias 460: fatal("no head revision in RCS file for %s",
461: cf->file_path);
1.112 joris 462:
463: if (tag != NULL) {
1.155 fcambus 464: free(crev);
465: free(rrev);
1.133 tobias 466: brev = rcs_sym_getrev(cf->file_rcs, tag);
1.112 joris 467: crev = rcs_translate_tag(tag, cf->file_rcs);
1.133 tobias 468: if (brev == NULL || crev == NULL) {
1.112 joris 469: fatal("failed to resolve existing tag: %s",
470: tag);
471: }
472:
1.133 tobias 473: rrev = rcsnum_alloc();
474: rcsnum_cpy(brev, rrev, brev->rn_len - 1);
475:
476: if (RCSNUM_ISBRANCHREV(crev) &&
477: rcsnum_cmp(crev, rrev, 0)) {
1.112 joris 478: nrev = rcsnum_alloc();
479: rcsnum_cpy(crev, nrev, 0);
480: rcsnum_inc(nrev);
481: } else if (!RCSNUM_ISBRANCH(crev)) {
482: nrev = rcsnum_brtorev(brev);
483: if (nrev == NULL)
484: fatal("failed to create branch rev");
485: } else {
486: fatal("this isnt suppose to happen, honestly");
487: }
488:
1.155 fcambus 489: free(brev);
490: free(rrev);
1.112 joris 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));
1.93 joris 498: } else {
1.61 joris 499: strlcpy(rbuf, "Non-existent", sizeof(rbuf));
1.93 joris 500: }
1.61 joris 501:
1.155 fcambus 502: free(rrev);
1.67 joris 503: isnew = 0;
1.66 joris 504: if (cf->file_status == FILE_ADDED) {
1.67 joris 505: isnew = 1;
1.66 joris 506: rcsflags = RCS_CREATE;
1.143 tobias 507: openflags = O_CREAT | O_RDONLY;
1.66 joris 508: if (cf->file_rcs != NULL) {
1.143 tobias 509: if (!onbranch) {
510: if (cf->in_attic == 0)
511: cvs_log(LP_ERR, "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_ERR, "warning: expected %s "
517: "to be dead", cf->file_path);
518:
519: cvs_get_repository_path(cf->file_wd, repo,
1.153 deraadt 520: PATH_MAX);
521: (void)xsnprintf(rcsfile, PATH_MAX, "%s/%s%s",
1.143 tobias 522: repo, cf->file_name, RCS_FILE_EXT);
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));
528:
1.154 nicm 529: free(cf->file_rpath);
1.143 tobias 530: cf->file_rpath = xstrdup(rcsfile);
531: isnew = 0;
532: }
1.66 joris 533:
534: rcsflags = RCS_READ | RCS_PARSE_FULLY;
535: openflags = O_RDONLY;
536: rcs_close(cf->file_rcs);
537: }
538:
539: cf->repo_fd = open(cf->file_rpath, openflags);
1.160 ! deraadt 540: if (cf->repo_fd == -1)
1.61 joris 541: fatal("cvs_commit_local: %s", strerror(errno));
542:
543: cf->file_rcs = rcs_open(cf->file_rpath, cf->repo_fd,
1.103 otto 544: rcsflags, 0444);
1.61 joris 545: if (cf->file_rcs == NULL)
546: fatal("cvs_commit_local: failed to create RCS file "
547: "for %s", cf->file_path);
1.71 xsa 548:
549: commit_desc_set(cf);
1.143 tobias 550:
551: if (branchadded)
552: strlcpy(rbuf, "Non-existent", sizeof(rbuf));
1.61 joris 553: }
1.36 joris 554:
1.77 reyk 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: }
1.142 tobias 560:
561: if (isnew == 0 && cf->file_rcs->rf_head == NULL)
562: fatal("no head revision in RCS file for %s", cf->file_path);
1.7 jfb 563:
1.112 joris 564: if (isnew == 0 && onbranch == 0)
565: d = commit_diff(cf, cf->file_rcs->rf_head, 0);
1.7 jfb 566:
1.56 joris 567: if (cf->file_status == FILE_REMOVED) {
1.112 joris 568: b = rcs_rev_getbuf(cf->file_rcs, crev, 0);
569: } else if (onbranch == 1) {
570: b = commit_diff(cf, crev, 1);
1.61 joris 571: } else {
1.150 ray 572: b = buf_load_fd(cf->fd);
1.56 joris 573: }
1.7 jfb 574:
1.112 joris 575: if (isnew == 0 && onbranch == 0) {
576: if (rcs_deltatext_set(cf->file_rcs, crev, d) == -1)
1.61 joris 577: fatal("cvs_commit_local: failed to set delta");
578: }
1.3 krapht 579:
1.112 joris 580: if (rcs_rev_add(cf->file_rcs, nrev, logmsg, -1, NULL) == -1)
1.55 joris 581: fatal("cvs_commit_local: failed to add new revision");
1.3 krapht 582:
1.112 joris 583: if (nrev == RCS_HEAD_REV)
584: nrev = cf->file_rcs->rf_head;
585:
586: if (rcs_deltatext_set(cf->file_rcs, nrev, b) == -1)
1.55 joris 587: fatal("cvs_commit_local: failed to set new HEAD delta");
1.3 krapht 588:
1.56 joris 589: if (cf->file_status == FILE_REMOVED) {
1.112 joris 590: if (rcs_state_set(cf->file_rcs, nrev, RCS_STATE_DEAD) == -1)
1.56 joris 591: fatal("cvs_commit_local: failed to set state");
1.101 xsa 592: }
593:
594: if (cf->file_status == FILE_ADDED && cf->file_ent->ce_opts != NULL) {
1.126 tobias 595: int cf_kflag;
1.101 xsa 596:
1.126 tobias 597: cf_kflag = rcs_kflag_get(cf->file_ent->ce_opts + 2);
598: rcs_kwexp_set(cf->file_rcs, cf_kflag);
1.56 joris 599: }
600:
1.55 joris 601: rcs_write(cf->file_rcs);
1.6 jfb 602:
1.56 joris 603: if (cf->file_status == FILE_REMOVED) {
1.77 reyk 604: strlcpy(nbuf, "Removed", sizeof(nbuf));
1.61 joris 605: } else if (cf->file_status == FILE_ADDED) {
1.66 joris 606: if (cf->file_rcs->rf_dead == 1)
1.77 reyk 607: strlcpy(nbuf, "Initial Revision", sizeof(nbuf));
1.63 joris 608: else
1.112 joris 609: rcsnum_tostr(nrev, nbuf, sizeof(nbuf));
1.56 joris 610: } else if (cf->file_status == FILE_MODIFIED) {
1.112 joris 611: rcsnum_tostr(nrev, nbuf, sizeof(nbuf));
1.56 joris 612: }
613:
1.77 reyk 614: if (verbosity > 1)
615: cvs_printf("new revision: %s\n", nbuf);
1.3 krapht 616:
1.55 joris 617: (void)unlink(cf->file_path);
618: (void)close(cf->fd);
619: cf->fd = -1;
1.56 joris 620:
621: if (cf->file_status != FILE_REMOVED) {
1.112 joris 622: cvs_checkout_file(cf, nrev, NULL, CO_COMMIT);
1.56 joris 623: } else {
624: entlist = cvs_ent_open(cf->file_wd);
625: cvs_ent_remove(entlist, cf->file_name);
1.64 joris 626:
1.153 deraadt 627: cvs_get_repository_path(cf->file_wd, repo, PATH_MAX);
1.64 joris 628:
1.153 deraadt 629: (void)xsnprintf(attic, PATH_MAX, "%s/%s",
1.102 xsa 630: repo, CVS_PATH_ATTIC);
1.64 joris 631:
632: if (mkdir(attic, 0755) == -1 && errno != EEXIST)
633: fatal("cvs_commit_local: failed to create Attic");
634:
1.153 deraadt 635: (void)xsnprintf(attic, PATH_MAX, "%s/%s/%s%s", repo,
1.64 joris 636: CVS_PATH_ATTIC, cf->file_name, RCS_FILE_EXT);
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:
1.85 joris 642: if (cvs_server_active == 1)
643: cvs_server_update_entry("Remove-entry", cf);
1.56 joris 644: }
1.3 krapht 645:
1.77 reyk 646: if (verbosity > 1)
647: cvs_printf("done\n");
648: else {
649: cvs_log(LP_NOTICE, "checking in '%s'; revision %s -> %s",
650: cf->file_path, rbuf, nbuf);
1.137 joris 651: }
652:
653: if (line_list != NULL) {
654: fi = xcalloc(1, sizeof(*fi));
655: fi->file_path = xstrdup(cf->file_path);
656: fi->crevstr = xstrdup(rbuf);
657: fi->nrevstr = xstrdup(nbuf);
1.140 joris 658: if (tag != NULL)
659: fi->tag_new = xstrdup(tag);
1.137 joris 660: TAILQ_INSERT_TAIL(&files_info, fi, flist);
1.77 reyk 661: }
1.107 joris 662:
663: switch (cf->file_status) {
664: case FILE_MODIFIED:
665: histtype = CVS_HISTORY_COMMIT_MODIFIED;
666: break;
667: case FILE_ADDED:
668: histtype = CVS_HISTORY_COMMIT_ADDED;
669: break;
670: case FILE_REMOVED:
671: histtype = CVS_HISTORY_COMMIT_REMOVED;
672: break;
1.144 joris 673: default:
674: histtype = -1;
675: break;
1.107 joris 676: }
1.125 joris 677:
1.155 fcambus 678: free(crev);
1.107 joris 679:
1.144 joris 680: if (histtype != -1)
681: cvs_history_add(histtype, cf, NULL);
682: else
683: cvs_log(LP_NOTICE, "histtype was -1 for %s", cf->file_path);
1.39 xsa 684: }
685:
1.91 joris 686: static BUF *
1.112 joris 687: commit_diff(struct cvs_file *cf, RCSNUM *rev, int reverse)
1.39 xsa 688: {
1.151 nicm 689: int fd1, fd2, d;
690: char *p1, *p2;
1.122 tobias 691: BUF *b;
1.97 joris 692:
693: (void)xasprintf(&p1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir);
1.39 xsa 694:
1.63 joris 695: if (cf->file_status == FILE_MODIFIED ||
696: cf->file_status == FILE_ADDED) {
1.150 ray 697: b = buf_load_fd(cf->fd);
698: fd1 = buf_write_stmp(b, p1, NULL);
699: buf_free(b);
1.63 joris 700: } else {
1.131 joris 701: fd1 = rcs_rev_write_stmp(cf->file_rcs, rev, p1, 0);
1.56 joris 702: }
1.3 krapht 703:
1.97 joris 704: (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir);
1.131 joris 705: fd2 = rcs_rev_write_stmp(cf->file_rcs, rev, p2, RCS_KWEXP_NONE);
1.55 joris 706:
1.150 ray 707: b = buf_alloc(128);
1.55 joris 708:
709: diff_format = D_RCSDIFF;
1.112 joris 710:
1.151 nicm 711: if (reverse == 1)
712: d = diffreg(p2, p1, fd2, fd1, b, D_FORCEASCII);
713: else
714: d = diffreg(p1, p2, fd1, fd2, b, D_FORCEASCII);
715: if (d == D_ERROR)
1.112 joris 716: fatal("commit_diff: failed to get RCS patch");
1.131 joris 717:
718: close(fd1);
719: close(fd2);
1.96 joris 720:
1.154 nicm 721: free(p1);
722: free(p2);
1.55 joris 723:
1.122 tobias 724: return (b);
1.71 xsa 725: }
726:
727: static void
728: commit_desc_set(struct cvs_file *cf)
729: {
730: BUF *bp;
1.102 xsa 731: int fd;
1.153 deraadt 732: char desc_path[PATH_MAX], *desc;
1.71 xsa 733:
1.153 deraadt 734: (void)xsnprintf(desc_path, PATH_MAX, "%s/%s/%s%s",
1.134 tobias 735: cf->file_wd, CVS_PATH_CVSDIR, cf->file_name, CVS_DESCR_FILE_EXT);
1.71 xsa 736:
1.100 otto 737: if ((fd = open(desc_path, O_RDONLY)) == -1)
1.71 xsa 738: return;
739:
1.150 ray 740: bp = buf_load_fd(fd);
741: buf_putc(bp, '\0');
742: desc = buf_release(bp);
1.71 xsa 743:
744: rcs_desc_set(cf->file_rcs, desc);
745:
1.76 joris 746: (void)close(fd);
1.71 xsa 747: (void)cvs_unlink(desc_path);
748:
1.154 nicm 749: free(desc);
1.1 jfb 750: }