diff options
Diffstat (limited to 'contrib/cvs/src/import.c')
-rw-r--r-- | contrib/cvs/src/import.c | 325 |
1 files changed, 203 insertions, 122 deletions
diff --git a/contrib/cvs/src/import.c b/contrib/cvs/src/import.c index 3243a96..0a2af7f 100644 --- a/contrib/cvs/src/import.c +++ b/contrib/cvs/src/import.c @@ -3,7 +3,7 @@ * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License as - * specified in the README file that comes with the CVS 1.4 kit. + * specified in the README file that comes with the CVS source distribution. * * "import" checks in the vendor release located in the current directory into * the CVS source repository. The CVS vendor branch support is utilized. @@ -23,7 +23,6 @@ #define FILE_HOLDER ".#cvsxxx" static char *get_comment PROTO((char *user)); -static int expand_at_signs PROTO((char *buf, off_t size, FILE *fp)); static int add_rev PROTO((char *message, RCSNode *rcs, char *vfile, char *vers)); static int add_tags PROTO((RCSNode *rcs, char *vfile, char *vtag, int targc, @@ -56,6 +55,7 @@ static const char *const import_usage[] = "\t-b bra\tVendor branch id.\n", "\t-m msg\tLog message.\n", "\t-W spec\tWrappers specification line.\n", + "(Specify the --help global option for a list of other help options)\n", NULL }; @@ -104,9 +104,9 @@ import (argc, argv) break; case 'm': #ifdef FORCE_USE_EDITOR - use_editor = TRUE; + use_editor = 1; #else - use_editor = FALSE; + use_editor = 0; #endif message = xstrdup(optarg); break; @@ -199,6 +199,7 @@ import (argc, argv) if (msglen == 0 || message[msglen - 1] != '\n') { char *nm = xmalloc (msglen + 2); + *nm = '\0'; if (message != NULL) { (void) strcpy (nm, message); @@ -467,6 +468,8 @@ process_import_file (message, vfile, vtag, targc, targv) if (!isfile (attic_name)) { int retval; + char *free_opt = NULL; + char *our_opt = keyword_opt; free (attic_name); /* @@ -474,8 +477,42 @@ process_import_file (message, vfile, vtag, targc, targv) * repository nor in the Attic -- create it anew. */ add_log ('N', vfile); - retval = add_rcs_file (message, rcs, vfile, vhead, vbranch, - vtag, targc, targv, logfp); + +#ifdef SERVER_SUPPORT + /* The most reliable information on whether the file is binary + is what the client told us. That is because if the client had + the wrong idea about binaryness, it corrupted the file, so + we might as well believe the client. */ + if (server_active) + { + Node *node; + List *entries; + + /* Reading all the entries for each file is fairly silly, and + probably slow. But I am too lazy at the moment to do + anything else. */ + entries = Entries_Open (0); + node = findnode_fn (entries, vfile); + if (node != NULL) + { + Entnode *entdata = (Entnode *) node->data; + if (entdata->type == ENT_FILE) + { + assert (entdata->options[0] == '-' + && entdata->options[1] == 'k'); + our_opt = xstrdup (entdata->options + 2); + free_opt = our_opt; + } + } + Entries_Close (entries); + } +#endif + + retval = add_rcs_file (message, rcs, vfile, vhead, our_opt, + vbranch, vtag, targc, targv, + NULL, 0, logfp); + if (free_opt != NULL) + free (free_opt); free (rcs); return retval; } @@ -602,12 +639,14 @@ add_rev (message, rcs, vfile, vers) /* Before RCS_lock existed, we were directing stdout, as well as stderr, from the RCS command, to DEVNULL. I wouldn't guess that was necessary, but I don't know for sure. */ - if (RCS_lock (rcs, vbranch, 1) != 0) - { - error (0, errno, "fork failed"); - return (1); - } + /* Earlier versions of this function printed a `fork failed' error + when RCS_lock returned an error code. That's not appropriate + now that RCS_lock is librarified, but should the error text be + preserved? */ + if (RCS_lock (rcs, vbranch, 1) != 0) + return 1; locked = 1; + RCS_rewrite (rcs, NULL, NULL); } tocvsPath = wrap_tocvs_process_file (vfile); if (tocvsPath == NULL) @@ -632,7 +671,7 @@ add_rev (message, rcs, vfile, vers) } } - status = RCS_checkin (rcs->path, tocvsPath == NULL ? vfile : tocvsPath, + status = RCS_checkin (rcs, tocvsPath == NULL ? vfile : tocvsPath, message, vbranch, (RCS_FLAGS_QUIET | (use_file_modtime ? RCS_FLAGS_MODTIME : 0))); @@ -656,6 +695,7 @@ add_rev (message, rcs, vfile, vers) if (locked) { (void) RCS_unlock(rcs, vbranch, 0); + RCS_rewrite (rcs, NULL, NULL); } return (1); } @@ -693,6 +733,7 @@ add_tags (rcs, vfile, vtag, targc, targv) "ERROR: Failed to set tag %s in %s", vtag, rcs->path); return (1); } + RCS_rewrite (rcs, NULL, NULL); memset (&finfo, 0, sizeof finfo); finfo.file = vfile; @@ -705,7 +746,9 @@ add_tags (rcs, vfile, vtag, targc, targv) vers = Version_TS (&finfo, NULL, vtag, NULL, 1, 0); for (i = 0; i < targc; i++) { - if ((retcode = RCS_settag (rcs, targv[i], vers->vn_rcs)) != 0) + if ((retcode = RCS_settag (rcs, targv[i], vers->vn_rcs)) == 0) + RCS_rewrite (rcs, NULL, NULL); + else { ierrno = errno; fperror (logfp, 0, retcode == -1 ? ierrno : 0, @@ -879,23 +922,33 @@ get_comment (user) /* Create a new RCS file from scratch. This probably should be moved to rcs.c now that it is called from - places outside import.c. */ + places outside import.c. + + Return value is 0 for success, or nonzero for failure (in which + case an error message will have already been printed). */ int -add_rcs_file (message, rcs, user, add_vhead, add_vbranch, vtag, targc, targv, - add_logfp) - /* Log message for the addition. */ +add_rcs_file (message, rcs, user, add_vhead, key_opt, + add_vbranch, vtag, targc, targv, + desctext, desclen, add_logfp) + /* Log message for the addition. Not used if add_vhead == NULL. */ char *message; /* Filename of the RCS file to create. */ char *rcs; /* Filename of the file to serve as the contents of the initial - revision. */ + revision. Even if add_vhead is NULL, we use this to determine + the modes to give the new RCS file. */ char *user; /* Revision number of head that we are adding. Normally 1.1 but could be another revision as long as ADD_VBRANCH is a branch - from it. */ + from it. If NULL, then just add an empty file without any + revisions (similar to the one created by "rcs -i"). */ char *add_vhead; + /* Keyword expansion mode, e.g., "b" for binary. NULL means the + default behavior. */ + char *key_opt; + /* Vendor branch to import to, or NULL if none. If non-NULL, then vtag should also be non-NULL. */ char *add_vbranch; @@ -903,6 +956,11 @@ add_rcs_file (message, rcs, user, add_vhead, add_vbranch, vtag, targc, targv, int targc; char *targv[]; + /* If non-NULL, description for the file. If NULL, the description + will be empty. */ + char *desctext; + size_t desclen; + /* Write errors to here as well as via error (), or NULL if we should use only error (). */ FILE *add_logfp; @@ -912,20 +970,24 @@ add_rcs_file (message, rcs, user, add_vhead, add_vbranch, vtag, targc, targv, struct tm *ftm; time_t now; char altdate1[MAXDATELEN]; -#ifndef HAVE_RCS5 - char altdate2[MAXDATELEN]; -#endif char *author; int i, ierrno, err = 0; mode_t mode; char *tocvsPath; char *userfile; - char *local_opt = keyword_opt; + char *local_opt = key_opt; char *free_opt = NULL; if (noexec) return (0); + /* Note that as the code stands now, the -k option overrides any + settings in wrappers (whether CVSROOT/cvswrappers, -W, or + whatever). Some have suggested this should be the other way + around. As far as I know the documentation doesn't say one way + or the other. Before making a change of this sort, should think + about what is best, document it (in cvs.texinfo and NEWS), &c. */ + if (local_opt == NULL) { if (wrap_name_has (user, WRAP_RCSOPTION)) @@ -936,7 +998,17 @@ add_rcs_file (message, rcs, user, add_vhead, add_vbranch, vtag, targc, targv, tocvsPath = wrap_tocvs_process_file (user); userfile = (tocvsPath == NULL ? user : tocvsPath); - fpuser = CVS_FOPEN (userfile, "r"); + + /* Opening in text mode is probably never the right thing for the + server (because the protocol encodes text files in a fashion + which does not depend on what the client or server OS is, as + documented in cvsclient.texi), but as long as the server just + runs on unix it is a moot point. */ + fpuser = CVS_FOPEN (userfile, + ((local_opt != NULL && strcmp (local_opt, "b") == 0) + ? "rb" + : "r") + ); if (fpuser == NULL) { /* not fatal, continue import */ @@ -954,8 +1026,17 @@ add_rcs_file (message, rcs, user, add_vhead, add_vbranch, vtag, targc, targv, /* * putadmin() */ - if (fprintf (fprcs, "head %s;\012", add_vhead) < 0) - goto write_error; + if (add_vhead != NULL) + { + if (fprintf (fprcs, "head %s;\012", add_vhead) < 0) + goto write_error; + } + else + { + if (fprintf (fprcs, "head ;\012") < 0) + goto write_error; + } + if (add_vbranch != NULL) { if (fprintf (fprcs, "branch %s;\012", add_vbranch) < 0) @@ -1001,125 +1082,125 @@ add_rcs_file (message, rcs, user, add_vhead, add_vbranch, vtag, targc, targv, if (fprintf (fprcs, "\012") < 0) goto write_error; - /* - * puttree() - */ + /* Get information on modtime and mode. */ if (fstat (fileno (fpuser), &sb) < 0) error (1, errno, "cannot fstat %s", user); - if (use_file_modtime) - now = sb.st_mtime; - else - (void) time (&now); -#ifdef HAVE_RCS5 - ftm = gmtime (&now); -#else - ftm = localtime (&now); -#endif - (void) sprintf (altdate1, DATEFORM, - ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900), - ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour, - ftm->tm_min, ftm->tm_sec); -#ifdef HAVE_RCS5 -#define altdate2 altdate1 -#else - /* - * If you don't have RCS V5 or later, you need to lie about the ci - * time, since RCS V4 and earlier insist that the times differ. - */ - now++; - ftm = localtime (&now); - (void) sprintf (altdate2, DATEFORM, - ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900), - ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour, - ftm->tm_min, ftm->tm_sec); -#endif - author = getcaller (); - if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 || + /* Write the revision(s), with the date and author and so on + (that is "delta" rather than "deltatext" from rcsfile(5)). */ + if (add_vhead != NULL) + { + if (use_file_modtime) + now = sb.st_mtime; + else + (void) time (&now); + ftm = gmtime (&now); + (void) sprintf (altdate1, DATEFORM, + ftm->tm_year + (ftm->tm_year < 100 ? 0 : 1900), + ftm->tm_mon + 1, ftm->tm_mday, ftm->tm_hour, + ftm->tm_min, ftm->tm_sec); + author = getcaller (); + + if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 || fprintf (fprcs, "date %s; author %s; state Exp;\012", altdate1, author) < 0) goto write_error; - if (fprintf (fprcs, "branches") < 0) - goto write_error; - if (add_vbranch != NULL) - { - if (fprintf (fprcs, " %s.1", add_vbranch) < 0) + if (fprintf (fprcs, "branches") < 0) + goto write_error; + if (add_vbranch != NULL) + { + if (fprintf (fprcs, " %s.1", add_vbranch) < 0) + goto write_error; + } + if (fprintf (fprcs, ";\012") < 0) goto write_error; - } - if (fprintf (fprcs, ";\012") < 0) - goto write_error; - if (fprintf (fprcs, "next ;\012") < 0) - goto write_error; - if (add_vbranch != NULL) - { - if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 || - fprintf (fprcs, "date %s; author %s; state Exp;\012", - altdate2, author) < 0 || - fprintf (fprcs, "branches ;\012") < 0 || - fprintf (fprcs, "next ;\012\012") < 0) + if (fprintf (fprcs, "next ;\012") < 0) goto write_error; + if (add_vbranch != NULL) + { + if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 || + fprintf (fprcs, "date %s; author %s; state Exp;\012", + altdate1, author) < 0 || + fprintf (fprcs, "branches ;\012") < 0 || + fprintf (fprcs, "next ;\012\012") < 0) + goto write_error; + } } - if ( - /* - * putdesc() - */ - fprintf (fprcs, "\012desc\012") < 0 || - fprintf (fprcs, "@@\012\012\012") < 0 || - /* - * putdelta() - */ - fprintf (fprcs, "\012%s\012", add_vhead) < 0 || - fprintf (fprcs, "log\012@") < 0) + + /* Now write the description (possibly empty). */ + if (fprintf (fprcs, "\012desc\012") < 0 || + fprintf (fprcs, "@") < 0) goto write_error; - if (add_vbranch != NULL) - { - /* We are going to put the log message in the revision on the - branch. So putting it here too seems kind of redundant, I - guess (and that is what CVS has always done, anyway). */ - if (fprintf (fprcs, "Initial revision\012") < 0) - goto write_error; - } - else + if (desctext != NULL) { - if (expand_at_signs (message, (off_t) strlen (message), fprcs) < 0) + /* The use of off_t not size_t for the second argument is very + strange, since we are dealing with something which definitely + fits in memory. */ + if (expand_at_signs (desctext, (off_t) desclen, fprcs) < 0) goto write_error; } - if (fprintf (fprcs, "@\012") < 0 || - fprintf (fprcs, "text\012@") < 0) - { + if (fprintf (fprcs, "@\012\012\012") < 0) goto write_error; - } - /* Now copy over the contents of the file, expanding at signs. */ + /* Now write the log messages and contents for the revision(s) (that + is, "deltatext" rather than "delta" from rcsfile(5)). */ + if (add_vhead != NULL) { - char buf[8192]; - unsigned int len; + if (fprintf (fprcs, "\012%s\012", add_vhead) < 0 || + fprintf (fprcs, "log\012@") < 0) + goto write_error; + if (add_vbranch != NULL) + { + /* We are going to put the log message in the revision on the + branch. So putting it here too seems kind of redundant, I + guess (and that is what CVS has always done, anyway). */ + if (fprintf (fprcs, "Initial revision\012") < 0) + goto write_error; + } + else + { + if (expand_at_signs (message, (off_t) strlen (message), fprcs) < 0) + goto write_error; + } + if (fprintf (fprcs, "@\012") < 0 || + fprintf (fprcs, "text\012@") < 0) + { + goto write_error; + } - while (1) + /* Now copy over the contents of the file, expanding at signs. */ { - len = fread (buf, 1, sizeof buf, fpuser); - if (len == 0) + char buf[8192]; + unsigned int len; + + while (1) { - if (ferror (fpuser)) - error (1, errno, "cannot read file %s for copying", user); - break; + len = fread (buf, 1, sizeof buf, fpuser); + if (len == 0) + { + if (ferror (fpuser)) + error (1, errno, "cannot read file %s for copying", + user); + break; + } + if (expand_at_signs (buf, len, fprcs) < 0) + goto write_error; } - if (expand_at_signs (buf, len, fprcs) < 0) - goto write_error; } - } - if (fprintf (fprcs, "@\012\012") < 0) - goto write_error; - if (add_vbranch != NULL) - { - if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 || - fprintf (fprcs, "log\012@") < 0 || - expand_at_signs (message, (off_t) strlen (message), fprcs) < 0 || - fprintf (fprcs, "@\012text\012") < 0 || - fprintf (fprcs, "@@\012") < 0) + if (fprintf (fprcs, "@\012\012") < 0) goto write_error; + if (add_vbranch != NULL) + { + if (fprintf (fprcs, "\012%s.1\012", add_vbranch) < 0 || + fprintf (fprcs, "log\012@") < 0 || + expand_at_signs (message, + (off_t) strlen (message), fprcs) < 0 || + fprintf (fprcs, "@\012text\012") < 0 || + fprintf (fprcs, "@@\012") < 0) + goto write_error; + } } if (fclose (fprcs) == EOF) @@ -1184,7 +1265,7 @@ read_error: * signs. If an error occurs, return a negative value and set errno * to indicate the error. If not, return a nonnegative value. */ -static int +int expand_at_signs (buf, size, fp) char *buf; off_t size; |