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