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.
22 static char *get_comment (const char *user);
23 static int add_rev (char *message, RCSNode *rcs, char *vfile,
25 static int add_tags (RCSNode *rcs, char *vfile, char *vtag, int targc,
27 static int import_descend (char *message, char *vtag, int targc, char *targv[]);
28 static int import_descend_dir (char *message, char *dir, char *vtag,
29 int targc, char *targv[]);
30 static int process_import_file (char *message, char *vfile, char *vtag,
31 int targc, char *targv[]);
32 static int update_rcs_file (char *message, char *vfile, char *vtag, int targc,
33 char *targv[], int inattic);
34 #ifdef PRESERVE_PERMISSIONS_SUPPORT
35 static int preserve_initial_permissions (FILE *fprcs, const char *userfile,
36 mode_t file_type, struct stat *sbp);
38 static int expand_and_copy_contents (FILE *fprcs, mode_t file_type,
39 const char *user, FILE *fpuser);
40 static void add_log (int ch, char *fname);
46 static char *repository;
48 static int use_file_modtime;
49 static char *keyword_opt = NULL;
52 static const char *const import_usage[] =
54 "Usage: %s %s [-dX] [-k subst] [-I ign] [-m msg] [-b branch]\n",
55 " [-W spec] repository vendor-tag release-tags...\n",
56 "\t-d\tUse the file's modification time as the time of import.\n",
57 "\t-X\tWhen importing new files, mark their trunk revisions as dead.\n",
58 "\t-k sub\tSet default RCS keyword substitution mode.\n",
59 "\t-I ign\tMore files to ignore (! to reset).\n",
60 "\t-b bra\tVendor branch id.\n",
61 "\t-m msg\tLog message.\n",
62 "\t-W spec\tWrappers specification line.\n",
63 "(Specify the --help global option for a list of other help options)\n",
68 import (int argc, char **argv)
73 int i, c, msglen, err;
76 struct logfile_info *li;
81 /* Force -X behaviour or not based on the CVS repository
82 CVSROOT/config setting. */
83 #if defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT)
84 killnew = !current_parsed_root->isremote
85 && config->ImportNewFilesToVendorBranchOnly;
87 killnew = config->ImportNewFilesToVendorBranchOnly;
88 #endif /* defined (CLIENT_SUPPORT) || defined (SERVER_SUPPORT) */
94 vbranch = xstrdup (CVSBRANCH);
96 while ((c = getopt (argc, argv, "+Qqdb:m:I:k:W:X")) != -1)
102 #ifdef SERVER_SUPPORT
103 /* The CVS 1.5 client sends these options (in addition to
104 Global_option requests), so we must ignore them. */
108 "-q or -Q must be specified before \"%s\"",
112 #ifdef SERVER_SUPPORT
115 /* CVS 1.10 and older clients will send this, but it
116 doesn't do any good. So tell the user we can't
117 cope, rather than silently losing. */
119 "warning: not setting the time of import from the file");
120 error (0, 0, "due to client limitations");
123 use_file_modtime = 1;
127 vbranch = xstrdup (optarg);
130 #ifdef FORCE_USE_EDITOR
135 message = xstrdup(optarg);
141 /* RCS_check_kflag returns strings of the form -kxx. We
142 only use it for validation, so we can free the value
143 as soon as it is returned. */
144 free (RCS_check_kflag (optarg));
145 keyword_opt = optarg;
148 wrap_add (optarg, 0);
155 usage (import_usage);
162 usage (import_usage);
164 #ifdef SERVER_SUPPORT
165 /* This is for handling the Checkin-time request. It might seem a
166 bit odd to enable the use_file_modtime code even in the case
167 where Checkin-time was not sent for a particular file. The
168 effect is that we use the time of upload, rather than the time
169 when we call RCS_checkin. Since those times are both during
170 CVS's run, that seems OK, and it is easier to implement than
171 putting the "was Checkin-time sent" flag in CVS/Entries or some
175 use_file_modtime = 1;
178 /* Don't allow "CVS" as any directory in module path.
180 * Could abstract this to valid_module_path, but I don't think we'll need
181 * to call it from anywhere else.
183 if ((cp = strstr(argv[0], "CVS")) && /* path contains "CVS" AND ... */
184 ((cp == argv[0]) || ISSLASH(*(cp-1))) && /* /^CVS/ OR m#/CVS# AND ... */
185 ((*(cp+3) == '\0') || ISSLASH(*(cp+3))) /* /CVS$/ OR m#CVS/# */
189 "The word `CVS' is reserved by CVS and may not be used");
190 error (1, 0, "as a directory in a path or as a file name.");
193 for (i = 1; i < argc; i++) /* check the tags for validity */
197 RCS_check_tag (argv[i]);
198 for (j = 1; j < i; j++)
199 if (strcmp (argv[j], argv[i]) == 0)
200 error (1, 0, "tag `%s' was specified more than once", argv[i]);
203 if (isabsolute (argv[0]) || pathname_levels (argv[0]) > 0)
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",
210 if (current_parsed_root == NULL)
212 error (0, 0, "missing CVSROOT environment variable\n");
213 error (1, 0, "Set it or specify the '-d' option to %s.",
216 repository = Xasprintf ("%s/%s", current_parsed_root->directory, argv[0]);
217 repos_len = strlen (current_parsed_root->directory);
220 * Consistency checks on the specified vendor branch. It must be
221 * composed of only numbers and dots ('.'). Also, for now we only
222 * support branching to a single level, so the specified vendor branch
223 * must only have two dots in it (like "1.1.1").
227 assert (!regcomp (&pat, "^[1-9][0-9]*\\.[1-9][0-9]*\\.[1-9][0-9]*$",
229 if (regexec (&pat, vbranch, 0, NULL, 0))
232 "Only numeric branch specifications with two dots are\n"
233 "supported by import, not `%s'. For example: `1.1.1'.",
239 /* Set vhead to the branch's parent. */
240 vhead = xstrdup (vbranch);
241 cp = strrchr (vhead, '.');
244 #ifdef CLIENT_SUPPORT
245 if (current_parsed_root->isremote)
247 /* For rationale behind calling start_server before do_editor, see
254 #ifdef SERVER_SUPPORT
259 do_editor ((char *) NULL, &message,
260 #ifdef CLIENT_SUPPORT
261 current_parsed_root->isremote ? (char *) NULL :
266 do_verify (&message, repository);
267 msglen = message == NULL ? 0 : strlen (message);
268 if (msglen == 0 || message[msglen - 1] != '\n')
270 char *nm = xmalloc (msglen + 2);
274 (void) strcpy (nm, message);
277 (void) strcat (nm + msglen, "\n");
281 #ifdef CLIENT_SUPPORT
282 if (current_parsed_root->isremote)
286 if (vbranch[0] != '\0')
287 option_with_arg ("-b", vbranch);
288 option_with_arg ("-m", message ? message : "");
289 if (keyword_opt != NULL)
290 option_with_arg ("-k", keyword_opt);
293 /* The only ignore processing which takes place on the server side
294 is the CVSROOT/cvsignore file. But if the user specified -I !,
295 the documented behavior is to not process said file. */
296 if (ign_inhibit_server)
305 for (i = 0; i < argc; ++i)
310 client_import_setup (repository);
311 err = import_descend (message, argv[1], argc - 2, argv + 2);
312 client_import_done ();
318 send_to_server ("import\012", 0);
319 err += get_responses_and_close ();
324 if (!safe_location ( NULL ))
326 error (1, 0, "attempt to import the repository");
330 * Make all newly created directories writable. Should really use a more
331 * sophisticated security mechanism here.
333 (void) umask (cvsumask);
334 make_directories (repository);
336 /* Create the logfile that will be logged upon completion */
337 if ((logfp = cvs_temp_file (&tmpfile)) == NULL)
338 error (1, errno, "cannot create temporary file `%s'", tmpfile);
339 /* On systems where we can unlink an open file, do so, so it will go
340 away no matter how we exit. FIXME-maybe: Should be checking for
341 errors but I'm not sure which error(s) we get if we are on a system
342 where one can't unlink open files. */
343 (void) CVS_UNLINK (tmpfile);
344 (void) fprintf (logfp, "\nVendor Tag:\t%s\n", argv[1]);
345 (void) fprintf (logfp, "Release Tags:\t");
346 for (i = 2; i < argc; i++)
347 (void) fprintf (logfp, "%s\n\t\t", argv[i]);
348 (void) fprintf (logfp, "\n");
351 err = import_descend (message, argv[1], argc - 2, argv + 2);
352 if (conflicts || killnew)
358 cvs_output_tagged ("+importmergecmd", NULL);
359 cvs_output_tagged ("newline", NULL);
361 sprintf (buf, "%d", conflicts);
363 sprintf (buf, "%s", "No");
364 cvs_output_tagged ("conflicts", buf);
365 cvs_output_tagged ("text", " conflicts created by this import.");
366 cvs_output_tagged ("newline", NULL);
367 cvs_output_tagged ("text",
368 "Use the following command to help the merge:");
369 cvs_output_tagged ("newline", NULL);
370 cvs_output_tagged ("newline", NULL);
371 cvs_output_tagged ("text", "\t");
372 cvs_output_tagged ("text", program_name);
373 if (CVSroot_cmdline != NULL)
375 cvs_output_tagged ("text", " -d ");
376 cvs_output_tagged ("text", CVSroot_cmdline);
378 cvs_output_tagged ("text", " checkout -j");
379 cvs_output_tagged ("mergetag1", "<prev_rel_tag>");
380 cvs_output_tagged ("text", " -j");
381 cvs_output_tagged ("mergetag2", argv[2]);
382 cvs_output_tagged ("text", " ");
383 cvs_output_tagged ("repository", argv[0]);
384 cvs_output_tagged ("newline", NULL);
385 cvs_output_tagged ("newline", NULL);
386 cvs_output_tagged ("-importmergecmd", NULL);
389 /* FIXME: I'm not sure whether we need to put this information
390 into the loginfo. If we do, then note that it does not
391 report any required -d option. There is no particularly
392 clean way to tell the server about the -d option used by
395 (void) fprintf (logfp, "\n%d", conflicts);
397 (void) fprintf (logfp, "\nNo");
398 (void) fprintf (logfp, " conflicts created by this import.\n");
399 (void) fprintf (logfp,
400 "Use the following command to help the merge:\n\n");
401 (void) fprintf (logfp, "\t%s checkout ", program_name);
402 (void) fprintf (logfp, "-j%s:yesterday -j%s %s\n\n",
403 argv[1], argv[1], argv[0]);
408 cvs_output ("\nNo conflicts created by this import\n\n", 0);
409 (void) fprintf (logfp, "\nNo conflicts created by this import\n\n");
413 * Write out the logfile and clean up.
418 p->delproc = update_delproc;
419 p->key = xstrdup ("- Imported sources");
420 li = (struct logfile_info *) xmalloc (sizeof (struct logfile_info));
422 li->tag = xstrdup (vbranch);
423 li->rev_old = li->rev_new = NULL;
425 (void) addnode (ulist, p);
426 Update_Logfile (repository, message, logfp, ulist);
428 if (fclose (logfp) < 0)
429 error (0, errno, "error closing %s", tmpfile);
431 /* Make sure the temporary file goes away, even on systems that don't let
432 you delete a file that's in use. */
433 if (CVS_UNLINK (tmpfile) < 0 && !existence_error (errno))
434 error (0, errno, "cannot remove %s", tmpfile);
446 /* Process all the files in ".", then descend into other directories.
447 Returns 0 for success, or >0 on error (in which case a message
448 will have been printed). */
450 import_descend (char *message, char *vtag, int targc, char **targv)
455 List *dirlist = NULL;
457 /* first, load up any per-directory ignore lists */
458 ign_add_file (CVSDOTIGNORE, 1);
459 wrap_add_file (CVSDOTWRAPPER, 1);
461 if ((dirp = CVS_OPENDIR (".")) == NULL)
463 error (0, errno, "cannot open directory");
469 while ((dp = CVS_READDIR (dirp)) != NULL)
471 if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0)
472 goto one_more_time_boys;
473 #ifdef SERVER_SUPPORT
474 /* CVS directories are created in the temp directory by
475 server.c because it doesn't special-case import. So
476 don't print a message about them, regardless of -I!. */
477 if (server_active && strcmp (dp->d_name, CVSADM) == 0)
478 goto one_more_time_boys;
480 if (ign_name (dp->d_name))
482 add_log ('I', dp->d_name);
483 goto one_more_time_boys;
488 (dp->d_type == DT_DIR
489 || (dp->d_type == DT_UNKNOWN && isdir (dp->d_name)))
493 && !wrap_name_has (dp->d_name, WRAP_TOCVS)
502 n->key = xstrdup (dp->d_name);
508 || (dp->d_type == DT_UNKNOWN && islink (dp->d_name))
514 add_log ('L', dp->d_name);
519 #ifdef CLIENT_SUPPORT
520 if (current_parsed_root->isremote)
521 err += client_process_import_file (message, dp->d_name,
524 keyword_opt != NULL &&
525 keyword_opt[0] == 'b',
529 err += process_import_file (message, dp->d_name,
537 error (0, errno, "cannot read directory");
540 (void) CVS_CLOSEDIR (dirp);
547 head = dirlist->list;
548 for (p = head->next; p != head; p = p->next)
550 err += import_descend_dir (message, p->key, vtag, targc, targv);
560 * Process the argument import file.
563 process_import_file (char *message, char *vfile, char *vtag, int targc, char **targv)
568 rcs = xmalloc (strlen (repository) + strlen (vfile) + sizeof (RCSEXT)
570 (void) sprintf (rcs, "%s/%s%s", repository, vfile, RCSEXT);
575 attic_name = xmalloc (strlen (repository) + strlen (vfile) +
576 sizeof (CVSATTIC) + sizeof (RCSEXT) + 10);
577 (void) sprintf (attic_name, "%s/%s/%s%s", repository, CVSATTIC,
579 if (!isfile (attic_name))
582 char *free_opt = NULL;
583 char *our_opt = keyword_opt;
585 /* If marking newly-imported files as dead, they must be
586 created in the attic! */
594 /* Attempt to make the Attic directory, in case it
596 (void) sprintf (rcs, "%s/%s", repository, CVSATTIC);
597 if (CVS_MKDIR (rcs, 0777 ) != 0 && errno != EEXIST)
598 error (1, errno, "cannot make directory `%s'", rcs);
600 /* Note that the above clobbered the path name, so we
602 (void) sprintf (rcs, "%s/%s/%s%s", repository, CVSATTIC,
607 * A new import source file; it doesn't exist as a ,v within the
608 * repository nor in the Attic -- create it anew.
610 add_log ('N', vfile);
612 #ifdef SERVER_SUPPORT
613 /* The most reliable information on whether the file is binary
614 is what the client told us. That is because if the client had
615 the wrong idea about binaryness, it corrupted the file, so
616 we might as well believe the client. */
622 /* Reading all the entries for each file is fairly silly, and
623 probably slow. But I am too lazy at the moment to do
625 entries = Entries_Open (0, NULL);
626 node = findnode_fn (entries, vfile);
629 Entnode *entdata = node->data;
631 if (entdata->type == ENT_FILE)
633 assert (entdata->options[0] == '-'
634 && entdata->options[1] == 'k');
635 our_opt = xstrdup (entdata->options + 2);
639 Entries_Close (entries);
643 retval = add_rcs_file (message, rcs, vfile, vhead, our_opt,
644 vbranch, vtag, targc, targv,
645 NULL, 0, logfp, killnew);
646 if (free_opt != NULL)
657 * an rcs file exists. have to do things the official, slow, way.
659 return (update_rcs_file (message, vfile, vtag, targc, targv, inattic));
663 * The RCS file exists; update it by adding the new import file to the
664 * (possibly already existing) vendor branch.
667 update_rcs_file (char *message, char *vfile, char *vtag, int targc, char **targv, int inattic)
673 struct file_info finfo;
675 memset (&finfo, 0, sizeof finfo);
677 /* Not used, so don't worry about it. */
678 finfo.update_dir = NULL;
679 finfo.fullname = finfo.file;
680 finfo.repository = repository;
681 finfo.entries = NULL;
683 vers = Version_TS (&finfo, (char *) NULL, vbranch, (char *) NULL,
685 if (vers->vn_rcs != NULL
686 && !RCS_isdead(vers->srcfile, vers->vn_rcs))
691 * The rcs file does have a revision on the vendor branch. Compare
692 * this revision with the import file; if they match exactly, there
693 * is no need to install the new import file as a new revision to the
694 * branch. Just tag the revision with the new import tags.
696 * This is to try to cut down the number of "C" conflict messages for
697 * locally modified import source files.
699 tocvsPath = wrap_tocvs_process_file (vfile);
700 /* FIXME: Why don't we pass tocvsPath to RCS_cmp_file if it is
702 expand = vers->srcfile->expand != NULL &&
703 vers->srcfile->expand[0] == 'b' ? "-kb" : "-ko";
704 different = RCS_cmp_file( vers->srcfile, vers->vn_rcs, (char **)NULL,
705 (char *)NULL, expand, vfile );
707 if (unlink_file_dir (tocvsPath) < 0)
708 error (0, errno, "cannot remove %s", tocvsPath);
715 * The two files are identical. Just update the tags, print the
716 * "U", signifying that the file has changed, but needs no
717 * attention, and we're done.
719 if (add_tags (vers->srcfile, vfile, vtag, targc, targv))
721 add_log ('U', vfile);
727 /* We may have failed to parse the RCS file; check just in case */
728 if (vers->srcfile == NULL ||
729 add_rev (message, vers->srcfile, vfile, vers->vn_rcs) ||
730 add_tags (vers->srcfile, vfile, vtag, targc, targv))
736 if (vers->srcfile->branch == NULL || inattic ||
737 strcmp (vers->srcfile->branch, vbranch) != 0)
744 add_log (letter, vfile);
751 * Add the revision to the vendor branch
754 add_rev (char *message, RCSNode *rcs, char *vfile, char *vers)
756 int locked, status, ierrno;
765 /* Before RCS_lock existed, we were directing stdout, as well as
766 stderr, from the RCS command, to DEVNULL. I wouldn't guess that
767 was necessary, but I don't know for sure. */
768 /* Earlier versions of this function printed a `fork failed' error
769 when RCS_lock returned an error code. That's not appropriate
770 now that RCS_lock is librarified, but should the error text be
772 if (RCS_lock (rcs, vbranch, 1) != 0)
775 RCS_rewrite (rcs, NULL, NULL);
777 tocvsPath = wrap_tocvs_process_file (vfile);
779 status = RCS_checkin (rcs, NULL, tocvsPath == NULL ? vfile : tocvsPath,
781 (RCS_FLAGS_QUIET | RCS_FLAGS_KEEPFILE
782 | (use_file_modtime ? RCS_FLAGS_MODTIME : 0)));
785 if ((tocvsPath != NULL) && (unlink_file_dir (tocvsPath) < 0))
786 error (0, errno, "cannot remove %s", tocvsPath);
792 fperrmsg (logfp, 0, status == -1 ? ierrno : 0,
793 "ERROR: Check-in of %s failed", rcs->path);
794 error (0, status == -1 ? ierrno : 0,
795 "ERROR: Check-in of %s failed", rcs->path);
799 (void) RCS_unlock(rcs, vbranch, 0);
800 RCS_rewrite (rcs, NULL, NULL);
808 * Add the vendor branch tag and all the specified import release tags to the
809 * RCS file. The vendor branch tag goes on the branch root (1.1.1) while the
810 * vendor release tags go on the newly added leaf of the branch (1.1.1.1,
814 add_tags (RCSNode *rcs, char *vfile, char *vtag, int targc, char **targv)
819 struct file_info finfo;
824 if ((retcode = RCS_settag(rcs, vtag, vbranch)) != 0)
827 fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
828 "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
829 error (0, retcode == -1 ? ierrno : 0,
830 "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
833 RCS_rewrite (rcs, NULL, NULL);
835 memset (&finfo, 0, sizeof finfo);
837 /* Not used, so don't worry about it. */
838 finfo.update_dir = NULL;
839 finfo.fullname = finfo.file;
840 finfo.repository = repository;
841 finfo.entries = NULL;
843 vers = Version_TS (&finfo, NULL, vtag, NULL, 1, 0);
844 for (i = 0; i < targc; i++)
846 if ((retcode = RCS_settag (rcs, targv[i], vers->vn_rcs)) == 0)
847 RCS_rewrite (rcs, NULL, NULL);
851 fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
852 "WARNING: Couldn't add tag %s to %s", targv[i],
854 error (0, retcode == -1 ? ierrno : 0,
855 "WARNING: Couldn't add tag %s to %s", targv[i],
864 * Stolen from rcs/src/rcsfnms.c, and adapted/extended.
868 char *suffix, *comlead;
871 static const struct compair comtable[] =
875 * comtable pairs each filename suffix with a comment leader. The comment
876 * leader is placed before each line generated by the $Log keyword. This
877 * table is used to guess the proper comment leader from the working file's
878 * suffix during initial ci (see InitAdmin()). Comment leaders are needed for
879 * languages without multiline comments; for others they are optional.
881 * I believe that the comment leader is unused if you are using RCS 5.7, which
882 * decides what leader to use based on the text surrounding the $Log keyword
883 * rather than a specified comment leader.
885 {"a", "-- "}, /* Ada */
888 {"asm", ";; "}, /* assembler (MS-DOS) */
889 {"ads", "-- "}, /* Ada */
890 {"bas", "' "}, /* Visual Basic code */
891 {"bat", ":: "}, /* batch (MS-DOS) */
892 {"body", "-- "}, /* Ada */
893 {"c", " * "}, /* C */
894 {"c++", "// "}, /* C++ in all its infinite guises */
898 {"m", "// "}, /* Objective-C */
899 {"cl", ";;; "}, /* Common Lisp */
900 {"cmd", ":: "}, /* command (OS/2) */
901 {"cmf", "c "}, /* CM Fortran */
902 {"cs", " * "}, /* C* */
903 {"csh", "# "}, /* shell */
904 {"dlg", " * "}, /* MS Windows dialog file */
905 {"e", "# "}, /* efl */
906 {"epsf", "% "}, /* encapsulated postscript */
907 {"epsi", "% "}, /* encapsulated postscript */
908 {"el", "; "}, /* Emacs Lisp */
909 {"f", "c "}, /* Fortran */
911 {"frm", "' "}, /* Visual Basic form */
912 {"h", " * "}, /* C-header */
913 {"hh", "// "}, /* C++ header */
916 {"in", "# "}, /* for Makefile.in */
917 {"l", " * "}, /* lex (conflict between lex and
919 {"mac", ";; "}, /* macro (DEC-10, MS-DOS, PDP-11,
921 {"mak", "# "}, /* makefile, e.g. Visual C++ */
922 {"me", ".\\\" "}, /* me-macros t/nroff */
923 {"ml", "; "}, /* mocklisp */
924 {"mm", ".\\\" "}, /* mm-macros t/nroff */
925 {"ms", ".\\\" "}, /* ms-macros t/nroff */
926 {"man", ".\\\" "}, /* man-macros t/nroff */
927 {"1", ".\\\" "}, /* feeble attempt at man pages... */
936 {"p", " * "}, /* pascal */
938 {"pl", "# "}, /* perl (conflict with Prolog) */
939 {"ps", "% "}, /* postscript */
940 {"psw", "% "}, /* postscript wrap */
941 {"pswm", "% "}, /* postscript wrap */
942 {"r", "# "}, /* ratfor */
943 {"rc", " * "}, /* Microsoft Windows resource file */
944 {"red", "% "}, /* psl/rlisp */
946 {"s", "! "}, /* assembler */
949 {"s", "| "}, /* assembler */
952 {"s", "/ "}, /* assembler */
955 {"s", "# "}, /* assembler */
958 {"s", "# "}, /* assembler */
959 {"S", "# "}, /* Macro assembler */
961 {"sh", "# "}, /* shell */
962 {"sl", "% "}, /* psl */
963 {"spec", "-- "}, /* Ada */
964 {"tex", "% "}, /* tex */
965 {"y", " * "}, /* yacc */
966 {"ye", " * "}, /* yacc-efl */
967 {"yr", " * "}, /* yacc-ratfor */
968 {"", "# "}, /* default for empty suffix */
969 {NULL, "# "} /* default for unknown suffix; */
970 /* must always be last */
976 get_comment (const char *user)
983 suffix_path = xmalloc (strlen (user) + 5);
984 cp = strrchr (user, '.');
990 * Convert to lower-case, since we are not concerned about the
991 * case-ness of the suffix.
993 (void) strcpy (suffix_path, cp);
994 for (cp = suffix_path; *cp; cp++)
995 if (isupper ((unsigned char) *cp))
997 suffix = suffix_path;
1000 suffix = ""; /* will use the default */
1003 if (comtable[i].suffix == NULL)
1005 /* Default. Note we'll always hit this case before we
1006 ever return NULL. */
1007 retval = comtable[i].comlead;
1010 if (strcmp (suffix, comtable[i].suffix) == 0)
1012 retval = comtable[i].comlead;
1020 /* Create a new RCS file from scratch.
1022 * This probably should be moved to rcs.c now that it is called from
1023 * places outside import.c.
1026 * message Log message for the addition. Not used if add_vhead == NULL.
1027 * rcs Filename of the RCS file to create. Note that if 'do_killnew'
1028 * is set, this file should be in the Attic directory, and the
1029 * Attic directory must already exist.
1030 * user Filename of the file to serve as the contents of the initial
1031 * revision. Even if add_vhead is NULL, we use this to determine
1032 * the modes to give the new RCS file.
1033 * add_vhead Revision number of head that we are adding. Normally 1.1 but
1034 * could be another revision as long as ADD_VBRANCH is a branch
1035 * from it. If NULL, then just add an empty file without any
1036 * revisions (similar to the one created by "rcs -i").
1037 * key_opt Keyword expansion mode, e.g., "b" for binary. NULL means the
1040 * Vendor branch to import to, or NULL if none. If non-NULL, then
1041 * vtag should also be non-NULL.
1043 * targc Number of elements in TARGV.
1044 * targv The list of tags to attached to this imported revision.
1045 * desctext If non-NULL, description for the file. If NULL, the
1046 * description will be empty.
1047 * desclen The number of bytes in desctext.
1048 * add_logfp Write errors to here as well as via error (), or NULL if we
1049 * should use only error ().
1050 * do_killnew Mark newly-imported files as being dead on the trunk, i.e.,
1051 * as being imported only to the vendor branch.
1054 * Return value is 0 for success, or nonzero for failure (in which
1055 * case an error message will have already been printed).
1058 add_rcs_file (const char *message, const char *rcs, const char *user,
1059 const char *add_vhead, const char *key_opt,
1060 const char *add_vbranch, const char *vtag, int targc,
1061 char **targv, const char *desctext, size_t desclen,
1062 FILE *add_logfp, bool do_killnew)
1064 FILE *fprcs, *fpuser;
1068 char altdate1[MAXDATELEN];
1070 int i, ierrno, err = 0;
1073 const char *userfile;
1074 char *free_opt = NULL;
1076 char *dead_revision = NULL;
1086 /* If we are marking the newly imported file as dead, we must
1087 have a head revision. */
1088 if (add_vhead == NULL)
1089 error (1, 0, "killing new file attempted when no head revision is being added");
1091 /* One extra byte for NUL, plus one for carry generated by adding
1092 one to the last number in the add_vhead revision. */
1093 dead_revision = xmalloc (strlen (add_vhead) + 2);
1094 strcpy (dead_revision, add_vhead);
1096 /* Find the loacation of the last number, which we will increment
1097 and overwrite. Note that this handles single numbers (w/o
1098 dots), which is probably unnecessary. */
1099 if ((last_place = strrchr (dead_revision, '.')) != NULL)
1102 last_place = dead_revision;
1103 last_number = atoi (last_place);
1104 if (++last_number <= 0)
1105 error (1, 0, "invalid revision number %s", add_vhead);
1106 sprintf (last_place, "%d", last_number);
1109 /* Note that as the code stands now, the -k option overrides any
1110 settings in wrappers (whether CVSROOT/cvswrappers, -W, or
1111 whatever). Some have suggested this should be the other way
1112 around. As far as I know the documentation doesn't say one way
1113 or the other. Before making a change of this sort, should think
1114 about what is best, document it (in cvs.texinfo and NEWS), &c. */
1116 if (key_opt == NULL)
1118 if (wrap_name_has (user, WRAP_RCSOPTION))
1120 key_opt = free_opt = wrap_rcsoption (user, 0);
1124 tocvsPath = wrap_tocvs_process_file (user);
1125 userfile = (tocvsPath == NULL ? user : tocvsPath);
1127 /* Opening in text mode is probably never the right thing for the
1128 server (because the protocol encodes text files in a fashion
1129 which does not depend on what the client or server OS is, as
1130 documented in cvsclient.texi), but as long as the server just
1131 runs on unix it is a moot point. */
1133 /* If PreservePermissions is set, then make sure that the file
1134 is a plain file before trying to open it. Longstanding (although
1135 often unpopular) CVS behavior has been to follow symlinks, so we
1136 maintain that behavior if PreservePermissions is not on.
1138 NOTE: this error message used to be `cannot fstat', but is now
1139 `cannot lstat'. I don't see a way around this, since we must
1140 stat the file before opening it. -twp */
1142 if (CVS_LSTAT (userfile, &sb) < 0)
1144 /* not fatal, continue import */
1145 if (add_logfp != NULL)
1146 fperrmsg (add_logfp, 0, errno,
1147 "ERROR: cannot lstat file %s", userfile);
1148 error (0, errno, "cannot lstat file %s", userfile);
1151 file_type = sb.st_mode & S_IFMT;
1155 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1156 !config->preserve_perms ||
1157 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
1158 file_type == S_IFREG)
1160 fpuser = CVS_FOPEN (userfile,
1161 ((key_opt != NULL && strcmp (key_opt, "b") == 0)
1167 /* not fatal, continue import */
1168 if (add_logfp != NULL)
1169 fperrmsg (add_logfp, 0, errno,
1170 "ERROR: cannot read file %s", userfile);
1171 error (0, errno, "ERROR: cannot read file %s", userfile);
1176 fprcs = CVS_FOPEN (rcs, "w+b");
1180 goto write_error_noclose;
1186 if (add_vhead != NULL)
1188 if (fprintf (fprcs, "head %s;\012",
1189 do_killnew ? dead_revision : add_vhead) < 0)
1194 if (fprintf (fprcs, "head ;\012") < 0)
1198 /* This sets the default branch. If using the 'do_killnew' functionality,
1199 where imports don't show up until merged, no default branch should
1201 if (add_vbranch != NULL && ! do_killnew)
1203 if (fprintf (fprcs, "branch %s;\012", add_vbranch) < 0)
1206 if (fprintf (fprcs, "access ;\012") < 0 ||
1207 fprintf (fprcs, "symbols ") < 0)
1212 for (i = targc - 1; i >= 0; i--)
1214 /* RCS writes the symbols backwards */
1215 assert (add_vbranch != NULL);
1216 if (fprintf (fprcs, "%s:%s.1 ", targv[i], add_vbranch) < 0)
1220 if (add_vbranch != NULL)
1222 if (fprintf (fprcs, "%s:%s", vtag, add_vbranch) < 0)
1225 if (fprintf (fprcs, ";\012") < 0)
1228 if (fprintf (fprcs, "locks ; strict;\012") < 0 ||
1229 /* XXX - make sure @@ processing works in the RCS file */
1230 fprintf (fprcs, "comment @%s@;\012", get_comment (user)) < 0)
1235 if (key_opt != NULL && strcmp (key_opt, "kv") != 0)
1237 if (fprintf (fprcs, "expand @%s@;\012", key_opt) < 0)
1243 if (fprintf (fprcs, "\012") < 0)
1246 /* Write the revision(s), with the date and author and so on
1247 (that is "delta" rather than "deltatext" from rcsfile(5)). */
1249 if (use_file_modtime)
1253 ftm = gmtime (&now);
1254 (void) sprintf (altdate1, DATEFORM,
1255 ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
1256 ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
1257 ftm->tm_min, ftm->tm_sec);
1258 author = getcaller ();
1262 if (fprintf (fprcs, "\012%s\012", dead_revision) < 0 ||
1263 fprintf (fprcs, "date %s; author %s; state %s;\012",
1264 altdate1, author, RCSDEAD) < 0)
1267 if (fprintf (fprcs, "branches;\012") < 0)
1269 if (fprintf (fprcs, "next %s;\012", add_vhead) < 0)
1272 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1273 /* Store initial permissions if necessary. */
1274 if (config->preserve_perms)
1276 if (preserve_initial_permissions (fprcs, userfile,
1283 if (add_vhead != NULL)
1285 if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
1286 fprintf (fprcs, "date %s; author %s; state Exp;\012",
1287 altdate1, author) < 0)
1290 if (fprintf (fprcs, "branches") < 0)
1292 if (add_vbranch != NULL)
1294 if (fprintf (fprcs, " %s.1", add_vbranch) < 0)
1297 if (fprintf (fprcs, ";\012") < 0)
1300 if (fprintf (fprcs, "next ;\012") < 0)
1303 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1304 /* Store initial permissions if necessary. */
1305 if (config->preserve_perms)
1307 if (preserve_initial_permissions (fprcs, userfile,
1313 if (add_vbranch != NULL)
1315 if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1316 fprintf (fprcs, "date %s; author %s; state Exp;\012",
1317 altdate1, author) < 0 ||
1318 fprintf (fprcs, "branches ;\012") < 0 ||
1319 fprintf (fprcs, "next ;\012") < 0)
1322 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1323 /* Store initial permissions if necessary. */
1324 if (config->preserve_perms)
1326 if (preserve_initial_permissions (fprcs, userfile,
1332 if (fprintf (fprcs, "\012") < 0)
1337 /* Now write the description (possibly empty). */
1338 if (fprintf (fprcs, "\012desc\012") < 0 ||
1339 fprintf (fprcs, "@") < 0)
1341 if (desctext != NULL)
1343 /* The use of off_t not size_t for the second argument is very
1344 strange, since we are dealing with something which definitely
1346 if (expand_at_signs (desctext, (off_t) desclen, fprcs) < 0)
1349 if (fprintf (fprcs, "@\012\012\012") < 0)
1352 /* Now write the log messages and contents for the revision(s) (that
1353 is, "deltatext" rather than "delta" from rcsfile(5)). */
1357 if (fprintf (fprcs, "\012%s\012", dead_revision) < 0 ||
1358 fprintf (fprcs, "log\012@") < 0)
1360 if (fprintf (fprcs, "Revision %s was added on the vendor branch.\012",
1363 if (fprintf (fprcs, "@\012") < 0 ||
1364 fprintf (fprcs, "text\012@") < 0)
1369 /* Now copy over the contents of the file, expanding at signs. */
1370 if (expand_and_copy_contents (fprcs, file_type, user, fpuser))
1373 if (fprintf (fprcs, "@\012\012") < 0)
1377 if (add_vhead != NULL)
1379 if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
1380 fprintf (fprcs, "log\012@") < 0)
1382 if (add_vbranch != NULL)
1384 /* We are going to put the log message in the revision on the
1385 branch. So putting it here too seems kind of redundant, I
1386 guess (and that is what CVS has always done, anyway). */
1387 if (fprintf (fprcs, "Initial revision\012") < 0)
1392 if (expand_at_signs (message, (off_t) strlen (message), fprcs) < 0)
1395 if (fprintf (fprcs, "@\012") < 0 ||
1396 fprintf (fprcs, "text\012@") < 0)
1401 /* Now copy over the contents of the file, expanding at signs.
1402 * If config->preserve_perms is set, do this only for regular files.
1406 /* Now copy over the contents of the file, expanding at signs,
1407 if not done as part of do_killnew handling above. */
1408 if (expand_and_copy_contents (fprcs, file_type, user, fpuser))
1412 if (fprintf (fprcs, "@\012\012") < 0)
1415 if (add_vbranch != NULL)
1417 if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1418 fprintf (fprcs, "log\012@") < 0 ||
1419 expand_at_signs (message,
1420 (off_t) strlen (message), fprcs) < 0 ||
1421 fprintf (fprcs, "@\012text\012") < 0 ||
1422 fprintf (fprcs, "@@\012") < 0)
1427 if (fclose (fprcs) == EOF)
1430 goto write_error_noclose;
1432 /* Close fpuser only if we opened it to begin with. */
1435 if (fclose (fpuser) < 0)
1436 error (0, errno, "cannot close %s", user);
1440 * Fix the modes on the RCS files. The user modes of the original
1441 * user file are propagated to the group and other modes as allowed
1442 * by the repository umask, except that all write permissions are
1445 mode = (sb.st_mode |
1446 (sb.st_mode & S_IRWXU) >> 3 |
1447 (sb.st_mode & S_IRWXU) >> 6) &
1449 ~(S_IWRITE | S_IWGRP | S_IWOTH);
1450 if (chmod (rcs, mode) < 0)
1453 if (add_logfp != NULL)
1454 fperrmsg (add_logfp, 0, ierrno,
1455 "WARNING: cannot change mode of file %s", rcs);
1456 error (0, ierrno, "WARNING: cannot change mode of file %s", rcs);
1460 if (unlink_file_dir (tocvsPath) < 0)
1461 error (0, errno, "cannot remove %s", tocvsPath);
1462 if (free_opt != NULL)
1468 if (fclose (fprcs) < 0)
1469 error (0, errno, "cannot close %s", rcs);
1470 write_error_noclose:
1471 if (fclose (fpuser) < 0)
1472 error (0, errno, "cannot close %s", user);
1473 if (add_logfp != NULL)
1474 fperrmsg (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
1475 error (0, ierrno, "ERROR: cannot write file %s", rcs);
1476 if (ierrno == ENOSPC)
1478 if (CVS_UNLINK (rcs) < 0)
1479 error (0, errno, "cannot remove %s", rcs);
1480 if (add_logfp != NULL)
1481 fperrmsg (add_logfp, 0, 0, "ERROR: out of space - aborting");
1482 error (1, 0, "ERROR: out of space - aborting");
1486 if (unlink_file_dir (tocvsPath) < 0)
1487 error (0, errno, "cannot remove %s", tocvsPath);
1489 if (free_opt != NULL)
1495 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1496 /* Write file permissions and symlink information for a file being
1497 * added into its RCS file.
1500 * fprcs FILE pointer for the (newly-created) RCS file. Permisisons
1501 * and symlink information should be written here.
1502 * userfile Filename of the file being added. (Used to read symbolic
1503 * link contents, for symlinks.)
1504 * file_type File type of userfile, extracted from sbp->st_mode.
1505 * sbp 'stat' information for userfile.
1508 * Return value is 0 for success, or nonzero for failure (in which case
1509 * no error message has yet been printed).
1512 preserve_initial_permissions (fprcs, userfile, file_type, sbp)
1514 const char *userfile;
1518 if (file_type == S_IFLNK)
1520 char *link = Xreadlink (userfile, sbp->st_size);
1521 if (fprintf (fprcs, "symlink\t@") < 0 ||
1522 expand_at_signs (link, strlen (link), fprcs) < 0 ||
1523 fprintf (fprcs, "@;\012") < 0)
1529 if (fprintf (fprcs, "owner\t%u;\012", sbp->st_uid) < 0)
1531 if (fprintf (fprcs, "group\t%u;\012", sbp->st_gid) < 0)
1533 if (fprintf (fprcs, "permissions\t%o;\012",
1534 sbp->st_mode & 07777) < 0)
1538 case S_IFREG: break;
1541 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1542 if (fprintf (fprcs, "special\t%s %lu;\012",
1543 (file_type == S_IFCHR
1546 (unsigned long) sbp->st_rdev) < 0)
1550 "can't import %s: unable to import device files on this system",
1556 "can't import %s: unknown kind of special file",
1565 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
1567 /* Copy file contents into an RCS file, expanding at signs.
1569 * If config->preserve_perms is set, nothing is copied if the source is not
1573 * fprcs FILE pointer for the (newly-created) RCS file. The expanded
1574 * contents should be written here.
1575 * file_type File type of the data source. No data is copied if
1576 * preserve_permissions is set and the source is not a
1578 * user Filename of the data source (used to print error messages).
1579 * fpuser FILE pointer for the data source, whose data is being
1580 * copied into the RCS file.
1583 * Return value is 0 for success, or nonzero for failure (in which case
1584 * no error message has yet been printed).
1587 expand_and_copy_contents (fprcs, file_type, user, fpuser)
1588 FILE *fprcs, *fpuser;
1593 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1594 !config->preserve_perms ||
1595 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
1596 file_type == S_IFREG)
1603 len = fread (buf, 1, sizeof buf, fpuser);
1606 if (ferror (fpuser))
1607 error (1, errno, "cannot read file %s for copying",
1611 if (expand_at_signs (buf, len, fprcs) < 0)
1622 * Write SIZE bytes at BUF to FP, expanding @ signs into double @
1623 * signs. If an error occurs, return a negative value and set errno
1624 * to indicate the error. If not, return a nonnegative value.
1627 expand_at_signs (const char *buf, size_t size, FILE *fp)
1629 register const char *cp, *next;
1632 while ((next = memchr (cp, '@', size)) != NULL)
1634 size_t len = ++next - cp;
1635 if (fwrite (cp, 1, len, fp) != len)
1637 if (putc ('@', fp) == EOF)
1643 if (fwrite (cp, 1, size, fp) != size)
1650 * Write an update message to (potentially) the screen and the log file.
1653 add_log (int ch, char *fname)
1655 if (!really_quiet) /* write to terminal */
1660 cvs_output (buf, 2);
1663 cvs_output (repository + repos_len + 1, 0);
1664 cvs_output ("/", 1);
1666 else if (repository[0] != '\0')
1668 cvs_output (repository, 0);
1669 cvs_output ("/", 1);
1671 cvs_output (fname, 0);
1672 cvs_output ("\n", 1);
1675 if (repos_len) /* write to logfile */
1676 (void) fprintf (logfp, "%c %s/%s\n", ch,
1677 repository + repos_len + 1, fname);
1678 else if (repository[0])
1679 (void) fprintf (logfp, "%c %s/%s\n", ch, repository, fname);
1681 (void) fprintf (logfp, "%c %s\n", ch, fname);
1685 * This is the recursive function that walks the argument directory looking
1686 * for sub-directories that have CVS administration files in them and updates
1689 * Note that we do not follow symbolic links here, which is a feature!
1692 import_descend_dir (char *message, char *dir, char *vtag, int targc,
1695 struct saved_cwd cwd;
1702 if (save_cwd (&cwd))
1704 fperrmsg (logfp, 0, errno, "Failed to save current directory.");
1708 /* Concatenate DIR to the end of REPOSITORY. */
1709 if (repository[0] == '\0')
1711 char *new = xstrdup (dir);
1717 char *new = xmalloc (strlen (repository) + strlen (dir) + 10);
1718 strcpy (new, repository);
1719 (void) strcat (new, "/");
1720 (void) strcat (new, dir);
1725 #ifdef CLIENT_SUPPORT
1726 if (!quiet && !current_parsed_root->isremote)
1730 error (0, 0, "Importing %s", repository);
1732 if ( CVS_CHDIR (dir) < 0)
1735 fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository);
1736 error (0, ierrno, "ERROR: cannot chdir to %s", repository);
1740 #ifdef CLIENT_SUPPORT
1741 if (!current_parsed_root->isremote && !isdir (repository))
1743 if (!isdir (repository))
1746 rcs = xmalloc (strlen (repository) + sizeof (RCSEXT) + 5);
1747 (void) sprintf (rcs, "%s%s", repository, RCSEXT);
1748 if (isfile (repository) || isfile(rcs))
1750 fperrmsg (logfp, 0, 0,
1751 "ERROR: %s is a file, should be a directory!",
1753 error (0, 0, "ERROR: %s is a file, should be a directory!",
1758 if (noexec == 0 && CVS_MKDIR (repository, 0777) < 0)
1761 fperrmsg (logfp, 0, ierrno,
1762 "ERROR: cannot mkdir %s -- not added", repository);
1764 "ERROR: cannot mkdir %s -- not added", repository);
1769 err = import_descend (message, vtag, targc, targv);
1773 if ((cp = strrchr (repository, '/')) != NULL)
1776 repository[0] = '\0';
1777 if (restore_cwd (&cwd))
1778 error (1, errno, "Failed to restore current directory, `%s'.",