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