2 * Copyright (c) 1992, Brian Berliner and Jeff Polk
3 * Copyright (c) 1989-1992, Brian Berliner
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.
8 * "import" checks in the vendor release located in the current directory into
9 * the CVS source repository. The CVS vendor branch support is utilized.
11 * At least three arguments are expected to follow the options:
12 * repository Where the source belongs relative to the CVSROOT
13 * VendorTag Vendor's major tag
14 * VendorReleTag Tag for this particular release
16 * Additional arguments specify more Vendor Release Tags.
25 static char *get_comment PROTO((const char *user));
26 static int add_rev PROTO((char *message, RCSNode *rcs, char *vfile,
28 static int add_tags PROTO((RCSNode *rcs, char *vfile, char *vtag, int targc,
30 static int import_descend PROTO((char *message, char *vtag, int targc, char *targv[]));
31 static int import_descend_dir PROTO((char *message, char *dir, char *vtag,
32 int targc, char *targv[]));
33 static int process_import_file PROTO((char *message, char *vfile, char *vtag,
34 int targc, char *targv[]));
35 static int update_rcs_file PROTO((char *message, char *vfile, char *vtag, int targc,
36 char *targv[], int inattic));
37 static void add_log PROTO((int ch, char *fname));
43 static char *repository;
45 static int use_file_modtime;
46 static char *keyword_opt = NULL;
48 static const char *const import_usage[] =
50 "Usage: %s %s [-d] [-k subst] [-I ign] [-m msg] [-b branch]\n",
51 " [-W spec] repository vendor-tag release-tags...\n",
52 "\t-d\tUse the file's modification time as the time of import.\n",
53 "\t-k sub\tSet default RCS keyword substitution mode.\n",
54 "\t-I ign\tMore files to ignore (! to reset).\n",
55 "\t-b bra\tVendor branch id.\n",
56 "\t-m msg\tLog message.\n",
57 "\t-W spec\tWrappers specification line.\n",
58 "(Specify the --help global option for a list of other help options)\n",
70 int i, c, msglen, err;
73 struct logfile_info *li;
81 vbranch = xstrdup (CVSBRANCH);
83 while ((c = getopt (argc, argv, "+Qqdb:m:I:k:W:")) != -1)
90 /* The CVS 1.5 client sends these options (in addition to
91 Global_option requests), so we must ignore them. */
95 "-q or -Q must be specified before \"%s\"",
102 /* CVS 1.10 and older clients will send this, but it
103 doesn't do any good. So tell the user we can't
104 cope, rather than silently losing. */
106 "warning: not setting the time of import from the file");
107 error (0, 0, "due to client limitations");
110 use_file_modtime = 1;
114 vbranch = xstrdup (optarg);
117 #ifdef FORCE_USE_EDITOR
122 message = xstrdup(optarg);
128 /* RCS_check_kflag returns strings of the form -kxx. We
129 only use it for validation, so we can free the value
130 as soon as it is returned. */
131 free (RCS_check_kflag (optarg));
132 keyword_opt = optarg;
135 wrap_add (optarg, 0);
139 usage (import_usage);
146 usage (import_usage);
148 #ifdef SERVER_SUPPORT
149 /* This is for handling the Checkin-time request. It might seem a
150 bit odd to enable the use_file_modtime code even in the case
151 where Checkin-time was not sent for a particular file. The
152 effect is that we use the time of upload, rather than the time
153 when we call RCS_checkin. Since those times are both during
154 CVS's run, that seems OK, and it is easier to implement than
155 putting the "was Checkin-time sent" flag in CVS/Entries or some
159 use_file_modtime = 1;
162 /* Don't allow "CVS" as any directory in module path.
164 * Could abstract this to valid_module_path, but I don't think we'll need
165 * to call it from anywhere else.
167 if ((cp = strstr(argv[0], "CVS")) && /* path contains "CVS" AND ... */
168 ((cp == argv[0]) || ISDIRSEP(*(cp-1))) && /* /^CVS/ OR m#/CVS# AND ... */
169 ((*(cp+3) == '\0') || ISDIRSEP(*(cp+3))) /* /CVS$/ OR m#CVS/# */
173 "The word `CVS' is reserved by CVS and may not be used");
174 error (1, 0, "as a directory in a path or as a file name.");
177 for (i = 1; i < argc; i++) /* check the tags for validity */
181 RCS_check_tag (argv[i]);
182 for (j = 1; j < i; j++)
183 if (strcmp (argv[j], argv[i]) == 0)
184 error (1, 0, "tag `%s' was specified more than once", argv[i]);
187 /* XXX - this should be a module, not just a pathname */
188 if (!isabsolute (argv[0]) && pathname_levels (argv[0]) == 0)
190 if (current_parsed_root == NULL)
192 error (0, 0, "missing CVSROOT environment variable\n");
193 error (1, 0, "Set it or specify the '-d' option to %s.",
196 repository = xmalloc (strlen (current_parsed_root->directory)
199 (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
200 repos_len = strlen (current_parsed_root->directory);
204 /* It is somewhere between a security hole and "unexpected" to
205 let the client start mucking around outside the cvsroot
206 (wouldn't get the right CVSROOT configuration, &c). */
207 error (1, 0, "directory %s not relative within the repository",
212 * Consistency checks on the specified vendor branch. It must be
213 * composed of only numbers and dots ('.'). Also, for now we only
214 * support branching to a single level, so the specified vendor branch
215 * must only have two dots in it (like "1.1.1").
217 for (cp = vbranch; *cp != '\0'; cp++)
218 if (!isdigit ((unsigned char) *cp) && *cp != '.')
219 error (1, 0, "%s is not a numeric branch", vbranch);
220 if (numdots (vbranch) != 2)
221 error (1, 0, "Only branches with two dots are supported: %s", vbranch);
222 vhead = xstrdup (vbranch);
223 cp = strrchr (vhead, '.');
226 #ifdef CLIENT_SUPPORT
227 if (current_parsed_root->isremote)
229 /* For rationale behind calling start_server before do_editor, see
236 #ifdef SERVER_SUPPORT
241 do_editor ((char *) NULL, &message,
242 #ifdef CLIENT_SUPPORT
243 current_parsed_root->isremote ? (char *) NULL :
248 do_verify (&message, repository);
249 msglen = message == NULL ? 0 : strlen (message);
250 if (msglen == 0 || message[msglen - 1] != '\n')
252 char *nm = xmalloc (msglen + 2);
256 (void) strcpy (nm, message);
259 (void) strcat (nm + msglen, "\n");
263 #ifdef CLIENT_SUPPORT
264 if (current_parsed_root->isremote)
268 if (vbranch[0] != '\0')
269 option_with_arg ("-b", vbranch);
270 option_with_arg ("-m", message ? message : "");
271 if (keyword_opt != NULL)
272 option_with_arg ("-k", keyword_opt);
273 /* The only ignore processing which takes place on the server side
274 is the CVSROOT/cvsignore file. But if the user specified -I !,
275 the documented behavior is to not process said file. */
276 if (ign_inhibit_server)
285 for (i = 0; i < argc; ++i)
290 client_import_setup (repository);
291 err = import_descend (message, argv[1], argc - 2, argv + 2);
292 client_import_done ();
298 send_to_server ("import\012", 0);
299 err += get_responses_and_close ();
304 if (!safe_location ( NULL ))
306 error (1, 0, "attempt to import the repository");
310 * Make all newly created directories writable. Should really use a more
311 * sophisticated security mechanism here.
313 (void) umask (cvsumask);
314 make_directories (repository);
316 /* Create the logfile that will be logged upon completion */
317 if ((logfp = cvs_temp_file (&tmpfile)) == NULL)
318 error (1, errno, "cannot create temporary file `%s'", tmpfile);
319 /* On systems where we can unlink an open file, do so, so it will go
320 away no matter how we exit. FIXME-maybe: Should be checking for
321 errors but I'm not sure which error(s) we get if we are on a system
322 where one can't unlink open files. */
323 (void) CVS_UNLINK (tmpfile);
324 (void) fprintf (logfp, "\nVendor Tag:\t%s\n", argv[1]);
325 (void) fprintf (logfp, "Release Tags:\t");
326 for (i = 2; i < argc; i++)
327 (void) fprintf (logfp, "%s\n\t\t", argv[i]);
328 (void) fprintf (logfp, "\n");
331 err = import_descend (message, argv[1], argc - 2, argv + 2);
338 cvs_output_tagged ("+importmergecmd", NULL);
339 cvs_output_tagged ("newline", NULL);
340 sprintf (buf, "%d", conflicts);
341 cvs_output_tagged ("conflicts", buf);
342 cvs_output_tagged ("text", " conflicts created by this import.");
343 cvs_output_tagged ("newline", NULL);
344 cvs_output_tagged ("text",
345 "Use the following command to help the merge:");
346 cvs_output_tagged ("newline", NULL);
347 cvs_output_tagged ("newline", NULL);
348 cvs_output_tagged ("text", "\t");
349 cvs_output_tagged ("text", program_name);
350 if (CVSroot_cmdline != NULL)
352 cvs_output_tagged ("text", " -d ");
353 cvs_output_tagged ("text", CVSroot_cmdline);
355 cvs_output_tagged ("text", " checkout -j");
356 cvs_output_tagged ("mergetag1", "<prev_rel_tag>");
357 cvs_output_tagged ("text", " -j");
358 cvs_output_tagged ("mergetag2", argv[2]);
359 cvs_output_tagged ("text", " ");
360 cvs_output_tagged ("repository", argv[0]);
361 cvs_output_tagged ("newline", NULL);
362 cvs_output_tagged ("newline", NULL);
363 cvs_output_tagged ("-importmergecmd", NULL);
366 /* FIXME: I'm not sure whether we need to put this information
367 into the loginfo. If we do, then note that it does not
368 report any required -d option. There is no particularly
369 clean way to tell the server about the -d option used by
371 (void) fprintf (logfp, "\n%d conflicts created by this import.\n",
373 (void) fprintf (logfp,
374 "Use the following command to help the merge:\n\n");
375 (void) fprintf (logfp, "\t%s checkout ", program_name);
376 (void) fprintf (logfp, "-j%s:yesterday -j%s %s\n\n",
377 argv[1], argv[1], argv[0]);
382 cvs_output ("\nNo conflicts created by this import\n\n", 0);
383 (void) fprintf (logfp, "\nNo conflicts created by this import\n\n");
387 * Write out the logfile and clean up.
392 p->delproc = update_delproc;
393 p->key = xstrdup ("- Imported sources");
394 li = (struct logfile_info *) xmalloc (sizeof (struct logfile_info));
396 li->tag = xstrdup (vbranch);
397 li->rev_old = li->rev_new = NULL;
399 (void) addnode (ulist, p);
400 Update_Logfile (repository, message, logfp, ulist);
402 if (fclose (logfp) < 0)
403 error (0, errno, "error closing %s", tmpfile);
405 /* Make sure the temporary file goes away, even on systems that don't let
406 you delete a file that's in use. */
407 if (CVS_UNLINK (tmpfile) < 0 && !existence_error (errno))
408 error (0, errno, "cannot remove %s", tmpfile);
420 /* Process all the files in ".", then descend into other directories.
421 Returns 0 for success, or >0 on error (in which case a message
422 will have been printed). */
424 import_descend (message, vtag, targc, targv)
433 List *dirlist = NULL;
435 /* first, load up any per-directory ignore lists */
436 ign_add_file (CVSDOTIGNORE, 1);
437 wrap_add_file (CVSDOTWRAPPER, 1);
439 if ((dirp = CVS_OPENDIR (".")) == NULL)
441 error (0, errno, "cannot open directory");
447 while ((dp = CVS_READDIR (dirp)) != NULL)
449 if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0)
450 goto one_more_time_boys;
451 #ifdef SERVER_SUPPORT
452 /* CVS directories are created in the temp directory by
453 server.c because it doesn't special-case import. So
454 don't print a message about them, regardless of -I!. */
455 if (server_active && strcmp (dp->d_name, CVSADM) == 0)
456 goto one_more_time_boys;
458 if (ign_name (dp->d_name))
460 add_log ('I', dp->d_name);
461 goto one_more_time_boys;
466 (dp->d_type == DT_DIR
467 || (dp->d_type == DT_UNKNOWN && isdir (dp->d_name)))
471 && !wrap_name_has (dp->d_name, WRAP_TOCVS)
480 n->key = xstrdup (dp->d_name);
486 || (dp->d_type == DT_UNKNOWN && islink (dp->d_name))
492 add_log ('L', dp->d_name);
497 #ifdef CLIENT_SUPPORT
498 if (current_parsed_root->isremote)
499 err += client_process_import_file (message, dp->d_name,
502 keyword_opt != NULL &&
503 keyword_opt[0] == 'b',
507 err += process_import_file (message, dp->d_name,
515 error (0, errno, "cannot read directory");
518 (void) CVS_CLOSEDIR (dirp);
525 head = dirlist->list;
526 for (p = head->next; p != head; p = p->next)
528 err += import_descend_dir (message, p->key, vtag, targc, targv);
538 * Process the argument import file.
541 process_import_file (message, vfile, vtag, targc, targv)
551 rcs = xmalloc (strlen (repository) + strlen (vfile) + sizeof (RCSEXT)
553 (void) sprintf (rcs, "%s/%s%s", repository, vfile, RCSEXT);
558 attic_name = xmalloc (strlen (repository) + strlen (vfile) +
559 sizeof (CVSATTIC) + sizeof (RCSEXT) + 10);
560 (void) sprintf (attic_name, "%s/%s/%s%s", repository, CVSATTIC,
562 if (!isfile (attic_name))
565 char *free_opt = NULL;
566 char *our_opt = keyword_opt;
570 * A new import source file; it doesn't exist as a ,v within the
571 * repository nor in the Attic -- create it anew.
573 add_log ('N', vfile);
575 #ifdef SERVER_SUPPORT
576 /* The most reliable information on whether the file is binary
577 is what the client told us. That is because if the client had
578 the wrong idea about binaryness, it corrupted the file, so
579 we might as well believe the client. */
585 /* Reading all the entries for each file is fairly silly, and
586 probably slow. But I am too lazy at the moment to do
588 entries = Entries_Open (0, NULL);
589 node = findnode_fn (entries, vfile);
592 Entnode *entdata = node->data;
594 if (entdata->type == ENT_FILE)
596 assert (entdata->options[0] == '-'
597 && entdata->options[1] == 'k');
598 our_opt = xstrdup (entdata->options + 2);
602 Entries_Close (entries);
606 retval = add_rcs_file (message, rcs, vfile, vhead, our_opt,
607 vbranch, vtag, targc, targv,
609 if (free_opt != NULL)
620 * an rcs file exists. have to do things the official, slow, way.
622 return (update_rcs_file (message, vfile, vtag, targc, targv, inattic));
626 * The RCS file exists; update it by adding the new import file to the
627 * (possibly already existing) vendor branch.
630 update_rcs_file (message, vfile, vtag, targc, targv, inattic)
642 struct file_info finfo;
644 memset (&finfo, 0, sizeof finfo);
646 /* Not used, so don't worry about it. */
647 finfo.update_dir = NULL;
648 finfo.fullname = finfo.file;
649 finfo.repository = repository;
650 finfo.entries = NULL;
652 vers = Version_TS (&finfo, (char *) NULL, vbranch, (char *) NULL,
654 if (vers->vn_rcs != NULL
655 && !RCS_isdead(vers->srcfile, vers->vn_rcs))
660 * The rcs file does have a revision on the vendor branch. Compare
661 * this revision with the import file; if they match exactly, there
662 * is no need to install the new import file as a new revision to the
663 * branch. Just tag the revision with the new import tags.
665 * This is to try to cut down the number of "C" conflict messages for
666 * locally modified import source files.
668 tocvsPath = wrap_tocvs_process_file (vfile);
669 /* FIXME: Why don't we pass tocvsPath to RCS_cmp_file if it is
671 expand = vers->srcfile->expand != NULL &&
672 vers->srcfile->expand[0] == 'b' ? "-kb" : "-ko";
673 different = RCS_cmp_file( vers->srcfile, vers->vn_rcs, (char **)NULL,
674 (char *)NULL, expand, vfile );
676 if (unlink_file_dir (tocvsPath) < 0)
677 error (0, errno, "cannot remove %s", tocvsPath);
684 * The two files are identical. Just update the tags, print the
685 * "U", signifying that the file has changed, but needs no
686 * attention, and we're done.
688 if (add_tags (vers->srcfile, vfile, vtag, targc, targv))
690 add_log ('U', vfile);
696 /* We may have failed to parse the RCS file; check just in case */
697 if (vers->srcfile == NULL ||
698 add_rev (message, vers->srcfile, vfile, vers->vn_rcs) ||
699 add_tags (vers->srcfile, vfile, vtag, targc, targv))
705 if (vers->srcfile->branch == NULL || inattic ||
706 strcmp (vers->srcfile->branch, vbranch) != 0)
713 add_log (letter, vfile);
720 * Add the revision to the vendor branch
723 add_rev (message, rcs, vfile, vers)
729 int locked, status, ierrno;
738 /* Before RCS_lock existed, we were directing stdout, as well as
739 stderr, from the RCS command, to DEVNULL. I wouldn't guess that
740 was necessary, but I don't know for sure. */
741 /* Earlier versions of this function printed a `fork failed' error
742 when RCS_lock returned an error code. That's not appropriate
743 now that RCS_lock is librarified, but should the error text be
745 if (RCS_lock (rcs, vbranch, 1) != 0)
748 RCS_rewrite (rcs, NULL, NULL);
750 tocvsPath = wrap_tocvs_process_file (vfile);
752 status = RCS_checkin (rcs, tocvsPath == NULL ? vfile : tocvsPath,
754 (RCS_FLAGS_QUIET | RCS_FLAGS_KEEPFILE
755 | (use_file_modtime ? RCS_FLAGS_MODTIME : 0)));
758 if ((tocvsPath != NULL) && (unlink_file_dir (tocvsPath) < 0))
759 error (0, errno, "cannot remove %s", tocvsPath);
765 fperrmsg (logfp, 0, status == -1 ? ierrno : 0,
766 "ERROR: Check-in of %s failed", rcs->path);
767 error (0, status == -1 ? ierrno : 0,
768 "ERROR: Check-in of %s failed", rcs->path);
772 (void) RCS_unlock(rcs, vbranch, 0);
773 RCS_rewrite (rcs, NULL, NULL);
781 * Add the vendor branch tag and all the specified import release tags to the
782 * RCS file. The vendor branch tag goes on the branch root (1.1.1) while the
783 * vendor release tags go on the newly added leaf of the branch (1.1.1.1,
787 add_tags (rcs, vfile, vtag, targc, targv)
797 struct file_info finfo;
802 if ((retcode = RCS_settag(rcs, vtag, vbranch)) != 0)
805 fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
806 "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
807 error (0, retcode == -1 ? ierrno : 0,
808 "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
811 RCS_rewrite (rcs, NULL, NULL);
813 memset (&finfo, 0, sizeof finfo);
815 /* Not used, so don't worry about it. */
816 finfo.update_dir = NULL;
817 finfo.fullname = finfo.file;
818 finfo.repository = repository;
819 finfo.entries = NULL;
821 vers = Version_TS (&finfo, NULL, vtag, NULL, 1, 0);
822 for (i = 0; i < targc; i++)
824 if ((retcode = RCS_settag (rcs, targv[i], vers->vn_rcs)) == 0)
825 RCS_rewrite (rcs, NULL, NULL);
829 fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
830 "WARNING: Couldn't add tag %s to %s", targv[i],
832 error (0, retcode == -1 ? ierrno : 0,
833 "WARNING: Couldn't add tag %s to %s", targv[i],
842 * Stolen from rcs/src/rcsfnms.c, and adapted/extended.
846 char *suffix, *comlead;
849 static const struct compair comtable[] =
853 * comtable pairs each filename suffix with a comment leader. The comment
854 * leader is placed before each line generated by the $Log keyword. This
855 * table is used to guess the proper comment leader from the working file's
856 * suffix during initial ci (see InitAdmin()). Comment leaders are needed for
857 * languages without multiline comments; for others they are optional.
859 * I believe that the comment leader is unused if you are using RCS 5.7, which
860 * decides what leader to use based on the text surrounding the $Log keyword
861 * rather than a specified comment leader.
863 {"a", "-- "}, /* Ada */
866 {"asm", ";; "}, /* assembler (MS-DOS) */
867 {"ads", "-- "}, /* Ada */
868 {"bas", "' "}, /* Visual Basic code */
869 {"bat", ":: "}, /* batch (MS-DOS) */
870 {"body", "-- "}, /* Ada */
871 {"c", " * "}, /* C */
872 {"c++", "// "}, /* C++ in all its infinite guises */
876 {"m", "// "}, /* Objective-C */
877 {"cl", ";;; "}, /* Common Lisp */
878 {"cmd", ":: "}, /* command (OS/2) */
879 {"cmf", "c "}, /* CM Fortran */
880 {"cs", " * "}, /* C* */
881 {"csh", "# "}, /* shell */
882 {"dlg", " * "}, /* MS Windows dialog file */
883 {"e", "# "}, /* efl */
884 {"epsf", "% "}, /* encapsulated postscript */
885 {"epsi", "% "}, /* encapsulated postscript */
886 {"el", "; "}, /* Emacs Lisp */
887 {"f", "c "}, /* Fortran */
889 {"frm", "' "}, /* Visual Basic form */
890 {"h", " * "}, /* C-header */
891 {"hh", "// "}, /* C++ header */
894 {"in", "# "}, /* for Makefile.in */
895 {"l", " * "}, /* lex (conflict between lex and
897 {"mac", ";; "}, /* macro (DEC-10, MS-DOS, PDP-11,
899 {"mak", "# "}, /* makefile, e.g. Visual C++ */
900 {"me", ".\\\" "}, /* me-macros t/nroff */
901 {"ml", "; "}, /* mocklisp */
902 {"mm", ".\\\" "}, /* mm-macros t/nroff */
903 {"ms", ".\\\" "}, /* ms-macros t/nroff */
904 {"man", ".\\\" "}, /* man-macros t/nroff */
905 {"1", ".\\\" "}, /* feeble attempt at man pages... */
914 {"p", " * "}, /* pascal */
916 {"pl", "# "}, /* perl (conflict with Prolog) */
917 {"ps", "% "}, /* postscript */
918 {"psw", "% "}, /* postscript wrap */
919 {"pswm", "% "}, /* postscript wrap */
920 {"r", "# "}, /* ratfor */
921 {"rc", " * "}, /* Microsoft Windows resource file */
922 {"red", "% "}, /* psl/rlisp */
924 {"s", "! "}, /* assembler */
927 {"s", "| "}, /* assembler */
930 {"s", "/ "}, /* assembler */
933 {"s", "# "}, /* assembler */
936 {"s", "# "}, /* assembler */
937 {"S", "# "}, /* Macro assembler */
939 {"sh", "# "}, /* shell */
940 {"sl", "% "}, /* psl */
941 {"spec", "-- "}, /* Ada */
942 {"tex", "% "}, /* tex */
943 {"y", " * "}, /* yacc */
944 {"ye", " * "}, /* yacc-efl */
945 {"yr", " * "}, /* yacc-ratfor */
946 {"", "# "}, /* default for empty suffix */
947 {NULL, "# "} /* default for unknown suffix; */
948 /* must always be last */
960 suffix_path = xmalloc (strlen (user) + 5);
961 cp = strrchr (user, '.');
967 * Convert to lower-case, since we are not concerned about the
968 * case-ness of the suffix.
970 (void) strcpy (suffix_path, cp);
971 for (cp = suffix_path; *cp; cp++)
972 if (isupper ((unsigned char) *cp))
974 suffix = suffix_path;
977 suffix = ""; /* will use the default */
980 if (comtable[i].suffix == NULL)
982 /* Default. Note we'll always hit this case before we
984 retval = comtable[i].comlead;
987 if (strcmp (suffix, comtable[i].suffix) == 0)
989 retval = comtable[i].comlead;
997 /* Create a new RCS file from scratch.
999 This probably should be moved to rcs.c now that it is called from
1000 places outside import.c.
1002 Return value is 0 for success, or nonzero for failure (in which
1003 case an error message will have already been printed). */
1005 add_rcs_file (message, rcs, user, add_vhead, key_opt,
1006 add_vbranch, vtag, targc, targv,
1007 desctext, desclen, add_logfp)
1008 /* Log message for the addition. Not used if add_vhead == NULL. */
1009 const char *message;
1010 /* Filename of the RCS file to create. */
1012 /* Filename of the file to serve as the contents of the initial
1013 revision. Even if add_vhead is NULL, we use this to determine
1014 the modes to give the new RCS file. */
1017 /* Revision number of head that we are adding. Normally 1.1 but
1018 could be another revision as long as ADD_VBRANCH is a branch
1019 from it. If NULL, then just add an empty file without any
1020 revisions (similar to the one created by "rcs -i"). */
1021 const char *add_vhead;
1023 /* Keyword expansion mode, e.g., "b" for binary. NULL means the
1024 default behavior. */
1025 const char *key_opt;
1027 /* Vendor branch to import to, or NULL if none. If non-NULL, then
1028 vtag should also be non-NULL. */
1029 const char *add_vbranch;
1034 /* If non-NULL, description for the file. If NULL, the description
1036 const char *desctext;
1039 /* Write errors to here as well as via error (), or NULL if we should
1040 use only error (). */
1043 FILE *fprcs, *fpuser;
1047 char altdate1[MAXDATELEN];
1049 int i, ierrno, err = 0;
1052 const char *userfile;
1053 char *free_opt = NULL;
1059 /* Note that as the code stands now, the -k option overrides any
1060 settings in wrappers (whether CVSROOT/cvswrappers, -W, or
1061 whatever). Some have suggested this should be the other way
1062 around. As far as I know the documentation doesn't say one way
1063 or the other. Before making a change of this sort, should think
1064 about what is best, document it (in cvs.texinfo and NEWS), &c. */
1066 if (key_opt == NULL)
1068 if (wrap_name_has (user, WRAP_RCSOPTION))
1070 key_opt = free_opt = wrap_rcsoption (user, 0);
1074 tocvsPath = wrap_tocvs_process_file (user);
1075 userfile = (tocvsPath == NULL ? user : tocvsPath);
1077 /* Opening in text mode is probably never the right thing for the
1078 server (because the protocol encodes text files in a fashion
1079 which does not depend on what the client or server OS is, as
1080 documented in cvsclient.texi), but as long as the server just
1081 runs on unix it is a moot point. */
1083 /* If PreservePermissions is set, then make sure that the file
1084 is a plain file before trying to open it. Longstanding (although
1085 often unpopular) CVS behavior has been to follow symlinks, so we
1086 maintain that behavior if PreservePermissions is not on.
1088 NOTE: this error message used to be `cannot fstat', but is now
1089 `cannot lstat'. I don't see a way around this, since we must
1090 stat the file before opening it. -twp */
1092 if (CVS_LSTAT (userfile, &sb) < 0)
1094 /* not fatal, continue import */
1095 if (add_logfp != NULL)
1096 fperrmsg (add_logfp, 0, errno,
1097 "ERROR: cannot lstat file %s", userfile);
1098 error (0, errno, "cannot lstat file %s", userfile);
1101 file_type = sb.st_mode & S_IFMT;
1104 if (!preserve_perms || file_type == S_IFREG)
1106 fpuser = CVS_FOPEN (userfile,
1107 ((key_opt != NULL && strcmp (key_opt, "b") == 0)
1113 /* not fatal, continue import */
1114 if (add_logfp != NULL)
1115 fperrmsg (add_logfp, 0, errno,
1116 "ERROR: cannot read file %s", userfile);
1117 error (0, errno, "ERROR: cannot read file %s", userfile);
1122 fprcs = CVS_FOPEN (rcs, "w+b");
1126 goto write_error_noclose;
1132 if (add_vhead != NULL)
1134 if (fprintf (fprcs, "head %s;\012", add_vhead) < 0)
1139 if (fprintf (fprcs, "head ;\012") < 0)
1143 if (add_vbranch != NULL)
1145 if (fprintf (fprcs, "branch %s;\012", add_vbranch) < 0)
1148 if (fprintf (fprcs, "access ;\012") < 0 ||
1149 fprintf (fprcs, "symbols ") < 0)
1154 for (i = targc - 1; i >= 0; i--)
1156 /* RCS writes the symbols backwards */
1157 assert (add_vbranch != NULL);
1158 if (fprintf (fprcs, "%s:%s.1 ", targv[i], add_vbranch) < 0)
1162 if (add_vbranch != NULL)
1164 if (fprintf (fprcs, "%s:%s", vtag, add_vbranch) < 0)
1167 if (fprintf (fprcs, ";\012") < 0)
1170 if (fprintf (fprcs, "locks ; strict;\012") < 0 ||
1171 /* XXX - make sure @@ processing works in the RCS file */
1172 fprintf (fprcs, "comment @%s@;\012", get_comment (user)) < 0)
1177 if (key_opt != NULL && strcmp (key_opt, "kv") != 0)
1179 if (fprintf (fprcs, "expand @%s@;\012", key_opt) < 0)
1185 if (fprintf (fprcs, "\012") < 0)
1188 /* Write the revision(s), with the date and author and so on
1189 (that is "delta" rather than "deltatext" from rcsfile(5)). */
1190 if (add_vhead != NULL)
1192 if (use_file_modtime)
1196 ftm = gmtime (&now);
1197 (void) sprintf (altdate1, DATEFORM,
1198 ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
1199 ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
1200 ftm->tm_min, ftm->tm_sec);
1201 author = getcaller ();
1203 if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
1204 fprintf (fprcs, "date %s; author %s; state Exp;\012",
1205 altdate1, author) < 0)
1208 if (fprintf (fprcs, "branches") < 0)
1210 if (add_vbranch != NULL)
1212 if (fprintf (fprcs, " %s.1", add_vbranch) < 0)
1215 if (fprintf (fprcs, ";\012") < 0)
1218 if (fprintf (fprcs, "next ;\012") < 0)
1221 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1222 /* Store initial permissions if necessary. */
1225 if (file_type == S_IFLNK)
1227 char *link = xreadlink (userfile);
1228 if (fprintf (fprcs, "symlink\t@") < 0 ||
1229 expand_at_signs (link, strlen (link), fprcs) < 0 ||
1230 fprintf (fprcs, "@;\012") < 0)
1236 if (fprintf (fprcs, "owner\t%u;\012", sb.st_uid) < 0)
1238 if (fprintf (fprcs, "group\t%u;\012", sb.st_gid) < 0)
1240 if (fprintf (fprcs, "permissions\t%o;\012",
1241 sb.st_mode & 07777) < 0)
1245 case S_IFREG: break;
1248 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1249 if (fprintf (fprcs, "special\t%s %lu;\012",
1250 (file_type == S_IFCHR
1253 (unsigned long) sb.st_rdev) < 0)
1257 "can't import %s: unable to import device files on this system",
1263 "can't import %s: unknown kind of special file",
1270 if (add_vbranch != NULL)
1272 if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1273 fprintf (fprcs, "date %s; author %s; state Exp;\012",
1274 altdate1, author) < 0 ||
1275 fprintf (fprcs, "branches ;\012") < 0 ||
1276 fprintf (fprcs, "next ;\012") < 0)
1279 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1280 /* Store initial permissions if necessary. */
1283 if (file_type == S_IFLNK)
1285 char *link = xreadlink (userfile);
1286 if (fprintf (fprcs, "symlink\t@") < 0 ||
1287 expand_at_signs (link, strlen (link), fprcs) < 0 ||
1288 fprintf (fprcs, "@;\012") < 0)
1294 if (fprintf (fprcs, "owner\t%u;\012", sb.st_uid) < 0 ||
1295 fprintf (fprcs, "group\t%u;\012", sb.st_gid) < 0 ||
1296 fprintf (fprcs, "permissions\t%o;\012",
1297 sb.st_mode & 07777) < 0)
1302 case S_IFREG: break;
1305 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1306 if (fprintf (fprcs, "special\t%s %lu;\012",
1307 (file_type == S_IFCHR
1310 (unsigned long) sb.st_rdev) < 0)
1314 "can't import %s: unable to import device files on this system",
1320 "cannot import %s: special file of unknown type",
1327 if (fprintf (fprcs, "\012") < 0)
1332 /* Now write the description (possibly empty). */
1333 if (fprintf (fprcs, "\012desc\012") < 0 ||
1334 fprintf (fprcs, "@") < 0)
1336 if (desctext != NULL)
1338 /* The use of off_t not size_t for the second argument is very
1339 strange, since we are dealing with something which definitely
1341 if (expand_at_signs (desctext, (off_t) desclen, fprcs) < 0)
1344 if (fprintf (fprcs, "@\012\012\012") < 0)
1347 /* Now write the log messages and contents for the revision(s) (that
1348 is, "deltatext" rather than "delta" from rcsfile(5)). */
1349 if (add_vhead != NULL)
1351 if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
1352 fprintf (fprcs, "log\012@") < 0)
1354 if (add_vbranch != NULL)
1356 /* We are going to put the log message in the revision on the
1357 branch. So putting it here too seems kind of redundant, I
1358 guess (and that is what CVS has always done, anyway). */
1359 if (fprintf (fprcs, "Initial revision\012") < 0)
1364 if (expand_at_signs (message, (off_t) strlen (message), fprcs) < 0)
1367 if (fprintf (fprcs, "@\012") < 0 ||
1368 fprintf (fprcs, "text\012@") < 0)
1373 /* Now copy over the contents of the file, expanding at signs.
1374 If preserve_perms is set, do this only for regular files. */
1375 if (!preserve_perms || file_type == S_IFREG)
1382 len = fread (buf, 1, sizeof buf, fpuser);
1385 if (ferror (fpuser))
1386 error (1, errno, "cannot read file %s for copying",
1390 if (expand_at_signs (buf, len, fprcs) < 0)
1394 if (fprintf (fprcs, "@\012\012") < 0)
1396 if (add_vbranch != NULL)
1398 if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1399 fprintf (fprcs, "log\012@") < 0 ||
1400 expand_at_signs (message,
1401 (off_t) strlen (message), fprcs) < 0 ||
1402 fprintf (fprcs, "@\012text\012") < 0 ||
1403 fprintf (fprcs, "@@\012") < 0)
1408 if (fclose (fprcs) == EOF)
1411 goto write_error_noclose;
1413 /* Close fpuser only if we opened it to begin with. */
1416 if (fclose (fpuser) < 0)
1417 error (0, errno, "cannot close %s", user);
1421 * Fix the modes on the RCS files. The user modes of the original
1422 * user file are propagated to the group and other modes as allowed
1423 * by the repository umask, except that all write permissions are
1426 mode = (sb.st_mode |
1427 (sb.st_mode & S_IRWXU) >> 3 |
1428 (sb.st_mode & S_IRWXU) >> 6) &
1430 ~(S_IWRITE | S_IWGRP | S_IWOTH);
1431 if (chmod (rcs, mode) < 0)
1434 if (add_logfp != NULL)
1435 fperrmsg (add_logfp, 0, ierrno,
1436 "WARNING: cannot change mode of file %s", rcs);
1437 error (0, ierrno, "WARNING: cannot change mode of file %s", rcs);
1441 if (unlink_file_dir (tocvsPath) < 0)
1442 error (0, errno, "cannot remove %s", tocvsPath);
1443 if (free_opt != NULL)
1449 if (fclose (fprcs) < 0)
1450 error (0, errno, "cannot close %s", rcs);
1451 write_error_noclose:
1452 if (fclose (fpuser) < 0)
1453 error (0, errno, "cannot close %s", user);
1454 if (add_logfp != NULL)
1455 fperrmsg (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
1456 error (0, ierrno, "ERROR: cannot write file %s", rcs);
1457 if (ierrno == ENOSPC)
1459 if (CVS_UNLINK (rcs) < 0)
1460 error (0, errno, "cannot remove %s", rcs);
1461 if (add_logfp != NULL)
1462 fperrmsg (add_logfp, 0, 0, "ERROR: out of space - aborting");
1463 error (1, 0, "ERROR: out of space - aborting");
1467 if (unlink_file_dir (tocvsPath) < 0)
1468 error (0, errno, "cannot remove %s", tocvsPath);
1470 if (free_opt != NULL)
1477 * Write SIZE bytes at BUF to FP, expanding @ signs into double @
1478 * signs. If an error occurs, return a negative value and set errno
1479 * to indicate the error. If not, return a nonnegative value.
1482 expand_at_signs (buf, size, fp)
1487 register const char *cp, *next;
1490 while ((next = memchr (cp, '@', size)) != NULL)
1492 size_t len = ++next - cp;
1493 if (fwrite (cp, 1, len, fp) != len)
1495 if (putc ('@', fp) == EOF)
1501 if (fwrite (cp, 1, size, fp) != size)
1508 * Write an update message to (potentially) the screen and the log file.
1515 if (!really_quiet) /* write to terminal */
1520 cvs_output (buf, 2);
1523 cvs_output (repository + repos_len + 1, 0);
1524 cvs_output ("/", 1);
1526 else if (repository[0] != '\0')
1528 cvs_output (repository, 0);
1529 cvs_output ("/", 1);
1531 cvs_output (fname, 0);
1532 cvs_output ("\n", 1);
1535 if (repos_len) /* write to logfile */
1536 (void) fprintf (logfp, "%c %s/%s\n", ch,
1537 repository + repos_len + 1, fname);
1538 else if (repository[0])
1539 (void) fprintf (logfp, "%c %s/%s\n", ch, repository, fname);
1541 (void) fprintf (logfp, "%c %s\n", ch, fname);
1545 * This is the recursive function that walks the argument directory looking
1546 * for sub-directories that have CVS administration files in them and updates
1549 * Note that we do not follow symbolic links here, which is a feature!
1552 import_descend_dir (message, dir, vtag, targc, targv)
1559 struct saved_cwd cwd;
1566 if (save_cwd (&cwd))
1568 fperrmsg (logfp, 0, 0, "ERROR: cannot get working directory");
1572 /* Concatenate DIR to the end of REPOSITORY. */
1573 if (repository[0] == '\0')
1575 char *new = xstrdup (dir);
1581 char *new = xmalloc (strlen (repository) + strlen (dir) + 10);
1582 strcpy (new, repository);
1583 (void) strcat (new, "/");
1584 (void) strcat (new, dir);
1589 #ifdef CLIENT_SUPPORT
1590 if (!quiet && !current_parsed_root->isremote)
1594 error (0, 0, "Importing %s", repository);
1596 if ( CVS_CHDIR (dir) < 0)
1599 fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository);
1600 error (0, ierrno, "ERROR: cannot chdir to %s", repository);
1604 #ifdef CLIENT_SUPPORT
1605 if (!current_parsed_root->isremote && !isdir (repository))
1607 if (!isdir (repository))
1610 rcs = xmalloc (strlen (repository) + sizeof (RCSEXT) + 5);
1611 (void) sprintf (rcs, "%s%s", repository, RCSEXT);
1612 if (isfile (repository) || isfile(rcs))
1614 fperrmsg (logfp, 0, 0,
1615 "ERROR: %s is a file, should be a directory!",
1617 error (0, 0, "ERROR: %s is a file, should be a directory!",
1622 if (noexec == 0 && CVS_MKDIR (repository, 0777) < 0)
1625 fperrmsg (logfp, 0, ierrno,
1626 "ERROR: cannot mkdir %s -- not added", repository);
1628 "ERROR: cannot mkdir %s -- not added", repository);
1633 err = import_descend (message, vtag, targc, targv);
1637 if ((cp = strrchr (repository, '/')) != NULL)
1640 repository[0] = '\0';
1641 if (restore_cwd (&cwd, NULL))