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