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