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