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