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.
23 static char *get_comment PROTO((char *user));
24 static int add_rev PROTO((char *message, RCSNode *rcs, char *vfile,
26 static int add_tags PROTO((RCSNode *rcs, char *vfile, char *vtag, int targc,
28 static int import_descend PROTO((char *message, char *vtag, int targc, char *targv[]));
29 static int import_descend_dir PROTO((char *message, char *dir, char *vtag,
30 int targc, char *targv[]));
31 static int process_import_file PROTO((char *message, char *vfile, char *vtag,
32 int targc, char *targv[]));
33 static int update_rcs_file PROTO((char *message, char *vfile, char *vtag, int targc,
34 char *targv[], int inattic));
35 static void add_log PROTO((int ch, char *fname));
41 static char *repository;
43 static int use_file_modtime;
44 static char *keyword_opt = NULL;
46 static const char *const import_usage[] =
48 "Usage: %s %s [-d] [-k subst] [-I ign] [-m msg] [-b branch]\n",
49 " [-W spec] repository vendor-tag release-tags...\n",
50 "\t-d\tUse the file's modification time as the time of import.\n",
51 "\t-k sub\tSet default RCS keyword substitution mode.\n",
52 "\t-I ign\tMore files to ignore (! to reset).\n",
53 "\t-b bra\tVendor branch id.\n",
54 "\t-m msg\tLog message.\n",
55 "\t-W spec\tWrappers specification line.\n",
56 "(Specify the --help global option for a list of other help options)\n",
68 int i, c, msglen, err;
71 struct logfile_info *li;
79 vbranch = xstrdup (CVSBRANCH);
81 while ((c = getopt (argc, argv, "+Qqdb:m:I:k:W:")) != -1)
88 /* The CVS 1.5 client sends these options (in addition to
89 Global_option requests), so we must ignore them. */
93 "-q or -Q must be specified before \"%s\"",
100 /* CVS 1.10 and older clients will send this, but it
101 doesn't do any good. So tell the user we can't
102 cope, rather than silently losing. */
104 "warning: not setting the time of import from the file");
105 error (0, 0, "due to client limitations");
108 use_file_modtime = 1;
112 vbranch = xstrdup (optarg);
115 #ifdef FORCE_USE_EDITOR
120 message = xstrdup(optarg);
126 /* RCS_check_kflag returns strings of the form -kxx. We
127 only use it for validation, so we can free the value
128 as soon as it is returned. */
129 free (RCS_check_kflag (optarg));
130 keyword_opt = optarg;
133 wrap_add (optarg, 0);
137 usage (import_usage);
144 usage (import_usage);
146 #ifdef SERVER_SUPPORT
147 /* This is for handling the Checkin-time request. It might seem a
148 bit odd to enable the use_file_modtime code even in the case
149 where Checkin-time was not sent for a particular file. The
150 effect is that we use the time of upload, rather than the time
151 when we call RCS_checkin. Since those times are both during
152 CVS's run, that seems OK, and it is easier to implement than
153 putting the "was Checkin-time sent" flag in CVS/Entries or some
157 use_file_modtime = 1;
160 for (i = 1; i < argc; i++) /* check the tags for validity */
164 RCS_check_tag (argv[i]);
165 for (j = 1; j < i; j++)
166 if (strcmp (argv[j], argv[i]) == 0)
167 error (1, 0, "tag `%s' was specified more than once", argv[i]);
170 /* XXX - this should be a module, not just a pathname */
171 if (! isabsolute (argv[0])
172 && pathname_levels (argv[0]) == 0)
174 if (current_parsed_root == NULL)
176 error (0, 0, "missing CVSROOT environment variable\n");
177 error (1, 0, "Set it or specify the '-d' option to %s.",
180 repository = xmalloc (strlen (current_parsed_root->directory)
183 (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
184 repos_len = strlen (current_parsed_root->directory);
188 /* It is somewhere between a security hole and "unexpected" to
189 let the client start mucking around outside the cvsroot
190 (wouldn't get the right CVSROOT configuration, &c). */
191 error (1, 0, "directory %s not relative within the repository",
196 * Consistency checks on the specified vendor branch. It must be
197 * composed of only numbers and dots ('.'). Also, for now we only
198 * support branching to a single level, so the specified vendor branch
199 * must only have two dots in it (like "1.1.1").
201 for (cp = vbranch; *cp != '\0'; cp++)
202 if (!isdigit ((unsigned char) *cp) && *cp != '.')
203 error (1, 0, "%s is not a numeric branch", vbranch);
204 if (numdots (vbranch) != 2)
205 error (1, 0, "Only branches with two dots are supported: %s", vbranch);
206 vhead = xstrdup (vbranch);
207 cp = strrchr (vhead, '.');
210 #ifdef CLIENT_SUPPORT
211 if (current_parsed_root->isremote)
213 /* For rationale behind calling start_server before do_editor, see
220 #ifdef SERVER_SUPPORT
225 do_editor ((char *) NULL, &message,
226 #ifdef CLIENT_SUPPORT
227 current_parsed_root->isremote ? (char *) NULL :
232 do_verify (&message, repository);
233 msglen = message == NULL ? 0 : strlen (message);
234 if (msglen == 0 || message[msglen - 1] != '\n')
236 char *nm = xmalloc (msglen + 2);
240 (void) strcpy (nm, message);
243 (void) strcat (nm + msglen, "\n");
247 #ifdef CLIENT_SUPPORT
248 if (current_parsed_root->isremote)
252 if (vbranch[0] != '\0')
253 option_with_arg ("-b", vbranch);
254 option_with_arg ("-m", message ? message : "");
255 if (keyword_opt != NULL)
256 option_with_arg ("-k", keyword_opt);
257 /* The only ignore processing which takes place on the server side
258 is the CVSROOT/cvsignore file. But if the user specified -I !,
259 the documented behavior is to not process said file. */
260 if (ign_inhibit_server)
269 for (i = 0; i < argc; ++i)
274 client_import_setup (repository);
275 err = import_descend (message, argv[1], argc - 2, argv + 2);
276 client_import_done ();
282 send_to_server ("import\012", 0);
283 err += get_responses_and_close ();
288 if (!safe_location ( NULL ))
290 error (1, 0, "attempt to import the repository");
294 * Make all newly created directories writable. Should really use a more
295 * sophisticated security mechanism here.
297 (void) umask (cvsumask);
298 make_directories (repository);
300 /* Create the logfile that will be logged upon completion */
301 if ((logfp = cvs_temp_file (&tmpfile)) == NULL)
302 error (1, errno, "cannot create temporary file `%s'", tmpfile);
303 /* On systems where we can unlink an open file, do so, so it will go
304 away no matter how we exit. FIXME-maybe: Should be checking for
305 errors but I'm not sure which error(s) we get if we are on a system
306 where one can't unlink open files. */
307 (void) CVS_UNLINK (tmpfile);
308 (void) fprintf (logfp, "\nVendor Tag:\t%s\n", argv[1]);
309 (void) fprintf (logfp, "Release Tags:\t");
310 for (i = 2; i < argc; i++)
311 (void) fprintf (logfp, "%s\n\t\t", argv[i]);
312 (void) fprintf (logfp, "\n");
315 err = import_descend (message, argv[1], argc - 2, argv + 2);
322 cvs_output_tagged ("+importmergecmd", NULL);
323 cvs_output_tagged ("newline", NULL);
324 sprintf (buf, "%d", conflicts);
325 cvs_output_tagged ("conflicts", buf);
326 cvs_output_tagged ("text", " conflicts created by this import.");
327 cvs_output_tagged ("newline", NULL);
328 cvs_output_tagged ("text",
329 "Use the following command to help the merge:");
330 cvs_output_tagged ("newline", NULL);
331 cvs_output_tagged ("newline", NULL);
332 cvs_output_tagged ("text", "\t");
333 cvs_output_tagged ("text", program_name);
334 if (CVSroot_cmdline != NULL)
336 cvs_output_tagged ("text", " -d ");
337 cvs_output_tagged ("text", CVSroot_cmdline);
339 cvs_output_tagged ("text", " checkout -j");
340 cvs_output_tagged ("mergetag1", "<prev_rel_tag>");
341 cvs_output_tagged ("text", " -j");
342 cvs_output_tagged ("mergetag2", argv[2]);
343 cvs_output_tagged ("text", " ");
344 cvs_output_tagged ("repository", argv[0]);
345 cvs_output_tagged ("newline", NULL);
346 cvs_output_tagged ("newline", NULL);
347 cvs_output_tagged ("-importmergecmd", NULL);
350 /* FIXME: I'm not sure whether we need to put this information
351 into the loginfo. If we do, then note that it does not
352 report any required -d option. There is no particularly
353 clean way to tell the server about the -d option used by
355 (void) fprintf (logfp, "\n%d conflicts created by this import.\n",
357 (void) fprintf (logfp,
358 "Use the following command to help the merge:\n\n");
359 (void) fprintf (logfp, "\t%s checkout ", program_name);
360 (void) fprintf (logfp, "-j%s:yesterday -j%s %s\n\n",
361 argv[1], argv[1], argv[0]);
366 cvs_output ("\nNo conflicts created by this import\n\n", 0);
367 (void) fprintf (logfp, "\nNo conflicts created by this import\n\n");
371 * Write out the logfile and clean up.
376 p->delproc = update_delproc;
377 p->key = xstrdup ("- Imported sources");
378 li = (struct logfile_info *) xmalloc (sizeof (struct logfile_info));
380 li->tag = xstrdup (vbranch);
381 li->rev_old = li->rev_new = NULL;
382 p->data = (char *) li;
383 (void) addnode (ulist, p);
384 Update_Logfile (repository, message, logfp, ulist);
386 if (fclose (logfp) < 0)
387 error (0, errno, "error closing %s", tmpfile);
389 /* Make sure the temporary file goes away, even on systems that don't let
390 you delete a file that's in use. */
391 if (CVS_UNLINK (tmpfile) < 0 && !existence_error (errno))
392 error (0, errno, "cannot remove %s", tmpfile);
404 /* Process all the files in ".", then descend into other directories.
405 Returns 0 for success, or >0 on error (in which case a message
406 will have been printed). */
408 import_descend (message, vtag, targc, targv)
417 List *dirlist = NULL;
419 /* first, load up any per-directory ignore lists */
420 ign_add_file (CVSDOTIGNORE, 1);
421 wrap_add_file (CVSDOTWRAPPER, 1);
423 if ((dirp = CVS_OPENDIR (".")) == NULL)
425 error (0, errno, "cannot open directory");
431 while ((dp = CVS_READDIR (dirp)) != NULL)
433 if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0)
434 goto one_more_time_boys;
435 #ifdef SERVER_SUPPORT
436 /* CVS directories are created in the temp directory by
437 server.c because it doesn't special-case import. So
438 don't print a message about them, regardless of -I!. */
439 if (server_active && strcmp (dp->d_name, CVSADM) == 0)
440 goto one_more_time_boys;
442 if (ign_name (dp->d_name))
444 add_log ('I', dp->d_name);
445 goto one_more_time_boys;
450 (dp->d_type == DT_DIR
451 || (dp->d_type == DT_UNKNOWN && isdir (dp->d_name)))
455 && !wrap_name_has (dp->d_name, WRAP_TOCVS)
464 n->key = xstrdup (dp->d_name);
470 || (dp->d_type == DT_UNKNOWN && islink (dp->d_name))
476 add_log ('L', dp->d_name);
481 #ifdef CLIENT_SUPPORT
482 if (current_parsed_root->isremote)
483 err += client_process_import_file (message, dp->d_name,
486 keyword_opt != NULL &&
487 keyword_opt[0] == 'b',
491 err += process_import_file (message, dp->d_name,
499 error (0, errno, "cannot read directory");
502 (void) CVS_CLOSEDIR (dirp);
509 head = dirlist->list;
510 for (p = head->next; p != head; p = p->next)
512 err += import_descend_dir (message, p->key, vtag, targc, targv);
522 * Process the argument import file.
525 process_import_file (message, vfile, vtag, targc, targv)
535 rcs = xmalloc (strlen (repository) + strlen (vfile) + sizeof (RCSEXT)
537 (void) sprintf (rcs, "%s/%s%s", repository, vfile, RCSEXT);
542 attic_name = xmalloc (strlen (repository) + strlen (vfile) +
543 sizeof (CVSATTIC) + sizeof (RCSEXT) + 10);
544 (void) sprintf (attic_name, "%s/%s/%s%s", repository, CVSATTIC,
546 if (!isfile (attic_name))
549 char *free_opt = NULL;
550 char *our_opt = keyword_opt;
554 * A new import source file; it doesn't exist as a ,v within the
555 * repository nor in the Attic -- create it anew.
557 add_log ('N', vfile);
559 #ifdef SERVER_SUPPORT
560 /* The most reliable information on whether the file is binary
561 is what the client told us. That is because if the client had
562 the wrong idea about binaryness, it corrupted the file, so
563 we might as well believe the client. */
569 /* Reading all the entries for each file is fairly silly, and
570 probably slow. But I am too lazy at the moment to do
572 entries = Entries_Open (0, NULL);
573 node = findnode_fn (entries, vfile);
576 Entnode *entdata = (Entnode *) node->data;
577 if (entdata->type == ENT_FILE)
579 assert (entdata->options[0] == '-'
580 && entdata->options[1] == 'k');
581 our_opt = xstrdup (entdata->options + 2);
585 Entries_Close (entries);
589 retval = add_rcs_file (message, rcs, vfile, vhead, our_opt,
590 vbranch, vtag, targc, targv,
592 if (free_opt != NULL)
603 * an rcs file exists. have to do things the official, slow, way.
605 return (update_rcs_file (message, vfile, vtag, targc, targv, inattic));
609 * The RCS file exists; update it by adding the new import file to the
610 * (possibly already existing) vendor branch.
613 update_rcs_file (message, vfile, vtag, targc, targv, inattic)
625 struct file_info finfo;
627 memset (&finfo, 0, sizeof finfo);
629 /* Not used, so don't worry about it. */
630 finfo.update_dir = NULL;
631 finfo.fullname = finfo.file;
632 finfo.repository = repository;
633 finfo.entries = NULL;
635 vers = Version_TS (&finfo, (char *) NULL, vbranch, (char *) NULL,
637 if (vers->vn_rcs != NULL
638 && !RCS_isdead(vers->srcfile, vers->vn_rcs))
643 * The rcs file does have a revision on the vendor branch. Compare
644 * this revision with the import file; if they match exactly, there
645 * is no need to install the new import file as a new revision to the
646 * branch. Just tag the revision with the new import tags.
648 * This is to try to cut down the number of "C" conflict messages for
649 * locally modified import source files.
651 tocvsPath = wrap_tocvs_process_file (vfile);
652 /* FIXME: Why don't we pass tocvsPath to RCS_cmp_file if it is
654 expand = vers->srcfile->expand != NULL &&
655 vers->srcfile->expand[0] == 'b' ? "-kb" : "-ko";
656 different = RCS_cmp_file (vers->srcfile, vers->vn_rcs, expand, vfile);
658 if (unlink_file_dir (tocvsPath) < 0)
659 error (0, errno, "cannot remove %s", tocvsPath);
666 * The two files are identical. Just update the tags, print the
667 * "U", signifying that the file has changed, but needs no
668 * attention, and we're done.
670 if (add_tags (vers->srcfile, vfile, vtag, targc, targv))
672 add_log ('U', vfile);
678 /* We may have failed to parse the RCS file; check just in case */
679 if (vers->srcfile == NULL ||
680 add_rev (message, vers->srcfile, vfile, vers->vn_rcs) ||
681 add_tags (vers->srcfile, vfile, vtag, targc, targv))
687 if (vers->srcfile->branch == NULL || inattic ||
688 strcmp (vers->srcfile->branch, vbranch) != 0)
695 add_log (letter, vfile);
702 * Add the revision to the vendor branch
705 add_rev (message, rcs, vfile, vers)
711 int locked, status, ierrno;
720 /* Before RCS_lock existed, we were directing stdout, as well as
721 stderr, from the RCS command, to DEVNULL. I wouldn't guess that
722 was necessary, but I don't know for sure. */
723 /* Earlier versions of this function printed a `fork failed' error
724 when RCS_lock returned an error code. That's not appropriate
725 now that RCS_lock is librarified, but should the error text be
727 if (RCS_lock (rcs, vbranch, 1) != 0)
730 RCS_rewrite (rcs, NULL, NULL);
732 tocvsPath = wrap_tocvs_process_file (vfile);
734 status = RCS_checkin (rcs, tocvsPath == NULL ? vfile : tocvsPath,
736 (RCS_FLAGS_QUIET | RCS_FLAGS_KEEPFILE
737 | (use_file_modtime ? RCS_FLAGS_MODTIME : 0)));
740 if ((tocvsPath != NULL) && (unlink_file_dir (tocvsPath) < 0))
741 error (0, errno, "cannot remove %s", tocvsPath);
747 fperrmsg (logfp, 0, status == -1 ? ierrno : 0,
748 "ERROR: Check-in of %s failed", rcs->path);
749 error (0, status == -1 ? ierrno : 0,
750 "ERROR: Check-in of %s failed", rcs->path);
754 (void) RCS_unlock(rcs, vbranch, 0);
755 RCS_rewrite (rcs, NULL, NULL);
763 * Add the vendor branch tag and all the specified import release tags to the
764 * RCS file. The vendor branch tag goes on the branch root (1.1.1) while the
765 * vendor release tags go on the newly added leaf of the branch (1.1.1.1,
769 add_tags (rcs, vfile, vtag, targc, targv)
779 struct file_info finfo;
784 if ((retcode = RCS_settag(rcs, vtag, vbranch)) != 0)
787 fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
788 "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
789 error (0, retcode == -1 ? ierrno : 0,
790 "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
793 RCS_rewrite (rcs, NULL, NULL);
795 memset (&finfo, 0, sizeof finfo);
797 /* Not used, so don't worry about it. */
798 finfo.update_dir = NULL;
799 finfo.fullname = finfo.file;
800 finfo.repository = repository;
801 finfo.entries = NULL;
803 vers = Version_TS (&finfo, NULL, vtag, NULL, 1, 0);
804 for (i = 0; i < targc; i++)
806 if ((retcode = RCS_settag (rcs, targv[i], vers->vn_rcs)) == 0)
807 RCS_rewrite (rcs, NULL, NULL);
811 fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
812 "WARNING: Couldn't add tag %s to %s", targv[i],
814 error (0, retcode == -1 ? ierrno : 0,
815 "WARNING: Couldn't add tag %s to %s", targv[i],
824 * Stolen from rcs/src/rcsfnms.c, and adapted/extended.
828 char *suffix, *comlead;
831 static const struct compair comtable[] =
835 * comtable pairs each filename suffix with a comment leader. The comment
836 * leader is placed before each line generated by the $Log keyword. This
837 * table is used to guess the proper comment leader from the working file's
838 * suffix during initial ci (see InitAdmin()). Comment leaders are needed for
839 * languages without multiline comments; for others they are optional.
841 * I believe that the comment leader is unused if you are using RCS 5.7, which
842 * decides what leader to use based on the text surrounding the $Log keyword
843 * rather than a specified comment leader.
845 {"a", "-- "}, /* Ada */
848 {"asm", ";; "}, /* assembler (MS-DOS) */
849 {"ads", "-- "}, /* Ada */
850 {"bas", "' "}, /* Visual Basic code */
851 {"bat", ":: "}, /* batch (MS-DOS) */
852 {"body", "-- "}, /* Ada */
853 {"c", " * "}, /* C */
854 {"c++", "// "}, /* C++ in all its infinite guises */
858 {"m", "// "}, /* Objective-C */
859 {"cl", ";;; "}, /* Common Lisp */
860 {"cmd", ":: "}, /* command (OS/2) */
861 {"cmf", "c "}, /* CM Fortran */
862 {"cs", " * "}, /* C* */
863 {"csh", "# "}, /* shell */
864 {"dlg", " * "}, /* MS Windows dialog file */
865 {"e", "# "}, /* efl */
866 {"epsf", "% "}, /* encapsulated postscript */
867 {"epsi", "% "}, /* encapsulated postscript */
868 {"el", "; "}, /* Emacs Lisp */
869 {"f", "c "}, /* Fortran */
871 {"frm", "' "}, /* Visual Basic form */
872 {"h", " * "}, /* C-header */
873 {"hh", "// "}, /* C++ header */
876 {"in", "# "}, /* for Makefile.in */
877 {"l", " * "}, /* lex (conflict between lex and
879 {"mac", ";; "}, /* macro (DEC-10, MS-DOS, PDP-11,
881 {"mak", "# "}, /* makefile, e.g. Visual C++ */
882 {"me", ".\\\" "}, /* me-macros t/nroff */
883 {"ml", "; "}, /* mocklisp */
884 {"mm", ".\\\" "}, /* mm-macros t/nroff */
885 {"ms", ".\\\" "}, /* ms-macros t/nroff */
886 {"man", ".\\\" "}, /* man-macros t/nroff */
887 {"1", ".\\\" "}, /* feeble attempt at man pages... */
896 {"p", " * "}, /* pascal */
898 {"pl", "# "}, /* perl (conflict with Prolog) */
899 {"ps", "% "}, /* postscript */
900 {"psw", "% "}, /* postscript wrap */
901 {"pswm", "% "}, /* postscript wrap */
902 {"r", "# "}, /* ratfor */
903 {"rc", " * "}, /* Microsoft Windows resource file */
904 {"red", "% "}, /* psl/rlisp */
906 {"s", "! "}, /* assembler */
909 {"s", "| "}, /* assembler */
912 {"s", "/ "}, /* assembler */
915 {"s", "# "}, /* assembler */
918 {"s", "# "}, /* assembler */
919 {"S", "# "}, /* Macro assembler */
921 {"sh", "# "}, /* shell */
922 {"sl", "% "}, /* psl */
923 {"spec", "-- "}, /* Ada */
924 {"tex", "% "}, /* tex */
925 {"y", " * "}, /* yacc */
926 {"ye", " * "}, /* yacc-efl */
927 {"yr", " * "}, /* yacc-ratfor */
928 {"", "# "}, /* default for empty suffix */
929 {NULL, "# "} /* default for unknown suffix; */
930 /* must always be last */
942 suffix_path = xmalloc (strlen (user) + 5);
943 cp = strrchr (user, '.');
949 * Convert to lower-case, since we are not concerned about the
950 * case-ness of the suffix.
952 (void) strcpy (suffix_path, cp);
953 for (cp = suffix_path; *cp; cp++)
954 if (isupper ((unsigned char) *cp))
956 suffix = suffix_path;
959 suffix = ""; /* will use the default */
962 if (comtable[i].suffix == NULL)
964 /* Default. Note we'll always hit this case before we
966 retval = comtable[i].comlead;
969 if (strcmp (suffix, comtable[i].suffix) == 0)
971 retval = comtable[i].comlead;
979 /* Create a new RCS file from scratch.
981 This probably should be moved to rcs.c now that it is called from
982 places outside import.c.
984 Return value is 0 for success, or nonzero for failure (in which
985 case an error message will have already been printed). */
987 add_rcs_file (message, rcs, user, add_vhead, key_opt,
988 add_vbranch, vtag, targc, targv,
989 desctext, desclen, add_logfp)
990 /* Log message for the addition. Not used if add_vhead == NULL. */
992 /* Filename of the RCS file to create. */
994 /* Filename of the file to serve as the contents of the initial
995 revision. Even if add_vhead is NULL, we use this to determine
996 the modes to give the new RCS file. */
999 /* Revision number of head that we are adding. Normally 1.1 but
1000 could be another revision as long as ADD_VBRANCH is a branch
1001 from it. If NULL, then just add an empty file without any
1002 revisions (similar to the one created by "rcs -i"). */
1005 /* Keyword expansion mode, e.g., "b" for binary. NULL means the
1006 default behavior. */
1009 /* Vendor branch to import to, or NULL if none. If non-NULL, then
1010 vtag should also be non-NULL. */
1016 /* If non-NULL, description for the file. If NULL, the description
1021 /* Write errors to here as well as via error (), or NULL if we should
1022 use only error (). */
1025 FILE *fprcs, *fpuser;
1029 char altdate1[MAXDATELEN];
1031 int i, ierrno, err = 0;
1035 char *local_opt = key_opt;
1036 char *free_opt = NULL;
1042 /* Note that as the code stands now, the -k option overrides any
1043 settings in wrappers (whether CVSROOT/cvswrappers, -W, or
1044 whatever). Some have suggested this should be the other way
1045 around. As far as I know the documentation doesn't say one way
1046 or the other. Before making a change of this sort, should think
1047 about what is best, document it (in cvs.texinfo and NEWS), &c. */
1049 if (local_opt == NULL)
1051 if (wrap_name_has (user, WRAP_RCSOPTION))
1053 local_opt = free_opt = wrap_rcsoption (user, 0);
1057 tocvsPath = wrap_tocvs_process_file (user);
1058 userfile = (tocvsPath == NULL ? user : tocvsPath);
1060 /* Opening in text mode is probably never the right thing for the
1061 server (because the protocol encodes text files in a fashion
1062 which does not depend on what the client or server OS is, as
1063 documented in cvsclient.texi), but as long as the server just
1064 runs on unix it is a moot point. */
1066 /* If PreservePermissions is set, then make sure that the file
1067 is a plain file before trying to open it. Longstanding (although
1068 often unpopular) CVS behavior has been to follow symlinks, so we
1069 maintain that behavior if PreservePermissions is not on.
1071 NOTE: this error message used to be `cannot fstat', but is now
1072 `cannot lstat'. I don't see a way around this, since we must
1073 stat the file before opening it. -twp */
1075 if (CVS_LSTAT (userfile, &sb) < 0)
1077 /* not fatal, continue import */
1078 if (add_logfp != NULL)
1079 fperrmsg (add_logfp, 0, errno,
1080 "ERROR: cannot lstat file %s", userfile);
1081 error (0, errno, "cannot lstat file %s", userfile);
1084 file_type = sb.st_mode & S_IFMT;
1087 if (!preserve_perms || file_type == S_IFREG)
1089 fpuser = CVS_FOPEN (userfile,
1090 ((local_opt != NULL && strcmp (local_opt, "b") == 0)
1096 /* not fatal, continue import */
1097 if (add_logfp != NULL)
1098 fperrmsg (add_logfp, 0, errno,
1099 "ERROR: cannot read file %s", userfile);
1100 error (0, errno, "ERROR: cannot read file %s", userfile);
1105 fprcs = CVS_FOPEN (rcs, "w+b");
1109 goto write_error_noclose;
1115 if (add_vhead != NULL)
1117 if (fprintf (fprcs, "head %s;\012", add_vhead) < 0)
1122 if (fprintf (fprcs, "head ;\012") < 0)
1126 if (add_vbranch != NULL)
1128 if (fprintf (fprcs, "branch %s;\012", add_vbranch) < 0)
1131 if (fprintf (fprcs, "access ;\012") < 0 ||
1132 fprintf (fprcs, "symbols ") < 0)
1137 for (i = targc - 1; i >= 0; i--)
1139 /* RCS writes the symbols backwards */
1140 assert (add_vbranch != NULL);
1141 if (fprintf (fprcs, "%s:%s.1 ", targv[i], add_vbranch) < 0)
1145 if (add_vbranch != NULL)
1147 if (fprintf (fprcs, "%s:%s", vtag, add_vbranch) < 0)
1150 if (fprintf (fprcs, ";\012") < 0)
1153 if (fprintf (fprcs, "locks ; strict;\012") < 0 ||
1154 /* XXX - make sure @@ processing works in the RCS file */
1155 fprintf (fprcs, "comment @%s@;\012", get_comment (user)) < 0)
1160 if (local_opt != NULL && strcmp (local_opt, "kv") != 0)
1162 if (fprintf (fprcs, "expand @%s@;\012", local_opt) < 0)
1168 if (fprintf (fprcs, "\012") < 0)
1171 /* Write the revision(s), with the date and author and so on
1172 (that is "delta" rather than "deltatext" from rcsfile(5)). */
1173 if (add_vhead != NULL)
1175 if (use_file_modtime)
1179 ftm = gmtime (&now);
1180 (void) sprintf (altdate1, DATEFORM,
1181 ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900),
1182 ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour,
1183 ftm->tm_min, ftm->tm_sec);
1184 author = getcaller ();
1186 if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
1187 fprintf (fprcs, "date %s; author %s; state Exp;\012",
1188 altdate1, author) < 0)
1191 if (fprintf (fprcs, "branches") < 0)
1193 if (add_vbranch != NULL)
1195 if (fprintf (fprcs, " %s.1", add_vbranch) < 0)
1198 if (fprintf (fprcs, ";\012") < 0)
1201 if (fprintf (fprcs, "next ;\012") < 0)
1204 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1205 /* Store initial permissions if necessary. */
1208 if (file_type == S_IFLNK)
1210 char *link = xreadlink (userfile);
1211 if (fprintf (fprcs, "symlink\t@") < 0 ||
1212 expand_at_signs (link, strlen (link), fprcs) < 0 ||
1213 fprintf (fprcs, "@;\012") < 0)
1219 if (fprintf (fprcs, "owner\t%u;\012", sb.st_uid) < 0)
1221 if (fprintf (fprcs, "group\t%u;\012", sb.st_gid) < 0)
1223 if (fprintf (fprcs, "permissions\t%o;\012",
1224 sb.st_mode & 07777) < 0)
1228 case S_IFREG: break;
1231 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1232 if (fprintf (fprcs, "special\t%s %lu;\012",
1233 (file_type == S_IFCHR
1236 (unsigned long) sb.st_rdev) < 0)
1240 "can't import %s: unable to import device files on this system",
1246 "can't import %s: unknown kind of special file",
1253 if (add_vbranch != NULL)
1255 if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1256 fprintf (fprcs, "date %s; author %s; state Exp;\012",
1257 altdate1, author) < 0 ||
1258 fprintf (fprcs, "branches ;\012") < 0 ||
1259 fprintf (fprcs, "next ;\012") < 0)
1262 #ifdef PRESERVE_PERMISSIONS_SUPPORT
1263 /* Store initial permissions if necessary. */
1266 if (file_type == S_IFLNK)
1268 char *link = xreadlink (userfile);
1269 if (fprintf (fprcs, "symlink\t@") < 0 ||
1270 expand_at_signs (link, strlen (link), fprcs) < 0 ||
1271 fprintf (fprcs, "@;\012") < 0)
1277 if (fprintf (fprcs, "owner\t%u;\012", sb.st_uid) < 0 ||
1278 fprintf (fprcs, "group\t%u;\012", sb.st_gid) < 0 ||
1279 fprintf (fprcs, "permissions\t%o;\012",
1280 sb.st_mode & 07777) < 0)
1285 case S_IFREG: break;
1288 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1289 if (fprintf (fprcs, "special\t%s %lu;\012",
1290 (file_type == S_IFCHR
1293 (unsigned long) sb.st_rdev) < 0)
1297 "can't import %s: unable to import device files on this system",
1303 "cannot import %s: special file of unknown type",
1310 if (fprintf (fprcs, "\012") < 0)
1315 /* Now write the description (possibly empty). */
1316 if (fprintf (fprcs, "\012desc\012") < 0 ||
1317 fprintf (fprcs, "@") < 0)
1319 if (desctext != NULL)
1321 /* The use of off_t not size_t for the second argument is very
1322 strange, since we are dealing with something which definitely
1324 if (expand_at_signs (desctext, (off_t) desclen, fprcs) < 0)
1327 if (fprintf (fprcs, "@\012\012\012") < 0)
1330 /* Now write the log messages and contents for the revision(s) (that
1331 is, "deltatext" rather than "delta" from rcsfile(5)). */
1332 if (add_vhead != NULL)
1334 if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 ||
1335 fprintf (fprcs, "log\012@") < 0)
1337 if (add_vbranch != NULL)
1339 /* We are going to put the log message in the revision on the
1340 branch. So putting it here too seems kind of redundant, I
1341 guess (and that is what CVS has always done, anyway). */
1342 if (fprintf (fprcs, "Initial revision\012") < 0)
1347 if (expand_at_signs (message, (off_t) strlen (message), fprcs) < 0)
1350 if (fprintf (fprcs, "@\012") < 0 ||
1351 fprintf (fprcs, "text\012@") < 0)
1356 /* Now copy over the contents of the file, expanding at signs.
1357 If preserve_perms is set, do this only for regular files. */
1358 if (!preserve_perms || file_type == S_IFREG)
1365 len = fread (buf, 1, sizeof buf, fpuser);
1368 if (ferror (fpuser))
1369 error (1, errno, "cannot read file %s for copying",
1373 if (expand_at_signs (buf, len, fprcs) < 0)
1377 if (fprintf (fprcs, "@\012\012") < 0)
1379 if (add_vbranch != NULL)
1381 if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 ||
1382 fprintf (fprcs, "log\012@") < 0 ||
1383 expand_at_signs (message,
1384 (off_t) strlen (message), fprcs) < 0 ||
1385 fprintf (fprcs, "@\012text\012") < 0 ||
1386 fprintf (fprcs, "@@\012") < 0)
1391 if (fclose (fprcs) == EOF)
1394 goto write_error_noclose;
1396 /* Close fpuser only if we opened it to begin with. */
1399 if (fclose (fpuser) < 0)
1400 error (0, errno, "cannot close %s", user);
1404 * Fix the modes on the RCS files. The user modes of the original
1405 * user file are propagated to the group and other modes as allowed
1406 * by the repository umask, except that all write permissions are
1409 mode = (sb.st_mode |
1410 (sb.st_mode & S_IRWXU) >> 3 |
1411 (sb.st_mode & S_IRWXU) >> 6) &
1413 ~(S_IWRITE | S_IWGRP | S_IWOTH);
1414 if (chmod (rcs, mode) < 0)
1417 if (add_logfp != NULL)
1418 fperrmsg (add_logfp, 0, ierrno,
1419 "WARNING: cannot change mode of file %s", rcs);
1420 error (0, ierrno, "WARNING: cannot change mode of file %s", rcs);
1424 if (unlink_file_dir (tocvsPath) < 0)
1425 error (0, errno, "cannot remove %s", tocvsPath);
1426 if (free_opt != NULL)
1432 if (fclose (fprcs) < 0)
1433 error (0, errno, "cannot close %s", rcs);
1434 write_error_noclose:
1435 if (fclose (fpuser) < 0)
1436 error (0, errno, "cannot close %s", user);
1437 if (add_logfp != NULL)
1438 fperrmsg (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
1439 error (0, ierrno, "ERROR: cannot write file %s", rcs);
1440 if (ierrno == ENOSPC)
1442 if (CVS_UNLINK (rcs) < 0)
1443 error (0, errno, "cannot remove %s", rcs);
1444 if (add_logfp != NULL)
1445 fperrmsg (add_logfp, 0, 0, "ERROR: out of space - aborting");
1446 error (1, 0, "ERROR: out of space - aborting");
1450 if (unlink_file_dir (tocvsPath) < 0)
1451 error (0, errno, "cannot remove %s", tocvsPath);
1453 if (free_opt != NULL)
1460 * Write SIZE bytes at BUF to FP, expanding @ signs into double @
1461 * signs. If an error occurs, return a negative value and set errno
1462 * to indicate the error. If not, return a nonnegative value.
1465 expand_at_signs (buf, size, fp)
1470 register char *cp, *next;
1473 while ((next = memchr (cp, '@', size)) != NULL)
1479 if (fwrite (cp, 1, len, fp) != len)
1481 if (putc ('@', fp) == EOF)
1487 if (fwrite (cp, 1, size, fp) != size)
1494 * Write an update message to (potentially) the screen and the log file.
1501 if (!really_quiet) /* write to terminal */
1506 cvs_output (buf, 2);
1509 cvs_output (repository + repos_len + 1, 0);
1510 cvs_output ("/", 1);
1512 else if (repository[0] != '\0')
1514 cvs_output (repository, 0);
1515 cvs_output ("/", 1);
1517 cvs_output (fname, 0);
1518 cvs_output ("\n", 1);
1521 if (repos_len) /* write to logfile */
1522 (void) fprintf (logfp, "%c %s/%s\n", ch,
1523 repository + repos_len + 1, fname);
1524 else if (repository[0])
1525 (void) fprintf (logfp, "%c %s/%s\n", ch, repository, fname);
1527 (void) fprintf (logfp, "%c %s\n", ch, fname);
1531 * This is the recursive function that walks the argument directory looking
1532 * for sub-directories that have CVS administration files in them and updates
1535 * Note that we do not follow symbolic links here, which is a feature!
1538 import_descend_dir (message, dir, vtag, targc, targv)
1545 struct saved_cwd cwd;
1552 if (save_cwd (&cwd))
1554 fperrmsg (logfp, 0, 0, "ERROR: cannot get working directory");
1558 /* Concatenate DIR to the end of REPOSITORY. */
1559 if (repository[0] == '\0')
1561 char *new = xstrdup (dir);
1567 char *new = xmalloc (strlen (repository) + strlen (dir) + 10);
1568 strcpy (new, repository);
1569 (void) strcat (new, "/");
1570 (void) strcat (new, dir);
1575 #ifdef CLIENT_SUPPORT
1576 if (!quiet && !current_parsed_root->isremote)
1580 error (0, 0, "Importing %s", repository);
1582 if ( CVS_CHDIR (dir) < 0)
1585 fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", repository);
1586 error (0, ierrno, "ERROR: cannot chdir to %s", repository);
1590 #ifdef CLIENT_SUPPORT
1591 if (!current_parsed_root->isremote && !isdir (repository))
1593 if (!isdir (repository))
1596 rcs = xmalloc (strlen (repository) + sizeof (RCSEXT) + 5);
1597 (void) sprintf (rcs, "%s%s", repository, RCSEXT);
1598 if (isfile (repository) || isfile(rcs))
1600 fperrmsg (logfp, 0, 0,
1601 "ERROR: %s is a file, should be a directory!",
1603 error (0, 0, "ERROR: %s is a file, should be a directory!",
1608 if (noexec == 0 && CVS_MKDIR (repository, 0777) < 0)
1611 fperrmsg (logfp, 0, ierrno,
1612 "ERROR: cannot mkdir %s -- not added", repository);
1614 "ERROR: cannot mkdir %s -- not added", repository);
1619 err = import_descend (message, vtag, targc, targv);
1623 if ((cp = strrchr (repository, '/')) != NULL)
1626 repository[0] = '\0';
1627 if (restore_cwd (&cwd, NULL))