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