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