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