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