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 source distribution. 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 #include "buffer.h" 46 #include "hardlink.h" 47 48 static int checkout_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts, 49 int adding, int merging, int update_server)); 50 #ifdef SERVER_SUPPORT 51 static void checkout_to_buffer PROTO ((void *, const char *, size_t)); 52 #endif 53 #ifdef SERVER_SUPPORT 54 static int patch_file PROTO ((struct file_info *finfo, 55 Vers_TS *vers_ts, 56 int *docheckout, struct stat *file_info, 57 unsigned char *checksum)); 58 static void patch_file_write PROTO ((void *, const char *, size_t)); 59 #endif 60 static int merge_file PROTO ((struct file_info *finfo, Vers_TS *vers)); 61 static int scratch_file PROTO((struct file_info *finfo)); 62 static Dtype update_dirent_proc PROTO ((void *callerdat, char *dir, 63 char *repository, char *update_dir, 64 List *entries)); 65 static int update_dirleave_proc PROTO ((void *callerdat, char *dir, 66 int err, char *update_dir, 67 List *entries)); 68 static int update_fileproc PROTO ((void *callerdat, struct file_info *)); 69 static int update_filesdone_proc PROTO ((void *callerdat, int err, 70 char *repository, char *update_dir, 71 List *entries)); 72 #ifdef PRESERVE_PERMISSIONS_SUPPORT 73 static int get_linkinfo_proc PROTO ((void *callerdat, struct file_info *)); 74 #endif 75 static void write_letter PROTO ((struct file_info *finfo, int letter)); 76 static void join_file PROTO ((struct file_info *finfo, Vers_TS *vers_ts)); 77 78 static char *options = NULL; 79 static char *tag = NULL; 80 static char *date = NULL; 81 /* This is a bit of a kludge. We call WriteTag at the beginning 82 before we know whether nonbranch is set or not. And then at the 83 end, once we have the right value for nonbranch, we call WriteTag 84 again. I don't know whether the first call is necessary or not. 85 rewrite_tag is nonzero if we are going to have to make that second 86 call. */ 87 static int rewrite_tag; 88 static int nonbranch; 89 90 /* If we set the tag or date for a subdirectory, we use this to undo 91 the setting. See update_dirent_proc. */ 92 static char *tag_update_dir; 93 94 static char *join_rev1, *date_rev1; 95 static char *join_rev2, *date_rev2; 96 static int aflag = 0; 97 static int force_tag_match = 1; 98 static int update_build_dirs = 0; 99 static int update_prune_dirs = 0; 100 static int pipeout = 0; 101 #ifdef SERVER_SUPPORT 102 static int patches = 0; 103 static int rcs_diff_patches = 0; 104 #endif 105 static List *ignlist = (List *) NULL; 106 static time_t last_register_time; 107 static const char *const update_usage[] = 108 { 109 "Usage: %s %s [-APdflRp] [-k kopt] [-r rev|-D date] [-j rev]\n", 110 " [-I ign] [-W spec] [files...]\n", 111 "\t-A\tReset any sticky tags/date/kopts.\n", 112 "\t-P\tPrune empty directories.\n", 113 "\t-d\tBuild directories, like checkout does.\n", 114 "\t-f\tForce a head revision match if tag/date not found.\n", 115 "\t-l\tLocal directory only, no recursion.\n", 116 "\t-R\tProcess directories recursively.\n", 117 "\t-p\tSend updates to standard output (avoids stickiness).\n", 118 "\t-k kopt\tUse RCS kopt -k option on checkout.\n", 119 "\t-r rev\tUpdate using specified revision/tag (is sticky).\n", 120 "\t-D date\tSet date to update from (is sticky).\n", 121 "\t-j rev\tMerge in changes made between current revision and rev.\n", 122 "\t-I ign\tMore files to ignore (! to reset).\n", 123 "\t-W spec\tWrappers specification line.\n", 124 "(Specify the --help global option for a list of other help options)\n", 125 NULL 126 }; 127 128 /* 129 * update is the argv,argc based front end for arg parsing 130 */ 131 int 132 update (argc, argv) 133 int argc; 134 char **argv; 135 { 136 int c, err; 137 int local = 0; /* recursive by default */ 138 int which; /* where to look for files and dirs */ 139 140 if (argc == -1) 141 usage (update_usage); 142 143 ign_setup (); 144 wrap_setup (); 145 146 /* parse the args */ 147 optind = 0; 148 while ((c = getopt (argc, argv, "+ApPflRQqduk:r:D:j:I:W:")) != -1) 149 { 150 switch (c) 151 { 152 case 'A': 153 aflag = 1; 154 break; 155 case 'I': 156 ign_add (optarg, 0); 157 break; 158 case 'W': 159 wrap_add (optarg, 0); 160 break; 161 case 'k': 162 if (options) 163 free (options); 164 options = RCS_check_kflag (optarg); 165 break; 166 case 'l': 167 local = 1; 168 break; 169 case 'R': 170 local = 0; 171 break; 172 case 'Q': 173 case 'q': 174 #ifdef SERVER_SUPPORT 175 /* The CVS 1.5 client sends these options (in addition to 176 Global_option requests), so we must ignore them. */ 177 if (!server_active) 178 #endif 179 error (1, 0, 180 "-q or -Q must be specified before \"%s\"", 181 command_name); 182 break; 183 case 'd': 184 update_build_dirs = 1; 185 break; 186 case 'f': 187 force_tag_match = 0; 188 break; 189 case 'r': 190 tag = optarg; 191 break; 192 case 'D': 193 date = Make_Date (optarg); 194 break; 195 case 'P': 196 update_prune_dirs = 1; 197 break; 198 case 'p': 199 pipeout = 1; 200 noexec = 1; /* so no locks will be created */ 201 break; 202 case 'j': 203 if (join_rev2) 204 error (1, 0, "only two -j options can be specified"); 205 if (join_rev1) 206 join_rev2 = optarg; 207 else 208 join_rev1 = optarg; 209 break; 210 case 'u': 211 #ifdef SERVER_SUPPORT 212 if (server_active) 213 { 214 patches = 1; 215 rcs_diff_patches = server_use_rcs_diff (); 216 } 217 else 218 #endif 219 usage (update_usage); 220 break; 221 case '?': 222 default: 223 usage (update_usage); 224 break; 225 } 226 } 227 argc -= optind; 228 argv += optind; 229 230 #ifdef CLIENT_SUPPORT 231 if (client_active) 232 { 233 int pass; 234 235 /* The first pass does the regular update. If we receive at least 236 one patch which failed, we do a second pass and just fetch 237 those files whose patches failed. */ 238 pass = 1; 239 do 240 { 241 int status; 242 243 start_server (); 244 245 if (local) 246 send_arg("-l"); 247 if (update_build_dirs) 248 send_arg("-d"); 249 if (pipeout) 250 send_arg("-p"); 251 if (!force_tag_match) 252 send_arg("-f"); 253 if (aflag) 254 send_arg("-A"); 255 if (update_prune_dirs) 256 send_arg("-P"); 257 client_prune_dirs = update_prune_dirs; 258 option_with_arg ("-r", tag); 259 if (options && options[0] != '\0') 260 send_arg (options); 261 if (date) 262 client_senddate (date); 263 if (join_rev1) 264 option_with_arg ("-j", join_rev1); 265 if (join_rev2) 266 option_with_arg ("-j", join_rev2); 267 wrap_send (); 268 269 /* If the server supports the command "update-patches", that means 270 that it knows how to handle the -u argument to update, which 271 means to send patches instead of complete files. 272 273 We don't send -u if failed_patches != NULL, so that the 274 server doesn't try to send patches which will just fail 275 again. At least currently, the client also clobbers the 276 file and tells the server it is lost, which also will get 277 a full file instead of a patch, but it seems clean to omit 278 -u. */ 279 if (failed_patches == NULL) 280 { 281 if (supported_request ("update-patches")) 282 send_arg ("-u"); 283 } 284 285 if (failed_patches == NULL) 286 { 287 send_file_names (argc, argv, SEND_EXPAND_WILD); 288 /* If noexec, probably could be setting SEND_NO_CONTENTS. 289 Same caveats as for "cvs status" apply. */ 290 send_files (argc, argv, local, aflag, 291 update_build_dirs ? SEND_BUILD_DIRS : 0); 292 } 293 else 294 { 295 int i; 296 297 (void) printf ("%s client: refetching unpatchable files\n", 298 program_name); 299 300 if (toplevel_wd != NULL 301 && CVS_CHDIR (toplevel_wd) < 0) 302 { 303 error (1, errno, "could not chdir to %s", toplevel_wd); 304 } 305 306 for (i = 0; i < failed_patches_count; i++) 307 (void) unlink_file (failed_patches[i]); 308 send_file_names (failed_patches_count, failed_patches, 0); 309 send_files (failed_patches_count, failed_patches, local, 310 aflag, update_build_dirs ? SEND_BUILD_DIRS : 0); 311 } 312 313 failed_patches = NULL; 314 failed_patches_count = 0; 315 316 send_to_server ("update\012", 0); 317 318 status = get_responses_and_close (); 319 320 /* If there are any conflicts, the server will return a 321 non-zero exit status. If any patches failed, we still 322 want to run the update again. We use a pass count to 323 avoid an endless loop. */ 324 325 /* Notes: (1) assuming that status != 0 implies a 326 potential conflict is the best we can cleanly do given 327 the current protocol. I suppose that trying to 328 re-fetch in cases where there was a more serious error 329 is probably more or less harmless, but it isn't really 330 ideal. (2) it would be nice to have a testsuite case for the 331 conflict-and-patch-failed case. */ 332 333 if (status != 0 334 && (failed_patches == NULL || pass > 1)) 335 { 336 return status; 337 } 338 339 ++pass; 340 } while (failed_patches != NULL); 341 342 return 0; 343 } 344 #endif 345 346 if (tag != NULL) 347 tag_check_valid (tag, argc, argv, local, aflag, ""); 348 if (join_rev1 != NULL) 349 tag_check_valid_join (join_rev1, argc, argv, local, aflag, ""); 350 if (join_rev2 != NULL) 351 tag_check_valid_join (join_rev2, argc, argv, local, aflag, ""); 352 353 /* 354 * If we are updating the entire directory (for real) and building dirs 355 * as we go, we make sure there is no static entries file and write the 356 * tag file as appropriate 357 */ 358 if (argc <= 0 && !pipeout) 359 { 360 if (update_build_dirs) 361 { 362 if (unlink_file (CVSADM_ENTSTAT) < 0 && ! existence_error (errno)) 363 error (1, errno, "cannot remove file %s", CVSADM_ENTSTAT); 364 #ifdef SERVER_SUPPORT 365 if (server_active) 366 server_clear_entstat (".", Name_Repository (NULL, NULL)); 367 #endif 368 } 369 370 /* keep the CVS/Tag file current with the specified arguments */ 371 if (aflag || tag || date) 372 { 373 WriteTag ((char *) NULL, tag, date, 0, 374 ".", Name_Repository (NULL, NULL)); 375 rewrite_tag = 1; 376 nonbranch = 0; 377 } 378 } 379 380 /* look for files/dirs locally and in the repository */ 381 which = W_LOCAL | W_REPOS; 382 383 /* look in the attic too if a tag or date is specified */ 384 if (tag != NULL || date != NULL || joining()) 385 which |= W_ATTIC; 386 387 /* call the command line interface */ 388 err = do_update (argc, argv, options, tag, date, force_tag_match, 389 local, update_build_dirs, aflag, update_prune_dirs, 390 pipeout, which, join_rev1, join_rev2, (char *) NULL); 391 392 /* free the space Make_Date allocated if necessary */ 393 if (date != NULL) 394 free (date); 395 396 return (err); 397 } 398 399 /* 400 * Command line interface to update (used by checkout) 401 */ 402 int 403 do_update (argc, argv, xoptions, xtag, xdate, xforce, local, xbuild, xaflag, 404 xprune, xpipeout, which, xjoin_rev1, xjoin_rev2, preload_update_dir) 405 int argc; 406 char **argv; 407 char *xoptions; 408 char *xtag; 409 char *xdate; 410 int xforce; 411 int local; 412 int xbuild; 413 int xaflag; 414 int xprune; 415 int xpipeout; 416 int which; 417 char *xjoin_rev1; 418 char *xjoin_rev2; 419 char *preload_update_dir; 420 { 421 int err = 0; 422 char *cp; 423 424 /* fill in the statics */ 425 options = xoptions; 426 tag = xtag; 427 date = xdate; 428 force_tag_match = xforce; 429 update_build_dirs = xbuild; 430 aflag = xaflag; 431 update_prune_dirs = xprune; 432 pipeout = xpipeout; 433 434 /* setup the join support */ 435 join_rev1 = xjoin_rev1; 436 join_rev2 = xjoin_rev2; 437 if (join_rev1 && (cp = strchr (join_rev1, ':')) != NULL) 438 { 439 *cp++ = '\0'; 440 date_rev1 = Make_Date (cp); 441 } 442 else 443 date_rev1 = (char *) NULL; 444 if (join_rev2 && (cp = strchr (join_rev2, ':')) != NULL) 445 { 446 *cp++ = '\0'; 447 date_rev2 = Make_Date (cp); 448 } 449 else 450 date_rev2 = (char *) NULL; 451 452 #ifdef PRESERVE_PERMISSIONS_SUPPORT 453 if (preserve_perms) 454 { 455 /* We need to do an extra recursion, bleah. It's to make sure 456 that we know as much as possible about file linkage. */ 457 hardlist = getlist(); 458 working_dir = xgetwd(); /* save top-level working dir */ 459 460 /* FIXME-twp: the arguments to start_recursion make me dizzy. This 461 function call was copied from the update_fileproc call that 462 follows it; someone should make sure that I did it right. */ 463 err = start_recursion (get_linkinfo_proc, (FILESDONEPROC) NULL, 464 (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL, 465 argc, argv, local, which, aflag, 1, 466 preload_update_dir, 1); 467 if (err) 468 return (err); 469 470 /* FIXME-twp: at this point we should walk the hardlist 471 and update the `links' field of each hardlink_info struct 472 to list the files that are linked on dist. That would make 473 it easier & more efficient to compare the disk linkage with 474 the repository linkage (a simple strcmp). */ 475 } 476 #endif 477 478 /* call the recursion processor */ 479 err = start_recursion (update_fileproc, update_filesdone_proc, 480 update_dirent_proc, update_dirleave_proc, NULL, 481 argc, argv, local, which, aflag, 1, 482 preload_update_dir, 1); 483 484 /* see if we need to sleep before returning */ 485 if (last_register_time) 486 { 487 time_t now; 488 489 (void) time (&now); 490 if (now == last_register_time) 491 sleep (1); /* to avoid time-stamp races */ 492 } 493 494 return (err); 495 } 496 497 #ifdef PRESERVE_PERMISSIONS_SUPPORT 498 /* 499 * The get_linkinfo_proc callback adds each file to the hardlist 500 * (see hardlink.c). 501 */ 502 503 static int 504 get_linkinfo_proc (callerdat, finfo) 505 void *callerdat; 506 struct file_info *finfo; 507 { 508 char *fullpath; 509 Node *linkp; 510 struct hardlink_info *hlinfo; 511 512 /* Get the full pathname of the current file. */ 513 fullpath = xmalloc (strlen(working_dir) + 514 strlen(finfo->fullname) + 2); 515 sprintf (fullpath, "%s/%s", working_dir, finfo->fullname); 516 517 /* To permit recursing into subdirectories, files 518 are keyed on the full pathname and not on the basename. */ 519 linkp = lookup_file_by_inode (fullpath); 520 if (linkp == NULL) 521 { 522 /* The file isn't on disk; we are probably restoring 523 a file that was removed. */ 524 return 0; 525 } 526 527 /* Create a new, empty hardlink_info node. */ 528 hlinfo = (struct hardlink_info *) 529 xmalloc (sizeof (struct hardlink_info)); 530 531 hlinfo->status = (Ctype) 0; /* is this dumb? */ 532 hlinfo->checked_out = 0; 533 hlinfo->links = NULL; 534 535 linkp->data = (char *) hlinfo; 536 537 return 0; 538 } 539 #endif 540 541 /* 542 * This is the callback proc for update. It is called for each file in each 543 * directory by the recursion code. The current directory is the local 544 * instantiation. file is the file name we are to operate on. update_dir is 545 * set to the path relative to where we started (for pretty printing). 546 * repository is the repository. entries and srcfiles are the pre-parsed 547 * entries and source control files. 548 * 549 * This routine decides what needs to be done for each file and does the 550 * appropriate magic for checkout 551 */ 552 static int 553 update_fileproc (callerdat, finfo) 554 void *callerdat; 555 struct file_info *finfo; 556 { 557 int retval; 558 Ctype status; 559 Vers_TS *vers; 560 int resurrecting; 561 562 resurrecting = 0; 563 564 status = Classify_File (finfo, tag, date, options, force_tag_match, 565 aflag, &vers, pipeout); 566 567 /* Keep track of whether TAG is a branch tag. 568 Note that if it is a branch tag in some files and a nonbranch tag 569 in others, treat it as a nonbranch tag. It is possible that case 570 should elicit a warning or an error. */ 571 if (rewrite_tag 572 && tag != NULL 573 && finfo->rcs != NULL) 574 { 575 char *rev = RCS_getversion (finfo->rcs, tag, NULL, 1, NULL); 576 if (rev != NULL 577 && !RCS_nodeisbranch (finfo->rcs, tag)) 578 nonbranch = 1; 579 if (rev != NULL) 580 free (rev); 581 } 582 583 if (pipeout) 584 { 585 /* 586 * We just return success without doing anything if any of the really 587 * funky cases occur 588 * 589 * If there is still a valid RCS file, do a regular checkout type 590 * operation 591 */ 592 switch (status) 593 { 594 case T_UNKNOWN: /* unknown file was explicitly asked 595 * about */ 596 case T_REMOVE_ENTRY: /* needs to be un-registered */ 597 case T_ADDED: /* added but not committed */ 598 retval = 0; 599 break; 600 case T_CONFLICT: /* old punt-type errors */ 601 retval = 1; 602 break; 603 case T_UPTODATE: /* file was already up-to-date */ 604 case T_NEEDS_MERGE: /* needs merging */ 605 case T_MODIFIED: /* locally modified */ 606 case T_REMOVED: /* removed but not committed */ 607 case T_CHECKOUT: /* needs checkout */ 608 #ifdef SERVER_SUPPORT 609 case T_PATCH: /* needs patch */ 610 #endif 611 retval = checkout_file (finfo, vers, 0, 0, 0); 612 break; 613 614 default: /* can't ever happen :-) */ 615 error (0, 0, 616 "unknown file status %d for file %s", status, finfo->file); 617 retval = 0; 618 break; 619 } 620 } 621 else 622 { 623 switch (status) 624 { 625 case T_UNKNOWN: /* unknown file was explicitly asked 626 * about */ 627 case T_UPTODATE: /* file was already up-to-date */ 628 retval = 0; 629 break; 630 case T_CONFLICT: /* old punt-type errors */ 631 retval = 1; 632 write_letter (finfo, 'C'); 633 break; 634 case T_NEEDS_MERGE: /* needs merging */ 635 if (noexec) 636 { 637 retval = 1; 638 write_letter (finfo, 'C'); 639 } 640 else 641 { 642 retval = merge_file (finfo, vers); 643 } 644 break; 645 case T_MODIFIED: /* locally modified */ 646 retval = 0; 647 if (vers->ts_conflict) 648 { 649 char *filestamp; 650 int retcode; 651 652 /* 653 * If the timestamp has changed and no conflict indicators 654 * are found, it isn't a 'C' any more. 655 */ 656 #ifdef SERVER_SUPPORT 657 if (server_active) 658 retcode = vers->ts_conflict[0] != '='; 659 else { 660 filestamp = time_stamp (finfo->file); 661 retcode = strcmp (vers->ts_conflict, filestamp); 662 free (filestamp); 663 } 664 #else 665 filestamp = time_stamp (finfo->file); 666 retcode = strcmp (vers->ts_conflict, filestamp); 667 free (filestamp); 668 #endif 669 670 if (retcode) 671 { 672 /* The timestamps differ. But if there are conflict 673 markers print 'C' anyway. */ 674 retcode = !file_has_markers (finfo); 675 } 676 677 if (!retcode) 678 { 679 write_letter (finfo, 'C'); 680 retval = 1; 681 } 682 else 683 { 684 /* Reregister to clear conflict flag. */ 685 Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_rcs, 686 vers->options, vers->tag, 687 vers->date, (char *)0); 688 } 689 } 690 if (!retval) 691 { 692 write_letter (finfo, 'M'); 693 retval = 0; 694 } 695 break; 696 #ifdef SERVER_SUPPORT 697 case T_PATCH: /* needs patch */ 698 if (patches) 699 { 700 int docheckout; 701 struct stat file_info; 702 unsigned char checksum[16]; 703 704 retval = patch_file (finfo, 705 vers, &docheckout, 706 &file_info, checksum); 707 if (! docheckout) 708 { 709 if (server_active && retval == 0) 710 server_updated (finfo, vers, 711 (rcs_diff_patches 712 ? SERVER_RCS_DIFF 713 : SERVER_PATCHED), 714 file_info.st_mode, checksum, 715 (struct buffer *) NULL); 716 break; 717 } 718 } 719 /* If we're not running as a server, just check the 720 file out. It's simpler and faster than producing 721 and applying patches. */ 722 /* Fall through. */ 723 #endif 724 case T_CHECKOUT: /* needs checkout */ 725 retval = checkout_file (finfo, vers, 0, 0, 1); 726 break; 727 case T_ADDED: /* added but not committed */ 728 write_letter (finfo, 'A'); 729 retval = 0; 730 break; 731 case T_REMOVED: /* removed but not committed */ 732 write_letter (finfo, 'R'); 733 retval = 0; 734 break; 735 case T_REMOVE_ENTRY: /* needs to be un-registered */ 736 retval = scratch_file (finfo); 737 #ifdef SERVER_SUPPORT 738 if (server_active && retval == 0) 739 { 740 if (vers->ts_user == NULL) 741 server_scratch_entry_only (); 742 server_updated (finfo, vers, 743 SERVER_UPDATED, (mode_t) -1, 744 (unsigned char *) NULL, 745 (struct buffer *) NULL); 746 } 747 #endif 748 break; 749 default: /* can't ever happen :-) */ 750 error (0, 0, 751 "unknown file status %d for file %s", status, finfo->file); 752 retval = 0; 753 break; 754 } 755 } 756 757 /* only try to join if things have gone well thus far */ 758 if (retval == 0 && join_rev1) 759 join_file (finfo, vers); 760 761 /* if this directory has an ignore list, add this file to it */ 762 if (ignlist) 763 { 764 Node *p; 765 766 p = getnode (); 767 p->type = FILES; 768 p->key = xstrdup (finfo->file); 769 if (addnode (ignlist, p) != 0) 770 freenode (p); 771 } 772 773 freevers_ts (&vers); 774 return (retval); 775 } 776 777 static void update_ignproc PROTO ((char *, char *)); 778 779 static void 780 update_ignproc (file, dir) 781 char *file; 782 char *dir; 783 { 784 struct file_info finfo; 785 786 memset (&finfo, 0, sizeof (finfo)); 787 finfo.file = file; 788 finfo.update_dir = dir; 789 if (dir[0] == '\0') 790 finfo.fullname = xstrdup (file); 791 else 792 { 793 finfo.fullname = xmalloc (strlen (file) + strlen (dir) + 10); 794 strcpy (finfo.fullname, dir); 795 strcat (finfo.fullname, "/"); 796 strcat (finfo.fullname, file); 797 } 798 799 write_letter (&finfo, '?'); 800 free (finfo.fullname); 801 } 802 803 /* ARGSUSED */ 804 static int 805 update_filesdone_proc (callerdat, err, repository, update_dir, entries) 806 void *callerdat; 807 int err; 808 char *repository; 809 char *update_dir; 810 List *entries; 811 { 812 if (rewrite_tag) 813 { 814 WriteTag (NULL, tag, date, nonbranch, update_dir, repository); 815 rewrite_tag = 0; 816 } 817 818 /* if this directory has an ignore list, process it then free it */ 819 if (ignlist) 820 { 821 ignore_files (ignlist, entries, update_dir, update_ignproc); 822 dellist (&ignlist); 823 } 824 825 /* Clean up CVS admin dirs if we are export */ 826 if (strcmp (command_name, "export") == 0) 827 { 828 /* I'm not sure the existence_error is actually possible (except 829 in cases where we really should print a message), but since 830 this code used to ignore all errors, I'll play it safe. */ 831 if (unlink_file_dir (CVSADM) < 0 && !existence_error (errno)) 832 error (0, errno, "cannot remove %s directory", CVSADM); 833 } 834 #ifdef SERVER_SUPPORT 835 else if (!server_active && !pipeout) 836 #else 837 else if (!pipeout) 838 #endif /* SERVER_SUPPORT */ 839 { 840 /* If there is no CVS/Root file, add one */ 841 if (!isfile (CVSADM_ROOT)) 842 Create_Root ((char *) NULL, CVSroot_original); 843 } 844 845 return (err); 846 } 847 848 /* 849 * update_dirent_proc () is called back by the recursion processor before a 850 * sub-directory is processed for update. In this case, update_dirent proc 851 * will probably create the directory unless -d isn't specified and this is a 852 * new directory. A return code of 0 indicates the directory should be 853 * processed by the recursion code. A return of non-zero indicates the 854 * recursion code should skip this directory. 855 */ 856 static Dtype 857 update_dirent_proc (callerdat, dir, repository, update_dir, entries) 858 void *callerdat; 859 char *dir; 860 char *repository; 861 char *update_dir; 862 List *entries; 863 { 864 if (ignore_directory (update_dir)) 865 { 866 /* print the warm fuzzy message */ 867 if (!quiet) 868 error (0, 0, "Ignoring %s", update_dir); 869 return R_SKIP_ALL; 870 } 871 872 if (!isdir (dir)) 873 { 874 /* if we aren't building dirs, blow it off */ 875 if (!update_build_dirs) 876 return (R_SKIP_ALL); 877 878 if (noexec) 879 { 880 /* ignore the missing dir if -n is specified */ 881 error (0, 0, "New directory `%s' -- ignored", update_dir); 882 return (R_SKIP_ALL); 883 } 884 else 885 { 886 /* otherwise, create the dir and appropriate adm files */ 887 888 /* If no tag or date were specified on the command line, 889 and we're not using -A, we want the subdirectory to use 890 the tag and date, if any, of the current directory. 891 That way, update -d will work correctly when working on 892 a branch. 893 894 We use TAG_UPDATE_DIR to undo the tag setting in 895 update_dirleave_proc. If we did not do this, we would 896 not correctly handle a working directory with multiple 897 tags (and maybe we should prohibit such working 898 directories, but they work now and we shouldn't make 899 them stop working without more thought). */ 900 if ((tag == NULL && date == NULL) && ! aflag) 901 { 902 ParseTag (&tag, &date, &nonbranch); 903 if (tag != NULL || date != NULL) 904 tag_update_dir = xstrdup (update_dir); 905 } 906 907 make_directory (dir); 908 Create_Admin (dir, update_dir, repository, tag, date, 909 /* This is a guess. We will rewrite it later 910 via WriteTag. */ 911 0, 912 0); 913 rewrite_tag = 1; 914 nonbranch = 0; 915 Subdir_Register (entries, (char *) NULL, dir); 916 } 917 } 918 /* Do we need to check noexec here? */ 919 else if (!pipeout) 920 { 921 char *cvsadmdir; 922 923 /* The directory exists. Check to see if it has a CVS 924 subdirectory. */ 925 926 cvsadmdir = xmalloc (strlen (dir) + 80); 927 strcpy (cvsadmdir, dir); 928 strcat (cvsadmdir, "/"); 929 strcat (cvsadmdir, CVSADM); 930 931 if (!isdir (cvsadmdir)) 932 { 933 /* We cannot successfully recurse into a directory without a CVS 934 subdirectory. Generally we will have already printed 935 "? foo". */ 936 free (cvsadmdir); 937 return R_SKIP_ALL; 938 } 939 free (cvsadmdir); 940 } 941 942 /* 943 * If we are building dirs and not going to stdout, we make sure there is 944 * no static entries file and write the tag file as appropriate 945 */ 946 if (!pipeout) 947 { 948 if (update_build_dirs) 949 { 950 char *tmp; 951 952 tmp = xmalloc (strlen (dir) + sizeof (CVSADM_ENTSTAT) + 10); 953 (void) sprintf (tmp, "%s/%s", dir, CVSADM_ENTSTAT); 954 if (unlink_file (tmp) < 0 && ! existence_error (errno)) 955 error (1, errno, "cannot remove file %s", tmp); 956 #ifdef SERVER_SUPPORT 957 if (server_active) 958 server_clear_entstat (update_dir, repository); 959 #endif 960 free (tmp); 961 } 962 963 /* keep the CVS/Tag file current with the specified arguments */ 964 if (aflag || tag || date) 965 { 966 WriteTag (dir, tag, date, 0, update_dir, repository); 967 rewrite_tag = 1; 968 nonbranch = 0; 969 } 970 971 /* initialize the ignore list for this directory */ 972 ignlist = getlist (); 973 } 974 975 /* print the warm fuzzy message */ 976 if (!quiet) 977 error (0, 0, "Updating %s", update_dir); 978 979 return (R_PROCESS); 980 } 981 982 /* 983 * update_dirleave_proc () is called back by the recursion code upon leaving 984 * a directory. It will prune empty directories if needed and will execute 985 * any appropriate update programs. 986 */ 987 /* ARGSUSED */ 988 static int 989 update_dirleave_proc (callerdat, dir, err, update_dir, entries) 990 void *callerdat; 991 char *dir; 992 int err; 993 char *update_dir; 994 List *entries; 995 { 996 FILE *fp; 997 998 /* If we set the tag or date for a new subdirectory in 999 update_dirent_proc, and we're now done with that subdirectory, 1000 undo the tag/date setting. Note that we know that the tag and 1001 date were both originally NULL in this case. */ 1002 if (tag_update_dir != NULL && strcmp (update_dir, tag_update_dir) == 0) 1003 { 1004 if (tag != NULL) 1005 { 1006 free (tag); 1007 tag = NULL; 1008 } 1009 if (date != NULL) 1010 { 1011 free (date); 1012 date = NULL; 1013 } 1014 nonbranch = 0; 1015 free (tag_update_dir); 1016 tag_update_dir = NULL; 1017 } 1018 1019 /* run the update_prog if there is one */ 1020 /* FIXME: should be checking for errors from CVS_FOPEN and printing 1021 them if not existence_error. */ 1022 if (err == 0 && !pipeout && !noexec && 1023 (fp = CVS_FOPEN (CVSADM_UPROG, "r")) != NULL) 1024 { 1025 char *cp; 1026 char *repository; 1027 char *line = NULL; 1028 size_t line_allocated = 0; 1029 1030 repository = Name_Repository ((char *) NULL, update_dir); 1031 if (getline (&line, &line_allocated, fp) >= 0) 1032 { 1033 if ((cp = strrchr (line, '\n')) != NULL) 1034 *cp = '\0'; 1035 run_setup (line); 1036 run_arg (repository); 1037 cvs_output (program_name, 0); 1038 cvs_output (" ", 1); 1039 cvs_output (command_name, 0); 1040 cvs_output (": Executing '", 0); 1041 run_print (stdout); 1042 cvs_output ("'\n", 0); 1043 (void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL); 1044 } 1045 else if (ferror (fp)) 1046 error (0, errno, "cannot read %s", CVSADM_UPROG); 1047 else 1048 error (0, 0, "unexpected end of file on %s", CVSADM_UPROG); 1049 1050 if (fclose (fp) < 0) 1051 error (0, errno, "cannot close %s", CVSADM_UPROG); 1052 if (line != NULL) 1053 free (line); 1054 free (repository); 1055 } 1056 1057 if (strchr (dir, '/') == NULL) 1058 { 1059 /* FIXME: chdir ("..") loses with symlinks. */ 1060 /* Prune empty dirs on the way out - if necessary */ 1061 (void) CVS_CHDIR (".."); 1062 if (update_prune_dirs && isemptydir (dir, 0)) 1063 { 1064 /* I'm not sure the existence_error is actually possible (except 1065 in cases where we really should print a message), but since 1066 this code used to ignore all errors, I'll play it safe. */ 1067 if (unlink_file_dir (dir) < 0 && !existence_error (errno)) 1068 error (0, errno, "cannot remove %s directory", dir); 1069 Subdir_Deregister (entries, (char *) NULL, dir); 1070 } 1071 } 1072 1073 return (err); 1074 } 1075 1076 static int isremoved PROTO ((Node *, void *)); 1077 1078 /* Returns 1 if the file indicated by node has been removed. */ 1079 static int 1080 isremoved (node, closure) 1081 Node *node; 1082 void *closure; 1083 { 1084 Entnode *entdata = (Entnode*) node->data; 1085 1086 /* If the first character of the version is a '-', the file has been 1087 removed. */ 1088 return (entdata->version && entdata->version[0] == '-') ? 1 : 0; 1089 } 1090 1091 /* Returns 1 if the argument directory is completely empty, other than the 1092 existence of the CVS directory entry. Zero otherwise. If MIGHT_NOT_EXIST 1093 and the directory doesn't exist, then just return 0. */ 1094 int 1095 isemptydir (dir, might_not_exist) 1096 char *dir; 1097 int might_not_exist; 1098 { 1099 DIR *dirp; 1100 struct dirent *dp; 1101 1102 if ((dirp = CVS_OPENDIR (dir)) == NULL) 1103 { 1104 if (might_not_exist && existence_error (errno)) 1105 return 0; 1106 error (0, errno, "cannot open directory %s for empty check", dir); 1107 return (0); 1108 } 1109 errno = 0; 1110 while ((dp = readdir (dirp)) != NULL) 1111 { 1112 if (strcmp (dp->d_name, ".") != 0 1113 && strcmp (dp->d_name, "..") != 0) 1114 { 1115 if (strcmp (dp->d_name, CVSADM) != 0) 1116 { 1117 /* An entry other than the CVS directory. The directory 1118 is certainly not empty. */ 1119 (void) closedir (dirp); 1120 return (0); 1121 } 1122 else 1123 { 1124 /* The CVS directory entry. We don't have to worry about 1125 this unless the Entries file indicates that files have 1126 been removed, but not committed, in this directory. 1127 (Removing the directory would prevent people from 1128 comitting the fact that they removed the files!) */ 1129 List *l; 1130 int files_removed; 1131 struct saved_cwd cwd; 1132 1133 if (save_cwd (&cwd)) 1134 error_exit (); 1135 1136 if (CVS_CHDIR (dir) < 0) 1137 error (1, errno, "cannot change directory to %s", dir); 1138 l = Entries_Open (0, NULL); 1139 files_removed = walklist (l, isremoved, 0); 1140 Entries_Close (l); 1141 1142 if (restore_cwd (&cwd, NULL)) 1143 error_exit (); 1144 free_cwd (&cwd); 1145 1146 if (files_removed != 0) 1147 { 1148 /* There are files that have been removed, but not 1149 committed! Do not consider the directory empty. */ 1150 (void) closedir (dirp); 1151 return (0); 1152 } 1153 } 1154 } 1155 errno = 0; 1156 } 1157 if (errno != 0) 1158 { 1159 error (0, errno, "cannot read directory %s", dir); 1160 (void) closedir (dirp); 1161 return (0); 1162 } 1163 (void) closedir (dirp); 1164 return (1); 1165 } 1166 1167 /* 1168 * scratch the Entries file entry associated with a file 1169 */ 1170 static int 1171 scratch_file (finfo) 1172 struct file_info *finfo; 1173 { 1174 history_write ('W', finfo->update_dir, "", finfo->file, finfo->repository); 1175 Scratch_Entry (finfo->entries, finfo->file); 1176 if (unlink_file (finfo->file) < 0 && ! existence_error (errno)) 1177 error (0, errno, "unable to remove %s", finfo->fullname); 1178 return (0); 1179 } 1180 1181 /* 1182 * Check out a file. 1183 */ 1184 static int 1185 checkout_file (finfo, vers_ts, adding, merging, update_server) 1186 struct file_info *finfo; 1187 Vers_TS *vers_ts; 1188 int adding; 1189 int merging; 1190 int update_server; 1191 { 1192 char *backup; 1193 int set_time, retval = 0; 1194 int status; 1195 int file_is_dead; 1196 struct buffer *revbuf; 1197 1198 backup = NULL; 1199 revbuf = NULL; 1200 1201 /* Don't screw with backup files if we're going to stdout, or if 1202 we are the server. */ 1203 if (!pipeout 1204 #ifdef SERVER_SUPPORT 1205 && ! server_active 1206 #endif 1207 ) 1208 { 1209 backup = xmalloc (strlen (finfo->file) 1210 + sizeof (CVSADM) 1211 + sizeof (CVSPREFIX) 1212 + 10); 1213 (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file); 1214 if (isfile (finfo->file)) 1215 rename_file (finfo->file, backup); 1216 else 1217 { 1218 /* If -f/-t wrappers are being used to wrap up a directory, 1219 then backup might be a directory instead of just a file. */ 1220 if (unlink_file_dir (backup) < 0) 1221 { 1222 /* Not sure if the existence_error check is needed here. */ 1223 if (!existence_error (errno)) 1224 /* FIXME: should include update_dir in message. */ 1225 error (0, errno, "error removing %s", backup); 1226 } 1227 free (backup); 1228 backup = NULL; 1229 } 1230 } 1231 1232 file_is_dead = RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs); 1233 1234 if (!file_is_dead) 1235 { 1236 /* 1237 * if we are checking out to stdout, print a nice message to 1238 * stderr, and add the -p flag to the command */ 1239 if (pipeout) 1240 { 1241 if (!quiet) 1242 { 1243 cvs_outerr ("\ 1244 ===================================================================\n\ 1245 Checking out ", 0); 1246 cvs_outerr (finfo->fullname, 0); 1247 cvs_outerr ("\n\ 1248 RCS: ", 0); 1249 cvs_outerr (vers_ts->srcfile->path, 0); 1250 cvs_outerr ("\n\ 1251 VERS: ", 0); 1252 cvs_outerr (vers_ts->vn_rcs, 0); 1253 cvs_outerr ("\n***************\n", 0); 1254 } 1255 } 1256 1257 #ifdef SERVER_SUPPORT 1258 if (update_server 1259 && server_active 1260 && ! pipeout 1261 && ! file_gzip_level 1262 && ! joining () 1263 && ! wrap_name_has (finfo->file, WRAP_FROMCVS)) 1264 { 1265 revbuf = buf_nonio_initialize ((BUFMEMERRPROC) NULL); 1266 status = RCS_checkout (vers_ts->srcfile, (char *) NULL, 1267 vers_ts->vn_rcs, vers_ts->vn_tag, 1268 vers_ts->options, RUN_TTY, 1269 checkout_to_buffer, revbuf); 1270 } 1271 else 1272 #endif 1273 status = RCS_checkout (vers_ts->srcfile, 1274 pipeout ? NULL : finfo->file, 1275 vers_ts->vn_rcs, vers_ts->vn_tag, 1276 vers_ts->options, RUN_TTY, 1277 (RCSCHECKOUTPROC) NULL, (void *) NULL); 1278 } 1279 if (file_is_dead || status == 0) 1280 { 1281 mode_t mode; 1282 1283 mode = (mode_t) -1; 1284 1285 if (!pipeout) 1286 { 1287 Vers_TS *xvers_ts; 1288 1289 if (revbuf != NULL) 1290 { 1291 struct stat sb; 1292 1293 /* FIXME: We should have RCS_checkout return the mode. */ 1294 if (stat (vers_ts->srcfile->path, &sb) < 0) 1295 error (1, errno, "cannot stat %s", 1296 vers_ts->srcfile->path); 1297 mode = sb.st_mode &~ (S_IWRITE | S_IWGRP | S_IWOTH); 1298 } 1299 1300 if (cvswrite 1301 && !file_is_dead 1302 && !fileattr_get (finfo->file, "_watched")) 1303 { 1304 if (revbuf == NULL) 1305 xchmod (finfo->file, 1); 1306 else 1307 { 1308 /* We know that we are the server here, so 1309 although xchmod checks umask, we don't bother. */ 1310 mode |= (((mode & S_IRUSR) ? S_IWUSR : 0) 1311 | ((mode & S_IRGRP) ? S_IWGRP : 0) 1312 | ((mode & S_IROTH) ? S_IWOTH : 0)); 1313 } 1314 } 1315 1316 { 1317 /* A newly checked out file is never under the spell 1318 of "cvs edit". If we think we were editing it 1319 from a previous life, clean up. Would be better to 1320 check for same the working directory instead of 1321 same user, but that is hairy. */ 1322 1323 struct addremove_args args; 1324 1325 editor_set (finfo->file, getcaller (), NULL); 1326 1327 memset (&args, 0, sizeof args); 1328 args.remove_temp = 1; 1329 watch_modify_watchers (finfo->file, &args); 1330 } 1331 1332 /* set the time from the RCS file iff it was unknown before */ 1333 set_time = 1334 (!noexec 1335 && (vers_ts->vn_user == NULL || 1336 strncmp (vers_ts->ts_rcs, "Initial", 7) == 0) 1337 && !file_is_dead); 1338 1339 wrap_fromcvs_process_file (finfo->file); 1340 1341 xvers_ts = Version_TS (finfo, options, tag, date, 1342 force_tag_match, set_time); 1343 if (strcmp (xvers_ts->options, "-V4") == 0) 1344 xvers_ts->options[0] = '\0'; 1345 1346 if (revbuf != NULL) 1347 { 1348 /* If we stored the file data into a buffer, then we 1349 didn't create a file at all, so xvers_ts->ts_user 1350 is wrong. The correct value is to have it be the 1351 same as xvers_ts->ts_rcs, meaning that the working 1352 file is unchanged from the RCS file. 1353 1354 FIXME: We should tell Version_TS not to waste time 1355 statting the nonexistent file. 1356 1357 FIXME: Actually, I don't think the ts_user value 1358 matters at all here. The only use I know of is 1359 that it is printed in a trace message by 1360 Server_Register. */ 1361 1362 if (xvers_ts->ts_user != NULL) 1363 free (xvers_ts->ts_user); 1364 xvers_ts->ts_user = xstrdup (xvers_ts->ts_rcs); 1365 } 1366 1367 (void) time (&last_register_time); 1368 1369 if (file_is_dead) 1370 { 1371 if (xvers_ts->vn_user != NULL) 1372 { 1373 error (0, 0, 1374 "warning: %s is not (any longer) pertinent", 1375 finfo->fullname); 1376 } 1377 Scratch_Entry (finfo->entries, finfo->file); 1378 #ifdef SERVER_SUPPORT 1379 if (server_active && xvers_ts->ts_user == NULL) 1380 server_scratch_entry_only (); 1381 #endif 1382 /* FIXME: Rather than always unlink'ing, and ignoring the 1383 existence_error, we should do the unlink only if 1384 vers_ts->ts_user is non-NULL. Then there would be no 1385 need to ignore an existence_error (for example, if the 1386 user removes the file while we are running). */ 1387 if (unlink_file (finfo->file) < 0 && ! existence_error (errno)) 1388 { 1389 error (0, errno, "cannot remove %s", finfo->fullname); 1390 } 1391 } 1392 else 1393 Register (finfo->entries, finfo->file, 1394 adding ? "0" : xvers_ts->vn_rcs, 1395 xvers_ts->ts_user, xvers_ts->options, 1396 xvers_ts->tag, xvers_ts->date, 1397 (char *)0); /* Clear conflict flag on fresh checkout */ 1398 1399 /* fix up the vers structure, in case it is used by join */ 1400 if (join_rev1) 1401 { 1402 if (vers_ts->vn_user != NULL) 1403 free (vers_ts->vn_user); 1404 if (vers_ts->vn_rcs != NULL) 1405 free (vers_ts->vn_rcs); 1406 vers_ts->vn_user = xstrdup (xvers_ts->vn_rcs); 1407 vers_ts->vn_rcs = xstrdup (xvers_ts->vn_rcs); 1408 } 1409 1410 /* If this is really Update and not Checkout, recode history */ 1411 if (strcmp (command_name, "update") == 0) 1412 history_write ('U', finfo->update_dir, xvers_ts->vn_rcs, finfo->file, 1413 finfo->repository); 1414 1415 freevers_ts (&xvers_ts); 1416 1417 if (!really_quiet && !file_is_dead) 1418 { 1419 write_letter (finfo, 'U'); 1420 } 1421 } 1422 1423 #ifdef SERVER_SUPPORT 1424 if (update_server && server_active) 1425 server_updated (finfo, vers_ts, 1426 merging ? SERVER_MERGED : SERVER_UPDATED, 1427 mode, (unsigned char *) NULL, revbuf); 1428 #endif 1429 } 1430 else 1431 { 1432 if (backup != NULL) 1433 { 1434 rename_file (backup, finfo->file); 1435 free (backup); 1436 backup = NULL; 1437 } 1438 1439 error (0, 0, "could not check out %s", finfo->fullname); 1440 1441 retval = status; 1442 } 1443 1444 if (backup != NULL) 1445 { 1446 /* If -f/-t wrappers are being used to wrap up a directory, 1447 then backup might be a directory instead of just a file. */ 1448 if (unlink_file_dir (backup) < 0) 1449 { 1450 /* Not sure if the existence_error check is needed here. */ 1451 if (!existence_error (errno)) 1452 /* FIXME: should include update_dir in message. */ 1453 error (0, errno, "error removing %s", backup); 1454 } 1455 free (backup); 1456 } 1457 1458 return (retval); 1459 } 1460 1461 #ifdef SERVER_SUPPORT 1462 1463 /* This function is used to write data from a file being checked out 1464 into a buffer. */ 1465 1466 static void 1467 checkout_to_buffer (callerdat, data, len) 1468 void *callerdat; 1469 const char *data; 1470 size_t len; 1471 { 1472 struct buffer *buf = (struct buffer *) callerdat; 1473 1474 buf_output (buf, data, len); 1475 } 1476 1477 #endif /* SERVER_SUPPORT */ 1478 1479 #ifdef SERVER_SUPPORT 1480 1481 /* This structure is used to pass information between patch_file and 1482 patch_file_write. */ 1483 1484 struct patch_file_data 1485 { 1486 /* File name, for error messages. */ 1487 const char *filename; 1488 /* File to which to write. */ 1489 FILE *fp; 1490 /* Whether to compute the MD5 checksum. */ 1491 int compute_checksum; 1492 /* Data structure for computing the MD5 checksum. */ 1493 struct MD5Context context; 1494 /* Set if the file has a final newline. */ 1495 int final_nl; 1496 }; 1497 1498 /* Patch a file. Runs diff. This is only done when running as the 1499 * server. The hope is that the diff will be smaller than the file 1500 * itself. 1501 */ 1502 static int 1503 patch_file (finfo, vers_ts, docheckout, file_info, checksum) 1504 struct file_info *finfo; 1505 Vers_TS *vers_ts; 1506 int *docheckout; 1507 struct stat *file_info; 1508 unsigned char *checksum; 1509 { 1510 char *backup; 1511 char *file1; 1512 char *file2; 1513 int retval = 0; 1514 int retcode = 0; 1515 int fail; 1516 long file_size; 1517 FILE *e; 1518 struct patch_file_data data; 1519 1520 *docheckout = 0; 1521 1522 if (noexec || pipeout || joining ()) 1523 { 1524 *docheckout = 1; 1525 return 0; 1526 } 1527 1528 /* If this file has been marked as being binary, then never send a 1529 patch. */ 1530 if (strcmp (vers_ts->options, "-kb") == 0) 1531 { 1532 *docheckout = 1; 1533 return 0; 1534 } 1535 1536 /* First check that the first revision exists. If it has been nuked 1537 by cvs admin -o, then just fall back to checking out entire 1538 revisions. In some sense maybe we don't have to do this; after 1539 all cvs.texinfo says "Make sure that no-one has checked out a 1540 copy of the revision you outdate" but then again, that advice 1541 doesn't really make complete sense, because "cvs admin" operates 1542 on a working directory and so _someone_ will almost always have 1543 _some_ revision checked out. */ 1544 { 1545 char *rev; 1546 1547 rev = RCS_gettag (finfo->rcs, vers_ts->vn_user, 1, NULL); 1548 if (rev == NULL) 1549 { 1550 *docheckout = 1; 1551 return 0; 1552 } 1553 else 1554 free (rev); 1555 } 1556 1557 /* If the revision is dead, let checkout_file handle it rather 1558 than duplicating the processing here. */ 1559 if (RCS_isdead (vers_ts->srcfile, vers_ts->vn_rcs)) 1560 { 1561 *docheckout = 1; 1562 return 0; 1563 } 1564 1565 backup = xmalloc (strlen (finfo->file) 1566 + sizeof (CVSADM) 1567 + sizeof (CVSPREFIX) 1568 + 10); 1569 (void) sprintf (backup, "%s/%s%s", CVSADM, CVSPREFIX, finfo->file); 1570 if (isfile (finfo->file)) 1571 rename_file (finfo->file, backup); 1572 else 1573 (void) unlink_file (backup); 1574 1575 file1 = xmalloc (strlen (finfo->file) 1576 + sizeof (CVSADM) 1577 + sizeof (CVSPREFIX) 1578 + 10); 1579 (void) sprintf (file1, "%s/%s%s-1", CVSADM, CVSPREFIX, finfo->file); 1580 file2 = xmalloc (strlen (finfo->file) 1581 + sizeof (CVSADM) 1582 + sizeof (CVSPREFIX) 1583 + 10); 1584 (void) sprintf (file2, "%s/%s%s-2", CVSADM, CVSPREFIX, finfo->file); 1585 1586 fail = 0; 1587 1588 /* We need to check out both revisions first, to see if either one 1589 has a trailing newline. Because of this, we don't use rcsdiff, 1590 but just use diff. */ 1591 1592 e = CVS_FOPEN (file1, "w"); 1593 if (e == NULL) 1594 error (1, errno, "cannot open %s", file1); 1595 1596 data.filename = file1; 1597 data.fp = e; 1598 data.final_nl = 0; 1599 data.compute_checksum = 0; 1600 1601 retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL, 1602 vers_ts->vn_user, (char *) NULL, 1603 vers_ts->options, RUN_TTY, 1604 patch_file_write, (void *) &data); 1605 1606 if (fclose (e) < 0) 1607 error (1, errno, "cannot close %s", file1); 1608 1609 if (retcode != 0 || ! data.final_nl) 1610 fail = 1; 1611 1612 if (! fail) 1613 { 1614 e = CVS_FOPEN (file2, "w"); 1615 if (e == NULL) 1616 error (1, errno, "cannot open %s", file2); 1617 1618 data.filename = file2; 1619 data.fp = e; 1620 data.final_nl = 0; 1621 data.compute_checksum = 1; 1622 MD5Init (&data.context); 1623 1624 retcode = RCS_checkout (vers_ts->srcfile, (char *) NULL, 1625 vers_ts->vn_rcs, (char *) NULL, 1626 vers_ts->options, RUN_TTY, 1627 patch_file_write, (void *) &data); 1628 1629 if (fclose (e) < 0) 1630 error (1, errno, "cannot close %s", file2); 1631 1632 if (retcode != 0 || ! data.final_nl) 1633 fail = 1; 1634 else 1635 MD5Final (checksum, &data.context); 1636 } 1637 1638 retcode = 0; 1639 if (! fail) 1640 { 1641 char *diff_options; 1642 1643 /* FIXME: It might be better to come up with a diff library 1644 which can be shared with the diffutils. */ 1645 /* If the client does not support the Rcs-diff command, we 1646 send a context diff, and the client must invoke patch. 1647 That approach was problematical for various reasons. The 1648 new approach only requires running diff in the server; the 1649 client can handle everything without invoking an external 1650 program. */ 1651 if (! rcs_diff_patches) 1652 { 1653 /* We use -c, not -u, because we have no way of knowing 1654 which DIFF is in use. */ 1655 diff_options = "-c"; 1656 } 1657 else 1658 { 1659 /* Now that diff is librarified, we could be passing -a if 1660 we wanted to. However, it is unclear to me whether we 1661 would want to. Does diff -a, in any significant 1662 percentage of cases, produce patches which are smaller 1663 than the files it is patching? I guess maybe text 1664 files with character sets which diff regards as 1665 'binary'. Conversely, do they tend to be much larger 1666 in the bad cases? This needs some more 1667 thought/investigation, I suspect. */ 1668 1669 diff_options = "-n"; 1670 } 1671 retcode = diff_exec (file1, file2, diff_options, finfo->file); 1672 1673 /* A retcode of 0 means no differences. 1 means some differences. */ 1674 if (retcode != 0 1675 && retcode != 1) 1676 { 1677 fail = 1; 1678 } 1679 else 1680 { 1681 #define BINARY "Binary" 1682 char buf[sizeof BINARY]; 1683 unsigned int c; 1684 1685 /* Stat the original RCS file, and then adjust it the way 1686 that RCS_checkout would. FIXME: This is an abstraction 1687 violation. */ 1688 if (CVS_STAT (vers_ts->srcfile->path, file_info) < 0) 1689 error (1, errno, "could not stat %s", vers_ts->srcfile->path); 1690 if (chmod (finfo->file, 1691 file_info->st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH)) 1692 < 0) 1693 error (0, errno, "cannot change mode of file %s", finfo->file); 1694 if (cvswrite 1695 && !fileattr_get (finfo->file, "_watched")) 1696 xchmod (finfo->file, 1); 1697 1698 /* Check the diff output to make sure patch will be handle it. */ 1699 e = CVS_FOPEN (finfo->file, "r"); 1700 if (e == NULL) 1701 error (1, errno, "could not open diff output file %s", 1702 finfo->fullname); 1703 c = fread (buf, 1, sizeof BINARY - 1, e); 1704 buf[c] = '\0'; 1705 if (strcmp (buf, BINARY) == 0) 1706 { 1707 /* These are binary files. We could use diff -a, but 1708 patch can't handle that. */ 1709 fail = 1; 1710 } 1711 else { 1712 /* 1713 * Don't send a diff if just sending the entire file 1714 * would be smaller 1715 */ 1716 fseek(e, 0L, SEEK_END); 1717 if (file_size < ftell(e)) 1718 fail = 1; 1719 } 1720 1721 fclose (e); 1722 } 1723 } 1724 1725 if (! fail) 1726 { 1727 Vers_TS *xvers_ts; 1728 1729 /* This stuff is just copied blindly from checkout_file. I 1730 don't really know what it does. */ 1731 xvers_ts = Version_TS (finfo, options, tag, date, 1732 force_tag_match, 0); 1733 if (strcmp (xvers_ts->options, "-V4") == 0) 1734 xvers_ts->options[0] = '\0'; 1735 1736 Register (finfo->entries, finfo->file, xvers_ts->vn_rcs, 1737 xvers_ts->ts_user, xvers_ts->options, 1738 xvers_ts->tag, xvers_ts->date, NULL); 1739 1740 if (CVS_STAT (finfo->file, file_info) < 0) 1741 error (1, errno, "could not stat %s", finfo->file); 1742 1743 /* If this is really Update and not Checkout, recode history */ 1744 if (strcmp (command_name, "update") == 0) 1745 history_write ('P', finfo->update_dir, xvers_ts->vn_rcs, finfo->file, 1746 finfo->repository); 1747 1748 freevers_ts (&xvers_ts); 1749 1750 if (!really_quiet) 1751 { 1752 write_letter (finfo, 'P'); 1753 } 1754 } 1755 else 1756 { 1757 int old_errno = errno; /* save errno value over the rename */ 1758 1759 if (isfile (backup)) 1760 rename_file (backup, finfo->file); 1761 1762 if (retcode != 0 && retcode != 1) 1763 error (retcode == -1 ? 1 : 0, retcode == -1 ? old_errno : 0, 1764 "could not diff %s", finfo->fullname); 1765 1766 *docheckout = 1; 1767 retval = retcode; 1768 } 1769 1770 (void) unlink_file (backup); 1771 (void) unlink_file (file1); 1772 (void) unlink_file (file2); 1773 1774 free (backup); 1775 free (file1); 1776 free (file2); 1777 return (retval); 1778 } 1779 1780 /* Write data to a file. Record whether the last byte written was a 1781 newline. Optionally compute a checksum. This is called by 1782 patch_file via RCS_checkout. */ 1783 1784 static void 1785 patch_file_write (callerdat, buffer, len) 1786 void *callerdat; 1787 const char *buffer; 1788 size_t len; 1789 { 1790 struct patch_file_data *data = (struct patch_file_data *) callerdat; 1791 1792 if (fwrite (buffer, 1, len, data->fp) != len) 1793 error (1, errno, "cannot write %s", data->filename); 1794 1795 data->final_nl = (buffer[len - 1] == '\n'); 1796 1797 if (data->compute_checksum) 1798 MD5Update (&data->context, (unsigned char *) buffer, len); 1799 } 1800 1801 #endif /* SERVER_SUPPORT */ 1802 1803 /* 1804 * Several of the types we process only print a bit of information consisting 1805 * of a single letter and the name. 1806 */ 1807 static void 1808 write_letter (finfo, letter) 1809 struct file_info *finfo; 1810 int letter; 1811 { 1812 if (!really_quiet) 1813 { 1814 char *tag = NULL; 1815 /* Big enough for "+updated" or any of its ilk. */ 1816 char buf[80]; 1817 1818 switch (letter) 1819 { 1820 case 'U': 1821 tag = "updated"; 1822 break; 1823 default: 1824 /* We don't yet support tagged output except for "U". */ 1825 break; 1826 } 1827 1828 if (tag != NULL) 1829 { 1830 sprintf (buf, "+%s", tag); 1831 cvs_output_tagged (buf, NULL); 1832 } 1833 buf[0] = letter; 1834 buf[1] = ' '; 1835 buf[2] = '\0'; 1836 cvs_output_tagged ("text", buf); 1837 cvs_output_tagged ("fname", finfo->fullname); 1838 cvs_output_tagged ("newline", NULL); 1839 if (tag != NULL) 1840 { 1841 sprintf (buf, "-%s", tag); 1842 cvs_output_tagged (buf, NULL); 1843 } 1844 } 1845 return; 1846 } 1847 1848 /* 1849 * Do all the magic associated with a file which needs to be merged 1850 */ 1851 static int 1852 merge_file (finfo, vers) 1853 struct file_info *finfo; 1854 Vers_TS *vers; 1855 { 1856 char *backup; 1857 int status; 1858 int retcode = 0; 1859 int retval; 1860 1861 /* 1862 * The users currently modified file is moved to a backup file name 1863 * ".#filename.version", so that it will stay around for a few days 1864 * before being automatically removed by some cron daemon. The "version" 1865 * is the version of the file that the user was most up-to-date with 1866 * before the merge. 1867 */ 1868 backup = xmalloc (strlen (finfo->file) 1869 + strlen (vers->vn_user) 1870 + sizeof (BAKPREFIX) 1871 + 10); 1872 (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user); 1873 1874 (void) unlink_file (backup); 1875 copy_file (finfo->file, backup); 1876 xchmod (finfo->file, 1); 1877 1878 if (strcmp (vers->options, "-kb") == 0 1879 || wrap_merge_is_copy (finfo->file) 1880 || special_file_mismatch (finfo, NULL, vers->vn_rcs)) 1881 { 1882 /* For binary files, a merge is always a conflict. Same for 1883 files whose permissions or linkage do not match. We give the 1884 user the two files, and let them resolve it. It is possible 1885 that we should require a "touch foo" or similar step before 1886 we allow a checkin. */ 1887 1888 /* TODO: it may not always be necessary to regard a permission 1889 mismatch as a conflict. The working file and the RCS file 1890 have a common ancestor `A'; if the working file's permissions 1891 match A's, then it's probably safe to overwrite them with the 1892 RCS permissions. Only if the working file, the RCS file, and 1893 A all disagree should this be considered a conflict. But more 1894 thought needs to go into this, and in the meantime it is safe 1895 to treat any such mismatch as an automatic conflict. -twp */ 1896 1897 #ifdef SERVER_SUPPORT 1898 if (server_active) 1899 server_copy_file (finfo->file, finfo->update_dir, 1900 finfo->repository, backup); 1901 #endif 1902 1903 status = checkout_file (finfo, vers, 0, 1, 1); 1904 1905 /* Is there a better term than "nonmergeable file"? What we 1906 really mean is, not something that CVS cannot or does not 1907 want to merge (there might be an external manual or 1908 automatic merge process). */ 1909 error (0, 0, "nonmergeable file needs merge"); 1910 error (0, 0, "revision %s from repository is now in %s", 1911 vers->vn_rcs, finfo->fullname); 1912 error (0, 0, "file from working directory is now in %s", backup); 1913 write_letter (finfo, 'C'); 1914 1915 history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file, 1916 finfo->repository); 1917 retval = 0; 1918 goto out; 1919 } 1920 1921 status = RCS_merge(finfo->rcs, vers->srcfile->path, finfo->file, 1922 vers->options, vers->vn_user, vers->vn_rcs); 1923 if (status != 0 && status != 1) 1924 { 1925 error (0, status == -1 ? errno : 0, 1926 "could not merge revision %s of %s", vers->vn_user, finfo->fullname); 1927 error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s", 1928 finfo->fullname, backup); 1929 rename_file (backup, finfo->file); 1930 retval = 1; 1931 goto out; 1932 } 1933 1934 if (strcmp (vers->options, "-V4") == 0) 1935 vers->options[0] = '\0'; 1936 (void) time (&last_register_time); 1937 { 1938 char *cp = 0; 1939 1940 if (status) 1941 cp = time_stamp (finfo->file); 1942 Register (finfo->entries, finfo->file, vers->vn_rcs, vers->ts_rcs, vers->options, 1943 vers->tag, vers->date, cp); 1944 if (cp) 1945 free (cp); 1946 } 1947 1948 /* fix up the vers structure, in case it is used by join */ 1949 if (join_rev1) 1950 { 1951 if (vers->vn_user != NULL) 1952 free (vers->vn_user); 1953 vers->vn_user = xstrdup (vers->vn_rcs); 1954 } 1955 1956 #ifdef SERVER_SUPPORT 1957 /* Send the new contents of the file before the message. If we 1958 wanted to be totally correct, we would have the client write 1959 the message only after the file has safely been written. */ 1960 if (server_active) 1961 { 1962 server_copy_file (finfo->file, finfo->update_dir, finfo->repository, 1963 backup); 1964 server_updated (finfo, vers, SERVER_MERGED, 1965 (mode_t) -1, (unsigned char *) NULL, 1966 (struct buffer *) NULL); 1967 } 1968 #endif 1969 1970 if (!noexec && !xcmp (backup, finfo->file)) 1971 { 1972 printf ("%s already contains the differences between %s and %s\n", 1973 finfo->fullname, vers->vn_user, vers->vn_rcs); 1974 history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file, 1975 finfo->repository); 1976 retval = 0; 1977 goto out; 1978 } 1979 1980 if (status == 1) 1981 { 1982 if (!noexec) 1983 error (0, 0, "conflicts found in %s", finfo->fullname); 1984 1985 write_letter (finfo, 'C'); 1986 1987 history_write ('C', finfo->update_dir, vers->vn_rcs, finfo->file, finfo->repository); 1988 1989 } 1990 else if (retcode == -1) 1991 { 1992 error (1, errno, "fork failed while examining update of %s", 1993 finfo->fullname); 1994 } 1995 else 1996 { 1997 write_letter (finfo, 'M'); 1998 history_write ('G', finfo->update_dir, vers->vn_rcs, finfo->file, 1999 finfo->repository); 2000 } 2001 retval = 0; 2002 out: 2003 free (backup); 2004 return retval; 2005 } 2006 2007 /* 2008 * Do all the magic associated with a file which needs to be joined 2009 * (-j option) 2010 */ 2011 static void 2012 join_file (finfo, vers) 2013 struct file_info *finfo; 2014 Vers_TS *vers; 2015 { 2016 char *backup; 2017 char *options; 2018 int status; 2019 2020 char *rev1; 2021 char *rev2; 2022 char *jrev1; 2023 char *jrev2; 2024 char *jdate1; 2025 char *jdate2; 2026 2027 jrev1 = join_rev1; 2028 jrev2 = join_rev2; 2029 jdate1 = date_rev1; 2030 jdate2 = date_rev2; 2031 2032 /* Determine if we need to do anything at all. */ 2033 if (vers->srcfile == NULL || 2034 vers->srcfile->path == NULL) 2035 { 2036 return; 2037 } 2038 2039 /* If only one join revision is specified, it becomes the second 2040 revision. */ 2041 if (jrev2 == NULL) 2042 { 2043 jrev2 = jrev1; 2044 jrev1 = NULL; 2045 jdate2 = jdate1; 2046 jdate1 = NULL; 2047 } 2048 2049 /* Convert the second revision, walking branches and dates. */ 2050 rev2 = RCS_getversion (vers->srcfile, jrev2, jdate2, 1, (int *) NULL); 2051 2052 /* If this is a merge of two revisions, get the first revision. 2053 If only one join tag was specified, then the first revision is 2054 the greatest common ancestor of the second revision and the 2055 working file. */ 2056 if (jrev1 != NULL) 2057 rev1 = RCS_getversion (vers->srcfile, jrev1, jdate1, 1, (int *) NULL); 2058 else 2059 { 2060 /* Note that we use vn_rcs here, since vn_user may contain a 2061 special string such as "-nn". */ 2062 if (vers->vn_rcs == NULL) 2063 rev1 = NULL; 2064 else if (rev2 == NULL) 2065 { 2066 /* This means that the file never existed on the branch. 2067 It does not mean that the file was removed on the 2068 branch: that case is represented by a dead rev2. If 2069 the file never existed on the branch, then we have 2070 nothing to merge, so we just return. */ 2071 return; 2072 } 2073 else 2074 rev1 = gca (vers->vn_rcs, rev2); 2075 } 2076 2077 /* Handle a nonexistent or dead merge target. */ 2078 if (rev2 == NULL || RCS_isdead (vers->srcfile, rev2)) 2079 { 2080 char *mrev; 2081 2082 if (rev2 != NULL) 2083 free (rev2); 2084 2085 /* If the first revision doesn't exist either, then there is 2086 no change between the two revisions, so we don't do 2087 anything. */ 2088 if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1)) 2089 { 2090 if (rev1 != NULL) 2091 free (rev1); 2092 return; 2093 } 2094 2095 /* If we are merging two revisions, then the file was removed 2096 between the first revision and the second one. In this 2097 case we want to mark the file for removal. 2098 2099 If we are merging one revision, then the file has been 2100 removed between the greatest common ancestor and the merge 2101 revision. From the perspective of the branch on to which 2102 we ar emerging, which may be the trunk, either 1) the file 2103 does not currently exist on the target, or 2) the file has 2104 not been modified on the target branch since the greatest 2105 common ancestor, or 3) the file has been modified on the 2106 target branch since the greatest common ancestor. In case 2107 1 there is nothing to do. In case 2 we mark the file for 2108 removal. In case 3 we have a conflict. 2109 2110 Note that the handling is slightly different depending upon 2111 whether one or two join targets were specified. If two 2112 join targets were specified, we don't check whether the 2113 file was modified since a given point. My reasoning is 2114 that if you ask for an explicit merge between two tags, 2115 then you want to merge in whatever was changed between 2116 those two tags. If a file was removed between the two 2117 tags, then you want it to be removed. However, if you ask 2118 for a merge of a branch, then you want to merge in all 2119 changes which were made on the branch. If a file was 2120 removed on the branch, that is a change to the file. If 2121 the file was also changed on the main line, then that is 2122 also a change. These two changes--the file removal and the 2123 modification--must be merged. This is a conflict. */ 2124 2125 /* If the user file is dead, or does not exist, or has been 2126 marked for removal, then there is nothing to do. */ 2127 if (vers->vn_user == NULL 2128 || vers->vn_user[0] == '-' 2129 || RCS_isdead (vers->srcfile, vers->vn_user)) 2130 { 2131 if (rev1 != NULL) 2132 free (rev1); 2133 return; 2134 } 2135 2136 /* If the user file has been marked for addition, or has been 2137 locally modified, then we have a conflict which we can not 2138 resolve. No_Difference will already have been called in 2139 this case, so comparing the timestamps is sufficient to 2140 determine whether the file is locally modified. */ 2141 if (strcmp (vers->vn_user, "0") == 0 2142 || (vers->ts_user != NULL 2143 && strcmp (vers->ts_user, vers->ts_rcs) != 0)) 2144 { 2145 if (jdate2 != NULL) 2146 error (0, 0, 2147 "file %s is locally modified, but has been removed in revision %s as of %s", 2148 finfo->fullname, jrev2, jdate2); 2149 else 2150 error (0, 0, 2151 "file %s is locally modified, but has been removed in revision %s", 2152 finfo->fullname, jrev2); 2153 2154 /* FIXME: Should we arrange to return a non-zero exit 2155 status? */ 2156 2157 if (rev1 != NULL) 2158 free (rev1); 2159 2160 return; 2161 } 2162 2163 /* If only one join tag was specified, and the user file has 2164 been changed since the greatest common ancestor (rev1), 2165 then there is a conflict we can not resolve. See above for 2166 the rationale. */ 2167 if (join_rev2 == NULL 2168 && strcmp (rev1, vers->vn_user) != 0) 2169 { 2170 if (jdate2 != NULL) 2171 error (0, 0, 2172 "file %s has been modified, but has been removed in revision %s as of %s", 2173 finfo->fullname, jrev2, jdate2); 2174 else 2175 error (0, 0, 2176 "file %s has been modified, but has been removed in revision %s", 2177 finfo->fullname, jrev2); 2178 2179 /* FIXME: Should we arrange to return a non-zero exit 2180 status? */ 2181 2182 if (rev1 != NULL) 2183 free (rev1); 2184 2185 return; 2186 } 2187 2188 if (rev1 != NULL) 2189 free (rev1); 2190 2191 /* The user file exists and has not been modified. Mark it 2192 for removal. FIXME: If we are doing a checkout, this has 2193 the effect of first checking out the file, and then 2194 removing it. It would be better to just register the 2195 removal. */ 2196 #ifdef SERVER_SUPPORT 2197 if (server_active) 2198 { 2199 server_scratch (finfo->file); 2200 server_updated (finfo, vers, SERVER_UPDATED, (mode_t) -1, 2201 (unsigned char *) NULL, (struct buffer *) NULL); 2202 } 2203 #endif 2204 mrev = xmalloc (strlen (vers->vn_user) + 2); 2205 sprintf (mrev, "-%s", vers->vn_user); 2206 Register (finfo->entries, finfo->file, mrev, vers->ts_rcs, 2207 vers->options, vers->tag, vers->date, vers->ts_conflict); 2208 free (mrev); 2209 /* We need to check existence_error here because if we are 2210 running as the server, and the file is up to date in the 2211 working directory, the client will not have sent us a copy. */ 2212 if (unlink_file (finfo->file) < 0 && ! existence_error (errno)) 2213 error (0, errno, "cannot remove file %s", finfo->fullname); 2214 #ifdef SERVER_SUPPORT 2215 if (server_active) 2216 server_checked_in (finfo->file, finfo->update_dir, 2217 finfo->repository); 2218 #endif 2219 if (! really_quiet) 2220 error (0, 0, "scheduling %s for removal", finfo->fullname); 2221 2222 return; 2223 } 2224 2225 /* If the target of the merge is the same as the working file 2226 revision, then there is nothing to do. */ 2227 if (vers->vn_user != NULL && strcmp (rev2, vers->vn_user) == 0) 2228 { 2229 if (rev1 != NULL) 2230 free (rev1); 2231 free (rev2); 2232 return; 2233 } 2234 2235 /* If rev1 is dead or does not exist, then the file was added 2236 between rev1 and rev2. */ 2237 if (rev1 == NULL || RCS_isdead (vers->srcfile, rev1)) 2238 { 2239 if (rev1 != NULL) 2240 free (rev1); 2241 free (rev2); 2242 2243 /* If the file does not exist in the working directory, then 2244 we can just check out the new revision and mark it for 2245 addition. */ 2246 if (vers->vn_user == NULL) 2247 { 2248 Vers_TS *xvers; 2249 2250 xvers = Version_TS (finfo, vers->options, jrev2, jdate2, 1, 0); 2251 2252 /* FIXME: If checkout_file fails, we should arrange to 2253 return a non-zero exit status. */ 2254 status = checkout_file (finfo, xvers, 1, 0, 1); 2255 2256 freevers_ts (&xvers); 2257 2258 return; 2259 } 2260 2261 /* The file currently exists in the working directory, so we 2262 have a conflict which we can not resolve. Note that this 2263 is true even if the file is marked for addition or removal. */ 2264 2265 if (jdate2 != NULL) 2266 error (0, 0, 2267 "file %s exists, but has been added in revision %s as of %s", 2268 finfo->fullname, jrev2, jdate2); 2269 else 2270 error (0, 0, 2271 "file %s exists, but has been added in revision %s", 2272 finfo->fullname, jrev2); 2273 2274 return; 2275 } 2276 2277 /* If the two merge revisions are the same, then there is nothing 2278 to do. */ 2279 if (strcmp (rev1, rev2) == 0) 2280 { 2281 free (rev1); 2282 free (rev2); 2283 return; 2284 } 2285 2286 /* If there is no working file, then we can't do the merge. */ 2287 if (vers->vn_user == NULL) 2288 { 2289 free (rev1); 2290 free (rev2); 2291 2292 if (jdate2 != NULL) 2293 error (0, 0, 2294 "file %s is present in revision %s as of %s", 2295 finfo->fullname, jrev2, jdate2); 2296 else 2297 error (0, 0, 2298 "file %s is present in revision %s", 2299 finfo->fullname, jrev2); 2300 2301 /* FIXME: Should we arrange to return a non-zero exit status? */ 2302 2303 return; 2304 } 2305 2306 #ifdef SERVER_SUPPORT 2307 if (server_active && !isreadable (finfo->file)) 2308 { 2309 int retcode; 2310 /* The file is up to date. Need to check out the current contents. */ 2311 retcode = RCS_checkout (vers->srcfile, finfo->file, 2312 vers->vn_user, (char *) NULL, 2313 (char *) NULL, RUN_TTY, 2314 (RCSCHECKOUTPROC) NULL, (void *) NULL); 2315 if (retcode != 0) 2316 error (1, 0, 2317 "failed to check out %s file", finfo->fullname); 2318 } 2319 #endif 2320 2321 /* 2322 * The users currently modified file is moved to a backup file name 2323 * ".#filename.version", so that it will stay around for a few days 2324 * before being automatically removed by some cron daemon. The "version" 2325 * is the version of the file that the user was most up-to-date with 2326 * before the merge. 2327 */ 2328 backup = xmalloc (strlen (finfo->file) 2329 + strlen (vers->vn_user) 2330 + sizeof (BAKPREFIX) 2331 + 10); 2332 (void) sprintf (backup, "%s%s.%s", BAKPREFIX, finfo->file, vers->vn_user); 2333 2334 (void) unlink_file (backup); 2335 copy_file (finfo->file, backup); 2336 xchmod (finfo->file, 1); 2337 2338 options = vers->options; 2339 #if 0 2340 if (*options == '\0') 2341 options = "-kk"; /* to ignore keyword expansions */ 2342 #endif 2343 2344 /* If the source of the merge is the same as the working file 2345 revision, then we can just RCS_checkout the target (no merging 2346 as such). In the text file case, this is probably quite 2347 similar to the RCS_merge, but in the binary file case, 2348 RCS_merge gives all kinds of trouble. */ 2349 if (vers->vn_user != NULL 2350 && strcmp (rev1, vers->vn_user) == 0 2351 /* See comments above about how No_Difference has already been 2352 called. */ 2353 && vers->ts_user != NULL 2354 && strcmp (vers->ts_user, vers->ts_rcs) == 0 2355 2356 /* This is because of the worry below about $Name. If that 2357 isn't a problem, I suspect this code probably works for 2358 text files too. */ 2359 && (strcmp (options, "-kb") == 0 2360 || wrap_merge_is_copy (finfo->file))) 2361 { 2362 /* FIXME: what about nametag? What does RCS_merge do with 2363 $Name? */ 2364 if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, options, 2365 RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0) 2366 status = 2; 2367 else 2368 status = 0; 2369 2370 /* OK, this is really stupid. RCS_checkout carefully removes 2371 write permissions, and we carefully put them back. But 2372 until someone gets around to fixing it, that seems like the 2373 easiest way to get what would seem to be the right mode. 2374 I don't check CVSWRITE or _watched; I haven't thought about 2375 that in great detail, but it seems like a watched file should 2376 be checked out (writable) after a merge. */ 2377 xchmod (finfo->file, 1); 2378 2379 /* Traditionally, the text file case prints a whole bunch of 2380 scary looking and verbose output which fails to tell the user 2381 what is really going on (it gives them rev1 and rev2 but doesn't 2382 indicate in any way that rev1 == vn_user). I think just a 2383 simple "U foo" is good here; it seems analogous to the case in 2384 which the file was added on the branch in terms of what to 2385 print. */ 2386 write_letter (finfo, 'U'); 2387 } 2388 else if (strcmp (options, "-kb") == 0 2389 || wrap_merge_is_copy (finfo->file) 2390 || special_file_mismatch (finfo, rev1, rev2)) 2391 { 2392 /* We are dealing with binary files, or files with a 2393 permission/linkage mismatch, and real merging would 2394 need to take place. This is a conflict. We give the user 2395 the two files, and let them resolve it. It is possible 2396 that we should require a "touch foo" or similar step before 2397 we allow a checkin. */ 2398 if (RCS_checkout (finfo->rcs, finfo->file, rev2, NULL, options, 2399 RUN_TTY, (RCSCHECKOUTPROC)0, NULL) != 0) 2400 status = 2; 2401 else 2402 status = 0; 2403 2404 /* OK, this is really stupid. RCS_checkout carefully removes 2405 write permissions, and we carefully put them back. But 2406 until someone gets around to fixing it, that seems like the 2407 easiest way to get what would seem to be the right mode. 2408 I don't check CVSWRITE or _watched; I haven't thought about 2409 that in great detail, but it seems like a watched file should 2410 be checked out (writable) after a merge. */ 2411 xchmod (finfo->file, 1); 2412 2413 /* Hmm. We don't give them REV1 anywhere. I guess most people 2414 probably don't have a 3-way merge tool for the file type in 2415 question, and might just get confused if we tried to either 2416 provide them with a copy of the file from REV1, or even just 2417 told them what REV1 is so they can get it themself, but it 2418 might be worth thinking about. */ 2419 /* See comment in merge_file about the "nonmergeable file" 2420 terminology. */ 2421 error (0, 0, "nonmergeable file needs merge"); 2422 error (0, 0, "revision %s from repository is now in %s", 2423 rev2, finfo->fullname); 2424 error (0, 0, "file from working directory is now in %s", backup); 2425 write_letter (finfo, 'C'); 2426 } 2427 else 2428 status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file, 2429 options, rev1, rev2); 2430 2431 if (status != 0 && status != 1) 2432 { 2433 error (0, status == -1 ? errno : 0, 2434 "could not merge revision %s of %s", rev2, finfo->fullname); 2435 error (status == -1 ? 1 : 0, 0, "restoring %s from backup file %s", 2436 finfo->fullname, backup); 2437 rename_file (backup, finfo->file); 2438 } 2439 free (rev1); 2440 free (rev2); 2441 2442 #ifdef SERVER_SUPPORT 2443 /* 2444 * If we're in server mode, then we need to re-register the file 2445 * even if there were no conflicts (status == 0). 2446 * This tells server_updated() to send the modified file back to 2447 * the client. 2448 */ 2449 if (status == 1 || (status == 0 && server_active)) 2450 #else 2451 if (status == 1) 2452 #endif 2453 { 2454 char *cp = 0; 2455 2456 if (status) 2457 cp = time_stamp (finfo->file); 2458 Register (finfo->entries, finfo->file, 2459 vers->vn_rcs, vers->ts_rcs, vers->options, 2460 vers->tag, vers->date, cp); 2461 if (cp) 2462 free(cp); 2463 } 2464 2465 #ifdef SERVER_SUPPORT 2466 if (server_active) 2467 { 2468 server_copy_file (finfo->file, finfo->update_dir, finfo->repository, 2469 backup); 2470 server_updated (finfo, vers, SERVER_MERGED, 2471 (mode_t) -1, (unsigned char *) NULL, 2472 (struct buffer *) NULL); 2473 } 2474 #endif 2475 free (backup); 2476 } 2477 2478 /* 2479 * Report whether revisions REV1 and REV2 of FINFO agree on: 2480 * . file ownership 2481 * . permissions 2482 * . major and minor device numbers 2483 * . symbolic links 2484 * . hard links 2485 * 2486 * If either REV1 or REV2 is NULL, the working copy is used instead. 2487 * 2488 * Return 1 if the files differ on these data. 2489 */ 2490 2491 int 2492 special_file_mismatch (finfo, rev1, rev2) 2493 struct file_info *finfo; 2494 char *rev1; 2495 char *rev2; 2496 { 2497 #ifdef PRESERVE_PERMISSIONS_SUPPORT 2498 struct stat sb; 2499 RCSVers *vp; 2500 Node *n; 2501 uid_t rev1_uid, rev2_uid; 2502 gid_t rev1_gid, rev2_gid; 2503 mode_t rev1_mode, rev2_mode; 2504 unsigned long dev_long; 2505 dev_t rev1_dev, rev2_dev; 2506 char *rev1_symlink = NULL; 2507 char *rev2_symlink = NULL; 2508 char *rev1_hardlinks = NULL; 2509 char *rev2_hardlinks = NULL; 2510 int check_uids, check_gids, check_modes; 2511 int result; 2512 2513 /* If we don't care about special file info, then 2514 don't report a mismatch in any case. */ 2515 if (!preserve_perms) 2516 return 0; 2517 2518 /* When special_file_mismatch is called from No_Difference, the 2519 RCS file has been only partially parsed. We must read the 2520 delta tree in order to compare special file info recorded in 2521 the delta nodes. (I think this is safe. -twp) */ 2522 if (finfo->rcs->flags & PARTIAL) 2523 RCS_reparsercsfile (finfo->rcs, NULL, NULL); 2524 2525 check_uids = check_gids = check_modes = 1; 2526 2527 /* Obtain file information for REV1. If this is null, then stat 2528 finfo->file and use that info. */ 2529 /* If a revision does not know anything about its status, 2530 then presumably it doesn't matter, and indicates no conflict. */ 2531 2532 if (rev1 == NULL) 2533 { 2534 if (islink (finfo->file)) 2535 rev1_symlink = xreadlink (finfo->file); 2536 else 2537 { 2538 if (CVS_LSTAT (finfo->file, &sb) < 0) 2539 error (1, errno, "could not get file information for %s", 2540 finfo->file); 2541 rev1_uid = sb.st_uid; 2542 rev1_gid = sb.st_gid; 2543 rev1_mode = sb.st_mode; 2544 if (S_ISBLK (rev1_mode) || S_ISCHR (rev1_mode)) 2545 rev1_dev = sb.st_rdev; 2546 } 2547 rev1_hardlinks = list_files_linked_to (finfo->file); 2548 } 2549 else 2550 { 2551 n = findnode (finfo->rcs->versions, rev1); 2552 vp = (RCSVers *) n->data; 2553 2554 n = findnode (vp->other_delta, "symlink"); 2555 if (n != NULL) 2556 rev1_symlink = xstrdup (n->data); 2557 else 2558 { 2559 n = findnode (vp->other_delta, "owner"); 2560 if (n == NULL) 2561 check_uids = 0; /* don't care */ 2562 else 2563 rev1_uid = strtoul (n->data, NULL, 10); 2564 2565 n = findnode (vp->other_delta, "group"); 2566 if (n == NULL) 2567 check_gids = 0; /* don't care */ 2568 else 2569 rev1_gid = strtoul (n->data, NULL, 10); 2570 2571 n = findnode (vp->other_delta, "permissions"); 2572 if (n == NULL) 2573 check_modes = 0; /* don't care */ 2574 else 2575 rev1_mode = strtoul (n->data, NULL, 8); 2576 2577 n = findnode (vp->other_delta, "special"); 2578 if (n == NULL) 2579 rev1_mode |= S_IFREG; 2580 else 2581 { 2582 /* If the size of `ftype' changes, fix the sscanf call also */ 2583 char ftype[16+1]; 2584 if (sscanf (n->data, "%16s %lu", ftype, 2585 &dev_long) < 2) 2586 error (1, 0, "%s:%s has bad `special' newphrase %s", 2587 finfo->file, rev1, n->data); 2588 rev1_dev = dev_long; 2589 if (strcmp (ftype, "character") == 0) 2590 rev1_mode |= S_IFCHR; 2591 else if (strcmp (ftype, "block") == 0) 2592 rev1_mode |= S_IFBLK; 2593 else 2594 error (0, 0, "%s:%s unknown file type `%s'", 2595 finfo->file, rev1, ftype); 2596 } 2597 2598 n = findnode (vp->other_delta, "hardlinks"); 2599 if (n == NULL) 2600 rev1_hardlinks = xstrdup (""); 2601 else 2602 rev1_hardlinks = xstrdup (n->data); 2603 } 2604 } 2605 2606 /* Obtain file information for REV2. */ 2607 if (rev2 == NULL) 2608 { 2609 if (islink (finfo->file)) 2610 rev2_symlink = xreadlink (finfo->file); 2611 else 2612 { 2613 if (CVS_LSTAT (finfo->file, &sb) < 0) 2614 error (1, errno, "could not get file information for %s", 2615 finfo->file); 2616 rev2_uid = sb.st_uid; 2617 rev2_gid = sb.st_gid; 2618 rev2_mode = sb.st_mode; 2619 if (S_ISBLK (rev2_mode) || S_ISCHR (rev2_mode)) 2620 rev2_dev = sb.st_rdev; 2621 } 2622 rev2_hardlinks = list_files_linked_to (finfo->file); 2623 } 2624 else 2625 { 2626 n = findnode (finfo->rcs->versions, rev2); 2627 vp = (RCSVers *) n->data; 2628 2629 n = findnode (vp->other_delta, "symlink"); 2630 if (n != NULL) 2631 rev2_symlink = xstrdup (n->data); 2632 else 2633 { 2634 n = findnode (vp->other_delta, "owner"); 2635 if (n == NULL) 2636 check_uids = 0; /* don't care */ 2637 else 2638 rev2_uid = strtoul (n->data, NULL, 10); 2639 2640 n = findnode (vp->other_delta, "group"); 2641 if (n == NULL) 2642 check_gids = 0; /* don't care */ 2643 else 2644 rev2_gid = strtoul (n->data, NULL, 10); 2645 2646 n = findnode (vp->other_delta, "permissions"); 2647 if (n == NULL) 2648 check_modes = 0; /* don't care */ 2649 else 2650 rev2_mode = strtoul (n->data, NULL, 8); 2651 2652 n = findnode (vp->other_delta, "special"); 2653 if (n == NULL) 2654 rev2_mode |= S_IFREG; 2655 else 2656 { 2657 /* If the size of `ftype' changes, fix the sscanf call also */ 2658 char ftype[16+1]; 2659 if (sscanf (n->data, "%16s %lu", ftype, 2660 &dev_long) < 2) 2661 error (1, 0, "%s:%s has bad `special' newphrase %s", 2662 finfo->file, rev2, n->data); 2663 rev2_dev = dev_long; 2664 if (strcmp (ftype, "character") == 0) 2665 rev2_mode |= S_IFCHR; 2666 else if (strcmp (ftype, "block") == 0) 2667 rev2_mode |= S_IFBLK; 2668 else 2669 error (0, 0, "%s:%s unknown file type `%s'", 2670 finfo->file, rev2, ftype); 2671 } 2672 2673 n = findnode (vp->other_delta, "hardlinks"); 2674 if (n == NULL) 2675 rev2_hardlinks = xstrdup (""); 2676 else 2677 rev2_hardlinks = xstrdup (n->data); 2678 } 2679 } 2680 2681 /* Check the user/group ownerships and file permissions, printing 2682 an error for each mismatch found. Return 0 if all characteristics 2683 matched, and 1 otherwise. */ 2684 2685 result = 0; 2686 2687 /* Compare symlinks first, since symlinks are simpler (don't have 2688 any other characteristics). */ 2689 if (rev1_symlink != NULL && rev2_symlink == NULL) 2690 { 2691 error (0, 0, "%s is a symbolic link", 2692 (rev1 == NULL ? "working file" : rev1)); 2693 result = 1; 2694 } 2695 else if (rev1_symlink == NULL && rev2_symlink != NULL) 2696 { 2697 error (0, 0, "%s is a symbolic link", 2698 (rev2 == NULL ? "working file" : rev2)); 2699 result = 1; 2700 } 2701 else if (rev1_symlink != NULL) 2702 result = (strcmp (rev1_symlink, rev2_symlink) == 0); 2703 else 2704 { 2705 /* Compare user ownership. */ 2706 if (check_uids && rev1_uid != rev2_uid) 2707 { 2708 error (0, 0, "%s: owner mismatch between %s and %s", 2709 finfo->file, 2710 (rev1 == NULL ? "working file" : rev1), 2711 (rev2 == NULL ? "working file" : rev2)); 2712 result = 1; 2713 } 2714 2715 /* Compare group ownership. */ 2716 if (check_gids && rev1_gid != rev2_gid) 2717 { 2718 error (0, 0, "%s: group mismatch between %s and %s", 2719 finfo->file, 2720 (rev1 == NULL ? "working file" : rev1), 2721 (rev2 == NULL ? "working file" : rev2)); 2722 result = 1; 2723 } 2724 2725 /* Compare permissions. */ 2726 if (check_modes && 2727 (rev1_mode & 07777) != (rev2_mode & 07777)) 2728 { 2729 error (0, 0, "%s: permission mismatch between %s and %s", 2730 finfo->file, 2731 (rev1 == NULL ? "working file" : rev1), 2732 (rev2 == NULL ? "working file" : rev2)); 2733 result = 1; 2734 } 2735 2736 /* Compare device file characteristics. */ 2737 if ((rev1_mode & S_IFMT) != (rev2_mode & S_IFMT)) 2738 { 2739 error (0, 0, "%s: %s and %s are different file types", 2740 finfo->file, 2741 (rev1 == NULL ? "working file" : rev1), 2742 (rev2 == NULL ? "working file" : rev2)); 2743 result = 1; 2744 } 2745 else if (S_ISBLK (rev1_mode)) 2746 { 2747 if (rev1_dev != rev2_dev) 2748 { 2749 error (0, 0, "%s: device numbers of %s and %s do not match", 2750 finfo->file, 2751 (rev1 == NULL ? "working file" : rev1), 2752 (rev2 == NULL ? "working file" : rev2)); 2753 result = 1; 2754 } 2755 } 2756 2757 /* Compare hard links. */ 2758 if (strcmp (rev1_hardlinks, rev2_hardlinks) != 0) 2759 { 2760 error (0, 0, "%s: hard linkage of %s and %s do not match", 2761 finfo->file, 2762 (rev1 == NULL ? "working file" : rev1), 2763 (rev2 == NULL ? "working file" : rev2)); 2764 result = 1; 2765 } 2766 } 2767 2768 if (rev1_symlink != NULL) 2769 free (rev1_symlink); 2770 if (rev2_symlink != NULL) 2771 free (rev2_symlink); 2772 if (rev1_hardlinks != NULL) 2773 free (rev1_hardlinks); 2774 if (rev2_hardlinks != NULL) 2775 free (rev2_hardlinks); 2776 2777 return result; 2778 #else 2779 return 0; 2780 #endif 2781 } 2782 2783 int 2784 joining () 2785 { 2786 return (join_rev1 != NULL); 2787 } 2788