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