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