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