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 * "update" updates the version in the present directory with respect to the RCS 9 * repository. The present version must have been created by "checkout". The 10 * user can keep up-to-date by calling "update" whenever he feels like it. 11 * 12 * The present version can be committed by "commit", but this keeps the version 13 * in tact. 14 * 15 * Arguments following the options are taken to be file names to be updated, 16 * rather than updating the entire directory. 17 * 18 * Modified or non-existent RCS files are checked out and reported as U 19 * <user_file> 20 * 21 * Modified user files are reported as M <user_file>. If both the RCS file and 22 * the user file have been modified, the user file is replaced by the result 23 * of rcsmerge, and a backup file is written for the user in .#file.version. 24 * If this throws up irreconcilable differences, the file is reported as C 25 * <user_file>, and as M <user_file> otherwise. 26 * 27 * Files added but not yet committed are reported as A <user_file>. Files 28 * removed but not yet committed are reported as R <user_file>. 29 * 30 * If the current directory contains subdirectories that hold concurrent 31 * versions, these are updated too. If the -d option was specified, new 32 * directories added to the repository are automatically created and updated 33 * as well. 34 */ 35 36 #include "cvs.h" 37 #ifdef SERVER_SUPPORT 38 #include "md5.h" 39 #endif 40 #include "watch.h" 41 #include "fileattr.h" 42 #include "edit.h" 43 44 #ifndef lint 45 static const char rcsid[] = "$CVSid: @(#)update.c 1.95 94/10/22 $"; 46 USE(rcsid); 47 #endif 48 49 static int checkout_file PROTO((char *file, char *repository, List *entries, 50 List *srcfiles, Vers_TS *vers_ts, char *update_dir)); 51 #ifdef SERVER_SUPPORT 52 static int patch_file PROTO((char *file, char *repository, List *entries, 53 List *srcfiles, Vers_TS *vers_ts, char *update_dir, 54 int *docheckout, struct stat *file_info, 55 unsigned char *checksum)); 56 #endif 57 static int isemptydir PROTO((char *dir)); 58 static int merge_file PROTO((char *file, char *repository, List *entries, 59 Vers_TS *vers, char *update_dir)); 60 static int scratch_file PROTO((char *file, char *repository, List * entries, 61 char *update_dir)); 62 static Dtype update_dirent_proc PROTO((char *dir, char *repository, char *update_dir)); 63 static int update_dirleave_proc PROTO((char *dir, int err, char *update_dir)); 64 static int update_file_proc PROTO((char *file, char *update_dir, char *repository, 65 List * entries, List * srcfiles)); 66 static int update_filesdone_proc PROTO((int err, char *repository, 67 char *update_dir)); 68 static int write_letter PROTO((char *file, int letter, char *update_dir)); 69 #ifdef SERVER_SUPPORT 70 static void join_file PROTO((char *file, List *srcfiles, Vers_TS *vers_ts, 71 char *update_dir, List *entries, char *repository)); 72 #else 73 static void join_file PROTO((char *file, List *srcfiles, Vers_TS *vers_ts, 74 char *update_dir, List *entries)); 75 #endif 76 77 static char *options = NULL; 78 static char *tag = NULL; 79 static char *date = NULL; 80 static char *join_rev1, *date_rev1; 81 static char *join_rev2, *date_rev2; 82 static int aflag = 0; 83 static int force_tag_match = 1; 84 static int update_build_dirs = 0; 85 static int update_prune_dirs = 0; 86 static int pipeout = 0; 87 #ifdef SERVER_SUPPORT 88 static int patches = 0; 89 #endif 90 static List *ignlist = (List *) NULL; 91 static time_t last_register_time; 92 static const char *const update_usage[] = 93 { 94 "Usage: %s %s [-APdflRp] [-k kopt] [-r rev|-D date] [-j rev]\n", 95 " [-I ign] [-W spec] [files...]\n", 96 "\t-A\tReset any sticky tags/date/kopts.\n", 97 "\t-P\tPrune empty directories.\n", 98 "\t-d\tBuild directories, like checkout does.\n", 99 "\t-f\tForce a head revision match if tag/date not found.\n", 100 "\t-l\tLocal directory only, no recursion.\n", 101 "\t-R\tProcess directories recursively.\n", 102 "\t-p\tSend updates to standard output.\n", 103 "\t-k kopt\tUse RCS kopt -k option on checkout.\n", 104 "\t-r rev\tUpdate using specified revision/tag.\n", 105 "\t-D date\tSet date to update from.\n", 106 "\t-j rev\tMerge in changes made between current revision and rev.\n", 107 "\t-I ign\tMore files to ignore (! to reset).\n", 108 "\t-W spec\tWrappers specification line.\n", 109 NULL 110 }; 111 112 /* 113 * update is the argv,argc based front end for arg parsing 114 */ 115 int 116 update (argc, argv) 117 int argc; 118 char **argv; 119 { 120 int c, err; 121 int local = 0; /* recursive by default */ 122 int which; /* where to look for files and dirs */ 123 124 if (argc == -1) 125 usage (update_usage); 126 127 ign_setup (); 128 wrap_setup (); 129 130 /* parse the args */ 131 optind = 1; 132 while ((c = getopt (argc, argv, "ApPflRQqduk:r:D:j:I:W:")) != -1) 133 { 134 switch (c) 135 { 136 case 'A': 137 aflag = 1; 138 break; 139 case 'I': 140 ign_add (optarg, 0); 141 break; 142 case 'W': 143 wrap_add (optarg, 0); 144 break; 145 case 'k': 146 if (options) 147 free (options); 148 options = RCS_check_kflag (optarg); 149 break; 150 case 'l': 151 local = 1; 152 break; 153 case 'R': 154 local = 0; 155 break; 156 case 'Q': 157 case 'q': 158 #ifdef SERVER_SUPPORT 159 /* The CVS 1.5 client sends these options (in addition to 160 Global_option requests), so we must ignore them. */ 161 if (!server_active) 162 #endif 163 error (1, 0, 164 "-q or -Q must be specified before \"%s\"", 165 command_name); 166 break; 167 case 'd': 168 update_build_dirs = 1; 169 break; 170 case 'f': 171 force_tag_match = 0; 172 break; 173 case 'r': 174 tag = optarg; 175 break; 176 case 'D': 177 date = Make_Date (optarg); 178 break; 179 case 'P': 180 update_prune_dirs = 1; 181 break; 182 case 'p': 183 pipeout = 1; 184 noexec = 1; /* so no locks will be created */ 185 break; 186 case 'j': 187 if (join_rev2) 188 error (1, 0, "only two -j options can be specified"); 189 if (join_rev1) 190 join_rev2 = optarg; 191 else 192 join_rev1 = optarg; 193 break; 194 case 'u': 195 #ifdef SERVER_SUPPORT 196 if (server_active) 197 patches = 1; 198 else 199 #endif 200 usage (update_usage); 201 break; 202 case '?': 203 default: 204 usage (update_usage); 205 break; 206 } 207 } 208 argc -= optind; 209 argv += optind; 210 211 #ifdef CLIENT_SUPPORT 212 if (client_active) 213 { 214 /* The first pass does the regular update. If we receive at least 215 one patch which failed, we do a second pass and just fetch 216 those files whose patches failed. */ 217 do 218 { 219 int status; 220 221 start_server (); 222 223 if (local) 224 send_arg("-l"); 225 if (update_build_dirs) 226 send_arg("-d"); 227 if (pipeout) 228 send_arg("-p"); 229 if (!force_tag_match) 230 send_arg("-f"); 231 if (aflag) 232 send_arg("-A"); 233 if (update_prune_dirs) 234 send_arg("-P"); 235 client_prune_dirs = update_prune_dirs; 236 option_with_arg ("-r", tag); 237 if (date) 238 client_senddate (date); 239 if (join_rev1) 240 option_with_arg ("-j", join_rev1); 241 if (join_rev2) 242 option_with_arg ("-j", join_rev2); 243 244 /* If the server supports the command "update-patches", that means 245 that it knows how to handle the -u argument to update, which 246 means to send patches instead of complete files. */ 247 if (failed_patches == NULL) 248 { 249 struct request *rq; 250 251 for (rq = requests; rq->name != NULL; rq++) 252 { 253 if (strcmp (rq->name, "update-patches") == 0) 254 { 255 if (rq->status == rq_supported) 256 { 257 send_arg("-u"); 258 } 259 break; 260 } 261 } 262 } 263 264 if (failed_patches == NULL) 265 { 266 send_file_names (argc, argv); 267 send_files (argc, argv, local, aflag); 268 } 269 else 270 { 271 int i; 272 273 (void) printf ("%s client: refetching unpatchable files\n", 274 program_name); 275 276 if (toplevel_wd[0] != '\0' 277 && chdir (toplevel_wd) < 0) 278 { 279 error (1, errno, "could not chdir to %s", toplevel_wd); 280 } 281 282 for (i = 0; i < failed_patches_count; i++) 283 (void) unlink_file (failed_patches[i]); 284 send_file_names (failed_patches_count, failed_patches); 285 send_files (failed_patches_count, failed_patches, local, 286 aflag); 287 } 288 289 failed_patches = NULL; 290 failed_patches_count = 0; 291 292 send_to_server ("update\012", 0); 293 294 status = get_responses_and_close (); 295 if (status != 0) 296 return status; 297 298 } while (failed_patches != NULL); 299 300 return 0; 301 } 302 #endif 303 304 if (tag != NULL) 305 tag_check_valid (tag, argc, argv, local, aflag, ""); 306 /* FIXME: We don't call tag_check_valid on join_rev1 and join_rev2 307 yet (make sure to handle ':' correctly if we do, though). */ 308 309 /* 310 * If we are updating the entire directory (for real) and building dirs 311 * as we go, we make sure there is no static entries file and write the 312 * tag file as appropriate 313 */ 314 if (argc <= 0 && !pipeout) 315 { 316 if (update_build_dirs) 317 { 318 if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno)) 319 error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT); 320 #ifdef SERVER_SUPPORT 321 if (server_active) 322 server_clear_entstat (".", Name_Repository (NULL, NULL)); 323 #endif 324 } 325 326 /* keep the CVS/Tag file current with the specified arguments */ 327 if (aflag || tag || date) 328 { 329 WriteTag ((char *) NULL, tag, date); 330 #ifdef SERVER_SUPPORT 331 if (server_active) 332 server_set_sticky (".", Name_Repository (NULL, NULL), tag, date); 333 #endif 334 } 335 } 336 337 /* look for files/dirs locally and in the repository */ 338 which = W_LOCAL | W_REPOS; 339 340 /* look in the attic too if a tag or date is specified */ 341 if (tag != NULL || date != NULL || joining()) 342 which |= W_ATTIC; 343 344 /* call the command line interface */ 345 err = do_update (argc, argv, options, tag, date, force_tag_match, 346 local, update_build_dirs, aflag, update_prune_dirs, 347 pipeout, which, join_rev1, join_rev2, (char *) NULL); 348 349 /* free the space Make_Date allocated if necessary */ 350 if (date != NULL) 351 free (date); 352 353 return (err); 354 } 355 356 /* 357 * Command line interface to update (used by checkout) 358 */ 359 int 360 do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag, 361 xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir) 362 int argc; 363 char **argv; 364 char *xoptions; 365 char *xtag; 366 char *xdate; 367 int xforce; 368 int local; 369 int xbuild; 370 int xaflag; 371 int xprune; 372 int xpipeout; 373 int which; 374 char *xjoin_rev1; 375 char *xjoin_rev2; 376 char *preload_update_dir; 377 { 378 int err = 0; 379 char *cp; 380 381 /* fill in the statics */ 382 options = xoptions; 383 tag = xtag; 384 date = xdate; 385 force_tag_match = xforce; 386 update_build_dirs = xbuild; 387 aflag = xaflag; 388 update_prune_dirs = xprune; 389 pipeout = xpipeout; 390 391 /* setup the join support */ 392 join_rev1 = xjoin_rev1; 393 join_rev2 = xjoin_rev2; 394 if (join_rev1 && (cp = strchr (join_rev1, ':')) != NULL) 395 { 396 *cp++ = '\0'; 397 date_rev1 = Make_Date (cp); 398 } 399 else 400 date_rev1 = (char *) NULL; 401 if (join_rev2 && (cp = strchr (join_rev2, ':')) != NULL) 402 { 403 *cp++ = '\0'; 404 date_rev2 = Make_Date (cp); 405 } 406 else 407 date_rev2 = (char *) NULL; 408 409 /* call the recursion processor */ 410 err = start_recursion (update_file_proc, update_filesdone_proc, 411 update_dirent_proc, update_dirleave_proc, 412 argc, argv, local, which, aflag, 1, 413 preload_update_dir, 1, 0); 414 415 /* see if we need to sleep before returning */ 416 if (last_register_time) 417 { 418 time_t now; 419 420 (void) time (&now); 421 if (now == last_register_time) 422 sleep (1); /* to avoid time-stamp races */ 423 } 424 425 return (err); 426 } 427 428 /* 429 * This is the callback proc for update. It is called for each file in each 430 * directory by the recursion code. The current directory is the local 431 * instantiation. file is the file name we are to operate on. update_dir is 432 * set to the path relative to where we started (for pretty printing). 433 * repository is the repository. entries and srcfiles are the pre-parsed 434 * entries and source control files. 435 * 436 * This routine decides what needs to be done for each file and does the 437 * appropriate magic for checkout 438 */ 439 static int 440 update_file_proc (file, update_dir, repository, entries, srcfiles) 441 char *file; 442 char *update_dir; 443 char *repository; 444 List *entries; 445 List *srcfiles; 446 { 447 int retval; 448 Ctype status; 449 Vers_TS *vers; 450 451 status = Classify_File (file, tag, date, options, force_tag_match, 452 aflag, repository, entries, srcfiles, &vers, 453 update_dir, pipeout); 454 if (pipeout) 455 { 456 /* 457 * We just return success without doing anything if any of the really 458 * funky cases occur 459 * 460 * If there is still a valid RCS file, do a regular checkout type 461 * operation 462 */ 463 switch (status) 464 { 465 case T_UNKNOWN: /* unknown file was explicitly asked 466 * about */ 467 case T_REMOVE_ENTRY: /* needs to be un-registered */ 468 case T_ADDED: /* added but not committed */ 469 retval = 0; 470 break; 471 case T_CONFLICT: /* old punt-type errors */ 472 retval = 1; 473 break; 474 case T_UPTODATE: /* file was already up-to-date */ 475 case T_NEEDS_MERGE: /* needs merging */ 476 case T_MODIFIED: /* locally modified */ 477 case T_REMOVED: /* removed but not committed */ 478 case T_CHECKOUT: /* needs checkout */ 479 #ifdef SERVER_SUPPORT 480 case T_PATCH: /* needs patch */ 481 #endif 482 retval = checkout_file (file, repository, entries, srcfiles, 483 vers, update_dir); 484 break; 485 486 default: /* can't ever happen :-) */ 487 error (0, 0, 488 "unknown file status %d for file %s", status, file); 489 retval = 0; 490 break; 491 } 492 } 493 else 494 { 495 switch (status) 496 { 497 case T_UNKNOWN: /* unknown file was explicitly asked 498 * about */ 499 case T_UPTODATE: /* file was already up-to-date */ 500 retval = 0; 501 break; 502 case T_CONFLICT: /* old punt-type errors */ 503 retval = 1; 504 (void) write_letter (file, 'C', update_dir); 505 break; 506 case T_NEEDS_MERGE: /* needs merging */ 507 if (noexec) 508 { 509 retval = 1; 510 (void) write_letter (file, 'C', update_dir); 511 } 512 else 513 { 514 if (wrap_merge_is_copy (file)) 515 /* Should we be warning the user that we are 516 * overwriting the user's copy of the file? */ 517 retval = checkout_file (file, repository, entries, 518 srcfiles, vers, update_dir); 519 else 520 retval = merge_file (file, repository, entries, 521 vers, update_dir); 522 } 523 break; 524 case T_MODIFIED: /* locally modified */ 525 retval = 0; 526 if (vers->ts_conflict) 527 { 528 char *filestamp; 529 int retcode; 530 531 /* 532 * If the timestamp has changed and no conflict indicators 533 * are found, it isn't a 'C' any more. 534 */ 535 #ifdef SERVER_SUPPORT 536 if (server_active) 537 retcode = vers->ts_conflict[0] != '='; 538 else { 539 filestamp = time_stamp (file); 540 retcode = strcmp (vers->ts_conflict, filestamp); 541 free (filestamp); 542 } 543 #else 544 filestamp = time_stamp (file); 545 retcode = strcmp (vers->ts_conflict, filestamp); 546 free (filestamp); 547 #endif 548 549 if (retcode) 550 { 551 /* 552 * If the timestamps differ, look for Conflict 553 * indicators to see if 'C' anyway. 554 */ 555 run_setup ("%s", GREP); 556 run_arg (RCS_MERGE_PAT); 557 run_arg (file); 558 retcode = run_exec (RUN_TTY, DEVNULL, 559 RUN_TTY,RUN_NORMAL); 560 if (retcode == -1) 561 { 562 if (update_dir[0] == '\0') 563 error (1, errno, 564 "fork failed while examining conflict in `%s'", 565 file); 566 else 567 error (1, errno, 568 "fork failed while examining conflict in `%s/%s'", 569 update_dir, file); 570 } 571 } 572 if (!retcode) 573 { 574 (void) write_letter (file, 'C', update_dir); 575 retval = 1; 576 } 577 else 578 { 579 /* Reregister to clear conflict flag. */ 580 Register (entries, file, vers->vn_rcs, vers->ts_rcs, 581 vers->options, vers->tag, 582 vers->date, (char *)0); 583 } 584 } 585 if (!retval) 586 retval = write_letter (file, 'M', update_dir); 587 break; 588 #ifdef SERVER_SUPPORT 589 case T_PATCH: /* needs patch */ 590 if (patches) 591 { 592 int docheckout; 593 struct stat file_info; 594 unsigned char checksum[16]; 595 596 retval = patch_file (file, repository, entries, srcfiles, 597 vers, update_dir, &docheckout, 598 &file_info, checksum); 599 if (! docheckout) 600 { 601 if (server_active && retval == 0) 602 server_updated (file, update_dir, repository, 603 SERVER_PATCHED, &file_info, 604 checksum); 605 break; 606 } 607 } 608 /* Fall through. */ 609 /* If we're not running as a server, just check the 610 file out. It's simpler and faster than starting up 611 two new processes (diff and patch). */ 612 /* Fall through. */ 613 #endif 614 case T_CHECKOUT: /* needs checkout */ 615 retval = checkout_file (file, repository, entries, srcfiles, 616 vers, update_dir); 617 #ifdef SERVER_SUPPORT 618 if (server_active && retval == 0) 619 server_updated (file, update_dir, repository, 620 SERVER_UPDATED, (struct stat *) NULL, 621 (unsigned char *) NULL); 622 #endif 623 break; 624 case T_ADDED: /* added but not committed */ 625 retval = write_letter (file, 'A', update_dir); 626 break; 627 case T_REMOVED: /* removed but not committed */ 628 retval = write_letter (file, 'R', update_dir); 629 break; 630 case T_REMOVE_ENTRY: /* needs to be un-registered */ 631 retval = scratch_file (file, repository, entries, update_dir); 632 #ifdef SERVER_SUPPORT 633 if (server_active && retval == 0) 634 server_updated (file, update_dir, repository, 635 SERVER_UPDATED, (struct stat *) NULL, 636 (unsigned char *) NULL); 637 #endif 638 break; 639 default: /* can't ever happen :-) */ 640 error (0, 0, 641 "unknown file status %d for file %s", status, file); 642 retval = 0; 643 break; 644 } 645 } 646 647 /* only try to join if things have gone well thus far */ 648 if (retval == 0 && join_rev1) 649 #ifdef SERVER_SUPPORT 650 join_file (file, srcfiles, vers, update_dir, entries, repository); 651 #else 652 join_file (file, srcfiles, vers, update_dir, entries); 653 #endif 654 655 /* if this directory has an ignore list, add this file to it */ 656 if (ignlist) 657 { 658 Node *p; 659 660 p = getnode (); 661 p->type = FILES; 662 p->key = xstrdup (file); 663 if (addnode (ignlist, p) != 0) 664 freenode (p); 665 } 666 667 freevers_ts (&vers); 668 return (retval); 669 } 670 671 static void update_ignproc PROTO ((char *, char *)); 672 673 static void 674 update_ignproc (file, dir) 675 char *file; 676 char *dir; 677 { 678 (void) write_letter (file, '?', dir); 679 } 680 681 /* ARGSUSED */ 682 static int 683 update_filesdone_proc (err, repository, update_dir) 684 int err; 685 char *repository; 686 char *update_dir; 687 { 688 /* if this directory has an ignore list, process it then free it */ 689 if (ignlist) 690 { 691 ignore_files (ignlist, update_dir, update_ignproc); 692 dellist (&ignlist); 693 } 694 695 /* Clean up CVS admin dirs if we are export */ 696 if (strcmp (command_name, "export") == 0) 697 { 698 run_setup ("%s -fr", RM); 699 run_arg (CVSADM); 700 (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); 701 } 702 #ifdef CVSADM_ROOT 703 #ifdef SERVER_SUPPORT 704 else if (!server_active && !pipeout) 705 #else 706 else if (!pipeout) 707 #endif /* SERVER_SUPPORT */ 708 { 709 /* If there is no CVS/Root file, add one */ 710 if (!isfile (CVSADM_ROOT)) 711 Create_Root( (char *) NULL, CVSroot ); 712 } 713 #endif /* CVSADM_ROOT */ 714 715 return (err); 716 } 717 718 /* 719 * update_dirent_proc () is called back by the recursion processor before a 720 * sub-directory is processed for update. In this case, update_dirent proc 721 * will probably create the directory unless -d isn't specified and this is a 722 * new directory. A return code of 0 indicates the directory should be 723 * processed by the recursion code. A return of non-zero indicates the 724 * recursion code should skip this directory. 725 */ 726 static Dtype 727 update_dirent_proc (dir, repository, update_dir) 728 char *dir; 729 char *repository; 730 char *update_dir; 731 { 732 if (ignore_directory (update_dir)) 733 { 734 /* print the warm fuzzy message */ 735 if (!quiet) 736 error (0, 0, "Ignoring %s", update_dir); 737 return R_SKIP_ALL; 738 } 739 740 if (!isdir (dir)) 741 { 742 /* if we aren't building dirs, blow it off */ 743 if (!update_build_dirs) 744 return (R_SKIP_ALL); 745 746 if (noexec) 747 { 748 /* ignore the missing dir if -n is specified */ 749 error (0, 0, "New directory `%s' -- ignored", dir); 750 return (R_SKIP_ALL); 751 } 752 else 753 { 754 /* otherwise, create the dir and appropriate adm files */ 755 make_directory (dir); 756 Create_Admin (dir, update_dir, repository, tag, date); 757 } 758 } 759 760 /* 761 * If we are building dirs and not going to stdout, we make sure there is 762 * no static entries file and write the tag file as appropriate 763 */ 764 if (!pipeout) 765 { 766 if (update_build_dirs) 767 { 768 char tmp[PATH_MAX]; 769 770 (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENTSTAT); 771 if (unlink_file (tmp) < 0 && ! existence_error (errno)) 772 error (1, errno, "cannot remove file %s", tmp); 773 #ifdef SERVER_SUPPORT 774 if (server_active) 775 server_clear_entstat (update_dir, repository); 776 #endif 777 } 778 779 /* keep the CVS/Tag file current with the specified arguments */ 780 if (aflag || tag || date) 781 { 782 WriteTag (dir, tag, date); 783 #ifdef SERVER_SUPPORT 784 if (server_active) 785 server_set_sticky (update_dir, repository, tag, date); 786 #endif 787 } 788 789 /* initialize the ignore list for this directory */ 790 ignlist = getlist (); 791 } 792 793 /* print the warm fuzzy message */ 794 if (!quiet) 795 error (0, 0, "Updating %s", update_dir); 796 797 return (R_PROCESS); 798 } 799 800 /* 801 * update_dirleave_proc () is called back by the recursion code upon leaving 802 * a directory. It will prune empty directories if needed and will execute 803 * any appropriate update programs. 804 */ 805 /* ARGSUSED */ 806 static int 807 update_dirleave_proc (dir, err, update_dir) 808 char *dir; 809 int err; 810 char *update_dir; 811 { 812 FILE *fp; 813 814 /* run the update_prog if there is one */ 815 if (err == 0 && !pipeout && !noexec && 816 (fp = fopen (CVSADM_UPROG, "r")) != NULL) 817 { 818 char *cp; 819 char *repository; 820 char line[MAXLINELEN]; 821 822 repository = Name_Repository ((char *) NULL, update_dir); 823 if (fgets (line, sizeof (line), fp) != NULL) 824 { 825 if ((cp = strrchr (line, '\n')) != NULL) 826 *cp = '\0'; 827 run_setup ("%s %s", line, repository); 828 (void) printf ("%s %s: Executing '", program_name, command_name); 829 run_print (stdout); 830 (void) printf ("'\n"); 831 (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); 832 } 833 (void) fclose (fp); 834 free (repository); 835 } 836 837 /* FIXME: chdir ("..") loses with symlinks. */ 838 /* Prune empty dirs on the way out - if necessary */ 839 (void) chdir (".."); 840 if (update_prune_dirs && isemptydir (dir)) 841 { 842 run_setup ("%s -fr", RM); 843 run_arg (dir); 844 (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); 845 } 846 847 return (err); 848 } 849 850 /* 851 * Returns 1 if the argument directory is completely empty, other than the 852 * existence of the CVS directory entry. Zero otherwise. 853 */ 854 static int 855 isemptydir (dir) 856 char *dir; 857 { 858 DIR *dirp; 859 struct dirent *dp; 860 861 if ((dirp = opendir (dir)) == NULL) 862 { 863 error (0, 0, "cannot open directory %s for empty check", dir); 864 return (0); 865 } 866 while ((dp = readdir (dirp)) != NULL) 867 { 868 if (strcmp (dp->d_name, ".") != 0 && strcmp (dp->d_name, "..") != 0 && 869 strcmp (dp->d_name, CVSADM) != 0) 870 { 871 (void) closedir (dirp); 872 return (0); 873 } 874 } 875 (void) closedir (dirp); 876 return (1); 877 } 878 879 /* 880 * scratch the Entries file entry associated with a file 881 */ 882 static int 883 scratch_file (file, repository, entries, update_dir) 884 char *file; 885 char *repository; 886 List *entries; 887 char *update_dir; 888 { 889 history_write ('W', update_dir, "", file, repository); 890 Scratch_Entry (entries, file); 891 (void) unlink_file (file); 892 return (0); 893 } 894 895 /* 896 * check out a file - essentially returns the result of the fork on "co". 897 */ 898 static int 899 checkout_file (file, repository, entries, srcfiles, vers_ts, update_dir) 900 char *file; 901 char *repository; 902 List *entries; 903 List *srcfiles; 904 Vers_TS *vers_ts; 905 char *update_dir; 906 { 907 char backup[PATH_MAX]; 908 int set_time, retval = 0; 909 int retcode = 0; 910 #ifdef DEATH_SUPPORT 911 int file_is_dead; 912 #endif 913 914 /* don't screw with backup files if we're going to stdout */ 915 if (!pipeout) 916 { 917 (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, file); 918 if (isfile (file)) 919 rename_file (file, backup); 920 else 921 (void) unlink_file (backup); 922 } 923 924 #ifdef DEATH_SUPPORT 925 file_is_dead = RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs); 926 927 if (!file_is_dead) { 928 #endif 929 930 run_setup ("%s%s -q -r%s %s", Rcsbin, RCS_CO, vers_ts->vn_tag, 931 vers_ts->options); 932 933 /* 934 * if we are checking out to stdout, print a nice message to stderr, and 935 * add the -p flag to the command 936 */ 937 if (pipeout) 938 { 939 run_arg ("-p"); 940 if (!quiet) 941 { 942 (void) fprintf (stderr, "===================================================================\n"); 943 if (update_dir[0]) 944 (void) fprintf (stderr, "Checking out %s/%s\n", 945 update_dir, file); 946 else 947 (void) fprintf (stderr, "Checking out %s\n", file); 948 (void) fprintf (stderr, "RCS: %s\n", vers_ts->srcfile->path); 949 (void) fprintf (stderr, "VERS: %s\n", vers_ts->vn_rcs); 950 (void) fprintf (stderr, "***************\n"); 951 } 952 } 953 954 /* tack on the rcs and maybe the user file */ 955 run_arg (vers_ts->srcfile->path); 956 if (!pipeout) 957 run_arg (file); 958 959 #ifdef DEATH_SUPPORT 960 } 961 if (file_is_dead || (retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, 962 #else 963 if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, 964 #endif 965 (pipeout ? (RUN_NORMAL|RUN_REALLY) : RUN_NORMAL))) == 0) 966 { 967 if (!pipeout) 968 { 969 Vers_TS *xvers_ts; 970 #ifdef DEATH_SUPPORT 971 int resurrecting; 972 973 resurrecting = 0; 974 975 if (file_is_dead && joining()) 976 { 977 if (RCS_getversion (vers_ts->srcfile, join_rev1, 978 date_rev1, 1, 0) 979 || (join_rev2 != NULL && 980 RCS_getversion (vers_ts->srcfile, join_rev2, 981 date_rev2, 1, 0))) 982 { 983 /* when joining, we need to get dead files checked 984 out. Try harder. */ 985 run_setup ("%s%s -q -r%s %s", Rcsbin, RCS_CO, 986 vers_ts->vn_rcs, 987 vers_ts->options); 988 989 run_arg ("-f"); 990 run_arg (vers_ts->srcfile->path); 991 run_arg (file); 992 retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); 993 if (retcode != 0) 994 { 995 error (retcode == -1 ? 1 : 0, 996 retcode == -1 ? errno : 0, 997 "could not check out %s", file); 998 (void) unlink_file (backup); 999 return (retcode); 1000 } 1001 file_is_dead = 0; 1002 resurrecting = 1; 1003 } 1004 else 1005 { 1006 /* If the file is dead and does not contain either of 1007 the join revisions, then we don't want to check it 1008 out. */ 1009 return 0; 1010 } 1011 } 1012 #endif /* DEATH_SUPPORT */ 1013 1014 if (cvswrite == TRUE 1015 #ifdef DEATH_SUPPORT 1016 && !file_is_dead 1017 #endif 1018 && !fileattr_get (file, "_watched")) 1019 xchmod (file, 1); 1020 1021 { 1022 /* A newly checked out file is never under the spell 1023 of "cvs edit". If we think we were editing it 1024 from a previous life, clean up. Would be better to 1025 check for same the working directory instead of 1026 same user, but that is hairy. */ 1027 1028 struct addremove_args args; 1029 1030 editor_set (file, getcaller (), NULL); 1031 1032 memset (&args, 0, sizeof args); 1033 args.remove_temp = 1; 1034 watch_modify_watchers (file, &args); 1035 } 1036 1037 /* set the time from the RCS file iff it was unknown before */ 1038 if (vers_ts->vn_user == NULL || 1039 strncmp (vers_ts->ts_rcs, "Initial", 7) == 0) 1040 { 1041 set_time = 1; 1042 } 1043 else 1044 set_time = 0; 1045 1046 wrap_fromcvs_process_file (file); 1047 1048 xvers_ts = Version_TS (repository, options, tag, date, file, 1049 force_tag_match, set_time, entries, srcfiles); 1050 if (strcmp (xvers_ts->options, "-V4") == 0) 1051 xvers_ts->options[0] = '\0'; 1052 /* If no keyword expansion was specified on command line, 1053 use whatever was in the file. This is how we tell the client 1054 whether a file is binary. */ 1055 if (xvers_ts->options[0] == '\0') 1056 { 1057 if (vers_ts->srcfile->expand != NULL) 1058 { 1059 free (xvers_ts->options); 1060 xvers_ts->options = 1061 xmalloc (strlen (vers_ts->srcfile->expand) + 3); 1062 strcpy (xvers_ts->options, "-k"); 1063 strcat (xvers_ts->options, vers_ts->srcfile->expand); 1064 } 1065 } 1066 1067 (void) time (&last_register_time); 1068 1069 #ifdef DEATH_SUPPORT 1070 if (file_is_dead) 1071 { 1072 if (xvers_ts->vn_user != NULL) 1073 { 1074 if (update_dir[0] == '\0') 1075 error (0, 0, 1076 "warning: %s is not (any longer) pertinent", 1077 file); 1078 else 1079 error (0, 0, 1080 "warning: %s/%s is not (any longer) pertinent", 1081 update_dir, file); 1082 } 1083 Scratch_Entry (entries, file); 1084 if (unlink_file (file) < 0 && ! existence_error (errno)) 1085 { 1086 if (update_dir[0] == '\0') 1087 error (0, errno, "cannot remove %s", file); 1088 else 1089 error (0, errno, "cannot remove %s/%s", update_dir, 1090 file); 1091 } 1092 } 1093 else 1094 Register (entries, file, 1095 resurrecting ? "0" : xvers_ts->vn_rcs, 1096 xvers_ts->ts_user, xvers_ts->options, 1097 xvers_ts->tag, xvers_ts->date, 1098 (char *)0); /* Clear conflict flag on fresh checkout */ 1099 #else /* No DEATH_SUPPORT */ 1100 Register (entries, file, xvers_ts->vn_rcs, xvers_ts->ts_user, 1101 xvers_ts->options, xvers_ts->tag, xvers_ts->date, 1102 (char *)0); /* Clear conflict flag on fresh checkout */ 1103 #endif /* No DEATH_SUPPORT */ 1104 1105 /* fix up the vers structure, in case it is used by join */ 1106 if (join_rev1) 1107 { 1108 if (vers_ts->vn_user != NULL) 1109 free (vers_ts->vn_user); 1110 if (vers_ts->vn_rcs != NULL) 1111 free (vers_ts->vn_rcs); 1112 vers_ts->vn_user = xstrdup (xvers_ts->vn_rcs); 1113 vers_ts->vn_rcs = xstrdup (xvers_ts->vn_rcs); 1114 } 1115 1116 /* If this is really Update and not Checkout, recode history */ 1117 if (strcmp (command_name, "update") == 0) 1118 history_write ('U', update_dir, xvers_ts->vn_rcs, file, 1119 repository); 1120 1121 freevers_ts (&xvers_ts); 1122 1123 #ifdef DEATH_SUPPORT 1124 if (!really_quiet && !file_is_dead) 1125 #else 1126 if (!really_quiet) 1127 #endif 1128 { 1129 if (update_dir[0]) 1130 (void) printf ("U %s/%s\n", update_dir, file); 1131 else 1132 (void) printf ("U %s\n", file); 1133 } 1134 } 1135 } 1136 else 1137 { 1138 int old_errno = errno; /* save errno value over the rename */ 1139 1140 if (!pipeout && isfile (backup)) 1141 rename_file (backup, file); 1142 1143 error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0, 1144 "could not check out %s", file); 1145 1146 retval = retcode; 1147 } 1148 1149 if (!pipeout) 1150 (void) unlink_file (backup); 1151 1152 return (retval); 1153 } 1154 1155 #ifdef SERVER_SUPPORT 1156 /* Patch a file. Runs rcsdiff. This is only done when running as the 1157 * server. The hope is that the diff will be smaller than the file 1158 * itself. 1159 */ 1160 static int 1161 patch_file (file, repository, entries, srcfiles, vers_ts, update_dir, 1162 docheckout, file_info, checksum) 1163 char *file; 1164 char *repository; 1165 List *entries; 1166 List *srcfiles; 1167 Vers_TS *vers_ts; 1168 char *update_dir; 1169 int *docheckout; 1170 struct stat *file_info; 1171 unsigned char *checksum; 1172 { 1173 char backup[PATH_MAX]; 1174 char file1[PATH_MAX]; 1175 char file2[PATH_MAX]; 1176 int retval = 0; 1177 int retcode = 0; 1178 int fail; 1179 FILE *e; 1180 1181 *docheckout = 0; 1182 1183 if (pipeout || joining ()) 1184 { 1185 *docheckout = 1; 1186 return 0; 1187 } 1188 1189 (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, file); 1190 if (isfile (file)) 1191 rename_file (file, backup); 1192 else 1193 (void) unlink_file (backup); 1194 1195 (void) sprintf (file1, "%s/%s%s-1", CVSADM, CVSPREFIX, file); 1196 (void) sprintf (file2, "%s/%s%s-2", CVSADM, CVSPREFIX, file); 1197 1198 fail = 0; 1199 1200 /* We need to check out both revisions first, to see if either one 1201 has a trailing newline. Because of this, we don't use rcsdiff, 1202 but just use diff. */ 1203 run_setup ("%s%s -q -p -r%s %s %s", Rcsbin, RCS_CO, vers_ts->vn_user, 1204 vers_ts->options, vers_ts->srcfile->path); 1205 if (run_exec (RUN_TTY, file1, RUN_TTY, RUN_NORMAL) != 0) 1206 fail = 1; 1207 else 1208 { 1209 e = fopen (file1, "r"); 1210 if (e == NULL) 1211 fail = 1; 1212 else 1213 { 1214 if (fseek (e, (long) -1, SEEK_END) == 0 1215 && getc (e) != '\n') 1216 { 1217 fail = 1; 1218 } 1219 fclose (e); 1220 } 1221 } 1222 1223 if (! fail) 1224 { 1225 /* Check it out into file, and then move to file2, so that we 1226 can get the right modes into *FILE_INFO. We can't check it 1227 out directly into file2 because co doesn't understand how 1228 to do that. */ 1229 run_setup ("%s%s -q -r%s %s %s %s", Rcsbin, RCS_CO, vers_ts->vn_rcs, 1230 vers_ts->options, vers_ts->srcfile->path, file); 1231 if (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) != 0) 1232 fail = 1; 1233 else 1234 { 1235 if (!isreadable (file)) 1236 { 1237 /* File is dead. */ 1238 fail = 1; 1239 } 1240 else 1241 { 1242 rename_file (file, file2); 1243 if (cvswrite == TRUE 1244 && !fileattr_get (file, "_watched")) 1245 xchmod (file2, 1); 1246 e = fopen (file2, "r"); 1247 if (e == NULL) 1248 fail = 1; 1249 else 1250 { 1251 struct MD5Context context; 1252 int nl; 1253 unsigned char buf[8192]; 1254 unsigned len; 1255 1256 nl = 0; 1257 1258 /* Compute the MD5 checksum and make sure there is 1259 a trailing newline. */ 1260 MD5Init (&context); 1261 while ((len = fread (buf, 1, sizeof buf, e)) != 0) 1262 { 1263 nl = buf[len - 1] == '\n'; 1264 MD5Update (&context, buf, len); 1265 } 1266 MD5Final (checksum, &context); 1267 1268 if (ferror (e) || ! nl) 1269 { 1270 fail = 1; 1271 } 1272 1273 fclose (e); 1274 } 1275 } 1276 } 1277 } 1278 1279 if (! fail) 1280 { 1281 /* FIXME: This whole thing with diff/patch is rather more 1282 convoluted than necessary (lots of forks and execs, need to 1283 worry about versions of diff and patch, etc.). Also, we 1284 send context lines which aren't needed (in the rare case in 1285 which the diff doesn't apply, the checksum would catches it). 1286 Solution perhaps is to librarify the RCS routines which apply 1287 deltas or something equivalent. */ 1288 /* This is -c, not -u, because we have no way of knowing which 1289 DIFF is in use. */ 1290 run_setup ("%s -c %s %s", DIFF, file1, file2); 1291 1292 /* A retcode of 0 means no differences. 1 means some differences. */ 1293 if ((retcode = run_exec (RUN_TTY, file, RUN_TTY, RUN_NORMAL)) != 0 1294 && retcode != 1) 1295 { 1296 fail = 1; 1297 } 1298 else 1299 { 1300 #define BINARY "Binary" 1301 char buf[sizeof BINARY]; 1302 unsigned int c; 1303 1304 /* Check the diff output to make sure patch will be handle it. */ 1305 e = fopen (file, "r"); 1306 if (e == NULL) 1307 error (1, errno, "could not open diff output file %s", file); 1308 c = fread (buf, 1, sizeof BINARY - 1, e); 1309 buf[c] = '\0'; 1310 if (strcmp (buf, BINARY) == 0) 1311 { 1312 /* These are binary files. We could use diff -a, but 1313 patch can't handle that. */ 1314 fail = 1; 1315 } 1316 fclose (e); 1317 } 1318 } 1319 1320 if (! fail) 1321 { 1322 Vers_TS *xvers_ts; 1323 1324 /* This stuff is just copied blindly from checkout_file. I 1325 don't really know what it does. */ 1326 xvers_ts = Version_TS (repository, options, tag, date, file, 1327 force_tag_match, 0, entries, srcfiles); 1328 if (strcmp (xvers_ts->options, "-V4") == 0) 1329 xvers_ts->options[0] = '\0'; 1330 1331 Register (entries, file, xvers_ts->vn_rcs, 1332 xvers_ts->ts_user, xvers_ts->options, 1333 xvers_ts->tag, xvers_ts->date, NULL); 1334 1335 if (stat (file2, file_info) < 0) 1336 error (1, errno, "could not stat %s", file2); 1337 1338 /* If this is really Update and not Checkout, recode history */ 1339 if (strcmp (command_name, "update") == 0) 1340 history_write ('P', update_dir, xvers_ts->vn_rcs, file, 1341 repository); 1342 1343 freevers_ts (&xvers_ts); 1344 1345 if (!really_quiet) 1346 { 1347 if (update_dir[0]) 1348 (void) printf ("P %s/%s\n", update_dir, file); 1349 else 1350 (void) printf ("P %s\n", file); 1351 } 1352 } 1353 else 1354 { 1355 int old_errno = errno; /* save errno value over the rename */ 1356 1357 if (isfile (backup)) 1358 rename_file (backup, file); 1359 1360 if (retcode != 0 && retcode != 1) 1361 error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0, 1362 "could not diff %s", file); 1363 1364 *docheckout = 1; 1365 retval = retcode; 1366 } 1367 1368 (void) unlink_file (backup); 1369 (void) unlink_file (file1); 1370 (void) unlink_file (file2); 1371 1372 return (retval); 1373 } 1374 #endif 1375 1376 /* 1377 * Several of the types we process only print a bit of information consisting 1378 * of a single letter and the name. 1379 */ 1380 static int 1381 write_letter (file, letter, update_dir) 1382 char *file; 1383 int letter; 1384 char *update_dir; 1385 { 1386 if (!really_quiet) 1387 { 1388 if (update_dir[0]) 1389 (void) printf ("%c %s/%s\n", letter, update_dir, file); 1390 else 1391 (void) printf ("%c %s\n", letter, file); 1392 } 1393 return (0); 1394 } 1395 1396 /* 1397 * Do all the magic associated with a file which needs to be merged 1398 */ 1399 static int 1400 merge_file (file, repository, entries, vers, update_dir) 1401 char *file; 1402 char *repository; 1403 List *entries; 1404 Vers_TS *vers; 1405 char *update_dir; 1406 { 1407 char user[PATH_MAX]; 1408 char backup[PATH_MAX]; 1409 int status; 1410 int retcode = 0; 1411 1412 /* 1413 * The users currently modified file is moved to a backup file name 1414 * ".#filename.version", so that it will stay around for a few days 1415 * before being automatically removed by some cron daemon. The "version" 1416 * is the version of the file that the user was most up-to-date with 1417 * before the merge. 1418 */ 1419 (void) sprintf (backup, "%s%s.%s", BAKPREFIX, file, vers->vn_user); 1420 if (update_dir[0]) 1421 (void) sprintf (user, "%s/%s", update_dir, file); 1422 else 1423 (void) strcpy (user, file); 1424 1425 (void) unlink_file (backup); 1426 copy_file (file, backup); 1427 xchmod (file, 1); 1428 1429 status = RCS_merge(vers->srcfile->path, 1430 vers->options, vers->vn_user, vers->vn_rcs); 1431 if (status != 0 && status != 1) 1432 { 1433 error (0, status == -1 ? errno : 0, 1434 "could not merge revision %s of %s", vers->vn_user, user); 1435 error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s", 1436 user, backup); 1437 rename_file (backup, file); 1438 return (1); 1439 } 1440 1441 if (strcmp (vers->options, "-V4") == 0) 1442 vers->options[0] = '\0'; 1443 (void) time (&last_register_time); 1444 { 1445 char *cp = 0; 1446 1447 if (status) 1448 cp = time_stamp (file); 1449 Register (entries, file, vers->vn_rcs, vers->ts_rcs, vers->options, 1450 vers->tag, vers->date, cp); 1451 if (cp) 1452 free (cp); 1453 } 1454 1455 /* fix up the vers structure, in case it is used by join */ 1456 if (join_rev1) 1457 { 1458 if (vers->vn_user != NULL) 1459 free (vers->vn_user); 1460 vers->vn_user = xstrdup (vers->vn_rcs); 1461 } 1462 1463 #ifdef SERVER_SUPPORT 1464 /* Send the new contents of the file before the message. If we 1465 wanted to be totally correct, we would have the client write 1466 the message only after the file has safely been written. */ 1467 if (server_active) 1468 { 1469 server_copy_file (file, update_dir, repository, backup); 1470 server_updated (file, update_dir, repository, SERVER_MERGED, 1471 (struct stat *) NULL, (unsigned char *) NULL); 1472 } 1473 #endif 1474 1475 if (!noexec && !xcmp (backup, file)) 1476 { 1477 printf ("%s already contains the differences between %s and %s\n", 1478 user, vers->vn_user, vers->vn_rcs); 1479 history_write ('G', update_dir, vers->vn_rcs, file, repository); 1480 return (0); 1481 } 1482 1483 if (status == 1) 1484 { 1485 if (!noexec) 1486 error (0, 0, "conflicts found in %s", user); 1487 1488 if (!really_quiet) 1489 (void) printf ("C %s\n", user); 1490 1491 history_write ('C', update_dir, vers->vn_rcs, file, repository); 1492 1493 } 1494 else if (retcode == -1) 1495 { 1496 error (1, errno, "fork failed while examining update of %s", user); 1497 } 1498 else 1499 { 1500 if (!really_quiet) 1501 (void) printf ("M %s\n", user); 1502 history_write ('G', update_dir, vers->vn_rcs, file, repository); 1503 } 1504 return (0); 1505 } 1506 1507 /* 1508 * Do all the magic associated with a file which needs to be joined 1509 * (-j option) 1510 */ 1511 static void 1512 #ifdef SERVER_SUPPORT 1513 join_file (file, srcfiles, vers, update_dir, entries, repository) 1514 char *repository; 1515 #else 1516 join_file (file, srcfiles, vers, update_dir, entries) 1517 #endif 1518 char *file; 1519 List *srcfiles; 1520 Vers_TS *vers; 1521 char *update_dir; 1522 List *entries; 1523 { 1524 char user[PATH_MAX]; 1525 char backup[PATH_MAX]; 1526 char *options; 1527 int status; 1528 1529 char *rev1; 1530 char *rev2; 1531 char *jrev1; 1532 char *jrev2; 1533 char *jdate1; 1534 char *jdate2; 1535 1536 jrev1 = join_rev1; 1537 jrev2 = join_rev2; 1538 jdate1 = date_rev1; 1539 jdate2 = date_rev2; 1540 1541 if (wrap_merge_is_copy (file)) 1542 { 1543 /* FIXME: Should be including update_dir in message. */ 1544 error (0, 0, 1545 "Cannot merge %s because it is a merge-by-copy file.", file); 1546 return; 1547 } 1548 1549 /* determine if we need to do anything at all */ 1550 if (vers->srcfile == NULL || 1551 vers->srcfile->path == NULL) 1552 { 1553 return; 1554 } 1555 1556 /* in all cases, use two revs. */ 1557 1558 /* if only one rev is specified, it becomes the second rev */ 1559 if (jrev2 == NULL) 1560 { 1561 jrev2 = jrev1; 1562 jrev1 = NULL; 1563 jdate2 = jdate1; 1564 jdate1 = NULL; 1565 } 1566 1567 /* The file in the working directory doesn't exist in CVS/Entries. 1568 FIXME: Shouldn't this case result in additional processing (if 1569 the file was added going from rev1 to rev2, then do the equivalent 1570 of a "cvs add")? (yes; easier said than done.. :-) */ 1571 if (vers->vn_user == NULL) 1572 { 1573 /* No merge possible YET. */ 1574 if (jdate2 != NULL) 1575 error (0, 0, 1576 "file %s is present in revision %s as of %s", 1577 file, jrev2, jdate2); 1578 else 1579 error (0, 0, 1580 "file %s is present in revision %s", 1581 file, jrev2); 1582 return; 1583 } 1584 1585 /* Fix for bug CVS/193: 1586 * Used to dump core if the file had been removed on the current branch. 1587 */ 1588 if (strcmp(vers->vn_user, "0") == 0) 1589 { 1590 error(0, 0, 1591 "file %s has been deleted", 1592 file); 1593 return; 1594 } 1595 1596 /* convert the second rev spec, walking branches and dates. */ 1597 1598 rev2 = RCS_getversion (vers->srcfile, jrev2, jdate2, 1, 0); 1599 if (rev2 == NULL) 1600 { 1601 if (!quiet) 1602 { 1603 if (jdate2 != NULL) 1604 error (0, 0, 1605 "cannot find revision %s as of %s in file %s", 1606 jrev2, jdate2, file); 1607 else 1608 error (0, 0, 1609 "cannot find revision %s in file %s", 1610 jrev2, file); 1611 } 1612 return; 1613 } 1614 1615 /* skip joining identical revs */ 1616 if (strcmp (rev2, vers->vn_user) == 0) 1617 { 1618 /* No merge necessary. */ 1619 free (rev2); 1620 return; 1621 } 1622 1623 if (jrev1 == NULL) 1624 { 1625 char *tst; 1626 /* if the first rev is missing, then it is implied to be the 1627 greatest common ancestor of both the join rev, and the 1628 checked out rev. */ 1629 1630 /* FIXME: What is this check for '!' about? If it is legal to 1631 have '!' in the first character of vn_user, it isn't 1632 documented at struct vers_ts in cvs.h. */ 1633 tst = vers->vn_user; 1634 if (*tst == '!') 1635 { 1636 /* file was dead. merge anyway and pretend it's been 1637 added. */ 1638 ++tst; 1639 Register (entries, file, "0", vers->ts_user, vers->options, 1640 vers->tag, (char *) 0, (char *) 0); 1641 } 1642 rev1 = gca (tst, rev2); 1643 if (rev1 == NULL) 1644 { 1645 /* this should not be possible */ 1646 error (0, 0, "bad gca"); 1647 abort(); 1648 } 1649 1650 tst = RCS_gettag (vers->srcfile, rev2, 1, 0); 1651 if (tst == NULL) 1652 { 1653 /* this should not be possible. */ 1654 error (0, 0, "cannot find gca"); 1655 abort(); 1656 } 1657 1658 free (tst); 1659 1660 /* these two cases are noops */ 1661 if (strcmp (rev1, rev2) == 0) 1662 { 1663 free (rev1); 1664 free (rev2); 1665 return; 1666 } 1667 } 1668 else 1669 { 1670 /* otherwise, convert the first rev spec, walking branches and 1671 dates. */ 1672 1673 rev1 = RCS_getversion (vers->srcfile, jrev1, jdate1, 1, 0); 1674 if (rev1 == NULL) 1675 { 1676 if (!quiet) { 1677 if (jdate1 != NULL) 1678 error (0, 0, 1679 "cannot find revision %s as of %s in file %s", 1680 jrev1, jdate1, file); 1681 else 1682 error (0, 0, 1683 "cannot find revision %s in file %s", 1684 jrev1, file); 1685 } 1686 return; 1687 } 1688 } 1689 1690 /* do the join */ 1691 1692 #if 0 1693 dome { 1694 /* special handling when two revisions are specified */ 1695 if (join_rev1 && join_rev2) 1696 { 1697 rev = RCS_getversion (vers->srcfile, join_rev2, date_rev2, 1, 0); 1698 if (rev == NULL) 1699 { 1700 if (!quiet && date_rev2 == NULL) 1701 error (0, 0, 1702 "cannot find revision %s in file %s", join_rev2, file); 1703 return; 1704 } 1705 1706 baserev = RCS_getversion (vers->srcfile, join_rev1, date_rev1, 1, 0); 1707 if (baserev == NULL) 1708 { 1709 if (!quiet && date_rev1 == NULL) 1710 error (0, 0, 1711 "cannot find revision %s in file %s", join_rev1, file); 1712 free (rev); 1713 return; 1714 } 1715 1716 /* 1717 * nothing to do if: 1718 * second revision matches our BASE revision (vn_user) && 1719 * both revisions are on the same branch 1720 */ 1721 if (strcmp (vers->vn_user, rev) == 0 && 1722 numdots (baserev) == numdots (rev)) 1723 { 1724 /* might be the same branch. take a real look */ 1725 char *dot = strrchr (baserev, '.'); 1726 int len = (dot - baserev) + 1; 1727 1728 if (strncmp (baserev, rev, len) == 0) 1729 return; 1730 } 1731 } 1732 else 1733 { 1734 rev = RCS_getversion (vers->srcfile, join_rev1, date_rev1, 1, 0); 1735 if (rev == NULL) 1736 return; 1737 if (strcmp (rev, vers->vn_user) == 0) /* no merge necessary */ 1738 { 1739 free (rev); 1740 return; 1741 } 1742 1743 baserev = RCS_whatbranch (file, join_rev1, srcfiles); 1744 if (baserev) 1745 { 1746 char *cp; 1747 1748 /* we get a branch -- turn it into a revision, or NULL if trunk */ 1749 if ((cp = strrchr (baserev, '.')) == NULL) 1750 { 1751 free (baserev); 1752 baserev = (char *) NULL; 1753 } 1754 else 1755 *cp = '\0'; 1756 } 1757 } 1758 if (baserev && strcmp (baserev, rev) == 0) 1759 { 1760 /* they match -> nothing to do */ 1761 free (rev); 1762 free (baserev); 1763 return; 1764 } 1765 } 1766 #endif 1767 1768 /* OK, so we have two revisions; continue on */ 1769 1770 #ifdef SERVER_SUPPORT 1771 if (server_active && !isreadable (file)) 1772 { 1773 int retcode; 1774 /* The file is up to date. Need to check out the current contents. */ 1775 run_setup ("%s%s -q -r%s", Rcsbin, RCS_CO, vers->vn_user); 1776 run_arg (vers->srcfile->path); 1777 retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); 1778 if (retcode != 0) 1779 error (1, retcode == -1 ? errno : 0, 1780 "failed to check out %s file", file); 1781 } 1782 #endif 1783 1784 /* 1785 * The users currently modified file is moved to a backup file name 1786 * ".#filename.version", so that it will stay around for a few days 1787 * before being automatically removed by some cron daemon. The "version" 1788 * is the version of the file that the user was most up-to-date with 1789 * before the merge. 1790 */ 1791 (void) sprintf (backup, "%s%s.%s", BAKPREFIX, file, vers->vn_user); 1792 if (update_dir[0]) 1793 (void) sprintf (user, "%s/%s", update_dir, file); 1794 else 1795 (void) strcpy (user, file); 1796 1797 (void) unlink_file (backup); 1798 copy_file (file, backup); 1799 xchmod (file, 1); 1800 1801 options = vers->options; 1802 #ifdef HAVE_RCS5 1803 #if 0 1804 if (*options == '\0') 1805 options = "-kk"; /* to ignore keyword expansions */ 1806 #endif 1807 #endif 1808 1809 status = RCS_merge (vers->srcfile->path, options, rev1, rev2); 1810 if (status != 0 && status != 1) 1811 { 1812 error (0, status == -1 ? errno : 0, 1813 "could not merge revision %s of %s", rev2, user); 1814 error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s", 1815 user, backup); 1816 rename_file (backup, file); 1817 } 1818 free (rev1); 1819 free (rev2); 1820 1821 #ifdef SERVER_SUPPORT 1822 /* 1823 * If we're in server mode, then we need to re-register the file 1824 * even if there were no conflicts (status == 0). 1825 * This tells server_updated() to send the modified file back to 1826 * the client. 1827 */ 1828 if (status == 1 || (status == 0 && server_active)) 1829 #else 1830 if (status == 1) 1831 #endif 1832 { 1833 char *cp = 0; 1834 1835 if (status) 1836 cp = time_stamp (file); 1837 Register (entries, file, vers->vn_rcs, vers->ts_rcs, vers->options, 1838 vers->tag, vers->date, cp); 1839 if (cp) 1840 free(cp); 1841 } 1842 1843 #ifdef SERVER_SUPPORT 1844 if (server_active) 1845 { 1846 server_copy_file (file, update_dir, repository, backup); 1847 server_updated (file, update_dir, repository, SERVER_MERGED, 1848 (struct stat *) NULL, (unsigned char *) NULL); 1849 } 1850 #endif 1851 } 1852 1853 int 1854 joining () 1855 { 1856 return (join_rev1 != NULL); 1857 } 1858