1 /* $OpenBSD: commit.c,v 1.147 2009/03/26 22:54:37 joris 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.h> 22 #include <fcntl.h> 23 #include <libgen.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 int conflicts_found; 48 char *logmsg = NULL; 49 char *loginfo = NULL; 50 51 struct cvs_cmd cvs_cmd_commit = { 52 CVS_OP_COMMIT, CVS_USE_WDIR | CVS_LOCK_REPO, "commit", 53 { "ci", "com" }, 54 "Check files into the repository", 55 "[-flR] [-F logfile | -m msg] [-r rev] ...", 56 "F:flm:Rr:", 57 NULL, 58 cvs_commit 59 }; 60 61 int 62 cvs_commit(int argc, char **argv) 63 { 64 int flags; 65 int ch, Fflag, mflag; 66 struct module_checkout *mc; 67 struct cvs_recursion cr; 68 struct cvs_filelist *l; 69 struct file_info *fi; 70 char *arg = ".", repo[MAXPATHLEN]; 71 72 flags = CR_RECURSE_DIRS; 73 Fflag = mflag = 0; 74 75 while ((ch = getopt(argc, argv, cvs_cmd_commit.cmd_opts)) != -1) { 76 switch (ch) { 77 case 'F': 78 /* free previously assigned value */ 79 if (logmsg != NULL) 80 xfree(logmsg); 81 logmsg = cvs_logmsg_read(optarg); 82 Fflag = 1; 83 break; 84 case 'f': 85 break; 86 case 'l': 87 flags &= ~CR_RECURSE_DIRS; 88 break; 89 case 'm': 90 /* free previously assigned value */ 91 if (logmsg != NULL) 92 xfree(logmsg); 93 logmsg = xstrdup(optarg); 94 mflag = 1; 95 break; 96 case 'R': 97 flags |= CR_RECURSE_DIRS; 98 break; 99 case 'r': 100 break; 101 default: 102 fatal("%s", cvs_cmd_commit.cmd_synopsis); 103 } 104 } 105 106 argc -= optind; 107 argv += optind; 108 109 /* -F and -m are mutually exclusive */ 110 if (Fflag && mflag) 111 fatal("cannot specify both a log file and a message"); 112 113 RB_INIT(&files_affected); 114 RB_INIT(&files_added); 115 RB_INIT(&files_removed); 116 RB_INIT(&files_modified); 117 118 TAILQ_INIT(&files_info); 119 conflicts_found = 0; 120 121 cr.enterdir = NULL; 122 cr.leavedir = NULL; 123 cr.fileproc = cvs_commit_check_files; 124 cr.flags = flags; 125 126 if (argc > 0) 127 cvs_file_run(argc, argv, &cr); 128 else 129 cvs_file_run(1, &arg, &cr); 130 131 if (conflicts_found != 0) 132 fatal("%d conflicts found, please correct these first", 133 conflicts_found); 134 135 if (RB_EMPTY(&files_affected)) 136 return (0); 137 138 if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) { 139 if (logmsg == NULL) { 140 logmsg = cvs_logmsg_create(NULL, &files_added, 141 &files_removed, &files_modified); 142 if (logmsg == NULL) 143 fatal("This shouldnt happen, honestly!"); 144 } 145 cvs_client_connect_to_server(); 146 cr.fileproc = cvs_client_sendfile; 147 148 if (argc > 0) 149 cvs_file_run(argc, argv, &cr); 150 else 151 cvs_file_run(1, &arg, &cr); 152 153 if (!(flags & CR_RECURSE_DIRS)) 154 cvs_client_send_request("Argument -l"); 155 156 cvs_client_send_logmsg(logmsg); 157 cvs_client_send_files(argv, argc); 158 cvs_client_senddir("."); 159 cvs_client_send_request("ci"); 160 cvs_client_get_responses(); 161 } else { 162 cvs_get_repository_name(".", repo, MAXPATHLEN); 163 164 line_list = cvs_trigger_getlines(CVS_PATH_COMMITINFO, repo); 165 if (line_list != NULL) { 166 RB_FOREACH(l, cvs_flisthead, &files_affected) { 167 fi = xcalloc(1, sizeof(*fi)); 168 fi->file_path = xstrdup(l->file_path); 169 TAILQ_INSERT_TAIL(&files_info, fi, 170 flist); 171 } 172 173 if (cvs_trigger_handle(CVS_TRIGGER_COMMITINFO, 174 repo, NULL, line_list, &files_info)) { 175 cvs_log(LP_ERR, 176 "Pre-commit check failed"); 177 cvs_trigger_freelist(line_list); 178 goto end; 179 } 180 181 cvs_trigger_freelist(line_list); 182 cvs_trigger_freeinfo(&files_info); 183 } 184 185 if (cvs_server_active) { 186 if (logmsg == NULL) 187 fatal("no log message specified"); 188 } else if (logmsg == NULL) { 189 logmsg = cvs_logmsg_create(NULL, &files_added, 190 &files_removed, &files_modified); 191 if (logmsg == NULL) 192 fatal("This shouldnt happen, honestly!"); 193 } 194 195 if (cvs_logmsg_verify(logmsg)) 196 goto end; 197 198 cr.fileproc = cvs_commit_lock_dirs; 199 cvs_file_walklist(&files_affected, &cr); 200 201 line_list = cvs_trigger_getlines(CVS_PATH_LOGINFO, repo); 202 203 cr.fileproc = cvs_commit_local; 204 cvs_file_walklist(&files_affected, &cr); 205 206 if (line_list != NULL) { 207 cvs_commit_loginfo(repo); 208 209 cvs_trigger_handle(CVS_TRIGGER_LOGINFO, repo, 210 loginfo, line_list, &files_info); 211 212 xfree(loginfo); 213 cvs_trigger_freelist(line_list); 214 cvs_trigger_freeinfo(&files_info); 215 } 216 217 mc = cvs_module_lookup(repo); 218 if (mc->mc_prog != NULL && 219 (mc->mc_flags & MODULE_RUN_ON_COMMIT)) 220 cvs_exec(mc->mc_prog, NULL, 0); 221 } 222 223 end: 224 cvs_trigger_freeinfo(&files_info); 225 if (logmsg != NULL) 226 xfree(logmsg); 227 return (0); 228 } 229 230 void 231 cvs_commit_loginfo(char *repo) 232 { 233 BUF *buf; 234 char pwd[MAXPATHLEN]; 235 struct cvs_filelist *cf; 236 237 if (getcwd(pwd, sizeof(pwd)) == NULL) 238 fatal("Can't get working directory"); 239 240 buf = cvs_buf_alloc(1024); 241 242 cvs_trigger_loginfo_header(buf, repo); 243 244 if (!RB_EMPTY(&files_added)) { 245 cvs_buf_puts(buf, "Added Files:"); 246 247 RB_FOREACH(cf, cvs_flisthead, &files_added) { 248 cvs_buf_putc(buf, '\n'); 249 cvs_buf_putc(buf, '\t'); 250 cvs_buf_puts(buf, cf->file_path); 251 } 252 253 cvs_buf_putc(buf, '\n'); 254 } 255 256 if (!RB_EMPTY(&files_modified)) { 257 cvs_buf_puts(buf, "Modified Files:"); 258 259 RB_FOREACH(cf, cvs_flisthead, &files_modified) { 260 cvs_buf_putc(buf, '\n'); 261 cvs_buf_putc(buf, '\t'); 262 cvs_buf_puts(buf, cf->file_path); 263 } 264 265 cvs_buf_putc(buf, '\n'); 266 } 267 268 if (!RB_EMPTY(&files_removed)) { 269 cvs_buf_puts(buf, "Removed Files:"); 270 271 RB_FOREACH(cf, cvs_flisthead, &files_removed) { 272 cvs_buf_putc(buf, '\n'); 273 cvs_buf_putc(buf, '\t'); 274 cvs_buf_puts(buf, cf->file_path); 275 } 276 277 cvs_buf_putc(buf, '\n'); 278 } 279 280 cvs_buf_puts(buf, "Log Message:\n"); 281 282 cvs_buf_puts(buf, logmsg); 283 284 cvs_buf_putc(buf, '\n'); 285 cvs_buf_putc(buf, '\0'); 286 287 loginfo = cvs_buf_release(buf); 288 } 289 290 void 291 cvs_commit_lock_dirs(struct cvs_file *cf) 292 { 293 char repo[MAXPATHLEN]; 294 295 cvs_get_repository_path(cf->file_wd, repo, sizeof(repo)); 296 cvs_log(LP_TRACE, "cvs_commit_lock_dirs: %s", repo); 297 298 /* locks stay in place until we are fully done and exit */ 299 cvs_repository_lock(repo, 1); 300 } 301 302 void 303 cvs_commit_check_files(struct cvs_file *cf) 304 { 305 char *tag; 306 RCSNUM *branch, *brev; 307 308 branch = brev = NULL; 309 310 cvs_log(LP_TRACE, "cvs_commit_check_files(%s)", cf->file_path); 311 312 if (current_cvsroot->cr_method != CVS_METHOD_LOCAL) 313 cvs_remote_classify_file(cf); 314 else 315 cvs_file_classify(cf, cvs_directory_tag); 316 317 if (cf->file_type == CVS_DIR) { 318 if (verbosity > 1) 319 cvs_log(LP_NOTICE, "Examining %s", cf->file_path); 320 return; 321 } 322 323 if (cf->file_status == FILE_UPTODATE) 324 return; 325 326 if (cf->file_status == FILE_MERGE || 327 cf->file_status == FILE_PATCH || 328 cf->file_status == FILE_CHECKOUT || 329 cf->file_status == FILE_LOST || 330 cf->file_status == FILE_UNLINK) { 331 cvs_log(LP_ERR, "conflict: %s is not up-to-date", 332 cf->file_path); 333 conflicts_found++; 334 return; 335 } 336 337 if (cf->file_status == FILE_CONFLICT && 338 cf->file_ent->ce_conflict != NULL) { 339 cvs_log(LP_ERR, "conflict: unresolved conflicts in %s from " 340 "merging, please fix these first", cf->file_path); 341 conflicts_found++; 342 return; 343 } 344 345 if (cf->file_status == FILE_MODIFIED && 346 cf->file_ent->ce_conflict != NULL && 347 update_has_conflict_markers(cf)) { 348 cvs_log(LP_ERR, "warning: file %s seems to still contain " 349 "conflict indicators", cf->file_path); 350 } 351 352 if (cf->file_ent != NULL && cf->file_ent->ce_date != -1) { 353 cvs_log(LP_ERR, "conflict: cannot commit to sticky date for %s", 354 cf->file_path); 355 conflicts_found++; 356 return; 357 } 358 359 if (current_cvsroot->cr_method == CVS_METHOD_LOCAL) { 360 tag = cvs_directory_tag; 361 if (cf->file_ent != NULL) 362 tag = cf->file_ent->ce_tag; 363 364 if (tag != NULL && cf->file_rcs != NULL) { 365 brev = rcs_sym_getrev(cf->file_rcs, tag); 366 if (brev != NULL) { 367 if (RCSNUM_ISBRANCH(brev)) 368 goto next; 369 rcsnum_free(brev); 370 } 371 372 brev = rcs_translate_tag(tag, cf->file_rcs); 373 374 if (brev == NULL) { 375 if (cf->file_status == FILE_ADDED) 376 goto next; 377 fatal("failed to resolve tag: %s", 378 cf->file_ent->ce_tag); 379 } 380 381 if ((branch = rcsnum_revtobr(brev)) == NULL) { 382 cvs_log(LP_ERR, "sticky tag %s is not " 383 "a branch for file %s", tag, 384 cf->file_path); 385 conflicts_found++; 386 rcsnum_free(brev); 387 return; 388 } 389 390 if (!RCSNUM_ISBRANCHREV(brev)) { 391 cvs_log(LP_ERR, "sticky tag %s is not " 392 "a branch for file %s", tag, 393 cf->file_path); 394 conflicts_found++; 395 rcsnum_free(branch); 396 rcsnum_free(brev); 397 return; 398 } 399 400 if (!RCSNUM_ISBRANCH(branch)) { 401 cvs_log(LP_ERR, "sticky tag %s is not " 402 "a branch for file %s", tag, 403 cf->file_path); 404 conflicts_found++; 405 rcsnum_free(branch); 406 rcsnum_free(brev); 407 return; 408 } 409 } 410 } 411 412 next: 413 if (branch != NULL) 414 rcsnum_free(branch); 415 if (brev != NULL) 416 rcsnum_free(brev); 417 418 if (cf->file_status != FILE_ADDED && 419 cf->file_status != FILE_REMOVED && 420 cf->file_status != FILE_MODIFIED) 421 return; 422 423 cvs_file_get(cf->file_path, 0, &files_affected, CVS_FILE); 424 425 switch (cf->file_status) { 426 case FILE_ADDED: 427 cvs_file_get(cf->file_path, 0, &files_added, CVS_FILE); 428 break; 429 case FILE_REMOVED: 430 cvs_file_get(cf->file_path, 0, &files_removed, CVS_FILE); 431 break; 432 case FILE_MODIFIED: 433 cvs_file_get(cf->file_path, 0, &files_modified, CVS_FILE); 434 break; 435 } 436 } 437 438 void 439 cvs_commit_local(struct cvs_file *cf) 440 { 441 char *tag; 442 BUF *b, *d; 443 int onbranch, isnew, histtype, branchadded; 444 RCSNUM *nrev, *crev, *rrev, *brev; 445 int openflags, rcsflags; 446 char rbuf[CVS_REV_BUFSZ], nbuf[CVS_REV_BUFSZ]; 447 CVSENTRIES *entlist; 448 char attic[MAXPATHLEN], repo[MAXPATHLEN], rcsfile[MAXPATHLEN]; 449 struct file_info *fi; 450 451 cvs_log(LP_TRACE, "cvs_commit_local(%s)", cf->file_path); 452 cvs_file_classify(cf, cvs_directory_tag); 453 454 if (cvs_noexec == 1) 455 return; 456 457 if (cf->file_type != CVS_FILE) 458 fatal("cvs_commit_local: '%s' is not a file", cf->file_path); 459 460 tag = cvs_directory_tag; 461 if (cf->file_ent != NULL && cf->file_ent->ce_tag != NULL) 462 tag = cf->file_ent->ce_tag; 463 464 branchadded = 0; 465 switch (cf->file_status) { 466 case FILE_ADDED: 467 if (cf->file_rcs == NULL && tag != NULL) { 468 branchadded = 1; 469 cvs_add_tobranch(cf, tag); 470 } 471 break; 472 case FILE_MODIFIED: 473 case FILE_REMOVED: 474 if (cf->file_rcs == NULL) { 475 cvs_log(LP_ERR, "RCS file for %s got lost", 476 cf->file_path); 477 return; 478 } 479 break; 480 default: 481 cvs_log(LP_ERR, "skipping bogus file `%s'", cf->file_path); 482 return; 483 } 484 485 onbranch = 0; 486 nrev = RCS_HEAD_REV; 487 crev = NULL; 488 rrev = NULL; 489 d = NULL; 490 491 if (cf->file_rcs != NULL && cf->file_rcs->rf_branch != NULL) { 492 rcsnum_free(cf->file_rcs->rf_branch); 493 cf->file_rcs->rf_branch = NULL; 494 } 495 496 if (cf->file_rcs != NULL) { 497 rrev = rcs_head_get(cf->file_rcs); 498 crev = rcs_head_get(cf->file_rcs); 499 if (crev == NULL || rrev == NULL) 500 fatal("no head revision in RCS file for %s", 501 cf->file_path); 502 503 if (tag != NULL) { 504 rcsnum_free(crev); 505 rcsnum_free(rrev); 506 brev = rcs_sym_getrev(cf->file_rcs, tag); 507 crev = rcs_translate_tag(tag, cf->file_rcs); 508 if (brev == NULL || crev == NULL) { 509 fatal("failed to resolve existing tag: %s", 510 tag); 511 } 512 513 rrev = rcsnum_alloc(); 514 rcsnum_cpy(brev, rrev, brev->rn_len - 1); 515 516 if (RCSNUM_ISBRANCHREV(crev) && 517 rcsnum_cmp(crev, rrev, 0)) { 518 nrev = rcsnum_alloc(); 519 rcsnum_cpy(crev, nrev, 0); 520 rcsnum_inc(nrev); 521 } else if (!RCSNUM_ISBRANCH(crev)) { 522 nrev = rcsnum_brtorev(brev); 523 if (nrev == NULL) 524 fatal("failed to create branch rev"); 525 } else { 526 fatal("this isnt suppose to happen, honestly"); 527 } 528 529 rcsnum_free(brev); 530 rcsnum_free(rrev); 531 rrev = rcsnum_branch_root(nrev); 532 533 /* branch stuff was checked in cvs_commit_check_files */ 534 onbranch = 1; 535 } 536 537 rcsnum_tostr(crev, rbuf, sizeof(rbuf)); 538 } else { 539 strlcpy(rbuf, "Non-existent", sizeof(rbuf)); 540 } 541 542 if (rrev != NULL) 543 rcsnum_free(rrev); 544 isnew = 0; 545 if (cf->file_status == FILE_ADDED) { 546 isnew = 1; 547 rcsflags = RCS_CREATE; 548 openflags = O_CREAT | O_RDONLY; 549 if (cf->file_rcs != NULL) { 550 if (!onbranch) { 551 if (cf->in_attic == 0) 552 cvs_log(LP_ERR, "warning: expected %s " 553 "to be in the Attic", 554 cf->file_path); 555 556 if (cf->file_rcs->rf_dead == 0) 557 cvs_log(LP_ERR, "warning: expected %s " 558 "to be dead", cf->file_path); 559 560 cvs_get_repository_path(cf->file_wd, repo, 561 MAXPATHLEN); 562 (void)xsnprintf(rcsfile, MAXPATHLEN, "%s/%s%s", 563 repo, cf->file_name, RCS_FILE_EXT); 564 565 if (rename(cf->file_rpath, rcsfile) == -1) 566 fatal("cvs_commit_local: failed to " 567 "move %s outside the Attic: %s", 568 cf->file_path, strerror(errno)); 569 570 xfree(cf->file_rpath); 571 cf->file_rpath = xstrdup(rcsfile); 572 isnew = 0; 573 } 574 575 rcsflags = RCS_READ | RCS_PARSE_FULLY; 576 openflags = O_RDONLY; 577 rcs_close(cf->file_rcs); 578 } 579 580 cf->repo_fd = open(cf->file_rpath, openflags); 581 if (cf->repo_fd < 0) 582 fatal("cvs_commit_local: %s", strerror(errno)); 583 584 cf->file_rcs = rcs_open(cf->file_rpath, cf->repo_fd, 585 rcsflags, 0444); 586 if (cf->file_rcs == NULL) 587 fatal("cvs_commit_local: failed to create RCS file " 588 "for %s", cf->file_path); 589 590 commit_desc_set(cf); 591 592 if (branchadded) 593 strlcpy(rbuf, "Non-existent", sizeof(rbuf)); 594 } 595 596 if (verbosity > 1) { 597 cvs_printf("Checking in %s:\n", cf->file_path); 598 cvs_printf("%s <- %s\n", cf->file_rpath, cf->file_path); 599 cvs_printf("old revision: %s; ", rbuf); 600 } 601 602 if (isnew == 0 && cf->file_rcs->rf_head == NULL) 603 fatal("no head revision in RCS file for %s", cf->file_path); 604 605 if (isnew == 0 && onbranch == 0) 606 d = commit_diff(cf, cf->file_rcs->rf_head, 0); 607 608 if (cf->file_status == FILE_REMOVED) { 609 b = rcs_rev_getbuf(cf->file_rcs, crev, 0); 610 } else if (onbranch == 1) { 611 b = commit_diff(cf, crev, 1); 612 } else { 613 b = cvs_buf_load_fd(cf->fd); 614 } 615 616 if (isnew == 0 && onbranch == 0) { 617 if (rcs_deltatext_set(cf->file_rcs, crev, d) == -1) 618 fatal("cvs_commit_local: failed to set delta"); 619 } 620 621 if (rcs_rev_add(cf->file_rcs, nrev, logmsg, -1, NULL) == -1) 622 fatal("cvs_commit_local: failed to add new revision"); 623 624 if (nrev == RCS_HEAD_REV) 625 nrev = cf->file_rcs->rf_head; 626 627 if (rcs_deltatext_set(cf->file_rcs, nrev, b) == -1) 628 fatal("cvs_commit_local: failed to set new HEAD delta"); 629 630 if (cf->file_status == FILE_REMOVED) { 631 if (rcs_state_set(cf->file_rcs, nrev, RCS_STATE_DEAD) == -1) 632 fatal("cvs_commit_local: failed to set state"); 633 } 634 635 if (cf->file_status == FILE_ADDED && cf->file_ent->ce_opts != NULL) { 636 int cf_kflag; 637 638 cf_kflag = rcs_kflag_get(cf->file_ent->ce_opts + 2); 639 rcs_kwexp_set(cf->file_rcs, cf_kflag); 640 } 641 642 rcs_write(cf->file_rcs); 643 644 if (cf->file_status == FILE_REMOVED) { 645 strlcpy(nbuf, "Removed", sizeof(nbuf)); 646 } else if (cf->file_status == FILE_ADDED) { 647 if (cf->file_rcs->rf_dead == 1) 648 strlcpy(nbuf, "Initial Revision", sizeof(nbuf)); 649 else 650 rcsnum_tostr(nrev, nbuf, sizeof(nbuf)); 651 } else if (cf->file_status == FILE_MODIFIED) { 652 rcsnum_tostr(nrev, nbuf, sizeof(nbuf)); 653 } 654 655 if (verbosity > 1) 656 cvs_printf("new revision: %s\n", nbuf); 657 658 (void)unlink(cf->file_path); 659 (void)close(cf->fd); 660 cf->fd = -1; 661 662 if (cf->file_status != FILE_REMOVED) { 663 cvs_checkout_file(cf, nrev, NULL, CO_COMMIT); 664 } else { 665 entlist = cvs_ent_open(cf->file_wd); 666 cvs_ent_remove(entlist, cf->file_name); 667 668 cvs_get_repository_path(cf->file_wd, repo, MAXPATHLEN); 669 670 (void)xsnprintf(attic, MAXPATHLEN, "%s/%s", 671 repo, CVS_PATH_ATTIC); 672 673 if (mkdir(attic, 0755) == -1 && errno != EEXIST) 674 fatal("cvs_commit_local: failed to create Attic"); 675 676 (void)xsnprintf(attic, MAXPATHLEN, "%s/%s/%s%s", repo, 677 CVS_PATH_ATTIC, cf->file_name, RCS_FILE_EXT); 678 679 if (rename(cf->file_rpath, attic) == -1) 680 fatal("cvs_commit_local: failed to move %s to Attic", 681 cf->file_path); 682 683 if (cvs_server_active == 1) 684 cvs_server_update_entry("Remove-entry", cf); 685 } 686 687 if (verbosity > 1) 688 cvs_printf("done\n"); 689 else { 690 cvs_log(LP_NOTICE, "checking in '%s'; revision %s -> %s", 691 cf->file_path, rbuf, nbuf); 692 } 693 694 if (line_list != NULL) { 695 fi = xcalloc(1, sizeof(*fi)); 696 fi->file_path = xstrdup(cf->file_path); 697 fi->crevstr = xstrdup(rbuf); 698 fi->nrevstr = xstrdup(nbuf); 699 if (tag != NULL) 700 fi->tag_new = xstrdup(tag); 701 TAILQ_INSERT_TAIL(&files_info, fi, flist); 702 } 703 704 switch (cf->file_status) { 705 case FILE_MODIFIED: 706 histtype = CVS_HISTORY_COMMIT_MODIFIED; 707 break; 708 case FILE_ADDED: 709 histtype = CVS_HISTORY_COMMIT_ADDED; 710 break; 711 case FILE_REMOVED: 712 histtype = CVS_HISTORY_COMMIT_REMOVED; 713 break; 714 default: 715 histtype = -1; 716 break; 717 } 718 719 if (crev != NULL) 720 rcsnum_free(crev); 721 722 if (histtype != -1) 723 cvs_history_add(histtype, cf, NULL); 724 else 725 cvs_log(LP_NOTICE, "histtype was -1 for %s", cf->file_path); 726 } 727 728 static BUF * 729 commit_diff(struct cvs_file *cf, RCSNUM *rev, int reverse) 730 { 731 int fd1, fd2, f; 732 char *p1, *p2, *p; 733 BUF *b; 734 735 (void)xasprintf(&p1, "%s/diff1.XXXXXXXXXX", cvs_tmpdir); 736 737 if (cf->file_status == FILE_MODIFIED || 738 cf->file_status == FILE_ADDED) { 739 b = cvs_buf_load_fd(cf->fd); 740 fd1 = cvs_buf_write_stmp(b, p1, NULL); 741 cvs_buf_free(b); 742 } else { 743 fd1 = rcs_rev_write_stmp(cf->file_rcs, rev, p1, 0); 744 } 745 746 (void)xasprintf(&p2, "%s/diff2.XXXXXXXXXX", cvs_tmpdir); 747 fd2 = rcs_rev_write_stmp(cf->file_rcs, rev, p2, RCS_KWEXP_NONE); 748 749 b = cvs_buf_alloc(128); 750 751 diff_format = D_RCSDIFF; 752 753 if (reverse == 1) { 754 p = p1; 755 p1 = p2; 756 p2 = p; 757 758 f = fd1; 759 fd1 = fd2; 760 fd2 = f; 761 } 762 763 if (cvs_diffreg(p1, p2, fd1, fd2, b) == D_ERROR) 764 fatal("commit_diff: failed to get RCS patch"); 765 766 close(fd1); 767 close(fd2); 768 769 xfree(p1); 770 xfree(p2); 771 772 return (b); 773 } 774 775 static void 776 commit_desc_set(struct cvs_file *cf) 777 { 778 BUF *bp; 779 int fd; 780 char desc_path[MAXPATHLEN], *desc; 781 782 (void)xsnprintf(desc_path, MAXPATHLEN, "%s/%s/%s%s", 783 cf->file_wd, CVS_PATH_CVSDIR, cf->file_name, CVS_DESCR_FILE_EXT); 784 785 if ((fd = open(desc_path, O_RDONLY)) == -1) 786 return; 787 788 bp = cvs_buf_load_fd(fd); 789 cvs_buf_putc(bp, '\0'); 790 desc = cvs_buf_release(bp); 791 792 rcs_desc_set(cf->file_rcs, desc); 793 794 (void)close(fd); 795 (void)cvs_unlink(desc_path); 796 797 xfree(desc); 798 } 799