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