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