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 static void add_log (int ch, char *fname);
40 static char *repository;
42 static int use_file_modtime;
43 static char *keyword_opt = NULL;
45 static const char *const import_usage[] =
47 "Usage: %s %s [-d] [-k subst] [-I ign] [-m msg] [-b branch]\n",
48 " [-W spec] repository vendor-tag release-tags...\n",
49 "\t-d\tUse the file's modification time as the time of import.\n",
50 "\t-k sub\tSet default RCS keyword substitution mode.\n",
51 "\t-I ign\tMore files to ignore (! to reset).\n",
52 "\t-b bra\tVendor branch id.\n",
53 "\t-m msg\tLog message.\n",
54 "\t-W spec\tWrappers specification line.\n",
55 "(Specify the --help global option for a list of other help options)\n",
60 import (int argc, char **argv)
65 int i, c, msglen, err;
68 struct logfile_info *li;
76 vbranch = xstrdup (CVSBRANCH);
78 while ((c = getopt (argc, argv, "+Qqdb:m:I:k:W:")) != -1)
85 /* The CVS 1.5 client sends these options (in addition to
86 Global_option requests), so we must ignore them. */
90 "-q or -Q must be specified before \"%s\"",
97 /* CVS 1.10 and older clients will send this, but it
98 doesn't do any good. So tell the user we can't
99 cope, rather than silently losing. */
101 "warning: not setting the time of import from the file");
102 error (0, 0, "due to client limitations");
105 use_file_modtime = 1;
109 vbranch = xstrdup (optarg);
112 #ifdef FORCE_USE_EDITOR
117 message = xstrdup(optarg);
123 /* RCS_check_kflag returns strings of the form -kxx. We
124 only use it for validation, so we can free the value
125 as soon as it is returned. */
126 free (RCS_check_kflag (optarg));
127 keyword_opt = optarg;
130 wrap_add (optarg, 0);
134 usage (import_usage);
141 usage (import_usage);
143 #ifdef SERVER_SUPPORT
144 /* This is for handling the Checkin-time request. It might seem a
145 bit odd to enable the use_file_modtime code even in the case
146 where Checkin-time was not sent for a particular file. The
147 effect is that we use the time of upload, rather than the time
148 when we call RCS_checkin. Since those times are both during
149 CVS's run, that seems OK, and it is easier to implement than
150 putting the "was Checkin-time sent" flag in CVS/Entries or some
154 use_file_modtime = 1;
157 /* Don't allow "CVS" as any directory in module path.
159 * Could abstract this to valid_module_path, but I don't think we'll need
160 * to call it from anywhere else.
162 if ((cp = strstr(argv[0], "CVS")) && /* path contains "CVS" AND ... */
163 ((cp == argv[0]) || ISSLASH(*(cp-1))) && /* /^CVS/ OR m#/CVS# AND ... */
164 ((*(cp+3) == '\0') || ISSLASH(*(cp+3))) /* /CVS$/ OR m#CVS/# */
168 "The word `CVS' is reserved by CVS and may not be used");
169 error (1, 0, "as a directory in a path or as a file name.");
172 for (i = 1; i < argc; i++) /* check the tags for validity */
176 RCS_check_tag (argv[i]);
177 for (j = 1; j < i; j++)
178 if (strcmp (argv[j], argv[i]) == 0)
179 error (1, 0, "tag `%s' was specified more than once", argv[i]);
182 /* XXX - this should be a module, not just a pathname */
183 if (!isabsolute (argv[0]) && pathname_levels (argv[0]) == 0)
185 if (current_parsed_root == NULL)
187 error (0, 0, "missing CVSROOT environment variable\n");
188 error (1, 0, "Set it or specify the '-d' option to %s.",
191 repository = xmalloc (strlen (current_parsed_root->directory)
194 (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
195 repos_len = strlen (current_parsed_root->directory);
199 /* It is somewhere between a security hole and "unexpected" to
200 let the client start mucking around outside the cvsroot
201 (wouldn't get the right CVSROOT configuration, &c). */
202 error (1, 0, "directory %s not relative within the repository",
207 * Consistency checks on the specified vendor branch. It must be
208 * composed of only numbers and dots ('.'). Also, for now we only
209 * support branching to a single level, so the specified vendor branch
210 * must only have two dots in it (like "1.1.1").
212 for (cp = vbranch; *cp != '\0'; cp++)
213 if (!isdigit ((unsigned char) *cp) && *cp != '.')
214 error (1, 0, "%s is not a numeric branch", vbranch);
215 if (numdots (vbranch) != 2)
216 error (1, 0, "Only branches with two dots are supported: %s", vbranch);
217 vhead = xstrdup (vbranch);
218 cp = strrchr (vhead, '.');
221 #ifdef CLIENT_SUPPORT
222 if (current_parsed_root->isremote)
224 /* For rationale behind calling start_server before do_editor, see
231 #ifdef SERVER_SUPPORT
236 do_editor ((char *) NULL, &message,
237 #ifdef CLIENT_SUPPORT
238 current_parsed_root->isremote ? (char *) NULL :
243 do_verify (&message, repository);
244 msglen = message == NULL ? 0 : strlen (message);
245 if (msglen == 0 || message[msglen - 1] != '\n')
247 char *nm = xmalloc (msglen + 2);
251 (void) strcpy (nm, message);
254 (void) strcat (nm + msglen, "\n");
258 #ifdef CLIENT_SUPPORT
259 if (current_parsed_root->isremote)
263 if (vbranch[0] != '\0')
264 option_with_arg ("-b", vbranch);
265 option_with_arg ("-m", message ? message : "");
266 if (keyword_opt != NULL)
267 option_with_arg ("-k", keyword_opt);
268 /* The only ignore processing which takes place on the server side
269 is the CVSROOT/cvsignore file. But if the user specified -I !,
270 the documented behavior is to not process said file. */
271 if (ign_inhibit_server)
280 for (i = 0; i < argc; ++i)
285 client_import_setup (repository);
286 err = import_descend (message, argv[1], argc - 2, argv + 2);
287 client_import_done ();
293 send_to_server ("import\012", 0);
294 err += get_responses_and_close ();
299 if (!safe_location ( NULL ))
301 error (1, 0, "attempt to import the repository");
305 * Make all newly created directories writable. Should really use a more
306 * sophisticated security mechanism here.
308 (void) umask (cvsumask);
309 make_directories (repository);
311 /* Create the logfile that will be logged upon completion */
312 if ((logfp = cvs_temp_file (&tmpfile)) == NULL)
313 error (1, errno, "cannot create temporary file `%s'", tmpfile);
314 /* On systems where we can unlink an open file, do so, so it will go
315 away no matter how we exit. FIXME-maybe: Should be checking for
316 errors but I'm not sure which error(s) we get if we are on a system
317 where one can't unlink open files. */
318 (void) CVS_UNLINK (tmpfile);
319 (void) fprintf (logfp, "\nVendor Tag:\t%s\n", argv[1]);
320 (void) fprintf (logfp, "Release Tags:\t");
321 for (i = 2; i < argc; i++)
322 (void) fprintf (logfp, "%s\n\t\t", argv[i]);
323 (void) fprintf (logfp, "\n");
326 err = import_descend (message, argv[1], argc - 2, argv + 2);
333 cvs_output_tagged ("+importmergecmd", NULL);
334 cvs_output_tagged ("newline", NULL);
335 sprintf (buf, "%d", conflicts);
336 cvs_output_tagged ("conflicts", buf);
337 cvs_output_tagged ("text", " conflicts created by this import.");
338 cvs_output_tagged ("newline", NULL);
339 cvs_output_tagged ("text",
340 "Use the following command to help the merge:");
341 cvs_output_tagged ("newline", NULL);
342 cvs_output_tagged ("newline", NULL);
343 cvs_output_tagged ("text", "\t");
344 cvs_output_tagged ("text", program_name);
345 if (CVSroot_cmdline != NULL)
347 cvs_output_tagged ("text", " -d ");
348 cvs_output_tagged ("text", CVSroot_cmdline);
350 cvs_output_tagged ("text", " checkout -j");
351 cvs_output_tagged ("mergetag1", "<prev_rel_tag>");
352 cvs_output_tagged ("text", " -j");
353 cvs_output_tagged ("mergetag2", argv[2]);
354 cvs_output_tagged ("text", " ");
355 cvs_output_tagged ("repository", argv[0]);
356 cvs_output_tagged ("newline", NULL);
357 cvs_output_tagged ("newline", NULL);
358 cvs_output_tagged ("-importmergecmd", NULL);
361 /* FIXME: I'm not sure whether we need to put this information
362 into the loginfo. If we do, then note that it does not
363 report any required -d option. There is no particularly
364 clean way to tell the server about the -d option used by
366 (void) fprintf (logfp, "\n%d conflicts created by this import.\n",
368 (void) fprintf (logfp,
369 "Use the following command to help the merge:\n\n");
370 (void) fprintf (logfp, "\t%s checkout ", program_name);
371 (void) fprintf (logfp, "-j%s:yesterday -j%s %s\n\n",
372 argv[1], argv[1], argv[0]);
377 cvs_output ("\nNo conflicts created by this import\n\n", 0);
378 (void) fprintf (logfp, "\nNo conflicts created by this import\n\n");
382 * Write out the logfile and clean up.
387 p->delproc = update_delproc;
388 p->key = xstrdup ("- Imported sources");
389 li = (struct logfile_info *) xmalloc (sizeof (struct logfile_info));
391 li->tag = xstrdup (vbranch);
392 li->rev_old = li->rev_new = NULL;
394 (void) addnode (ulist, p);
395 Update_Logfile (repository, message, logfp, ulist);
397 if (fclose (logfp) < 0)
398 error (0, errno, "error closing %s", tmpfile);
400 /* Make sure the temporary file goes away, even on systems that don't let
401 you delete a file that's in use. */
402 if (CVS_UNLINK (tmpfile) < 0 && !existence_error (errno))
403 error (0, errno, "cannot remove %s", tmpfile);
415 /* Process all the files in ".", then descend into other directories.
416 Returns 0 for success, or >0 on error (in which case a message
417 will have been printed). */
419 import_descend (char *message, char *vtag, int targc, char **targv)
424 List *dirlist = NULL;
426 /* first, load up any per-directory ignore lists */
427 ign_add_file (CVSDOTIGNORE, 1);
428 wrap_add_file (CVSDOTWRAPPER, 1);
430 if ((dirp = CVS_OPENDIR (".")) == NULL)
432 error (0, errno, "cannot open directory");
438 while ((dp = CVS_READDIR (dirp)) != NULL)
440 if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0)
441 goto one_more_time_boys;
442 #ifdef SERVER_SUPPORT
443 /* CVS directories are created in the temp directory by
444 server.c because it doesn't special-case import. So
445 don't print a message about them, regardless of -I!. */
446 if (server_active && strcmp (dp->d_name, CVSADM) == 0)
447 goto one_more_time_boys;
449 if (ign_name (dp->d_name))
451 add_log ('I', dp->d_name);
452 goto one_more_time_boys;
457 (dp->d_type == DT_DIR
458 || (dp->d_type == DT_UNKNOWN && isdir (dp->d_name)))
462 && !wrap_name_has (dp->d_name, WRAP_TOCVS)
471 n->key = xstrdup (dp->d_name);
477 || (dp->d_type == DT_UNKNOWN && islink (dp->d_name))
483 add_log ('L', dp->d_name);
488 #ifdef CLIENT_SUPPORT
489 if (current_parsed_root->isremote)
490 err += client_process_import_file (message, dp->d_name,
493 keyword_opt != NULL &&
494 keyword_opt[0] == 'b',
498 err += process_import_file (message, dp->d_name,
506 error (0, errno, "cannot read directory");
509 (void) CVS_CLOSEDIR (dirp);
516 head = dirlist->list;
517 for (p = head->next; p != head; p = p->next)
519 err += import_descend_dir (message, p->key, vtag, targc, targv);
529 * Process the argument import file.
532 process_import_file (char *message, char *vfile, char *vtag, int targc, char **targv)
537 rcs = xmalloc (strlen (repository) + strlen (vfile) + sizeof (RCSEXT)
539 (void) sprintf (rcs, "%s/%s%s", repository, vfile, RCSEXT);
544 attic_name = xmalloc (strlen (repository) + strlen (vfile) +
545 sizeof (CVSATTIC) + sizeof (RCSEXT) + 10);
546 (void) sprintf (attic_name, "%s/%s/%s%s", repository, CVSATTIC,
548 if (!isfile (attic_name))
551 char *free_opt = NULL;
552 char *our_opt = keyword_opt;
556 * A new import source file; it doesn't exist as a ,v within the
557 * repository nor in the Attic -- create it anew.
559 add_log ('N', vfile);
561 #ifdef SERVER_SUPPORT
562 /* The most reliable information on whether the file is binary
563 is what the client told us. That is because if the client had
564 the wrong idea about binaryness, it corrupted the file, so
565 we might as well believe the client. */
571 /* Reading all the entries for each file is fairly silly, and
572 probably slow. But I am too lazy at the moment to do
574 entries = Entries_Open (0, NULL);
575 node = findnode_fn (entries, vfile);
578 Entnode *entdata = node->data;
580 if (entdata->type == ENT_FILE)
582 assert (entdata->options[0] == '-'
583 && entdata->options[1] == 'k');
584 our_opt = xstrdup (entdata->options + 2);
588 Entries_Close (entries);
592 retval = add_rcs_file (message, rcs, vfile, vhead, our_opt,
593 vbranch, vtag, targc, targv,
595 if (free_opt != NULL)
606 * an rcs file exists. have to do things the official, slow, way.
608 return (update_rcs_file (message, vfile, vtag, targc, targv, inattic));
612 * The RCS file exists; update it by adding the new import file to the
613 * (possibly already existing) vendor branch.
616 update_rcs_file (char *message, char *vfile, char *vtag, int targc, char **targv, int inattic)
622 struct file_info finfo;
624 memset (&finfo, 0, sizeof finfo);
626 /* Not used, so don't worry about it. */
627 finfo.update_dir = NULL;
628 finfo.fullname = finfo.file;
629 finfo.repository = repository;
630 finfo.entries = NULL;
632 vers = Version_TS (&finfo, (char *) NULL, vbranch, (char *) NULL,
634 if (vers->vn_rcs != NULL
635 && !RCS_isdead(vers->srcfile, vers->vn_rcs))
640 * The rcs file does have a revision on the vendor branch. Compare
641 * this revision with the import file; if they match exactly, there
642 * is no need to install the new import file as a new revision to the
643 * branch. Just tag the revision with the new import tags.
645 * This is to try to cut down the number of "C" conflict messages for
646 * locally modified import source files.
648 tocvsPath = wrap_tocvs_process_file (vfile);
649 /* FIXME: Why don't we pass tocvsPath to RCS_cmp_file if it is
651 expand = vers->srcfile->expand != NULL &&
652 vers->srcfile->expand[0] == 'b' ? "-kb" : "-ko";
653 different = RCS_cmp_file( vers->srcfile, vers->vn_rcs, (char **)NULL,
654 (char *)NULL, expand, vfile );
656 if (unlink_file_dir (tocvsPath) < 0)
657 error (0, errno, "cannot remove %s", tocvsPath);
664 * The two files are identical. Just update the tags, print the
665 * "U", signifying that the file has changed, but needs no
666 * attention, and we're done.
668 if (add_tags (vers->srcfile, vfile, vtag, targc, targv))
670 add_log ('U', vfile);
676 /* We may have failed to parse the RCS file; check just in case */
677 if (vers->srcfile == NULL ||
678 add_rev (message, vers->srcfile, vfile, vers->vn_rcs) ||
679 add_tags (vers->srcfile, vfile, vtag, targc, targv))
685 if (vers->srcfile->branch == NULL || inattic ||
686 strcmp (vers->srcfile->branch, vbranch) != 0)
693 add_log (letter, vfile);
700 * Add the revision to the vendor branch
703 add_rev (char *message, RCSNode *rcs, char *vfile, char *vers)
705 int locked, status, ierrno;
714 /* Before RCS_lock existed, we were directing stdout, as well as
715 stderr, from the RCS command, to DEVNULL. I wouldn't guess that
716 was necessary, but I don't know for sure. */
717 /* Earlier versions of this function printed a `fork failed' error
718 when RCS_lock returned an error code. That's not appropriate
719 now that RCS_lock is librarified, but should the error text be
721 if (RCS_lock (rcs, vbranch, 1) != 0)
724 RCS_rewrite (rcs, NULL, NULL);
726 tocvsPath = wrap_tocvs_process_file (vfile);
728 status = RCS_checkin (rcs, tocvsPath == NULL ? vfile : tocvsPath,
730 (RCS_FLAGS_QUIET | RCS_FLAGS_KEEPFILE
731 | (use_file_modtime ? RCS_FLAGS_MODTIME : 0)));
734 if ((tocvsPath != NULL) && (unlink_file_dir (tocvsPath) < 0))
735 error (0, errno, "cannot remove %s", tocvsPath);
741 fperrmsg (logfp, 0, status == -1 ? ierrno : 0,
742 "ERROR: Check-in of %s failed", rcs->path);
743 error (0, status == -1 ? ierrno : 0,
744 "ERROR: Check-in of %s failed", rcs->path);
748 (void) RCS_unlock(rcs, vbranch, 0);
749 RCS_rewrite (rcs, NULL, NULL);
757 * Add the vendor branch tag and all the specified import release tags to the
758 * RCS file. The vendor branch tag goes on the branch root (1.1.1) while the
759 * vendor release tags go on the newly added leaf of the branch (1.1.1.1,
763 add_tags (RCSNode *rcs, char *vfile, char *vtag, int targc, char **targv)
768 struct file_info finfo;
773 if ((retcode = RCS_settag(rcs, vtag, vbranch)) != 0)
776 fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
777 "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
778 error (0, retcode == -1 ? ierrno : 0,
779 "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
782 RCS_rewrite (rcs, NULL, NULL);
784 memset (&finfo, 0, sizeof finfo);
786 /* Not used, so don't worry about it. */
787 finfo.update_dir = NULL;
788 finfo.fullname = finfo.file;
789 finfo.repository = repository;
790 finfo.entries = NULL;
792 vers = Version_TS (&finfo, NULL, vtag, NULL, 1, 0);
793 for (i = 0; i < targc; i++)
795 if ((retcode = RCS_settag (rcs, targv[i], vers->vn_rcs)) == 0)
796 RCS_rewrite (rcs, NULL, NULL);
800 fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
801 "WARNING: Couldn't add tag %s to %s", targv[i],
803 error (0, retcode == -1 ? ierrno : 0,
804 "WARNING: Couldn't add tag %s to %s", targv[i],
813 * Stolen from rcs/src/rcsfnms.c, and adapted/extended.
817 char *suffix, *comlead;
820 static const struct compair comtable[] =
824 * comtable pairs each filename suffix with a comment leader. The comment
825 * leader is placed before each line generated by the $Log keyword. This
826 * table is used to guess the proper comment leader from the working file's
827 * suffix during initial ci (see InitAdmin()). Comment leaders are needed for
828 * languages without multiline comments; for others they are optional.
830 * I believe that the comment leader is unused if you are using RCS 5.7, which
831 * decides what leader to use based on the text surrounding the $Log keyword
832 * rather than a specified comment leader.
834 {"a", "-- "}, /* Ada */
837 {"asm", ";; "}, /* assembler (MS-DOS) */
838 {"ads", "-- "}, /* Ada */
839 {"bas", "' "}, /* Visual Basic code */
840 {"bat", ":: "}, /* batch (MS-DOS) */
841 {"body", "-- "}, /* Ada */
842 {"c", " * "}, /* C */
843 {"c++", "// "}, /* C++ in all its infinite guises */
847 {"m", "// "}, /* Objective-C */
848 {"cl", ";;; "}, /* Common Lisp */
849 {"cmd", ":: "}, /* command (OS/2) */
850 {"cmf", "c "}, /* CM Fortran */
851 {"cs", " * "}, /* C* */
852 {"csh", "# "}, /* shell */
853 {"dlg", " * "}, /* MS Windows dialog file */
854 {"e", "# "}, /* efl */
855 {"epsf", "% "}, /* encapsulated postscript */
856 {"epsi", "% "}, /* encapsulated postscript */
857 {"el", "; "}, /* Emacs Lisp */
858 {"f", "c "}, /* Fortran */
860 {"frm", "' "}, /* Visual Basic form */
861 {"h", " * "}, /* C-header */
862 {"hh", "// "}, /* C++ header */
865 {"in", "# "}, /* for Makefile.in */
866 {"l", " * "}, /* lex (conflict between lex and
868 {"mac", ";; "}, /* macro (DEC-10, MS-DOS, PDP-11,
870 {"mak", "# "}, /* makefile, e.g. Visual C++ */
871 {"me", ".\\\" "}, /* me-macros t/nroff */
872 {"ml", "; "}, /* mocklisp */
873 {"mm", ".\\\" "}, /* mm-macros t/nroff */
874 {"ms", ".\\\" "}, /* ms-macros t/nroff */
875 {"man", ".\\\" "}, /* man-macros t/nroff */
876 {"1", ".\\\" "}, /* feeble attempt at man pages... */
885 {"p", " * "}, /* pascal */
887 {"pl", "# "}, /* perl (conflict with Prolog) */
888 {"ps", "% "}, /* postscript */
889 {"psw", "% "}, /* postscript wrap */
890 {"pswm", "% "}, /* postscript wrap */
891 {"r", "# "}, /* ratfor */
892 {"rc", " * "}, /* Microsoft Windows resource file */
893 {"red", "% "}, /* psl/rlisp */
895 {"s", "! "}, /* assembler */
898 {"s", "| "}, /* assembler */
901 {"s", "/ "}, /* assembler */
904 {"s", "# "}, /* assembler */
907 {"s", "# "}, /* assembler */
908 {"S", "# "}, /* Macro assembler */
910 {"sh", "# "}, /* shell */
911 {"sl", "% "}, /* psl */
912 {"spec", "-- "}, /* Ada */
913 {"tex", "% "}, /* tex */
914 {"y", " * "}, /* yacc */
915 {"ye", " * "}, /* yacc-efl */
916 {"yr", " * "}, /* yacc-ratfor */
917 {"", "# "}, /* default for empty suffix */
918 {NULL, "# "} /* default for unknown suffix; */
919 /* must always be last */
925 get_comment (const char *user)
932 suffix_path = xmalloc (strlen (user) + 5);
933 cp = strrchr (user, '.');
939 * Convert to lower-case, since we are not concerned about the
940 * case-ness of the suffix.
942 (void) strcpy (suffix_path, cp);
943 for (cp = suffix_path; *cp; cp++)
944 if (isupper ((unsigned char) *cp))
946 suffix = suffix_path;
949 suffix = ""; /* will use the default */
952 if (comtable[i].suffix == NULL)
954 /* Default. Note we'll always hit this case before we
956 retval = comtable[i].comlead;
959 if (strcmp (suffix, comtable[i].suffix) == 0)
961 retval = comtable[i].comlead;
969 /* Create a new RCS file from scratch.
971 * This probably should be moved to rcs.c now that it is called from
972 * places outside import.c.
975 * message Log message for the addition. Not used if add_vhead == NULL.
976 * rcs Filename of the RCS file to create.
977 * user Filename of the file to serve as the contents of the initial
978 * revision. Even if add_vhead is NULL, we use this to determine
979 * the modes to give the new RCS file.
980 * add_vhead Revision number of head that we are adding. Normally 1.1 but
981 * could be another revision as long as ADD_VBRANCH is a branch
982 * from it. If NULL, then just add an empty file without any
983 * revisions (similar to the one created by "rcs -i").
984 * key_opt Keyword expansion mode, e.g., "b" for binary. NULL means the
987 * Vendor branch to import to, or NULL if none. If non-NULL, then
988 * vtag should also be non-NULL.
990 * targc Number of elements in TARGV.
991 * targv The list of tags to attached to this imported revision.
992 * desctext If non-NULL, description for the file. If NULL, the
993 * description will be empty.
994 * desclen The number of bytes in desctext.
995 * add_logfp Write errors to here as well as via error (), or NULL if we
996 * should use only error ().
999 * Return value is 0 for success, or nonzero for failure (in which
1000 * case an error message will have already been printed).
1003 add_rcs_file (const char *message, const char *rcs, const char *user,
1004 const char *add_vhead, const char *key_opt,
1005 const char *add_vbranch, const char *vtag, int targc,
1006 char **targv, const char *desctext, size_t desclen,
1009 FILE *fprcs, *fpuser;
1013 char altdate1[MAXDATELEN];
1015 int i, ierrno, err = 0;
1018 const char *userfile;
1019 char *free_opt = NULL;
1025 /* Note that as the code stands now, the -k option overrides any
1026 settings in wrappers (whether CVSROOT/cvswrappers, -W, or
1027 whatever). Some have suggested this should be the other way
1028 around. As far as I know the documentation doesn't say one way
1029 or the other. Before making a change of this sort, should think
1030 about what is best, document it (in cvs.texinfo and NEWS), &c. */
1032 if (key_opt == NULL)
1034 if (wrap_name_has (user, WRAP_RCSOPTION))
1036 key_opt = free_opt = wrap_rcsoption (user, 0);
1040 tocvsPath = wrap_tocvs_process_file (user);
1041 userfile = (tocvsPath == NULL ? user : tocvsPath);
1043 /* Opening in text mode is probably never the right thing for the
1044 server (because the protocol encodes text files in a fashion
1045 which does not depend on what the client or server OS is, as
1046 documented in cvsclient.texi), but as long as the server just
1047 runs on unix it is a moot point. */
1049 /* If PreservePermissions is set, then make sure that the file
1050 is a plain file before trying to open it. Longstanding (although
1051 often unpopular) CVS behavior has been to follow symlinks, so we
1052 maintain that behavior if PreservePermissions is not on.
1054 NOTE: this error message used to be `cannot fstat', but is now
1055 `cannot lstat'. I don't see a way around this, since we must
1056 stat the file before opening it. -twp */
1058 if (CVS_LSTAT (userfile, &sb) < 0)
1060 /* not fatal, continue import */
1061 if (add_logfp != NULL)
1062 fperrmsg (add_logfp, 0, errno,
1063 "ERROR: cannot lstat file %s", userfile);
1064 error (0, errno, "cannot lstat file %s", userfile);
1067 file_type = sb.st_mode & S_IFMT;
1070 if (!preserve_perms || file_type == S_IFREG)
1072 fpuser = CVS_FOPEN (userfile,
1073 ((key_opt != NULL && strcmp (key_opt, "b") == 0)
1079 /* not fatal, continue import */
1080 if (add_logfp != NULL)
1081 fperrmsg (add_logfp, 0, errno,
1082 "ERROR: cannot read file %s", userfile);
1083 error (0, errno, "ERROR: cannot read file %s", userfile);
1088 fprcs = CVS_FOPEN (rcs, "w+b");
1092 goto write_error_noclose;
1098 if (add_vhead != NULL)
1100 if (fprintf (fprcs, "head %s;\012", add_vhead) < 0)
1105 if (fprintf (fprcs, "head ;\012") < 0)
1109 if (add_vbranch != NULL)
1111 if (fprintf (fprcs, "branch %s;\012", add_vbranch) < 0)
1114 if (fprintf (fprcs, "access ;\012") < 0 ||
1115 fprintf (fprcs, "symbols ") < 0)
1120 for (i = targc - 1; i >= 0; i--)
1122 /* RCS writes the symbols backwards */
1123 assert (add_vbranch != NULL);
1124 if (fprintf (fprcs, "%s:%s.1 ", targv[i], add_vbranch) < 0)
1128 if (add_vbranch != NULL)
1130 if (fprintf (fprcs, "%s:%s", vtag, add_vbranch) < 0)
1133 if (fprintf (fprcs, ";\012") < 0)
1136 if (fprintf (fprcs, "locks ; strict;\012") < 0 ||
1137 /* XXX - make sure @@ processing works in the RCS file */
1138 fprintf (fprcs, "comment @%s@;\012", get_comment (user)) < 0)
1143 if (key_opt != NULL && strcmp (key_opt, "kv") != 0)
1145 if (fprintf (fprcs, "expand @%s@;\012", key_opt) < 0)
1151 if (fprintf (fprcs, "\012") < 0)
1154 /* Write the revision(s), with the date and author and so on
1155 (that is "delta" rather than "deltatext" from rcsfile(5)). */
1156 if (add_vhead != NULL)
1158 if (use_file_modtime)
1162 ftm = gmtime (&now);
1163 (void) sprintf (altdate1, DATEFORM,
1164 ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
1165 ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
1166 ftm->tm_min, ftm->tm_sec);
1167 author = getcaller ();
1169 if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
1170 fprintf (fprcs, "date %s; author %s; state Exp;\012",
1171 altdate1, author) < 0)
1174 if (fprintf (fprcs, "branches") < 0)
1176 if (add_vbranch != NULL)
1178 if (fprintf (fprcs, " %s.1", add_vbranch) < 0)
1181 if (fprintf (fprcs, ";\012") < 0)
1184 if (fprintf (fprcs, "next ;\012") < 0)
1187 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1188 /* Store initial permissions if necessary. */
1191 if (file_type == S_IFLNK)
1193 char *link = xreadlink (userfile);
1194 if (fprintf (fprcs, "symlink\t@") < 0 ||
1195 expand_at_signs (link, strlen (link), fprcs) < 0 ||
1196 fprintf (fprcs, "@;\012") < 0)
1202 if (fprintf (fprcs, "owner\t%u;\012", sb.st_uid) < 0)
1204 if (fprintf (fprcs, "group\t%u;\012", sb.st_gid) < 0)
1206 if (fprintf (fprcs, "permissions\t%o;\012",
1207 sb.st_mode & 07777) < 0)
1211 case S_IFREG: break;
1214 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1215 if (fprintf (fprcs, "special\t%s %lu;\012",
1216 (file_type == S_IFCHR
1219 (unsigned long) sb.st_rdev) < 0)
1223 "can't import %s: unable to import device files on this system",
1229 "can't import %s: unknown kind of special file",
1236 if (add_vbranch != NULL)
1238 if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1239 fprintf (fprcs, "date %s; author %s; state Exp;\012",
1240 altdate1, author) < 0 ||
1241 fprintf (fprcs, "branches ;\012") < 0 ||
1242 fprintf (fprcs, "next ;\012") < 0)
1245 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1246 /* Store initial permissions if necessary. */
1249 if (file_type == S_IFLNK)
1251 char *link = xreadlink (userfile);
1252 if (fprintf (fprcs, "symlink\t@") < 0 ||
1253 expand_at_signs (link, strlen (link), fprcs) < 0 ||
1254 fprintf (fprcs, "@;\012") < 0)
1260 if (fprintf (fprcs, "owner\t%u;\012", sb.st_uid) < 0 ||
1261 fprintf (fprcs, "group\t%u;\012", sb.st_gid) < 0 ||
1262 fprintf (fprcs, "permissions\t%o;\012",
1263 sb.st_mode & 07777) < 0)
1268 case S_IFREG: break;
1271 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1272 if (fprintf (fprcs, "special\t%s %lu;\012",
1273 (file_type == S_IFCHR
1276 (unsigned long) sb.st_rdev) < 0)
1280 "can't import %s: unable to import device files on this system",
1286 "cannot import %s: special file of unknown type",
1293 if (fprintf (fprcs, "\012") < 0)
1298 /* Now write the description (possibly empty). */
1299 if (fprintf (fprcs, "\012desc\012") < 0 ||
1300 fprintf (fprcs, "@") < 0)
1302 if (desctext != NULL)
1304 /* The use of off_t not size_t for the second argument is very
1305 strange, since we are dealing with something which definitely
1307 if (expand_at_signs (desctext, (off_t) desclen, fprcs) < 0)
1310 if (fprintf (fprcs, "@\012\012\012") < 0)
1313 /* Now write the log messages and contents for the revision(s) (that
1314 is, "deltatext" rather than "delta" from rcsfile(5)). */
1315 if (add_vhead != NULL)
1317 if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
1318 fprintf (fprcs, "log\012@") < 0)
1320 if (add_vbranch != NULL)
1322 /* We are going to put the log message in the revision on the
1323 branch. So putting it here too seems kind of redundant, I
1324 guess (and that is what CVS has always done, anyway). */
1325 if (fprintf (fprcs, "Initial revision\012") < 0)
1330 if (expand_at_signs (message, (off_t) strlen (message), fprcs) < 0)
1333 if (fprintf (fprcs, "@\012") < 0 ||
1334 fprintf (fprcs, "text\012@") < 0)
1339 /* Now copy over the contents of the file, expanding at signs.
1340 If preserve_perms is set, do this only for regular files. */
1341 if (!preserve_perms || file_type == S_IFREG)
1348 len = fread (buf, 1, sizeof buf, fpuser);
1351 if (ferror (fpuser))
1352 error (1, errno, "cannot read file %s for copying",
1356 if (expand_at_signs (buf, len, fprcs) < 0)
1360 if (fprintf (fprcs, "@\012\012") < 0)
1362 if (add_vbranch != NULL)
1364 if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1365 fprintf (fprcs, "log\012@") < 0 ||
1366 expand_at_signs (message,
1367 (off_t) strlen (message), fprcs) < 0 ||
1368 fprintf (fprcs, "@\012text\012") < 0 ||
1369 fprintf (fprcs, "@@\012") < 0)
1374 if (fclose (fprcs) == EOF)
1377 goto write_error_noclose;
1379 /* Close fpuser only if we opened it to begin with. */
1382 if (fclose (fpuser) < 0)
1383 error (0, errno, "cannot close %s", user);
1387 * Fix the modes on the RCS files. The user modes of the original
1388 * user file are propagated to the group and other modes as allowed
1389 * by the repository umask, except that all write permissions are
1392 mode = (sb.st_mode |
1393 (sb.st_mode & S_IRWXU) >> 3 |
1394 (sb.st_mode & S_IRWXU) >> 6) &
1396 ~(S_IWRITE | S_IWGRP | S_IWOTH);
1397 if (chmod (rcs, mode) < 0)
1400 if (add_logfp != NULL)
1401 fperrmsg (add_logfp, 0, ierrno,
1402 "WARNING: cannot change mode of file %s", rcs);
1403 error (0, ierrno, "WARNING: cannot change mode of file %s", rcs);
1407 if (unlink_file_dir (tocvsPath) < 0)
1408 error (0, errno, "cannot remove %s", tocvsPath);
1409 if (free_opt != NULL)
1415 if (fclose (fprcs) < 0)
1416 error (0, errno, "cannot close %s", rcs);
1417 write_error_noclose:
1418 if (fclose (fpuser) < 0)
1419 error (0, errno, "cannot close %s", user);
1420 if (add_logfp != NULL)
1421 fperrmsg (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
1422 error (0, ierrno, "ERROR: cannot write file %s", rcs);
1423 if (ierrno == ENOSPC)
1425 if (CVS_UNLINK (rcs) < 0)
1426 error (0, errno, "cannot remove %s", rcs);
1427 if (add_logfp != NULL)
1428 fperrmsg (add_logfp, 0, 0, "ERROR: out of space - aborting");
1429 error (1, 0, "ERROR: out of space - aborting");
1433 if (unlink_file_dir (tocvsPath) < 0)
1434 error (0, errno, "cannot remove %s", tocvsPath);
1436 if (free_opt != NULL)
1445 * Write SIZE bytes at BUF to FP, expanding @ signs into double @
1446 * signs. If an error occurs, return a negative value and set errno
1447 * to indicate the error. If not, return a nonnegative value.
1450 expand_at_signs (const char *buf, off_t size, FILE *fp)
1452 register const char *cp, *next;
1455 while ((next = memchr (cp, '@', size)) != NULL)
1457 size_t len = ++next - cp;
1458 if (fwrite (cp, 1, len, fp) != len)
1460 if (putc ('@', fp) == EOF)
1466 if (fwrite (cp, 1, size, fp) != size)
1473 * Write an update message to (potentially) the screen and the log file.
1476 add_log (int ch, char *fname)
1478 if (!really_quiet) /* write to terminal */
1483 cvs_output (buf, 2);
1486 cvs_output (repository + repos_len + 1, 0);
1487 cvs_output ("/", 1);
1489 else if (repository[0] != '\0')
1491 cvs_output (repository, 0);
1492 cvs_output ("/", 1);
1494 cvs_output (fname, 0);
1495 cvs_output ("\n", 1);
1498 if (repos_len) /* write to logfile */
1499 (void) fprintf (logfp, "%c %s/%s\n", ch,
1500 repository + repos_len + 1, fname);
1501 else if (repository[0])
1502 (void) fprintf (logfp, "%c %s/%s\n", ch, repository, fname);
1504 (void) fprintf (logfp, "%c %s\n", ch, fname);
1508 * This is the recursive function that walks the argument directory looking
1509 * for sub-directories that have CVS administration files in them and updates
1512 * Note that we do not follow symbolic links here, which is a feature!
1515 import_descend_dir (char *message, char *dir, char *vtag, int targc, char **targv)
1517 struct saved_cwd cwd;
1524 if (save_cwd (&cwd))
1526 fperrmsg (logfp, 0, 0, "ERROR: cannot get working directory");
1530 /* Concatenate DIR to the end of REPOSITORY. */
1531 if (repository[0] == '\0')
1533 char *new = xstrdup (dir);
1539 char *new = xmalloc (strlen (repository) + strlen (dir) + 10);
1540 strcpy (new, repository);
1541 (void) strcat (new, "/");
1542 (void) strcat (new, dir);
1547 #ifdef CLIENT_SUPPORT
1548 if (!quiet && !current_parsed_root->isremote)
1552 error (0, 0, "Importing %s", repository);
1554 if ( CVS_CHDIR (dir) < 0)
1557 fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository);
1558 error (0, ierrno, "ERROR: cannot chdir to %s", repository);
1562 #ifdef CLIENT_SUPPORT
1563 if (!current_parsed_root->isremote && !isdir (repository))
1565 if (!isdir (repository))
1568 rcs = xmalloc (strlen (repository) + sizeof (RCSEXT) + 5);
1569 (void) sprintf (rcs, "%s%s", repository, RCSEXT);
1570 if (isfile (repository) || isfile(rcs))
1572 fperrmsg (logfp, 0, 0,
1573 "ERROR: %s is a file, should be a directory!",
1575 error (0, 0, "ERROR: %s is a file, should be a directory!",
1580 if (noexec == 0 && CVS_MKDIR (repository, 0777) < 0)
1583 fperrmsg (logfp, 0, ierrno,
1584 "ERROR: cannot mkdir %s -- not added", repository);
1586 "ERROR: cannot mkdir %s -- not added", repository);
1591 err = import_descend (message, vtag, targc, targv);
1595 if ((cp = strrchr (repository, '/')) != NULL)
1598 repository[0] = '\0';
1599 if (restore_cwd (&cwd, NULL))
1600 exit (EXIT_FAILURE);