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