2 * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
4 * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
7 * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8 * Portions Copyright (C) 1989-1992, Brian Berliner
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.
13 * "import" checks in the vendor release located in the current directory into
14 * the CVS source repository. The CVS vendor branch support is utilized.
16 * At least three arguments are expected to follow the options:
17 * repository Where the source belongs relative to the CVSROOT
18 * VendorTag Vendor's major tag
19 * VendorReleTag Tag for this particular release
21 * Additional arguments specify more Vendor Release Tags.
27 static char *get_comment (const char *user);
28 static int add_rev (char *message, RCSNode *rcs, char *vfile,
30 static int add_tags (RCSNode *rcs, char *vfile, char *vtag, int targc,
32 static int import_descend (char *message, char *vtag, int targc, char *targv[]);
33 static int import_descend_dir (char *message, char *dir, char *vtag,
34 int targc, char *targv[]);
35 static int process_import_file (char *message, char *vfile, char *vtag,
36 int targc, char *targv[]);
37 static int update_rcs_file (char *message, char *vfile, char *vtag, int targc,
38 char *targv[], int inattic);
39 #ifdef PRESERVE_PERMISSIONS_SUPPORT
40 static int preserve_initial_permissions (FILE *fprcs, const char *userfile,
41 mode_t file_type, struct stat *sbp);
43 static int expand_and_copy_contents (FILE *fprcs, mode_t file_type,
44 const char *user, FILE *fpuser);
45 static void add_log (int ch, char *fname);
51 static char *repository;
53 static int use_file_modtime;
54 static char *keyword_opt = NULL;
57 static const char *const import_usage[] =
59 "Usage: %s %s [-dX] [-k subst] [-I ign] [-m msg] [-b branch]\n",
60 " [-W spec] repository vendor-tag release-tags...\n",
61 "\t-d\tUse the file's modification time as the time of import.\n",
62 "\t-X\tWhen importing new files, mark their trunk revisions as dead.\n",
63 "\t-k sub\tSet default RCS keyword substitution mode.\n",
64 "\t-I ign\tMore files to ignore (! to reset).\n",
65 "\t-b bra\tVendor branch id.\n",
66 "\t-m msg\tLog message.\n",
67 "\t-W spec\tWrappers specification line.\n",
68 "(Specify the --help global option for a list of other help options)\n",
73 import (int argc, char **argv)
78 int i, c, msglen, err;
81 struct logfile_info *li;
86 /* Force -X behaviour or not based on the CVS repository
87 CVSROOT/config setting. */
89 killnew = !current_parsed_root->isremote
90 && config->ImportNewFilesToVendorBranchOnly;
91 #else /* !CLIENT_SUPPORT */
92 killnew = config->ImportNewFilesToVendorBranchOnly;
93 #endif /* CLIENT_SUPPORT */
99 vbranch = xstrdup (CVSBRANCH);
101 while ((c = getopt (argc, argv, "+Qqdb:m:I:k:W:X")) != -1)
107 #ifdef SERVER_SUPPORT
108 /* The CVS 1.5 client sends these options (in addition to
109 Global_option requests), so we must ignore them. */
113 "-q or -Q must be specified before \"%s\"",
117 #ifdef SERVER_SUPPORT
120 /* CVS 1.10 and older clients will send this, but it
121 doesn't do any good. So tell the user we can't
122 cope, rather than silently losing. */
124 "warning: not setting the time of import from the file");
125 error (0, 0, "due to client limitations");
128 use_file_modtime = 1;
132 vbranch = xstrdup (optarg);
135 #ifdef FORCE_USE_EDITOR
140 if (message) free (message);
141 message = xstrdup (optarg);
147 /* RCS_check_kflag returns strings of the form -kxx. We
148 only use it for validation, so we can free the value
149 as soon as it is returned. */
150 free (RCS_check_kflag (optarg));
151 keyword_opt = optarg;
154 wrap_add (optarg, 0);
161 usage (import_usage);
168 usage (import_usage);
170 #ifdef SERVER_SUPPORT
171 /* This is for handling the Checkin-time request. It might seem a
172 bit odd to enable the use_file_modtime code even in the case
173 where Checkin-time was not sent for a particular file. The
174 effect is that we use the time of upload, rather than the time
175 when we call RCS_checkin. Since those times are both during
176 CVS's run, that seems OK, and it is easier to implement than
177 putting the "was Checkin-time sent" flag in CVS/Entries or some
181 use_file_modtime = 1;
184 /* Don't allow "CVS" as any directory in module path.
186 * Could abstract this to valid_module_path, but I don't think we'll need
187 * to call it from anywhere else.
189 if ((cp = strstr (argv[0], "CVS")) && /* path contains "CVS" AND ... */
190 ((cp == argv[0]) || ISSLASH (*(cp-1))) && /* /^CVS/ OR m#/CVS# AND ... */
191 ((*(cp+3) == '\0') || ISSLASH (*(cp+3))) /* /CVS$/ OR m#CVS/# */
195 "The word `CVS' is reserved by CVS and may not be used");
196 error (1, 0, "as a directory in a path or as a file name.");
199 for (i = 1; i < argc; i++) /* check the tags for validity */
203 RCS_check_tag (argv[i]);
204 for (j = 1; j < i; j++)
205 if (strcmp (argv[j], argv[i]) == 0)
206 error (1, 0, "tag `%s' was specified more than once", argv[i]);
209 if (isabsolute (argv[0]) || pathname_levels (argv[0]) > 0)
210 /* It is somewhere between a security hole and "unexpected" to
211 let the client start mucking around outside the cvsroot
212 (wouldn't get the right CVSROOT configuration, &c). */
213 error (1, 0, "directory %s not relative within the repository",
216 if (current_parsed_root == NULL)
218 error (0, 0, "missing CVSROOT environment variable\n");
219 error (1, 0, "Set it or specify the '-d' option to %s.",
222 repository = Xasprintf ("%s/%s", current_parsed_root->directory, argv[0]);
223 repos_len = strlen (current_parsed_root->directory);
226 * Consistency checks on the specified vendor branch. It must be
227 * composed of only numbers and dots ('.'). Also, for now we only
228 * support branching to a single level, so the specified vendor branch
229 * must only have two dots in it (like "1.1.1").
233 int ret = regcomp (&pat, "^[1-9][0-9]*\\.[1-9][0-9]*\\.[1-9][0-9]*$",
236 if (regexec (&pat, vbranch, 0, NULL, 0))
239 "Only numeric branch specifications with two dots are\n"
240 "supported by import, not `%s'. For example: `1.1.1'.",
246 /* Set vhead to the branch's parent. */
247 vhead = xstrdup (vbranch);
248 cp = strrchr (vhead, '.');
251 #ifdef CLIENT_SUPPORT
252 if (current_parsed_root->isremote)
254 /* For rationale behind calling start_server before do_editor, see
261 #ifdef SERVER_SUPPORT
266 do_editor (NULL, &message,
267 #ifdef CLIENT_SUPPORT
268 current_parsed_root->isremote ? NULL :
273 do_verify (&message, repository);
274 msglen = message == NULL ? 0 : strlen (message);
275 if (msglen == 0 || message[msglen - 1] != '\n')
277 char *nm = xmalloc (msglen + 2);
281 (void) strcpy (nm, message);
284 (void) strcat (nm + msglen, "\n");
288 #ifdef CLIENT_SUPPORT
289 if (current_parsed_root->isremote)
293 if (vbranch[0] != '\0')
294 option_with_arg ("-b", vbranch);
295 option_with_arg ("-m", message ? message : "");
296 if (keyword_opt != NULL)
297 option_with_arg ("-k", keyword_opt);
300 /* The only ignore processing which takes place on the server side
301 is the CVSROOT/cvsignore file. But if the user specified -I !,
302 the documented behavior is to not process said file. */
303 if (ign_inhibit_server)
312 for (i = 0; i < argc; ++i)
317 client_import_setup (repository);
318 err = import_descend (message, argv[1], argc - 2, argv + 2);
319 client_import_done ();
325 send_to_server ("import\012", 0);
326 err += get_responses_and_close ();
331 if (!safe_location (NULL))
333 error (1, 0, "attempt to import the repository");
337 * Make all newly created directories writable. Should really use a more
338 * sophisticated security mechanism here.
340 (void) umask (cvsumask);
341 make_directories (repository);
343 /* Create the logfile that will be logged upon completion */
344 if ((logfp = cvs_temp_file (&tmpfile)) == NULL)
345 error (1, errno, "cannot create temporary file `%s'", tmpfile);
346 /* On systems where we can unlink an open file, do so, so it will go
347 away no matter how we exit. FIXME-maybe: Should be checking for
348 errors but I'm not sure which error(s) we get if we are on a system
349 where one can't unlink open files. */
350 (void) CVS_UNLINK (tmpfile);
351 (void) fprintf (logfp, "\nVendor Tag:\t%s\n", argv[1]);
352 (void) fprintf (logfp, "Release Tags:\t");
353 for (i = 2; i < argc; i++)
354 (void) fprintf (logfp, "%s\n\t\t", argv[i]);
355 (void) fprintf (logfp, "\n");
358 err = import_descend (message, argv[1], argc - 2, argv + 2);
359 if (conflicts || killnew)
365 cvs_output_tagged ("+importmergecmd", NULL);
366 cvs_output_tagged ("newline", NULL);
368 sprintf (buf, "%d", conflicts);
371 cvs_output_tagged ("conflicts", buf);
372 cvs_output_tagged ("text", " conflicts created by this import.");
373 cvs_output_tagged ("newline", NULL);
374 cvs_output_tagged ("text",
375 "Use the following command to help the merge:");
376 cvs_output_tagged ("newline", NULL);
377 cvs_output_tagged ("newline", NULL);
378 cvs_output_tagged ("text", "\t");
379 cvs_output_tagged ("text", program_name);
380 if (CVSroot_cmdline != NULL)
382 cvs_output_tagged ("text", " -d ");
383 cvs_output_tagged ("text", CVSroot_cmdline);
385 cvs_output_tagged ("text", " checkout -j");
386 cvs_output_tagged ("mergetag1", "<prev_rel_tag>");
387 cvs_output_tagged ("text", " -j");
388 cvs_output_tagged ("mergetag2", argv[2]);
389 cvs_output_tagged ("text", " ");
390 cvs_output_tagged ("repository", argv[0]);
391 cvs_output_tagged ("newline", NULL);
392 cvs_output_tagged ("newline", NULL);
393 cvs_output_tagged ("-importmergecmd", NULL);
396 /* FIXME: I'm not sure whether we need to put this information
397 into the loginfo. If we do, then note that it does not
398 report any required -d option. There is no particularly
399 clean way to tell the server about the -d option used by
402 (void) fprintf (logfp, "\n%d", conflicts);
404 (void) fprintf (logfp, "\nNo");
405 (void) fprintf (logfp, " conflicts created by this import.\n");
406 (void) fprintf (logfp,
407 "Use the following command to help the merge:\n\n");
408 (void) fprintf (logfp, "\t%s checkout ", program_name);
409 (void) fprintf (logfp, "-j%s:yesterday -j%s %s\n\n",
410 argv[1], argv[1], argv[0]);
415 cvs_output ("\nNo conflicts created by this import\n\n", 0);
416 (void) fprintf (logfp, "\nNo conflicts created by this import\n\n");
420 * Write out the logfile and clean up.
425 p->delproc = update_delproc;
426 p->key = xstrdup ("- Imported sources");
427 li = xmalloc (sizeof (struct logfile_info));
429 li->tag = xstrdup (vbranch);
430 li->rev_old = li->rev_new = NULL;
432 (void) addnode (ulist, p);
433 Update_Logfile (repository, message, logfp, ulist);
435 if (fclose (logfp) < 0)
436 error (0, errno, "error closing %s", tmpfile);
438 /* Make sure the temporary file goes away, even on systems that don't let
439 you delete a file that's in use. */
440 if (CVS_UNLINK (tmpfile) < 0 && !existence_error (errno))
441 error (0, errno, "cannot remove %s", tmpfile);
453 /* Process all the files in ".", then descend into other directories.
454 Returns 0 for success, or >0 on error (in which case a message
455 will have been printed). */
457 import_descend (char *message, char *vtag, int targc, char **targv)
462 List *dirlist = NULL;
464 /* first, load up any per-directory ignore lists */
465 ign_add_file (CVSDOTIGNORE, 1);
466 wrap_add_file (CVSDOTWRAPPER, 1);
468 if ((dirp = CVS_OPENDIR (".")) == NULL)
470 error (0, errno, "cannot open directory");
476 while ((dp = CVS_READDIR (dirp)) != NULL)
478 if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0)
479 goto one_more_time_boys;
480 #ifdef SERVER_SUPPORT
481 /* CVS directories are created in the temp directory by
482 server.c because it doesn't special-case import. So
483 don't print a message about them, regardless of -I!. */
484 if (server_active && strcmp (dp->d_name, CVSADM) == 0)
485 goto one_more_time_boys;
487 if (ign_name (dp->d_name))
489 add_log ('I', dp->d_name);
490 goto one_more_time_boys;
495 (dp->d_type == DT_DIR
496 || (dp->d_type == DT_UNKNOWN && isdir (dp->d_name)))
500 && !wrap_name_has (dp->d_name, WRAP_TOCVS)
506 dirlist = getlist ();
509 n->key = xstrdup (dp->d_name);
510 addnode (dirlist, n);
515 || (dp->d_type == DT_UNKNOWN && islink (dp->d_name))
521 add_log ('L', dp->d_name);
526 #ifdef CLIENT_SUPPORT
527 if (current_parsed_root->isremote)
528 err += client_process_import_file (message, dp->d_name,
531 keyword_opt != NULL &&
532 keyword_opt[0] == 'b',
536 err += process_import_file (message, dp->d_name,
544 error (0, errno, "cannot read directory");
547 (void) CVS_CLOSEDIR (dirp);
554 head = dirlist->list;
555 for (p = head->next; p != head; p = p->next)
557 err += import_descend_dir (message, p->key, vtag, targc, targv);
567 * Process the argument import file.
570 process_import_file (char *message, char *vfile, char *vtag, int targc,
576 rcs = Xasprintf ("%s/%s%s", repository, vfile, RCSEXT);
581 attic_name = xmalloc (strlen (repository) + strlen (vfile) +
582 sizeof (CVSATTIC) + sizeof (RCSEXT) + 10);
583 (void) sprintf (attic_name, "%s/%s/%s%s", repository, CVSATTIC,
585 if (!isfile (attic_name))
588 char *free_opt = NULL;
589 char *our_opt = keyword_opt;
591 /* If marking newly-imported files as dead, they must be
592 created in the attic! */
600 /* Attempt to make the Attic directory, in case it
602 (void) sprintf (rcs, "%s/%s", repository, CVSATTIC);
603 if (CVS_MKDIR (rcs, 0777 ) != 0 && errno != EEXIST)
604 error (1, errno, "cannot make directory `%s'", rcs);
606 /* Note that the above clobbered the path name, so we
608 (void) sprintf (rcs, "%s/%s/%s%s", repository, CVSATTIC,
613 * A new import source file; it doesn't exist as a ,v within the
614 * repository nor in the Attic -- create it anew.
616 add_log ('N', vfile);
618 #ifdef SERVER_SUPPORT
619 /* The most reliable information on whether the file is binary
620 is what the client told us. That is because if the client had
621 the wrong idea about binaryness, it corrupted the file, so
622 we might as well believe the client. */
628 /* Reading all the entries for each file is fairly silly, and
629 probably slow. But I am too lazy at the moment to do
631 entries = Entries_Open (0, NULL);
632 node = findnode_fn (entries, vfile);
635 Entnode *entdata = node->data;
637 if (entdata->type == ENT_FILE)
639 assert (entdata->options[0] == '-'
640 && entdata->options[1] == 'k');
641 our_opt = xstrdup (entdata->options + 2);
645 Entries_Close (entries);
649 retval = add_rcs_file (message, rcs, vfile, vhead, our_opt,
650 vbranch, vtag, targc, targv,
651 NULL, 0, logfp, killnew);
652 if (free_opt != NULL)
663 * an rcs file exists. have to do things the official, slow, way.
665 return update_rcs_file (message, vfile, vtag, targc, targv, inattic);
669 * The RCS file exists; update it by adding the new import file to the
670 * (possibly already existing) vendor branch.
673 update_rcs_file (char *message, char *vfile, char *vtag, int targc,
674 char **targv, int inattic)
680 struct file_info finfo;
682 memset (&finfo, 0, sizeof finfo);
684 /* Not used, so don't worry about it. */
685 finfo.update_dir = NULL;
686 finfo.fullname = finfo.file;
687 finfo.repository = repository;
688 finfo.entries = NULL;
690 vers = Version_TS (&finfo, NULL, vbranch, NULL, 1, 0);
691 if (vers->vn_rcs != NULL
692 && !RCS_isdead (vers->srcfile, vers->vn_rcs))
697 * The rcs file does have a revision on the vendor branch. Compare
698 * this revision with the import file; if they match exactly, there
699 * is no need to install the new import file as a new revision to the
700 * branch. Just tag the revision with the new import tags.
702 * This is to try to cut down the number of "C" conflict messages for
703 * locally modified import source files.
705 tocvsPath = wrap_tocvs_process_file (vfile);
706 /* FIXME: Why don't we pass tocvsPath to RCS_cmp_file if it is
708 expand = (vers->srcfile->expand != NULL
709 && vers->srcfile->expand[0] == 'b') ? "-kb" : "-ko";
710 different = RCS_cmp_file (vers->srcfile, vers->vn_rcs, NULL,
711 NULL, expand, vfile);
713 if (unlink_file_dir (tocvsPath) < 0)
714 error (0, errno, "cannot remove %s", tocvsPath);
721 * The two files are identical. Just update the tags, print the
722 * "U", signifying that the file has changed, but needs no
723 * attention, and we're done.
725 if (add_tags (vers->srcfile, vfile, vtag, targc, targv))
727 add_log ('U', vfile);
733 /* We may have failed to parse the RCS file; check just in case */
734 if (vers->srcfile == NULL ||
735 add_rev (message, vers->srcfile, vfile, vers->vn_rcs) ||
736 add_tags (vers->srcfile, vfile, vtag, targc, targv))
742 if (vers->srcfile->branch == NULL || inattic ||
743 strcmp (vers->srcfile->branch, vbranch) != 0)
750 add_log (letter, vfile);
757 * Add the revision to the vendor branch
760 add_rev (char *message, RCSNode *rcs, char *vfile, char *vers)
762 int locked, status, ierrno;
771 /* Before RCS_lock existed, we were directing stdout, as well as
772 stderr, from the RCS command, to DEVNULL. I wouldn't guess that
773 was necessary, but I don't know for sure. */
774 /* Earlier versions of this function printed a `fork failed' error
775 when RCS_lock returned an error code. That's not appropriate
776 now that RCS_lock is librarified, but should the error text be
778 if (RCS_lock (rcs, vbranch, 1) != 0)
781 RCS_rewrite (rcs, NULL, NULL);
783 tocvsPath = wrap_tocvs_process_file (vfile);
785 status = RCS_checkin (rcs, NULL, tocvsPath == NULL ? vfile : tocvsPath,
787 (RCS_FLAGS_QUIET | RCS_FLAGS_KEEPFILE
788 | (use_file_modtime ? RCS_FLAGS_MODTIME : 0)));
791 if ((tocvsPath != NULL) && (unlink_file_dir (tocvsPath) < 0))
792 error (0, errno, "cannot remove %s", tocvsPath);
798 fperrmsg (logfp, 0, status == -1 ? ierrno : 0,
799 "ERROR: Check-in of %s failed", rcs->path);
800 error (0, status == -1 ? ierrno : 0,
801 "ERROR: Check-in of %s failed", rcs->path);
805 (void) RCS_unlock (rcs, vbranch, 0);
806 RCS_rewrite (rcs, NULL, NULL);
814 * Add the vendor branch tag and all the specified import release tags to the
815 * RCS file. The vendor branch tag goes on the branch root (1.1.1) while the
816 * vendor release tags go on the newly added leaf of the branch (1.1.1.1,
820 add_tags (RCSNode *rcs, char *vfile, char *vtag, int targc, char **targv)
825 struct file_info finfo;
830 if ((retcode = RCS_settag (rcs, vtag, vbranch)) != 0)
833 fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
834 "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
835 error (0, retcode == -1 ? ierrno : 0,
836 "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
839 RCS_rewrite (rcs, NULL, NULL);
841 memset (&finfo, 0, sizeof finfo);
843 /* Not used, so don't worry about it. */
844 finfo.update_dir = NULL;
845 finfo.fullname = finfo.file;
846 finfo.repository = repository;
847 finfo.entries = NULL;
849 vers = Version_TS (&finfo, NULL, vtag, NULL, 1, 0);
850 for (i = 0; i < targc; i++)
852 if ((retcode = RCS_settag (rcs, targv[i], vers->vn_rcs)) == 0)
853 RCS_rewrite (rcs, NULL, NULL);
857 fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
858 "WARNING: Couldn't add tag %s to %s", targv[i],
860 error (0, retcode == -1 ? ierrno : 0,
861 "WARNING: Couldn't add tag %s to %s", targv[i],
870 * Stolen from rcs/src/rcsfnms.c, and adapted/extended.
874 char *suffix, *comlead;
877 static const struct compair comtable[] =
881 * comtable pairs each filename suffix with a comment leader. The comment
882 * leader is placed before each line generated by the $Log keyword. This
883 * table is used to guess the proper comment leader from the working file's
884 * suffix during initial ci (see InitAdmin()). Comment leaders are needed for
885 * languages without multiline comments; for others they are optional.
887 * I believe that the comment leader is unused if you are using RCS 5.7, which
888 * decides what leader to use based on the text surrounding the $Log keyword
889 * rather than a specified comment leader.
891 {"a", "-- "}, /* Ada */
894 {"asm", ";; "}, /* assembler (MS-DOS) */
895 {"ads", "-- "}, /* Ada */
896 {"bas", "' "}, /* Visual Basic code */
897 {"bat", ":: "}, /* batch (MS-DOS) */
898 {"body", "-- "}, /* Ada */
899 {"c", " * "}, /* C */
900 {"c++", "// "}, /* C++ in all its infinite guises */
904 {"m", "// "}, /* Objective-C */
905 {"cl", ";;; "}, /* Common Lisp */
906 {"cmd", ":: "}, /* command (OS/2) */
907 {"cmf", "c "}, /* CM Fortran */
908 {"cs", " * "}, /* C* */
909 {"csh", "# "}, /* shell */
910 {"dlg", " * "}, /* MS Windows dialog file */
911 {"e", "# "}, /* efl */
912 {"epsf", "% "}, /* encapsulated postscript */
913 {"epsi", "% "}, /* encapsulated postscript */
914 {"el", "; "}, /* Emacs Lisp */
915 {"f", "c "}, /* Fortran */
917 {"frm", "' "}, /* Visual Basic form */
918 {"h", " * "}, /* C-header */
919 {"hh", "// "}, /* C++ header */
922 {"in", "# "}, /* for Makefile.in */
923 {"l", " * "}, /* lex (conflict between lex and
925 {"mac", ";; "}, /* macro (DEC-10, MS-DOS, PDP-11,
927 {"mak", "# "}, /* makefile, e.g. Visual C++ */
928 {"me", ".\\\" "}, /* me-macros t/nroff */
929 {"ml", "; "}, /* mocklisp */
930 {"mm", ".\\\" "}, /* mm-macros t/nroff */
931 {"ms", ".\\\" "}, /* ms-macros t/nroff */
932 {"man", ".\\\" "}, /* man-macros t/nroff */
933 {"1", ".\\\" "}, /* feeble attempt at man pages... */
942 {"p", " * "}, /* pascal */
944 {"pl", "# "}, /* perl (conflict with Prolog) */
945 {"ps", "% "}, /* postscript */
946 {"psw", "% "}, /* postscript wrap */
947 {"pswm", "% "}, /* postscript wrap */
948 {"r", "# "}, /* ratfor */
949 {"rc", " * "}, /* Microsoft Windows resource file */
950 {"red", "% "}, /* psl/rlisp */
952 {"s", "! "}, /* assembler */
955 {"s", "| "}, /* assembler */
958 {"s", "/ "}, /* assembler */
961 {"s", "# "}, /* assembler */
964 {"s", "# "}, /* assembler */
965 {"S", "# "}, /* Macro assembler */
967 {"sh", "# "}, /* shell */
968 {"sl", "% "}, /* psl */
969 {"spec", "-- "}, /* Ada */
970 {"tex", "% "}, /* tex */
971 {"y", " * "}, /* yacc */
972 {"ye", " * "}, /* yacc-efl */
973 {"yr", " * "}, /* yacc-ratfor */
974 {"", "# "}, /* default for empty suffix */
975 {NULL, "# "} /* default for unknown suffix; */
976 /* must always be last */
982 get_comment (const char *user)
989 suffix_path = xmalloc (strlen (user) + 5);
990 cp = strrchr (user, '.');
996 * Convert to lower-case, since we are not concerned about the
997 * case-ness of the suffix.
999 (void) strcpy (suffix_path, cp);
1000 for (cp = suffix_path; *cp; cp++)
1001 if (isupper ((unsigned char) *cp))
1002 *cp = tolower (*cp);
1003 suffix = suffix_path;
1006 suffix = ""; /* will use the default */
1009 if (comtable[i].suffix == NULL)
1011 /* Default. Note we'll always hit this case before we
1012 ever return NULL. */
1013 retval = comtable[i].comlead;
1016 if (strcmp (suffix, comtable[i].suffix) == 0)
1018 retval = comtable[i].comlead;
1026 /* Create a new RCS file from scratch.
1028 * This probably should be moved to rcs.c now that it is called from
1029 * places outside import.c.
1032 * message Log message for the addition. Not used if add_vhead == NULL.
1033 * rcs Filename of the RCS file to create. Note that if 'do_killnew'
1034 * is set, this file should be in the Attic directory, and the
1035 * Attic directory must already exist.
1036 * user Filename of the file to serve as the contents of the initial
1037 * revision. Even if add_vhead is NULL, we use this to determine
1038 * the modes to give the new RCS file.
1039 * add_vhead Revision number of head that we are adding. Normally 1.1 but
1040 * could be another revision as long as ADD_VBRANCH is a branch
1041 * from it. If NULL, then just add an empty file without any
1042 * revisions (similar to the one created by "rcs -i").
1043 * key_opt Keyword expansion mode, e.g., "b" for binary. NULL means the
1046 * Vendor branch to import to, or NULL if none. If non-NULL, then
1047 * vtag should also be non-NULL.
1049 * targc Number of elements in TARGV.
1050 * targv The list of tags to attached to this imported revision.
1051 * desctext If non-NULL, description for the file. If NULL, the
1052 * description will be empty.
1053 * desclen The number of bytes in desctext.
1054 * add_logfp Write errors to here as well as via error (), or NULL if we
1055 * should use only error ().
1056 * do_killnew Mark newly-imported files as being dead on the trunk, i.e.,
1057 * as being imported only to the vendor branch.
1060 * Return value is 0 for success, or nonzero for failure (in which
1061 * case an error message will have already been printed).
1064 add_rcs_file (const char *message, const char *rcs, const char *user,
1065 const char *add_vhead, const char *key_opt,
1066 const char *add_vbranch, const char *vtag, int targc,
1067 char **targv, const char *desctext, size_t desclen,
1068 FILE *add_logfp, bool do_killnew)
1070 FILE *fprcs, *fpuser;
1074 char altdate1[MAXDATELEN];
1076 int i, ierrno, err = 0;
1079 const char *userfile;
1080 char *free_opt = NULL;
1082 char *dead_revision = NULL;
1092 /* If we are marking the newly imported file as dead, we must
1093 have a head revision. */
1094 if (add_vhead == NULL)
1095 error (1, 0, "killing new file attempted when no head revision is being added");
1097 /* One extra byte for NUL, plus one for carry generated by adding
1098 one to the last number in the add_vhead revision. */
1099 dead_revision = xmalloc (strlen (add_vhead) + 2);
1100 strcpy (dead_revision, add_vhead);
1102 /* Find the loacation of the last number, which we will increment
1103 and overwrite. Note that this handles single numbers (w/o
1104 dots), which is probably unnecessary. */
1105 if ((last_place = strrchr (dead_revision, '.')) != NULL)
1108 last_place = dead_revision;
1109 last_number = atoi (last_place);
1110 if (++last_number <= 0)
1111 error (1, 0, "invalid revision number %s", add_vhead);
1112 sprintf (last_place, "%d", last_number);
1115 /* Note that as the code stands now, the -k option overrides any
1116 settings in wrappers (whether CVSROOT/cvswrappers, -W, or
1117 whatever). Some have suggested this should be the other way
1118 around. As far as I know the documentation doesn't say one way
1119 or the other. Before making a change of this sort, should think
1120 about what is best, document it (in cvs.texinfo and NEWS), &c. */
1122 if (key_opt == NULL)
1124 if (wrap_name_has (user, WRAP_RCSOPTION))
1126 key_opt = free_opt = wrap_rcsoption (user, 0);
1130 tocvsPath = wrap_tocvs_process_file (user);
1131 userfile = (tocvsPath == NULL ? user : tocvsPath);
1133 /* Opening in text mode is probably never the right thing for the
1134 server (because the protocol encodes text files in a fashion
1135 which does not depend on what the client or server OS is, as
1136 documented in cvsclient.texi), but as long as the server just
1137 runs on unix it is a moot point. */
1139 /* If PreservePermissions is set, then make sure that the file
1140 is a plain file before trying to open it. Longstanding (although
1141 often unpopular) CVS behavior has been to follow symlinks, so we
1142 maintain that behavior if PreservePermissions is not on.
1144 NOTE: this error message used to be `cannot fstat', but is now
1145 `cannot lstat'. I don't see a way around this, since we must
1146 stat the file before opening it. -twp */
1148 if (CVS_LSTAT (userfile, &sb) < 0)
1150 /* not fatal, continue import */
1151 if (add_logfp != NULL)
1152 fperrmsg (add_logfp, 0, errno,
1153 "ERROR: cannot lstat file %s", userfile);
1154 error (0, errno, "cannot lstat file %s", userfile);
1157 file_type = sb.st_mode & S_IFMT;
1161 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1162 !config->preserve_perms ||
1163 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
1164 file_type == S_IFREG)
1166 fpuser = CVS_FOPEN (userfile,
1167 ((key_opt != NULL && strcmp (key_opt, "b") == 0)
1173 /* not fatal, continue import */
1174 if (add_logfp != NULL)
1175 fperrmsg (add_logfp, 0, errno,
1176 "ERROR: cannot read file %s", userfile);
1177 error (0, errno, "ERROR: cannot read file %s", userfile);
1182 fprcs = CVS_FOPEN (rcs, "w+b");
1186 goto write_error_noclose;
1192 if (add_vhead != NULL)
1194 if (fprintf (fprcs, "head %s;\012",
1195 do_killnew ? dead_revision : add_vhead) < 0)
1200 if (fprintf (fprcs, "head ;\012") < 0)
1204 /* This sets the default branch. If using the 'do_killnew' functionality,
1205 where imports don't show up until merged, no default branch should
1207 if (add_vbranch != NULL && ! do_killnew)
1209 if (fprintf (fprcs, "branch %s;\012", add_vbranch) < 0)
1212 if (fprintf (fprcs, "access ;\012") < 0 ||
1213 fprintf (fprcs, "symbols ") < 0)
1218 for (i = targc - 1; i >= 0; i--)
1220 /* RCS writes the symbols backwards */
1221 assert (add_vbranch != NULL);
1222 if (fprintf (fprcs, "%s:%s.1 ", targv[i], add_vbranch) < 0)
1226 if (add_vbranch != NULL)
1228 if (fprintf (fprcs, "%s:%s", vtag, add_vbranch) < 0)
1231 if (fprintf (fprcs, ";\012") < 0)
1234 if (fprintf (fprcs, "locks ; strict;\012") < 0 ||
1235 /* XXX - make sure @@ processing works in the RCS file */
1236 fprintf (fprcs, "comment @%s@;\012", get_comment (user)) < 0)
1241 if (key_opt != NULL && strcmp (key_opt, "kv") != 0)
1243 if (fprintf (fprcs, "expand @%s@;\012", key_opt) < 0)
1249 if (fprintf (fprcs, "\012") < 0)
1252 /* Write the revision(s), with the date and author and so on
1253 (that is "delta" rather than "deltatext" from rcsfile(5)). */
1255 if (use_file_modtime)
1259 ftm = gmtime (&now);
1260 (void) sprintf (altdate1, DATEFORM,
1261 ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
1262 ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
1263 ftm->tm_min, ftm->tm_sec);
1264 author = getcaller ();
1268 if (fprintf (fprcs, "\012%s\012", dead_revision) < 0 ||
1269 fprintf (fprcs, "date %s; author %s; state %s;\012",
1270 altdate1, author, RCSDEAD) < 0)
1273 if (fprintf (fprcs, "branches;\012") < 0)
1275 if (fprintf (fprcs, "next %s;\012", add_vhead) < 0)
1278 if (fprintf (fprcs, "commitid %s;\012", global_session_id) < 0)
1281 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1282 /* Store initial permissions if necessary. */
1283 if (config->preserve_perms)
1285 if (preserve_initial_permissions (fprcs, userfile,
1292 if (add_vhead != NULL)
1294 if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
1295 fprintf (fprcs, "date %s; author %s; state Exp;\012",
1296 altdate1, author) < 0)
1299 if (fprintf (fprcs, "branches") < 0)
1301 if (add_vbranch != NULL)
1303 if (fprintf (fprcs, " %s.1", add_vbranch) < 0)
1306 if (fprintf (fprcs, ";\012") < 0)
1309 if (fprintf (fprcs, "next ;\012") < 0)
1312 if (fprintf (fprcs, "commitid %s;\012", global_session_id) < 0)
1315 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1316 /* Store initial permissions if necessary. */
1317 if (config->preserve_perms)
1319 if (preserve_initial_permissions (fprcs, userfile,
1325 if (add_vbranch != NULL)
1327 if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1328 fprintf (fprcs, "date %s; author %s; state Exp;\012",
1329 altdate1, author) < 0 ||
1330 fprintf (fprcs, "branches ;\012") < 0 ||
1331 fprintf (fprcs, "next ;\012") < 0 ||
1332 fprintf (fprcs, "commitid %s;\012", global_session_id) < 0)
1335 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1336 /* Store initial permissions if necessary. */
1337 if (config->preserve_perms)
1339 if (preserve_initial_permissions (fprcs, userfile,
1345 if (fprintf (fprcs, "\012") < 0)
1350 /* Now write the description (possibly empty). */
1351 if (fprintf (fprcs, "\012desc\012") < 0 ||
1352 fprintf (fprcs, "@") < 0)
1354 if (desctext != NULL)
1356 /* The use of off_t not size_t for the second argument is very
1357 strange, since we are dealing with something which definitely
1359 if (expand_at_signs (desctext, (off_t) desclen, fprcs) < 0)
1362 if (fprintf (fprcs, "@\012\012\012") < 0)
1365 /* Now write the log messages and contents for the revision(s) (that
1366 is, "deltatext" rather than "delta" from rcsfile(5)). */
1370 if (fprintf (fprcs, "\012%s\012", dead_revision) < 0 ||
1371 fprintf (fprcs, "log\012@") < 0)
1373 if (fprintf (fprcs, "Revision %s was added on the vendor branch.\012",
1376 if (fprintf (fprcs, "@\012") < 0 ||
1377 fprintf (fprcs, "text\012@") < 0)
1382 /* Now copy over the contents of the file, expanding at signs. */
1383 if (expand_and_copy_contents (fprcs, file_type, user, fpuser))
1386 if (fprintf (fprcs, "@\012\012") < 0)
1390 if (add_vhead != NULL)
1392 if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
1393 fprintf (fprcs, "log\012@") < 0)
1395 if (add_vbranch != NULL)
1397 /* We are going to put the log message in the revision on the
1398 branch. So putting it here too seems kind of redundant, I
1399 guess (and that is what CVS has always done, anyway). */
1400 if (fprintf (fprcs, "Initial revision\012") < 0)
1405 if (expand_at_signs (message, (off_t) strlen (message), fprcs) < 0)
1408 if (fprintf (fprcs, "@\012") < 0 ||
1409 fprintf (fprcs, "text\012@") < 0)
1414 /* Now copy over the contents of the file, expanding at signs.
1415 * If config->preserve_perms is set, do this only for regular files.
1419 /* Now copy over the contents of the file, expanding at signs,
1420 if not done as part of do_killnew handling above. */
1421 if (expand_and_copy_contents (fprcs, file_type, user, fpuser))
1425 if (fprintf (fprcs, "@\012\012") < 0)
1428 if (add_vbranch != NULL)
1430 if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1431 fprintf (fprcs, "log\012@") < 0 ||
1432 expand_at_signs (message,
1433 (off_t) strlen (message), fprcs) < 0 ||
1434 fprintf (fprcs, "@\012text\012") < 0 ||
1435 fprintf (fprcs, "@@\012") < 0)
1440 if (fclose (fprcs) == EOF)
1443 goto write_error_noclose;
1445 /* Close fpuser only if we opened it to begin with. */
1448 if (fclose (fpuser) < 0)
1449 error (0, errno, "cannot close %s", user);
1453 * Fix the modes on the RCS files. The user modes of the original
1454 * user file are propagated to the group and other modes as allowed
1455 * by the repository umask, except that all write permissions are
1458 mode = (sb.st_mode |
1459 (sb.st_mode & S_IRWXU) >> 3 |
1460 (sb.st_mode & S_IRWXU) >> 6) &
1462 ~(S_IWRITE | S_IWGRP | S_IWOTH);
1463 if (chmod (rcs, mode) < 0)
1466 if (add_logfp != NULL)
1467 fperrmsg (add_logfp, 0, ierrno,
1468 "WARNING: cannot change mode of file %s", rcs);
1469 error (0, ierrno, "WARNING: cannot change mode of file %s", rcs);
1473 if (unlink_file_dir (tocvsPath) < 0)
1474 error (0, errno, "cannot remove %s", tocvsPath);
1475 if (free_opt != NULL)
1481 if (fclose (fprcs) < 0)
1482 error (0, errno, "cannot close %s", rcs);
1483 write_error_noclose:
1484 if (fclose (fpuser) < 0)
1485 error (0, errno, "cannot close %s", user);
1486 if (add_logfp != NULL)
1487 fperrmsg (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
1488 error (0, ierrno, "ERROR: cannot write file %s", rcs);
1489 if (ierrno == ENOSPC)
1491 if (CVS_UNLINK (rcs) < 0)
1492 error (0, errno, "cannot remove %s", rcs);
1493 if (add_logfp != NULL)
1494 fperrmsg (add_logfp, 0, 0, "ERROR: out of space - aborting");
1495 error (1, 0, "ERROR: out of space - aborting");
1499 if (unlink_file_dir (tocvsPath) < 0)
1500 error (0, errno, "cannot remove %s", tocvsPath);
1502 if (free_opt != NULL)
1508 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1509 /* Write file permissions and symlink information for a file being
1510 * added into its RCS file.
1513 * fprcs FILE pointer for the (newly-created) RCS file. Permisisons
1514 * and symlink information should be written here.
1515 * userfile Filename of the file being added. (Used to read symbolic
1516 * link contents, for symlinks.)
1517 * file_type File type of userfile, extracted from sbp->st_mode.
1518 * sbp 'stat' information for userfile.
1521 * Return value is 0 for success, or nonzero for failure (in which case
1522 * no error message has yet been printed).
1525 preserve_initial_permissions (fprcs, userfile, file_type, sbp)
1527 const char *userfile;
1531 if (file_type == S_IFLNK)
1533 char *link = Xreadlink (userfile, sbp->st_size);
1534 if (fprintf (fprcs, "symlink\t@") < 0 ||
1535 expand_at_signs (link, strlen (link), fprcs) < 0 ||
1536 fprintf (fprcs, "@;\012") < 0)
1542 if (fprintf (fprcs, "owner\t%u;\012", sbp->st_uid) < 0)
1544 if (fprintf (fprcs, "group\t%u;\012", sbp->st_gid) < 0)
1546 if (fprintf (fprcs, "permissions\t%o;\012",
1547 sbp->st_mode & 07777) < 0)
1551 case S_IFREG: break;
1554 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1555 if (fprintf (fprcs, "special\t%s %lu;\012",
1556 (file_type == S_IFCHR
1559 (unsigned long) sbp->st_rdev) < 0)
1563 "can't import %s: unable to import device files on this system",
1569 "can't import %s: unknown kind of special file",
1578 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
1580 /* Copy file contents into an RCS file, expanding at signs.
1582 * If config->preserve_perms is set, nothing is copied if the source is not
1586 * fprcs FILE pointer for the (newly-created) RCS file. The expanded
1587 * contents should be written here.
1588 * file_type File type of the data source. No data is copied if
1589 * preserve_permissions is set and the source is not a
1591 * user Filename of the data source (used to print error messages).
1592 * fpuser FILE pointer for the data source, whose data is being
1593 * copied into the RCS file.
1596 * Return value is 0 for success, or nonzero for failure (in which case
1597 * no error message has yet been printed).
1600 expand_and_copy_contents (fprcs, file_type, user, fpuser)
1601 FILE *fprcs, *fpuser;
1606 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1607 !config->preserve_perms ||
1608 #endif /* PRESERVE_PERMISSIONS_SUPPORT */
1609 file_type == S_IFREG)
1616 len = fread (buf, 1, sizeof buf, fpuser);
1619 if (ferror (fpuser))
1620 error (1, errno, "cannot read file %s for copying",
1624 if (expand_at_signs (buf, len, fprcs) < 0)
1635 * Write SIZE bytes at BUF to FP, expanding @ signs into double @
1636 * signs. If an error occurs, return a negative value and set errno
1637 * to indicate the error. If not, return a nonnegative value.
1640 expand_at_signs (const char *buf, size_t size, FILE *fp)
1642 register const char *cp, *next;
1645 while ((next = memchr (cp, '@', size)) != NULL)
1647 size_t len = ++next - cp;
1648 if (fwrite (cp, 1, len, fp) != len)
1650 if (putc ('@', fp) == EOF)
1656 if (fwrite (cp, 1, size, fp) != size)
1663 * Write an update message to (potentially) the screen and the log file.
1666 add_log (int ch, char *fname)
1668 if (!really_quiet) /* write to terminal */
1673 cvs_output (buf, 2);
1676 cvs_output (repository + repos_len + 1, 0);
1677 cvs_output ("/", 1);
1679 else if (repository[0] != '\0')
1681 cvs_output (repository, 0);
1682 cvs_output ("/", 1);
1684 cvs_output (fname, 0);
1685 cvs_output ("\n", 1);
1688 if (repos_len) /* write to logfile */
1689 (void) fprintf (logfp, "%c %s/%s\n", ch,
1690 repository + repos_len + 1, fname);
1691 else if (repository[0])
1692 (void) fprintf (logfp, "%c %s/%s\n", ch, repository, fname);
1694 (void) fprintf (logfp, "%c %s\n", ch, fname);
1698 * This is the recursive function that walks the argument directory looking
1699 * for sub-directories that have CVS administration files in them and updates
1702 * Note that we do not follow symbolic links here, which is a feature!
1705 import_descend_dir (char *message, char *dir, char *vtag, int targc,
1708 struct saved_cwd cwd;
1715 if (save_cwd (&cwd))
1717 fperrmsg (logfp, 0, errno, "Failed to save current directory.");
1721 /* Concatenate DIR to the end of REPOSITORY. */
1722 if (repository[0] == '\0')
1724 char *new = xstrdup (dir);
1730 char *new = Xasprintf ("%s/%s", repository, dir);
1735 #ifdef CLIENT_SUPPORT
1736 if (!quiet && !current_parsed_root->isremote)
1740 error (0, 0, "Importing %s", repository);
1742 if (CVS_CHDIR (dir) < 0)
1745 fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository);
1746 error (0, ierrno, "ERROR: cannot chdir to %s", repository);
1750 #ifdef CLIENT_SUPPORT
1751 if (!current_parsed_root->isremote && !isdir (repository))
1753 if (!isdir (repository))
1756 rcs = Xasprintf ("%s%s", repository, RCSEXT);
1757 if (isfile (repository) || isfile (rcs))
1759 fperrmsg (logfp, 0, 0,
1760 "ERROR: %s is a file, should be a directory!",
1762 error (0, 0, "ERROR: %s is a file, should be a directory!",
1767 if (noexec == 0 && CVS_MKDIR (repository, 0777) < 0)
1770 fperrmsg (logfp, 0, ierrno,
1771 "ERROR: cannot mkdir %s -- not added", repository);
1773 "ERROR: cannot mkdir %s -- not added", repository);
1778 err = import_descend (message, vtag, targc, targv);
1782 if ((cp = strrchr (repository, '/')) != NULL)
1785 repository[0] = '\0';
1786 if (restore_cwd (&cwd))
1787 error (1, errno, "Failed to restore current directory, `%s'.",