checkout.c revision 25839
1/* 2 * Copyright (c) 1992, Brian Berliner and Jeff Polk 3 * Copyright (c) 1989-1992, Brian Berliner 4 * 5 * You may distribute under the terms of the GNU General Public License as 6 * specified in the README file that comes with the CVS 1.4 kit. 7 * 8 * Create Version 9 * 10 * "checkout" creates a "version" of an RCS repository. This version is owned 11 * totally by the user and is actually an independent copy, to be dealt with 12 * as seen fit. Once "checkout" has been called in a given directory, it 13 * never needs to be called again. The user can keep up-to-date by calling 14 * "update" when he feels like it; this will supply him with a merge of his 15 * own modifications and the changes made in the RCS original. See "update" 16 * for details. 17 * 18 * "checkout" can be given a list of directories or files to be updated and in 19 * the case of a directory, will recursivley create any sub-directories that 20 * exist in the repository. 21 * 22 * When the user is satisfied with his own modifications, the present version 23 * can be committed by "commit"; this keeps the present version in tact, 24 * usually. 25 * 26 * The call is cvs checkout [options] <module-name>... 27 * 28 * "checkout" creates a directory ./CVS, in which it keeps its administration, 29 * in two files, Repository and Entries. The first contains the name of the 30 * repository. The second contains one line for each registered file, 31 * consisting of the version number it derives from, its time stamp at 32 * derivation time and its name. Both files are normal files and can be 33 * edited by the user, if necessary (when the repository is moved, e.g.) 34 */ 35 36#include "cvs.h" 37 38static char *findslash PROTO((char *start, char *p)); 39static int checkout_proc PROTO((int *pargc, char **argv, char *where, 40 char *mwhere, char *mfile, int shorten, 41 int local_specified, char *omodule, 42 char *msg)); 43static int safe_location PROTO((void)); 44 45static const char *const checkout_usage[] = 46{ 47 "Usage:\n %s %s [-ANPRcflnps] [-r rev | -D date] [-d dir]\n", 48 " [-j rev1] [-j rev2] [-k kopt] modules...\n", 49 "\t-A\tReset any sticky tags/date/kopts.\n", 50 "\t-N\tDon't shorten module paths if -d specified.\n", 51 "\t-P\tPrune empty directories.\n", 52 "\t-R\tProcess directories recursively.\n", 53 "\t-c\t\"cat\" the module database.\n", 54 "\t-f\tForce a head revision match if tag/date not found.\n", 55 "\t-l\tLocal directory only, not recursive\n", 56 "\t-n\tDo not run module program (if any).\n", 57 "\t-p\tCheck out files to standard output (avoids stickiness).\n", 58 "\t-s\tLike -c, but include module status.\n", 59 "\t-r rev\tCheck out revision or tag. (implies -P) (is sticky)\n", 60 "\t-D date\tCheck out revisions as of date. (implies -P) (is sticky)\n", 61 "\t-d dir\tCheck out into dir instead of module name.\n", 62 "\t-k kopt\tUse RCS kopt -k option on checkout.\n", 63 "\t-j rev\tMerge in changes made between current revision and rev.\n", 64 NULL 65}; 66 67static const char *const export_usage[] = 68{ 69 "Usage: %s %s [-NRfln] [-r rev | -D date] [-d dir] [-k kopt] module...\n", 70 "\t-N\tDon't shorten module paths if -d specified.\n", 71 "\t-f\tForce a head revision match if tag/date not found.\n", 72 "\t-l\tLocal directory only, not recursive\n", 73 "\t-R\tProcess directories recursively (default).\n", 74 "\t-n\tDo not run module program (if any).\n", 75 "\t-r rev\tExport revision or tag.\n", 76 "\t-D date\tExport revisions as of date.\n", 77 "\t-d dir\tExport into dir instead of module name.\n", 78 "\t-k kopt\tUse RCS kopt -k option on checkout.\n", 79 NULL 80}; 81 82static int checkout_prune_dirs; 83static int force_tag_match = 1; 84static int pipeout; 85static int aflag; 86static char *options = NULL; 87static char *tag = NULL; 88static int tag_validated = 0; 89static char *date = NULL; 90static char *join_rev1 = NULL; 91static char *join_rev2 = NULL; 92static int join_tags_validated = 0; 93static char *preload_update_dir = NULL; 94static char *history_name = NULL; 95 96int 97checkout (argc, argv) 98 int argc; 99 char **argv; 100{ 101 int i; 102 int c; 103 DBM *db; 104 int cat = 0, err = 0, status = 0; 105 int run_module_prog = 1; 106 int local = 0; 107 int shorten = -1; 108 char *where = NULL; 109 char *valid_options; 110 const char *const *valid_usage; 111 enum mtype m_type; 112 113 /* 114 * A smaller subset of options are allowed for the export command, which 115 * is essentially like checkout, except that it hard-codes certain 116 * options to be default (like -kv) and takes care to remove the CVS 117 * directory when it has done its duty 118 */ 119 if (strcmp (command_name, "export") == 0) 120 { 121 m_type = EXPORT; 122 valid_options = "+Nnk:d:flRQqr:D:"; 123 valid_usage = export_usage; 124 } 125 else 126 { 127 m_type = CHECKOUT; 128 valid_options = "+ANnk:d:flRpQqcsr:D:j:P"; 129 valid_usage = checkout_usage; 130 } 131 132 if (argc == -1) 133 usage (valid_usage); 134 135 ign_setup (); 136 wrap_setup (); 137 138 optind = 1; 139 while ((c = getopt (argc, argv, valid_options)) != -1) 140 { 141 switch (c) 142 { 143 case 'A': 144 aflag = 1; 145 break; 146 case 'N': 147 shorten = 0; 148 break; 149 case 'k': 150 if (options) 151 free (options); 152 options = RCS_check_kflag (optarg); 153 break; 154 case 'n': 155 run_module_prog = 0; 156 break; 157 case 'Q': 158 case 'q': 159#ifdef SERVER_SUPPORT 160 /* The CVS 1.5 client sends these options (in addition to 161 Global_option requests), so we must ignore them. */ 162 if (!server_active) 163#endif 164 error (1, 0, 165 "-q or -Q must be specified before \"%s\"", 166 command_name); 167 break; 168 case 'l': 169 local = 1; 170 break; 171 case 'R': 172 local = 0; 173 break; 174 case 'P': 175 checkout_prune_dirs = 1; 176 break; 177 case 'p': 178 pipeout = 1; 179 run_module_prog = 0; /* don't run module prog when piping */ 180 noexec = 1; /* so no locks will be created */ 181 break; 182 case 'c': 183 cat = 1; 184 break; 185 case 'd': 186 where = optarg; 187 if (shorten == -1) 188 shorten = 1; 189 break; 190 case 's': 191 status = 1; 192 break; 193 case 'f': 194 force_tag_match = 0; 195 break; 196 case 'r': 197 tag = optarg; 198 checkout_prune_dirs = 1; 199 break; 200 case 'D': 201 date = Make_Date (optarg); 202 checkout_prune_dirs = 1; 203 break; 204 case 'j': 205 if (join_rev2) 206 error (1, 0, "only two -j options can be specified"); 207 if (join_rev1) 208 join_rev2 = optarg; 209 else 210 join_rev1 = optarg; 211 break; 212 case '?': 213 default: 214 usage (valid_usage); 215 break; 216 } 217 } 218 argc -= optind; 219 argv += optind; 220 221 if (shorten == -1) 222 shorten = 0; 223 224 if ((!(cat + status) && argc == 0) || ((cat + status) && argc != 0)) 225 usage (valid_usage); 226 227 if (where && pipeout) 228 error (1, 0, "-d and -p are mutually exclusive"); 229 230 if (strcmp (command_name, "export") == 0) 231 { 232 if (!tag && !date) 233 { 234 error (0, 0, "must specify a tag or date"); 235 usage (valid_usage); 236 } 237 if (tag && isdigit (tag[0])) 238 error (1, 0, "tag `%s' must be a symbolic tag", tag); 239/* 240 * mhy 950615: -kv doesn't work for binaries with RCS keywords. 241 * Instead use the default provided in the RCS file (-ko for binaries). 242 */ 243#if 0 244 if (!options) 245 options = RCS_check_kflag ("v");/* -kv is default */ 246#endif 247 } 248 249 if (!safe_location()) { 250 error(1, 0, "Cannot check out files into the repository itself"); 251 } 252 253#ifdef CLIENT_SUPPORT 254 if (client_active) 255 { 256 int expand_modules; 257 258 start_server (); 259 260 ign_setup (); 261 262 /* We have to expand names here because the "expand-modules" 263 directive to the server has the side-effect of having the 264 server send the check-in and update programs for the 265 various modules/dirs requested. If we turn this off and 266 simply request the names of the modules and directories (as 267 below in !expand_modules), those files (CVS/Checking.prog 268 or CVS/Update.prog) don't get created. Grrr. */ 269 270 expand_modules = (!cat && !status && !pipeout 271 && supported_request ("expand-modules")); 272 273 if (expand_modules) 274 { 275 /* This is done here because we need to read responses 276 from the server before we send the command checkout or 277 export files. */ 278 279 client_expand_modules (argc, argv, local); 280 } 281 282 if (!run_module_prog) send_arg ("-n"); 283 if (local) send_arg ("-l"); 284 if (pipeout) send_arg ("-p"); 285 if (!force_tag_match) send_arg ("-f"); 286 if (aflag) 287 send_arg("-A"); 288 if (!shorten) 289 send_arg("-N"); 290 if (checkout_prune_dirs && strcmp (command_name, "export") != 0) 291 send_arg("-P"); 292 client_prune_dirs = checkout_prune_dirs; 293 if (cat) 294 send_arg("-c"); 295 if (where != NULL) 296 { 297 option_with_arg ("-d", where); 298 } 299 if (status) 300 send_arg("-s"); 301 /* Why not send -k for export? This would appear to make 302 remote export differ from local export. FIXME. */ 303 if (strcmp (command_name, "export") != 0 304 && options != NULL 305 && options[0] != '\0') 306 send_arg (options); 307 option_with_arg ("-r", tag); 308 if (date) 309 client_senddate (date); 310 if (join_rev1 != NULL) 311 option_with_arg ("-j", join_rev1); 312 if (join_rev2 != NULL) 313 option_with_arg ("-j", join_rev2); 314 315 if (expand_modules) 316 { 317 client_send_expansions (local, where, 1); 318 } 319 else 320 { 321 int i; 322 for (i = 0; i < argc; ++i) 323 send_arg (argv[i]); 324 client_nonexpanded_setup (); 325 } 326 327 send_to_server (strcmp (command_name, "export") == 0 ? 328 "export\012" : "co\012", 329 0); 330 331 return get_responses_and_close (); 332 } 333#endif /* CLIENT_SUPPORT */ 334 335 if (cat || status) 336 { 337 cat_module (status); 338 return (0); 339 } 340 db = open_module (); 341 342 /* 343 * if we have more than one argument and where was specified, we make the 344 * where, cd into it, and try to shorten names as much as possible. 345 * Otherwise, we pass the where as a single argument to do_module. 346 */ 347 if (argc > 1 && where != NULL) 348 { 349 (void) CVS_MKDIR (where, 0777); 350 if ( CVS_CHDIR (where) < 0) 351 error (1, errno, "cannot chdir to %s", where); 352 preload_update_dir = xstrdup (where); 353 where = (char *) NULL; 354 if (!isfile (CVSADM)) 355 { 356 char *repository; 357 358 repository = xmalloc (strlen (CVSroot_directory) + 80); 359 (void) sprintf (repository, "%s/%s/%s", CVSroot_directory, 360 CVSROOTADM, CVSNULLREPOS); 361 if (!isfile (repository)) 362 { 363 mode_t omask; 364 omask = umask (cvsumask); 365 (void) CVS_MKDIR (repository, 0777); 366 (void) umask (omask); 367 } 368 369 /* I'm not sure whether this check is redundant. */ 370 if (!isdir (repository)) 371 error (1, 0, "there is no repository %s", repository); 372 373 Create_Admin (".", preload_update_dir, repository, 374 (char *) NULL, (char *) NULL, 0); 375 if (!noexec) 376 { 377 FILE *fp; 378 379 fp = open_file (CVSADM_ENTSTAT, "w+"); 380 if (fclose(fp) == EOF) 381 error(1, errno, "cannot close %s", CVSADM_ENTSTAT); 382#ifdef SERVER_SUPPORT 383 if (server_active) 384 server_set_entstat (preload_update_dir, repository); 385#endif 386 } 387 free (repository); 388 } 389 } 390 391 /* If we will be calling history_write, work out the name to pass 392 it. */ 393 if (strcmp (command_name, "export") != 0 && !pipeout) 394 { 395 if (tag && date) 396 { 397 history_name = xmalloc (strlen (tag) + strlen (date) + 2); 398 sprintf (history_name, "%s:%s", tag, date); 399 } 400 else if (tag) 401 history_name = tag; 402 else 403 history_name = date; 404 } 405 406 /* 407 * if where was specified (-d) and we have not taken care of it already 408 * with the multiple arg stuff, and it was not a simple directory name 409 * but rather a path, we strip off everything but the last component and 410 * attempt to cd to the indicated place. where then becomes simply the 411 * last component 412 */ 413 if (where != NULL && strchr (where, '/') != NULL) 414 { 415 char *slash; 416 417 slash = strrchr (where, '/'); 418 *slash = '\0'; 419 420 if ( CVS_CHDIR (where) < 0) 421 error (1, errno, "cannot chdir to %s", where); 422 423 preload_update_dir = xstrdup (where); 424 425 where = slash + 1; 426 if (*where == '\0') 427 where = NULL; 428 } 429 430 for (i = 0; i < argc; i++) 431 err += do_module (db, argv[i], m_type, "Updating", checkout_proc, 432 where, shorten, local, run_module_prog, 433 (char *) NULL); 434 close_module (db); 435 return (err); 436} 437 438static int 439safe_location () 440{ 441 char *current; 442 char hardpath[PATH_MAX+5]; 443 size_t hardpath_len; 444 int x; 445 int retval; 446 447#ifdef HAVE_READLINK 448 /* FIXME-arbitrary limit: should be retrying this like xgetwd. 449 But how does readlink let us know that the buffer was too small? 450 (by returning sizeof hardpath - 1?). */ 451 x = readlink(CVSroot_directory, hardpath, sizeof hardpath - 1); 452#else 453 x = -1; 454#endif 455 if (x == -1) 456 { 457 strcpy(hardpath, CVSroot_directory); 458 } 459 else 460 { 461 hardpath[x] = '\0'; 462 } 463 current = xgetwd (); 464 hardpath_len = strlen (hardpath); 465 if (strlen (current) >= hardpath_len 466 && strncmp (current, hardpath, hardpath_len) == 0) 467 { 468 if (/* Current is a subdirectory of hardpath. */ 469 current[hardpath_len] == '/' 470 471 /* Current is hardpath itself. */ 472 || current[hardpath_len] == '\0') 473 retval = 0; 474 else 475 /* It isn't a problem. For example, current is 476 "/foo/cvsroot-bar" and hardpath is "/foo/cvsroot". */ 477 retval = 1; 478 } 479 else 480 retval = 1; 481 free (current); 482 return retval; 483} 484 485struct dir_to_build 486{ 487 /* What to put in CVS/Repository. */ 488 char *repository; 489 /* The path to the directory. */ 490 char *dirpath; 491 492 struct dir_to_build *next; 493}; 494 495static int build_dirs_and_chdir PROTO ((struct dir_to_build *list, 496 int sticky)); 497 498static void build_one_dir PROTO ((char *, char *, int)); 499 500static void 501build_one_dir (repository, dirpath, sticky) 502 char *repository; 503 char *dirpath; 504 int sticky; 505{ 506 FILE *fp; 507 508 if (!isfile (CVSADM) && strcmp (command_name, "export") != 0) 509 { 510 /* I suspect that this check could be omitted. */ 511 if (!isdir (repository)) 512 error (1, 0, "there is no repository %s", repository); 513 514 Create_Admin (".", dirpath, repository, 515 sticky ? (char *) NULL : tag, 516 sticky ? (char *) NULL : date, 517 518 /* FIXME? This is a guess. If it is important 519 for nonbranch to be set correctly here I 520 think we need to write it one way now and 521 then rewrite it later via WriteTag, once 522 we've had a chance to call RCS_nodeisbranch 523 on each file. */ 524 0); 525 526 if (!noexec) 527 { 528 fp = open_file (CVSADM_ENTSTAT, "w+"); 529 if (fclose (fp) == EOF) 530 error (1, errno, "cannot close %s", CVSADM_ENTSTAT); 531#ifdef SERVER_SUPPORT 532 if (server_active) 533 server_set_entstat (dirpath, repository); 534#endif 535 } 536 } 537} 538 539/* 540 * process_module calls us back here so we do the actual checkout stuff 541 */ 542/* ARGSUSED */ 543static int 544checkout_proc (pargc, argv, where, mwhere, mfile, shorten, 545 local_specified, omodule, msg) 546 int *pargc; 547 char **argv; 548 char *where; 549 char *mwhere; 550 char *mfile; 551 int shorten; 552 int local_specified; 553 char *omodule; 554 char *msg; 555{ 556 int err = 0; 557 int which; 558 char *cp; 559 char *cp2; 560 char *repository; 561 char *xwhere = NULL; 562 char *oldupdate = NULL; 563 char *prepath; 564 565 /* 566 * OK, so we're doing the checkout! Our args are as follows: 567 * argc,argv contain either dir or dir followed by a list of files 568 * where contains where to put it (if supplied by checkout) 569 * mwhere contains the module name or -d from module file 570 * mfile says do only that part of the module 571 * shorten = TRUE says shorten as much as possible 572 * omodule is the original arg to do_module() 573 */ 574 575 /* set up the repository (maybe) for the bottom directory */ 576 repository = xmalloc (strlen (CVSroot_directory) + strlen (argv[0]) + 5); 577 (void) sprintf (repository, "%s/%s", CVSroot_directory, argv[0]); 578 579 /* save the original value of preload_update_dir */ 580 if (preload_update_dir != NULL) 581 oldupdate = xstrdup (preload_update_dir); 582 583 /* fix up argv[] for the case of partial modules */ 584 if (mfile != NULL) 585 { 586 char *file; 587 588 /* if mfile is really a path, straighten it out first */ 589 if ((cp = strrchr (mfile, '/')) != NULL) 590 { 591 *cp = 0; 592 repository = xrealloc (repository, 593 strlen (repository) + strlen (mfile) + 10); 594 (void) strcat (repository, "/"); 595 (void) strcat (repository, mfile); 596 597 /* 598 * Now we need to fill in the where correctly. if !shorten, tack 599 * the rest of the path onto where if where is filled in 600 * otherwise tack the rest of the path onto mwhere and make that 601 * the where 602 * 603 * If shorten is enabled, we might use mwhere to set where if 604 * nobody set it yet, so we'll need to setup mwhere as the last 605 * component of the path we are tacking onto repository 606 */ 607 if (!shorten) 608 { 609 if (where != NULL) 610 { 611 xwhere = xmalloc (strlen (where) + strlen (mfile) + 5); 612 (void) sprintf (xwhere, "%s/%s", where, mfile); 613 } 614 else 615 { 616 xwhere = xmalloc (strlen (mwhere) + strlen (mfile) + 5); 617 (void) sprintf (xwhere, "%s/%s", mwhere, mfile); 618 } 619 where = xwhere; 620 } 621 else 622 { 623 char *slash; 624 625 if ((slash = strrchr (mfile, '/')) != NULL) 626 mwhere = slash + 1; 627 else 628 mwhere = mfile; 629 } 630 mfile = cp + 1; 631 } 632 633 file = xmalloc (strlen (repository) + strlen (mfile) + 5); 634 (void) sprintf (file, "%s/%s", repository, mfile); 635 if (isdir (file)) 636 { 637 638 /* 639 * The portion of a module was a directory, so kludge up where to 640 * be the subdir, and fix up repository 641 */ 642 free (repository); 643 repository = xstrdup (file); 644 645 /* 646 * At this point, if shorten is not enabled, we make where either 647 * where with mfile concatenated, or if where hadn't been set we 648 * set it to mwhere with mfile concatenated. 649 * 650 * If shorten is enabled and where hasn't been set yet, then where 651 * becomes mfile 652 */ 653 if (!shorten) 654 { 655 if (where != NULL) 656 { 657 xwhere = xmalloc (strlen (where) + strlen (mfile) + 5); 658 (void) sprintf (xwhere, "%s/%s", where, mfile); 659 } 660 else 661 { 662 xwhere = xmalloc (strlen (mwhere) + strlen (mfile) + 5); 663 (void) sprintf (xwhere, "%s/%s", mwhere, mfile); 664 } 665 where = xwhere; 666 } 667 else if (where == NULL) 668 where = mfile; 669 } 670 else 671 { 672 int i; 673 674 /* 675 * The portion of a module was a file, so kludge up argv to be 676 * correct 677 */ 678 for (i = 1; i < *pargc; i++)/* free the old ones */ 679 free (argv[i]); 680 /* FIXME: Normally one has to realloc argv to make sure 681 argv[1] exists. But this argv does not points to the 682 beginning of an allocated block. For now we allocate 683 at least 4 entries for argv (in line2argv). */ 684 argv[1] = xstrdup (mfile); /* set up the new one */ 685 *pargc = 2; 686 687 /* where gets mwhere if where isn't set */ 688 if (where == NULL) 689 where = mwhere; 690 } 691 free (file); 692 } 693 694 /* 695 * if shorten is enabled and where isn't specified yet, we pluck the last 696 * directory component of argv[0] and make it the where 697 */ 698 if (shorten && where == NULL) 699 { 700 if ((cp = strrchr (argv[0], '/')) != NULL) 701 { 702 xwhere = xstrdup (cp + 1); 703 where = xwhere; 704 } 705 } 706 707 /* if where is still NULL, use mwhere if set or the argv[0] dir */ 708 if (where == NULL) 709 { 710 if (mwhere) 711 where = mwhere; 712 else 713 { 714 xwhere = xstrdup (argv[0]); 715 where = xwhere; 716 } 717 } 718 719 if (preload_update_dir != NULL) 720 { 721 preload_update_dir = 722 xrealloc (preload_update_dir, 723 strlen (preload_update_dir) + strlen (where) + 5); 724 strcat (preload_update_dir, "/"); 725 strcat (preload_update_dir, where); 726 } 727 else 728 preload_update_dir = xstrdup (where); 729 730 /* 731 * At this point, where is the directory we want to build, repository is 732 * the repository for the lowest level of the path. 733 */ 734 735 /* 736 * If we are sending everything to stdout, we can skip a whole bunch of 737 * work from here 738 */ 739 if (!pipeout) 740 { 741 size_t root_len; 742 struct dir_to_build *head; 743 744 /* We need to tell build_dirs not only the path we want it to 745 build, but also the repositories we want it to populate the 746 path with. To accomplish this, we walk the path backwards, 747 one pathname component at a time, constucting a linked 748 list of struct dir_to_build. */ 749 prepath = xstrdup (repository); 750 751 /* We don't want to start stripping elements off prepath after we 752 get to CVSROOT. */ 753 root_len = strlen (CVSroot_directory); 754 if (strncmp (repository, CVSroot_directory, root_len) != 0) 755 error (1, 0, "\ 756internal error: %s doesn't start with %s in checkout_proc", 757 repository, CVSroot_directory); 758 759 /* We always create at least one directory, which corresponds to 760 the entire strings for WHERE and REPOSITORY. */ 761 head = (struct dir_to_build *) xmalloc (sizeof (struct dir_to_build)); 762 /* Special marker to indicate that we don't want build_dirs_and_chdir 763 to create the CVSADM directory for us. */ 764 head->repository = NULL; 765 head->dirpath = xstrdup (where); 766 head->next = NULL; 767 768 cp = strrchr (where, '/'); 769 cp2 = strrchr (prepath, '/'); 770 771 while (cp != NULL) 772 { 773 struct dir_to_build *new; 774 new = (struct dir_to_build *) 775 xmalloc (sizeof (struct dir_to_build)); 776 new->dirpath = xmalloc (strlen (where)); 777 strncpy (new->dirpath, where, cp - where); 778 new->dirpath[cp - where] = '\0'; 779 if (cp2 == NULL || cp2 < prepath + root_len) 780 { 781 /* Don't walk up past CVSROOT; instead put in CVSNULLREPOS. */ 782 new->repository = 783 xmalloc (strlen (CVSroot_directory) + 80); 784 (void) sprintf (new->repository, "%s/%s/%s", 785 CVSroot_directory, 786 CVSROOTADM, CVSNULLREPOS); 787 if (!isfile (new->repository)) 788 { 789 mode_t omask; 790 omask = umask (cvsumask); 791 if (CVS_MKDIR (new->repository, 0777) < 0) 792 error (0, errno, "cannot create %s", 793 new->repository); 794 (void) umask (omask); 795 } 796 } 797 else 798 { 799 new->repository = xmalloc (strlen (prepath)); 800 strncpy (new->repository, prepath, cp2 - prepath); 801 new->repository[cp2 - prepath] = '\0'; 802 } 803 new->next = head; 804 head = new; 805 806 cp = findslash (where, cp - 1); 807 cp2 = findslash (prepath, cp2 - 1); 808 } 809 810 /* First build the top-level CVSADM directory. The value we 811 pass in here for repository is probably wrong; see modules3-7f 812 in the testsuite. */ 813 build_one_dir (head->repository != NULL ? head->repository : prepath, 814 ".", *pargc <= 1); 815 816 /* 817 * build dirs on the path if necessary and leave us in the bottom 818 * directory (where if where was specified) doesn't contain a CVS 819 * subdir yet, but all the others contain CVS and Entries.Static 820 * files 821 */ 822 if (build_dirs_and_chdir (head, *pargc <= 1) != 0) 823 { 824 error (0, 0, "ignoring module %s", omodule); 825 free (prepath); 826 err = 1; 827 goto out; 828 } 829 830 /* clean up */ 831 free (prepath); 832 833 /* set up the repository (or make sure the old one matches) */ 834 if (!isfile (CVSADM)) 835 { 836 FILE *fp; 837 838 if (!noexec && *pargc > 1) 839 { 840 /* I'm not sure whether this check is redundant. */ 841 if (!isdir (repository)) 842 error (1, 0, "there is no repository %s", repository); 843 844 Create_Admin (".", preload_update_dir, repository, 845 (char *) NULL, (char *) NULL, 0); 846 fp = open_file (CVSADM_ENTSTAT, "w+"); 847 if (fclose(fp) == EOF) 848 error(1, errno, "cannot close %s", CVSADM_ENTSTAT); 849#ifdef SERVER_SUPPORT 850 if (server_active) 851 server_set_entstat (where, repository); 852#endif 853 } 854 else 855 { 856 /* I'm not sure whether this check is redundant. */ 857 if (!isdir (repository)) 858 error (1, 0, "there is no repository %s", repository); 859 860 Create_Admin (".", preload_update_dir, repository, tag, date, 861 862 /* FIXME? This is a guess. If it is important 863 for nonbranch to be set correctly here I 864 think we need to write it one way now and 865 then rewrite it later via WriteTag, once 866 we've had a chance to call RCS_nodeisbranch 867 on each file. */ 868 0); 869 } 870 } 871 else 872 { 873 char *repos; 874 875 /* get the contents of the previously existing repository */ 876 repos = Name_Repository ((char *) NULL, preload_update_dir); 877 if (fncmp (repository, repos) != 0) 878 { 879 error (0, 0, "existing repository %s does not match %s", 880 repos, repository); 881 error (0, 0, "ignoring module %s", omodule); 882 free (repos); 883 err = 1; 884 goto out; 885 } 886 free (repos); 887 } 888 } 889 890 /* 891 * If we are going to be updating to stdout, we need to cd to the 892 * repository directory so the recursion processor can use the current 893 * directory as the place to find repository information 894 */ 895 if (pipeout) 896 { 897 if ( CVS_CHDIR (repository) < 0) 898 { 899 error (0, errno, "cannot chdir to %s", repository); 900 err = 1; 901 goto out; 902 } 903 which = W_REPOS; 904 if (tag != NULL && !tag_validated) 905 { 906 tag_check_valid (tag, *pargc - 1, argv + 1, 0, aflag, NULL); 907 tag_validated = 1; 908 } 909 } 910 else 911 { 912 which = W_LOCAL | W_REPOS; 913 if (tag != NULL && !tag_validated) 914 { 915 tag_check_valid (tag, *pargc - 1, argv + 1, 0, aflag, 916 repository); 917 tag_validated = 1; 918 } 919 } 920 921 if (tag != NULL || date != NULL || join_rev1 != NULL) 922 which |= W_ATTIC; 923 924 if (! join_tags_validated) 925 { 926 if (join_rev1 != NULL) 927 tag_check_valid_join (join_rev1, *pargc - 1, argv + 1, 0, aflag, 928 repository); 929 if (join_rev2 != NULL) 930 tag_check_valid_join (join_rev2, *pargc - 1, argv + 1, 0, aflag, 931 repository); 932 join_tags_validated = 1; 933 } 934 935 /* 936 * if we are going to be recursive (building dirs), go ahead and call the 937 * update recursion processor. We will be recursive unless either local 938 * only was specified, or we were passed arguments 939 */ 940 if (!(local_specified || *pargc > 1)) 941 { 942 if (strcmp (command_name, "export") != 0 && !pipeout) 943 history_write ('O', preload_update_dir, history_name, where, 944 repository); 945 else if (strcmp (command_name, "export") == 0 && !pipeout) 946 history_write ('E', preload_update_dir, tag ? tag : date, where, 947 repository); 948 err += do_update (0, (char **) NULL, options, tag, date, 949 force_tag_match, 0 /* !local */ , 950 1 /* update -d */ , aflag, checkout_prune_dirs, 951 pipeout, which, join_rev1, join_rev2, 952 preload_update_dir); 953 goto out; 954 } 955 956 if (!pipeout) 957 { 958 int i; 959 List *entries; 960 961 /* we are only doing files, so register them */ 962 entries = Entries_Open (0); 963 for (i = 1; i < *pargc; i++) 964 { 965 char *line; 966 Vers_TS *vers; 967 struct file_info finfo; 968 969 memset (&finfo, 0, sizeof finfo); 970 finfo.file = argv[i]; 971 /* Shouldn't be used, so set to arbitrary value. */ 972 finfo.update_dir = NULL; 973 finfo.fullname = argv[i]; 974 finfo.repository = repository; 975 finfo.entries = entries; 976 /* The rcs slot is needed to get the options from the RCS 977 file */ 978 finfo.rcs = RCS_parse (finfo.file, repository); 979 980 vers = Version_TS (&finfo, options, tag, date, 981 force_tag_match, 0); 982 if (vers->ts_user == NULL) 983 { 984 line = xmalloc (strlen (finfo.file) + 15); 985 (void) sprintf (line, "Initial %s", finfo.file); 986 Register (entries, finfo.file, 987 vers->vn_rcs ? vers->vn_rcs : "0", 988 line, vers->options, vers->tag, 989 vers->date, (char *) 0); 990 free (line); 991 } 992 freevers_ts (&vers); 993 freercsnode (&finfo.rcs); 994 } 995 996 Entries_Close (entries); 997 } 998 999 /* Don't log "export", just regular "checkouts" */ 1000 if (strcmp (command_name, "export") != 0 && !pipeout) 1001 history_write ('O', preload_update_dir, history_name, where, 1002 repository); 1003 1004 /* go ahead and call update now that everything is set */ 1005 err += do_update (*pargc - 1, argv + 1, options, tag, date, 1006 force_tag_match, local_specified, 1 /* update -d */, 1007 aflag, checkout_prune_dirs, pipeout, which, join_rev1, 1008 join_rev2, preload_update_dir); 1009out: 1010 free (preload_update_dir); 1011 preload_update_dir = oldupdate; 1012 if (xwhere != NULL) 1013 free (xwhere); 1014 free (repository); 1015 return (err); 1016} 1017 1018static char * 1019findslash (start, p) 1020 char *start; 1021 char *p; 1022{ 1023 while (p >= start && *p != '/') 1024 p--; 1025 /* FIXME: indexing off the start of the array like this is *NOT* 1026 OK according to ANSI, and will break some of the time on certain 1027 segmented architectures. */ 1028 if (p < start) 1029 return (NULL); 1030 else 1031 return (p); 1032} 1033 1034/* Build all the dirs along the path to DIRS with CVS subdirs with appropriate 1035 repositories. If ->repository is NULL, do not create a CVSADM directory 1036 for that subdirectory; just CVS_CHDIR into it. */ 1037static int 1038build_dirs_and_chdir (dirs, sticky) 1039 struct dir_to_build *dirs; 1040 int sticky; 1041{ 1042 int retval = 0; 1043 struct dir_to_build *nextdir; 1044 1045 while (dirs != NULL) 1046 { 1047 char *dir = last_component (dirs->dirpath); 1048 1049 mkdir_if_needed (dir); 1050 Subdir_Register (NULL, NULL, dir); 1051 if (CVS_CHDIR (dir) < 0) 1052 { 1053 error (0, errno, "cannot chdir to %s", dir); 1054 retval = 1; 1055 goto out; 1056 } 1057 if (dirs->repository != NULL) 1058 { 1059 build_one_dir (dirs->repository, dirs->dirpath, sticky); 1060 free (dirs->repository); 1061 } 1062 nextdir = dirs->next; 1063 free (dirs->dirpath); 1064 free (dirs); 1065 dirs = nextdir; 1066 } 1067 1068 out: 1069 return retval; 1070} 1071