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