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