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