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