summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/import.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cvs/src/import.c')
-rw-r--r--contrib/cvs/src/import.c1653
1 files changed, 0 insertions, 1653 deletions
diff --git a/contrib/cvs/src/import.c b/contrib/cvs/src/import.c
deleted file mode 100644
index bc918e0..0000000
--- a/contrib/cvs/src/import.c
+++ /dev/null
@@ -1,1653 +0,0 @@
-/*
- * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
- *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
- * and others.
- *
- * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
- * Portions 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 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.
- *
- * At least three arguments are expected to follow the options:
- * repository Where the source belongs relative to the CVSROOT
- * VendorTag Vendor's major tag
- * VendorReleTag Tag for this particular release
- *
- * Additional arguments specify more Vendor Release Tags.
- */
-
-#include "cvs.h"
-#include "savecwd.h"
-#include <assert.h>
-
-static char *get_comment PROTO((const char *user));
-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,
- char *targv[]));
-static int import_descend PROTO((char *message, char *vtag, int targc, char *targv[]));
-static int import_descend_dir PROTO((char *message, char *dir, char *vtag,
- int targc, char *targv[]));
-static int process_import_file PROTO((char *message, char *vfile, char *vtag,
- int targc, char *targv[]));
-static int update_rcs_file PROTO((char *message, char *vfile, char *vtag, int targc,
- char *targv[], int inattic));
-static void add_log PROTO((int ch, char *fname));
-
-static int repos_len;
-static char *vhead;
-static char *vbranch;
-static FILE *logfp;
-static char *repository;
-static int conflicts;
-static int use_file_modtime;
-static char *keyword_opt = NULL;
-
-static const char *const import_usage[] =
-{
- "Usage: %s %s [-d] [-k subst] [-I ign] [-m msg] [-b branch]\n",
- " [-W spec] repository vendor-tag release-tags...\n",
- "\t-d\tUse the file's modification time as the time of import.\n",
- "\t-k sub\tSet default RCS keyword substitution mode.\n",
- "\t-I ign\tMore files to ignore (! to reset).\n",
- "\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
-};
-
-int
-import (argc, argv)
- int argc;
- char **argv;
-{
- char *message = NULL;
- char *tmpfile;
- char *cp;
- int i, c, msglen, err;
- List *ulist;
- Node *p;
- struct logfile_info *li;
-
- if (argc == -1)
- usage (import_usage);
-
- ign_setup ();
- wrap_setup ();
-
- vbranch = xstrdup (CVSBRANCH);
- optind = 0;
- while ((c = getopt (argc, argv, "+Qqdb:m:I:k:W:")) != -1)
- {
- switch (c)
- {
- case 'Q':
- case 'q':
- /* The CVS 1.5 client sends these options (in addition to
- Global_option requests), so we must ignore them. */
- if (!server_active)
- error (1, 0,
- "-q or -Q must be specified before \"%s\"",
- cvs_cmd_name);
- break;
- case 'd':
- if (server_active)
- {
- /* CVS 1.10 and older clients will send this, but it
- doesn't do any good. So tell the user we can't
- cope, rather than silently losing. */
- error (0, 0,
- "warning: not setting the time of import from the file");
- error (0, 0, "due to client limitations");
- }
- use_file_modtime = 1;
- break;
- case 'b':
- free (vbranch);
- vbranch = xstrdup (optarg);
- break;
- case 'm':
-#ifdef FORCE_USE_EDITOR
- use_editor = 1;
-#else
- use_editor = 0;
-#endif
- if (message) free (message);
- message = xstrdup(optarg);
- break;
- case 'I':
- ign_add (optarg, 0);
- break;
- case 'k':
- /* RCS_check_kflag returns strings of the form -kxx. We
- only use it for validation, so we can free the value
- as soon as it is returned. */
- free (RCS_check_kflag (optarg));
- keyword_opt = optarg;
- break;
- case 'W':
- wrap_add (optarg, 0);
- break;
- case '?':
- default:
- usage (import_usage);
- break;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc < 3)
- usage (import_usage);
-
- /* This is for handling the Checkin-time request. It might seem a
- bit odd to enable the use_file_modtime code even in the case
- where Checkin-time was not sent for a particular file. The
- effect is that we use the time of upload, rather than the time
- when we call RCS_checkin. Since those times are both during
- CVS's run, that seems OK, and it is easier to implement than
- putting the "was Checkin-time sent" flag in CVS/Entries or some
- such place. */
-
- if (server_active)
- use_file_modtime = 1;
-
- /* Don't allow "CVS" as any directory in module path.
- *
- * Could abstract this to valid_module_path, but I don't think we'll need
- * to call it from anywhere else.
- */
- /* for each "CVS" in path... */
- cp = argv[0];
- while ((cp = strstr(cp, "CVS")) != NULL)
- {
- if ( /* /^CVS/ OR m#/CVS#... */
- (cp == argv[0] || ISDIRSEP(*(cp-1)))
- /* ...AND /CVS$/ OR m#CVS/# */
- && (*(cp+3) == '\0' || ISDIRSEP(*(cp+3)))
- )
- {
- error (0, 0,
- "The word `CVS' is reserved by CVS and may not be used");
- error (1, 0, "as a directory in a path or as a file name.");
- }
- cp += 3;
- }
-
- for (i = 1; i < argc; i++) /* check the tags for validity */
- {
- int j;
-
- RCS_check_tag (argv[i]);
- for (j = 1; j < i; j++)
- if (strcmp (argv[j], argv[i]) == 0)
- error (1, 0, "tag `%s' was specified more than once", argv[i]);
- }
-
- /* XXX - this should be a module, not just a pathname */
- if (!isabsolute (argv[0]) && pathname_levels (argv[0]) == 0)
- {
- if (current_parsed_root == NULL)
- {
- error (0, 0, "missing CVSROOT environment variable\n");
- error (1, 0, "Set it or specify the '-d' option to %s.",
- program_name);
- }
- repository = xmalloc (strlen (current_parsed_root->directory)
- + strlen (argv[0])
- + 2);
- (void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
- repos_len = strlen (current_parsed_root->directory);
- }
- else
- {
- /* It is somewhere between a security hole and "unexpected" to
- let the client start mucking around outside the cvsroot
- (wouldn't get the right CVSROOT configuration, &c). */
- error (1, 0, "directory %s not relative within the repository",
- argv[0]);
- }
-
- /*
- * Consistency checks on the specified vendor branch. It must be
- * composed of only numbers and dots ('.'). Also, for now we only
- * support branching to a single level, so the specified vendor branch
- * must only have two dots in it (like "1.1.1").
- */
- {
- regex_t pat;
- int ret = regcomp (&pat, "^[1-9][0-9]*\\.[1-9][0-9]*\\.[1-9][0-9]*$",
- REG_EXTENDED);
- assert (!ret);
- if (regexec (&pat, vbranch, 0, NULL, 0))
- {
- error (1, 0,
-"Only numeric branch specifications with two dots are\n"
-"supported by import, not `%s'. For example: `1.1.1'.",
- vbranch);
- }
- regfree (&pat);
- }
-
- /* Set vhead to the branch's parent. */
- vhead = xstrdup (vbranch);
- cp = strrchr (vhead, '.');
- *cp = '\0';
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- /* For rationale behind calling start_server before do_editor, see
- commit.c */
- start_server ();
- }
-#endif
-
- if (!server_active && use_editor)
- {
- do_editor ((char *) NULL, &message,
- current_parsed_root->isremote ? (char *) NULL : repository,
- (List *) NULL);
- }
- do_verify (&message, repository);
- msglen = message == NULL ? 0 : strlen (message);
- if (msglen == 0 || message[msglen - 1] != '\n')
- {
- char *nm = xmalloc (msglen + 2);
- *nm = '\0';
- if (message != NULL)
- {
- (void) strcpy (nm, message);
- free (message);
- }
- (void) strcat (nm + msglen, "\n");
- message = nm;
- }
-
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- {
- int err;
-
- if (vbranch[0] != '\0')
- option_with_arg ("-b", vbranch);
- option_with_arg ("-m", message ? message : "");
- if (keyword_opt != NULL)
- option_with_arg ("-k", keyword_opt);
- /* The only ignore processing which takes place on the server side
- is the CVSROOT/cvsignore file. But if the user specified -I !,
- the documented behavior is to not process said file. */
- if (ign_inhibit_server)
- {
- send_arg ("-I");
- send_arg ("!");
- }
- wrap_send ();
-
- {
- int i;
- for (i = 0; i < argc; ++i)
- send_arg (argv[i]);
- }
-
- logfp = stdin;
- client_import_setup (repository);
- err = import_descend (message, argv[1], argc - 2, argv + 2);
- client_import_done ();
- if (message)
- free (message);
- free (repository);
- free (vbranch);
- free (vhead);
- send_to_server ("import\012", 0);
- err += get_responses_and_close ();
- return err;
- }
-#endif
-
- if (!safe_location ( NULL ))
- {
- error (1, 0, "attempt to import the repository");
- }
-
- /*
- * Make all newly created directories writable. Should really use a more
- * sophisticated security mechanism here.
- */
- (void) umask (cvsumask);
- make_directories (repository);
-
- /* Create the logfile that will be logged upon completion */
- if ((logfp = cvs_temp_file (&tmpfile)) == NULL)
- error (1, errno, "cannot create temporary file `%s'",
- tmpfile ? tmpfile : "(null)");
- /* On systems where we can unlink an open file, do so, so it will go
- away no matter how we exit. FIXME-maybe: Should be checking for
- errors but I'm not sure which error(s) we get if we are on a system
- where one can't unlink open files. */
- (void) CVS_UNLINK (tmpfile);
- (void) fprintf (logfp, "\nVendor Tag:\t%s\n", argv[1]);
- (void) fprintf (logfp, "Release Tags:\t");
- for (i = 2; i < argc; i++)
- (void) fprintf (logfp, "%s\n\t\t", argv[i]);
- (void) fprintf (logfp, "\n");
-
- /* Just Do It. */
- err = import_descend (message, argv[1], argc - 2, argv + 2);
- if (conflicts)
- {
- if (!really_quiet)
- {
- char buf[20];
-
- cvs_output_tagged ("+importmergecmd", NULL);
- cvs_output_tagged ("newline", NULL);
- sprintf (buf, "%d", conflicts);
- cvs_output_tagged ("conflicts", buf);
- cvs_output_tagged ("text", " conflicts created by this import.");
- cvs_output_tagged ("newline", NULL);
- cvs_output_tagged ("text",
- "Use the following command to help the merge:");
- cvs_output_tagged ("newline", NULL);
- cvs_output_tagged ("newline", NULL);
- cvs_output_tagged ("text", "\t");
- cvs_output_tagged ("text", program_name);
- if (CVSroot_cmdline != NULL)
- {
- cvs_output_tagged ("text", " -d ");
- cvs_output_tagged ("text", CVSroot_cmdline);
- }
- cvs_output_tagged ("text", " checkout -j");
- cvs_output_tagged ("mergetag1", "<prev_rel_tag>");
- cvs_output_tagged ("text", " -j");
- cvs_output_tagged ("mergetag2", argv[2]);
- cvs_output_tagged ("text", " ");
- cvs_output_tagged ("repository", argv[0]);
- cvs_output_tagged ("newline", NULL);
- cvs_output_tagged ("newline", NULL);
- cvs_output_tagged ("-importmergecmd", NULL);
- }
-
- /* FIXME: I'm not sure whether we need to put this information
- into the loginfo. If we do, then note that it does not
- report any required -d option. There is no particularly
- clean way to tell the server about the -d option used by
- the client. */
- (void) fprintf (logfp, "\n%d conflicts created by this import.\n",
- conflicts);
- (void) fprintf (logfp,
- "Use the following command to help the merge:\n\n");
- (void) fprintf (logfp, "\t%s checkout ", program_name);
- (void) fprintf (logfp, "-j%s:yesterday -j%s %s\n\n",
- argv[1], argv[1], argv[0]);
- }
- else
- {
- if (!really_quiet)
- cvs_output ("\nNo conflicts created by this import\n\n", 0);
- (void) fprintf (logfp, "\nNo conflicts created by this import\n\n");
- }
-
- /*
- * Write out the logfile and clean up.
- */
- ulist = getlist ();
- p = getnode ();
- p->type = UPDATE;
- p->delproc = update_delproc;
- p->key = xstrdup ("- Imported sources");
- li = (struct logfile_info *) xmalloc (sizeof (struct logfile_info));
- li->type = T_TITLE;
- li->tag = xstrdup (vbranch);
- li->rev_old = li->rev_new = NULL;
- p->data = li;
- (void) addnode (ulist, p);
- Update_Logfile (repository, message, logfp, ulist);
- dellist (&ulist);
- if (fclose (logfp) < 0)
- error (0, errno, "error closing %s", tmpfile);
-
- /* Make sure the temporary file goes away, even on systems that don't let
- you delete a file that's in use. */
- if (CVS_UNLINK (tmpfile) < 0 && !existence_error (errno))
- error (0, errno, "cannot remove %s", tmpfile);
- free (tmpfile);
-
- if (message)
- free (message);
- free (repository);
- free (vbranch);
- free (vhead);
-
- return (err);
-}
-
-/* Process all the files in ".", then descend into other directories.
- Returns 0 for success, or >0 on error (in which case a message
- will have been printed). */
-static int
-import_descend (message, vtag, targc, targv)
- char *message;
- char *vtag;
- int targc;
- char *targv[];
-{
- DIR *dirp;
- struct dirent *dp;
- int err = 0;
- List *dirlist = NULL;
-
- /* first, load up any per-directory ignore lists */
- ign_add_file (CVSDOTIGNORE, 1);
- wrap_add_file (CVSDOTWRAPPER, 1);
-
- if (!current_parsed_root->isremote)
- lock_dir_for_write (repository);
-
- if ((dirp = CVS_OPENDIR (".")) == NULL)
- {
- error (0, errno, "cannot open directory");
- err++;
- }
- else
- {
- errno = 0;
- while ((dp = CVS_READDIR (dirp)) != NULL)
- {
- if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0)
- goto one_more_time_boys;
-
- /* CVS directories are created in the temp directory by
- server.c because it doesn't special-case import. So
- don't print a message about them, regardless of -I!. */
- if (server_active && strcmp (dp->d_name, CVSADM) == 0)
- goto one_more_time_boys;
-
- if (ign_name (dp->d_name))
- {
- add_log ('I', dp->d_name);
- goto one_more_time_boys;
- }
-
- if (
-#ifdef DT_DIR
- (dp->d_type == DT_DIR
- || (dp->d_type == DT_UNKNOWN && isdir (dp->d_name)))
-#else
- isdir (dp->d_name)
-#endif
- && !wrap_name_has (dp->d_name, WRAP_TOCVS)
- )
- {
- Node *n;
-
- if (dirlist == NULL)
- dirlist = getlist();
-
- n = getnode();
- n->key = xstrdup (dp->d_name);
- addnode(dirlist, n);
- }
- else if (
-#ifdef DT_DIR
- dp->d_type == DT_LNK
- || (dp->d_type == DT_UNKNOWN && islink (dp->d_name))
-#else
- islink (dp->d_name)
-#endif
- )
- {
- add_log ('L', dp->d_name);
- err++;
- }
- else
- {
-#ifdef CLIENT_SUPPORT
- if (current_parsed_root->isremote)
- err += client_process_import_file (message, dp->d_name,
- vtag, targc, targv,
- repository,
- keyword_opt != NULL &&
- keyword_opt[0] == 'b',
- use_file_modtime);
- else
-#endif
- err += process_import_file (message, dp->d_name,
- vtag, targc, targv);
- }
- one_more_time_boys:
- errno = 0;
- }
- if (errno != 0)
- {
- error (0, errno, "cannot read directory");
- ++err;
- }
- (void) CVS_CLOSEDIR (dirp);
- }
-
- if (!current_parsed_root->isremote)
- Lock_Cleanup ();
-
- if (dirlist != NULL)
- {
- Node *head, *p;
-
- head = dirlist->list;
- for (p = head->next; p != head; p = p->next)
- {
- err += import_descend_dir (message, p->key, vtag, targc, targv);
- }
-
- dellist(&dirlist);
- }
-
- return (err);
-}
-
-/*
- * Process the argument import file.
- */
-static int
-process_import_file (message, vfile, vtag, targc, targv)
- char *message;
- char *vfile;
- char *vtag;
- int targc;
- char *targv[];
-{
- char *rcs;
- int inattic = 0;
-
- rcs = xmalloc (strlen (repository) + strlen (vfile) + sizeof (RCSEXT)
- + 5);
- (void) sprintf (rcs, "%s/%s%s", repository, vfile, RCSEXT);
- if (!isfile (rcs))
- {
- char *attic_name;
-
- attic_name = xmalloc (strlen (repository) + strlen (vfile) +
- sizeof (CVSATTIC) + sizeof (RCSEXT) + 10);
- (void) sprintf (attic_name, "%s/%s/%s%s", repository, CVSATTIC,
- vfile, RCSEXT);
- if (!isfile (attic_name))
- {
- int retval;
- char *free_opt = NULL;
- char *our_opt = keyword_opt;
-
- free (attic_name);
- /*
- * A new import source file; it doesn't exist as a ,v within the
- * repository nor in the Attic -- create it anew.
- */
- add_log ('N', vfile);
-
-#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, NULL);
- node = findnode_fn (entries, vfile);
- if (node != NULL)
- {
- Entnode *entdata = 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;
- }
- free (attic_name);
- inattic = 1;
- }
-
- free (rcs);
- /*
- * an rcs file exists. have to do things the official, slow, way.
- */
- return (update_rcs_file (message, vfile, vtag, targc, targv, inattic));
-}
-
-/*
- * The RCS file exists; update it by adding the new import file to the
- * (possibly already existing) vendor branch.
- */
-static int
-update_rcs_file (message, vfile, vtag, targc, targv, inattic)
- char *message;
- char *vfile;
- char *vtag;
- int targc;
- char *targv[];
- int inattic;
-{
- Vers_TS *vers;
- int letter;
- char *tocvsPath;
- char *expand;
- struct file_info finfo;
-
- memset (&finfo, 0, sizeof finfo);
- finfo.file = vfile;
- /* Not used, so don't worry about it. */
- finfo.update_dir = NULL;
- finfo.fullname = finfo.file;
- finfo.repository = repository;
- finfo.entries = NULL;
- finfo.rcs = NULL;
- vers = Version_TS (&finfo, (char *) NULL, vbranch, (char *) NULL,
- 1, 0);
- if (vers->vn_rcs != NULL
- && !RCS_isdead(vers->srcfile, vers->vn_rcs))
- {
- int different;
-
- /*
- * The rcs file does have a revision on the vendor branch. Compare
- * this revision with the import file; if they match exactly, there
- * is no need to install the new import file as a new revision to the
- * branch. Just tag the revision with the new import tags.
- *
- * This is to try to cut down the number of "C" conflict messages for
- * locally modified import source files.
- */
- tocvsPath = wrap_tocvs_process_file (vfile);
- /* FIXME: Why don't we pass tocvsPath to RCS_cmp_file if it is
- not NULL? */
- expand = vers->srcfile->expand != NULL &&
- vers->srcfile->expand[0] == 'b' ? "-kb" : "-ko";
- different = RCS_cmp_file( vers->srcfile, vers->vn_rcs, (char **)NULL,
- (char *)NULL, expand, vfile );
- if (tocvsPath)
- if (unlink_file_dir (tocvsPath) < 0)
- error (0, errno, "cannot remove %s", tocvsPath);
-
- if (!different)
- {
- int retval = 0;
-
- /*
- * The two files are identical. Just update the tags, print the
- * "U", signifying that the file has changed, but needs no
- * attention, and we're done.
- */
- if (add_tags (vers->srcfile, vfile, vtag, targc, targv))
- retval = 1;
- add_log ('U', vfile);
- freevers_ts (&vers);
- return (retval);
- }
- }
-
- /* We may have failed to parse the RCS file; check just in case */
- if (vers->srcfile == NULL ||
- add_rev (message, vers->srcfile, vfile, vers->vn_rcs) ||
- add_tags (vers->srcfile, vfile, vtag, targc, targv))
- {
- freevers_ts (&vers);
- return (1);
- }
-
- if (vers->srcfile->branch == NULL || inattic ||
- strcmp (vers->srcfile->branch, vbranch) != 0)
- {
- conflicts++;
- letter = 'C';
- }
- else
- letter = 'U';
- add_log (letter, vfile);
-
- freevers_ts (&vers);
- return (0);
-}
-
-/*
- * Add the revision to the vendor branch
- */
-static int
-add_rev (message, rcs, vfile, vers)
- char *message;
- RCSNode *rcs;
- char *vfile;
- char *vers;
-{
- int locked, status, ierrno;
- char *tocvsPath;
-
- if (noexec)
- return (0);
-
- locked = 0;
- if (vers != NULL)
- {
- /* 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. */
- /* 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);
-
- status = RCS_checkin (rcs, tocvsPath == NULL ? vfile : tocvsPath,
- message, vbranch, 0,
- (RCS_FLAGS_QUIET | RCS_FLAGS_KEEPFILE
- | (use_file_modtime ? RCS_FLAGS_MODTIME : 0)));
- ierrno = errno;
-
- if ((tocvsPath != NULL) && (unlink_file_dir (tocvsPath) < 0))
- error (0, errno, "cannot remove %s", tocvsPath);
-
- if (status)
- {
- if (!noexec)
- {
- fperrmsg (logfp, 0, status == -1 ? ierrno : 0,
- "ERROR: Check-in of %s failed", rcs->path);
- error (0, status == -1 ? ierrno : 0,
- "ERROR: Check-in of %s failed", rcs->path);
- }
- if (locked)
- {
- (void) RCS_unlock(rcs, vbranch, 0);
- RCS_rewrite (rcs, NULL, NULL);
- }
- return (1);
- }
- return (0);
-}
-
-/*
- * Add the vendor branch tag and all the specified import release tags to the
- * RCS file. The vendor branch tag goes on the branch root (1.1.1) while the
- * vendor release tags go on the newly added leaf of the branch (1.1.1.1,
- * 1.1.1.2, ...).
- */
-static int
-add_tags (rcs, vfile, vtag, targc, targv)
- RCSNode *rcs;
- char *vfile;
- char *vtag;
- int targc;
- char *targv[];
-{
- int i, ierrno;
- Vers_TS *vers;
- int retcode = 0;
- struct file_info finfo;
-
- if (noexec)
- return (0);
-
- if ((retcode = RCS_settag(rcs, vtag, vbranch)) != 0)
- {
- ierrno = errno;
- fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
- "ERROR: Failed to set tag %s in %s", vtag, rcs->path);
- error (0, retcode == -1 ? ierrno : 0,
- "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;
- /* Not used, so don't worry about it. */
- finfo.update_dir = NULL;
- finfo.fullname = finfo.file;
- finfo.repository = repository;
- finfo.entries = NULL;
- finfo.rcs = NULL;
- 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)
- RCS_rewrite (rcs, NULL, NULL);
- else
- {
- ierrno = errno;
- fperrmsg (logfp, 0, retcode == -1 ? ierrno : 0,
- "WARNING: Couldn't add tag %s to %s", targv[i],
- rcs->path);
- error (0, retcode == -1 ? ierrno : 0,
- "WARNING: Couldn't add tag %s to %s", targv[i],
- rcs->path);
- }
- }
- freevers_ts (&vers);
- return (0);
-}
-
-/*
- * Stolen from rcs/src/rcsfnms.c, and adapted/extended.
- */
-struct compair
-{
- char *suffix, *comlead;
-};
-
-static const struct compair comtable[] =
-{
-
-/*
- * comtable pairs each filename suffix with a comment leader. The comment
- * leader is placed before each line generated by the $Log keyword. This
- * table is used to guess the proper comment leader from the working file's
- * suffix during initial ci (see InitAdmin()). Comment leaders are needed for
- * languages without multiline comments; for others they are optional.
- *
- * I believe that the comment leader is unused if you are using RCS 5.7, which
- * decides what leader to use based on the text surrounding the $Log keyword
- * rather than a specified comment leader.
- */
- {"a", "-- "}, /* Ada */
- {"ada", "-- "},
- {"adb", "-- "},
- {"asm", ";; "}, /* assembler (MS-DOS) */
- {"ads", "-- "}, /* Ada */
- {"bas", "' "}, /* Visual Basic code */
- {"bat", ":: "}, /* batch (MS-DOS) */
- {"body", "-- "}, /* Ada */
- {"c", " * "}, /* C */
- {"c++", "// "}, /* C++ in all its infinite guises */
- {"cc", "// "},
- {"cpp", "// "},
- {"cxx", "// "},
- {"m", "// "}, /* Objective-C */
- {"cl", ";;; "}, /* Common Lisp */
- {"cmd", ":: "}, /* command (OS/2) */
- {"cmf", "c "}, /* CM Fortran */
- {"cs", " * "}, /* C* */
- {"csh", "# "}, /* shell */
- {"dlg", " * "}, /* MS Windows dialog file */
- {"e", "# "}, /* efl */
- {"epsf", "% "}, /* encapsulated postscript */
- {"epsi", "% "}, /* encapsulated postscript */
- {"el", "; "}, /* Emacs Lisp */
- {"f", "c "}, /* Fortran */
- {"for", "c "},
- {"frm", "' "}, /* Visual Basic form */
- {"h", " * "}, /* C-header */
- {"hh", "// "}, /* C++ header */
- {"hpp", "// "},
- {"hxx", "// "},
- {"in", "# "}, /* for Makefile.in */
- {"l", " * "}, /* lex (conflict between lex and
- * franzlisp) */
- {"mac", ";; "}, /* macro (DEC-10, MS-DOS, PDP-11,
- * VMS, etc) */
- {"mak", "# "}, /* makefile, e.g. Visual C++ */
- {"me", ".\\\" "}, /* me-macros t/nroff */
- {"ml", "; "}, /* mocklisp */
- {"mm", ".\\\" "}, /* mm-macros t/nroff */
- {"ms", ".\\\" "}, /* ms-macros t/nroff */
- {"man", ".\\\" "}, /* man-macros t/nroff */
- {"1", ".\\\" "}, /* feeble attempt at man pages... */
- {"2", ".\\\" "},
- {"3", ".\\\" "},
- {"4", ".\\\" "},
- {"5", ".\\\" "},
- {"6", ".\\\" "},
- {"7", ".\\\" "},
- {"8", ".\\\" "},
- {"9", ".\\\" "},
- {"p", " * "}, /* pascal */
- {"pas", " * "},
- {"pl", "# "}, /* perl (conflict with Prolog) */
- {"ps", "% "}, /* postscript */
- {"psw", "% "}, /* postscript wrap */
- {"pswm", "% "}, /* postscript wrap */
- {"r", "# "}, /* ratfor */
- {"rc", " * "}, /* Microsoft Windows resource file */
- {"red", "% "}, /* psl/rlisp */
-#ifdef sparc
- {"s", "! "}, /* assembler */
-#endif
-#ifdef mc68000
- {"s", "| "}, /* assembler */
-#endif
-#ifdef pdp11
- {"s", "/ "}, /* assembler */
-#endif
-#ifdef vax
- {"s", "# "}, /* assembler */
-#endif
-#ifdef __ksr__
- {"s", "# "}, /* assembler */
- {"S", "# "}, /* Macro assembler */
-#endif
- {"sh", "# "}, /* shell */
- {"sl", "% "}, /* psl */
- {"spec", "-- "}, /* Ada */
- {"tex", "% "}, /* tex */
- {"y", " * "}, /* yacc */
- {"ye", " * "}, /* yacc-efl */
- {"yr", " * "}, /* yacc-ratfor */
- {"", "# "}, /* default for empty suffix */
- {NULL, "# "} /* default for unknown suffix; */
-/* must always be last */
-};
-
-static char *
-get_comment (user)
- const char *user;
-{
- char *cp, *suffix;
- char *suffix_path;
- int i;
- char *retval;
-
- suffix_path = xmalloc (strlen (user) + 5);
- cp = strrchr (user, '.');
- if (cp != NULL)
- {
- cp++;
-
- /*
- * Convert to lower-case, since we are not concerned about the
- * case-ness of the suffix.
- */
- (void) strcpy (suffix_path, cp);
- for (cp = suffix_path; *cp; cp++)
- if (isupper ((unsigned char) *cp))
- *cp = tolower (*cp);
- suffix = suffix_path;
- }
- else
- suffix = ""; /* will use the default */
- for (i = 0;; i++)
- {
- if (comtable[i].suffix == NULL)
- {
- /* Default. Note we'll always hit this case before we
- ever return NULL. */
- retval = comtable[i].comlead;
- break;
- }
- if (strcmp (suffix, comtable[i].suffix) == 0)
- {
- retval = comtable[i].comlead;
- break;
- }
- }
- free (suffix_path);
- return retval;
-}
-
-/* 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.
-
- 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, key_opt,
- add_vbranch, vtag, targc, targv,
- desctext, desclen, add_logfp)
- /* Log message for the addition. Not used if add_vhead == NULL. */
- const char *message;
- /* Filename of the RCS file to create. */
- const char *rcs;
- /* Filename of the file to serve as the contents of the initial
- revision. Even if add_vhead is NULL, we use this to determine
- the modes to give the new RCS file. */
- const 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. If NULL, then just add an empty file without any
- revisions (similar to the one created by "rcs -i"). */
- const char *add_vhead;
-
- /* Keyword expansion mode, e.g., "b" for binary. NULL means the
- default behavior. */
- const char *key_opt;
-
- /* Vendor branch to import to, or NULL if none. If non-NULL, then
- vtag should also be non-NULL. */
- const char *add_vbranch;
- const char *vtag;
- int targc;
- char *targv[];
-
- /* If non-NULL, description for the file. If NULL, the description
- will be empty. */
- const 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;
-{
- FILE *fprcs, *fpuser;
- struct stat sb;
- struct tm *ftm;
- time_t now;
- char altdate1[MAXDATELEN];
- char *author;
- int i, ierrno, err = 0;
- mode_t mode;
- char *tocvsPath;
- const char *userfile;
- char *free_opt = NULL;
- mode_t file_type;
-
- 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 (key_opt == NULL)
- {
- if (wrap_name_has (user, WRAP_RCSOPTION))
- {
- key_opt = free_opt = wrap_rcsoption (user, 0);
- }
- }
-
- tocvsPath = wrap_tocvs_process_file (user);
- userfile = (tocvsPath == NULL ? user : tocvsPath);
-
- /* 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. */
-
- /* If PreservePermissions is set, then make sure that the file
- is a plain file before trying to open it. Longstanding (although
- often unpopular) CVS behavior has been to follow symlinks, so we
- maintain that behavior if PreservePermissions is not on.
-
- NOTE: this error message used to be `cannot fstat', but is now
- `cannot lstat'. I don't see a way around this, since we must
- stat the file before opening it. -twp */
-
- if (CVS_LSTAT (userfile, &sb) < 0)
- {
- /* not fatal, continue import */
- if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, errno,
- "ERROR: cannot lstat file %s", userfile);
- error (0, errno, "cannot lstat file %s", userfile);
- goto read_error;
- }
- file_type = sb.st_mode & S_IFMT;
-
- fpuser = NULL;
- if (!preserve_perms || file_type == S_IFREG)
- {
- fpuser = CVS_FOPEN (userfile,
- ((key_opt != NULL && strcmp (key_opt, "b") == 0)
- ? "rb"
- : "r")
- );
- if (fpuser == NULL)
- {
- /* not fatal, continue import */
- if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, errno,
- "ERROR: cannot read file %s", userfile);
- error (0, errno, "ERROR: cannot read file %s", userfile);
- goto read_error;
- }
- }
-
- fprcs = CVS_FOPEN (rcs, "w+b");
- if (fprcs == NULL)
- {
- ierrno = errno;
- goto write_error_noclose;
- }
-
- /*
- * putadmin()
- */
- 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)
- goto write_error;
- }
- if (fprintf (fprcs, "access ;\012") < 0 ||
- fprintf (fprcs, "symbols ") < 0)
- {
- goto write_error;
- }
-
- for (i = targc - 1; i >= 0; i--)
- {
- /* RCS writes the symbols backwards */
- assert (add_vbranch != NULL);
- if (fprintf (fprcs, "%s:%s.1 ", targv[i], add_vbranch) < 0)
- goto write_error;
- }
-
- if (add_vbranch != NULL)
- {
- if (fprintf (fprcs, "%s:%s", vtag, add_vbranch) < 0)
- goto write_error;
- }
- if (fprintf (fprcs, ";\012") < 0)
- goto write_error;
-
- if (fprintf (fprcs, "locks ; strict;\012") < 0 ||
- /* XXX - make sure @@ processing works in the RCS file */
- fprintf (fprcs, "comment @%s@;\012", get_comment (user)) < 0)
- {
- goto write_error;
- }
-
- if (key_opt != NULL && strcmp (key_opt, "kv") != 0)
- {
- if (fprintf (fprcs, "expand @%s@;\012", key_opt) < 0)
- {
- goto write_error;
- }
- }
-
- if (fprintf (fprcs, "\012") < 0)
- goto write_error;
-
- /* 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)
- goto write_error;
- }
- if (fprintf (fprcs, ";\012") < 0)
- goto write_error;
-
- if (fprintf (fprcs, "next ;\012") < 0)
- goto write_error;
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- /* Store initial permissions if necessary. */
- if (preserve_perms)
- {
- if (file_type == S_IFLNK)
- {
- char *link = xreadlink (userfile);
- if (fprintf (fprcs, "symlink\t@") < 0 ||
- expand_at_signs (link, strlen (link), fprcs) < 0 ||
- fprintf (fprcs, "@;\012") < 0)
- goto write_error;
- free (link);
- }
- else
- {
- if (fprintf (fprcs, "owner\t%u;\012", sb.st_uid) < 0)
- goto write_error;
- if (fprintf (fprcs, "group\t%u;\012", sb.st_gid) < 0)
- goto write_error;
- if (fprintf (fprcs, "permissions\t%o;\012",
- sb.st_mode & 07777) < 0)
- goto write_error;
- switch (file_type)
- {
- case S_IFREG: break;
- case S_IFCHR:
- case S_IFBLK:
-#ifdef HAVE_STRUCT_STAT_ST_RDEV
- if (fprintf (fprcs, "special\t%s %lu;\012",
- (file_type == S_IFCHR
- ? "character"
- : "block"),
- (unsigned long) sb.st_rdev) < 0)
- goto write_error;
-#else
- error (0, 0,
-"can't import %s: unable to import device files on this system",
-userfile);
-#endif
- break;
- default:
- error (0, 0,
- "can't import %s: unknown kind of special file",
- userfile);
- }
- }
- }
-#endif
-
- 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") < 0)
- goto write_error;
-
-#ifdef PRESERVE_PERMISSIONS_SUPPORT
- /* Store initial permissions if necessary. */
- if (preserve_perms)
- {
- if (file_type == S_IFLNK)
- {
- char *link = xreadlink (userfile);
- if (fprintf (fprcs, "symlink\t@") < 0 ||
- expand_at_signs (link, strlen (link), fprcs) < 0 ||
- fprintf (fprcs, "@;\012") < 0)
- goto write_error;
- free (link);
- }
- else
- {
- if (fprintf (fprcs, "owner\t%u;\012", sb.st_uid) < 0 ||
- fprintf (fprcs, "group\t%u;\012", sb.st_gid) < 0 ||
- fprintf (fprcs, "permissions\t%o;\012",
- sb.st_mode & 07777) < 0)
- goto write_error;
-
- switch (file_type)
- {
- case S_IFREG: break;
- case S_IFCHR:
- case S_IFBLK:
-#ifdef HAVE_STRUCT_STAT_ST_RDEV
- if (fprintf (fprcs, "special\t%s %lu;\012",
- (file_type == S_IFCHR
- ? "character"
- : "block"),
- (unsigned long) sb.st_rdev) < 0)
- goto write_error;
-#else
- error (0, 0,
-"can't import %s: unable to import device files on this system",
-userfile);
-#endif
- break;
- default:
- error (0, 0,
- "cannot import %s: special file of unknown type",
- userfile);
- }
- }
- }
-#endif
-
- if (fprintf (fprcs, "\012") < 0)
- goto write_error;
- }
- }
-
- /* Now write the description (possibly empty). */
- if (fprintf (fprcs, "\012desc\012") < 0 ||
- fprintf (fprcs, "@") < 0)
- goto write_error;
- if (desctext != NULL)
- {
- /* 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\012\012") < 0)
- goto write_error;
-
- /* Now write the log messages and contents for the revision(s) (that
- is, "deltatext" rather than "delta" from rcsfile(5)). */
- if (add_vhead != NULL)
- {
- 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;
- }
-
- /* Now copy over the contents of the file, expanding at signs.
- If preserve_perms is set, do this only for regular files. */
- if (!preserve_perms || file_type == S_IFREG)
- {
- char buf[8192];
- unsigned int len;
-
- while (1)
- {
- 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 (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)
- {
- ierrno = errno;
- goto write_error_noclose;
- }
- /* Close fpuser only if we opened it to begin with. */
- if (fpuser != NULL)
- {
- if (fclose (fpuser) < 0)
- error (0, errno, "cannot close %s", user);
- }
-
- /*
- * Fix the modes on the RCS files. The user modes of the original
- * user file are propagated to the group and other modes as allowed
- * by the repository umask, except that all write permissions are
- * turned off.
- */
- mode = (sb.st_mode |
- (sb.st_mode & S_IRWXU) >> 3 |
- (sb.st_mode & S_IRWXU) >> 6) &
- ~cvsumask &
- ~(S_IWRITE | S_IWGRP | S_IWOTH);
- if (chmod (rcs, mode) < 0)
- {
- ierrno = errno;
- if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, ierrno,
- "WARNING: cannot change mode of file %s", rcs);
- error (0, ierrno, "WARNING: cannot change mode of file %s", rcs);
- err++;
- }
- if (tocvsPath)
- if (unlink_file_dir (tocvsPath) < 0)
- error (0, errno, "cannot remove %s", tocvsPath);
- if (free_opt != NULL)
- free (free_opt);
- return (err);
-
-write_error:
- ierrno = errno;
- if (fclose (fprcs) < 0)
- error (0, errno, "cannot close %s", rcs);
-write_error_noclose:
- if (fclose (fpuser) < 0)
- error (0, errno, "cannot close %s", user);
- if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, ierrno, "ERROR: cannot write file %s", rcs);
- error (0, ierrno, "ERROR: cannot write file %s", rcs);
- if (ierrno == ENOSPC)
- {
- if (CVS_UNLINK (rcs) < 0)
- error (0, errno, "cannot remove %s", rcs);
- if (add_logfp != NULL)
- fperrmsg (add_logfp, 0, 0, "ERROR: out of space - aborting");
- error (1, 0, "ERROR: out of space - aborting");
- }
-read_error:
- if (tocvsPath)
- if (unlink_file_dir (tocvsPath) < 0)
- error (0, errno, "cannot remove %s", tocvsPath);
-
- if (free_opt != NULL)
- free (free_opt);
-
- return (err + 1);
-}
-
-/*
- * Write SIZE bytes at BUF to FP, expanding @ signs into double @
- * signs. If an error occurs, return a negative value and set errno
- * to indicate the error. If not, return a nonnegative value.
- */
-int
-expand_at_signs (buf, size, fp)
- const char *buf;
- off_t size;
- FILE *fp;
-{
- register const char *cp, *next;
-
- cp = buf;
- while ((next = memchr (cp, '@', size)) != NULL)
- {
- size_t len = ++next - cp;
- if (fwrite (cp, 1, len, fp) != len)
- return EOF;
- if (putc ('@', fp) == EOF)
- return EOF;
- cp = next;
- size -= len;
- }
-
- if (fwrite (cp, 1, size, fp) != size)
- return EOF;
-
- return 1;
-}
-
-/*
- * Write an update message to (potentially) the screen and the log file.
- */
-static void
-add_log (ch, fname)
- int ch;
- char *fname;
-{
- if (!really_quiet) /* write to terminal */
- {
- char buf[2];
- buf[0] = ch;
- buf[1] = ' ';
- cvs_output (buf, 2);
- if (repos_len)
- {
- cvs_output (repository + repos_len + 1, 0);
- cvs_output ("/", 1);
- }
- else if (repository[0] != '\0')
- {
- cvs_output (repository, 0);
- cvs_output ("/", 1);
- }
- cvs_output (fname, 0);
- cvs_output ("\n", 1);
- }
-
- if (repos_len) /* write to logfile */
- (void) fprintf (logfp, "%c %s/%s\n", ch,
- repository + repos_len + 1, fname);
- else if (repository[0])
- (void) fprintf (logfp, "%c %s/%s\n", ch, repository, fname);
- else
- (void) fprintf (logfp, "%c %s\n", ch, fname);
-}
-
-/*
- * This is the recursive function that walks the argument directory looking
- * for sub-directories that have CVS administration files in them and updates
- * them recursively.
- *
- * Note that we do not follow symbolic links here, which is a feature!
- */
-static int
-import_descend_dir (message, dir, vtag, targc, targv)
- char *message;
- char *dir;
- char *vtag;
- int targc;
- char *targv[];
-{
- struct saved_cwd cwd;
- char *cp;
- int ierrno, err;
- char *rcs = NULL;
-
- if (islink (dir))
- return (0);
- if (save_cwd (&cwd))
- {
- fperrmsg (logfp, 0, 0, "ERROR: cannot get working directory");
- return (1);
- }
-
- /* Concatenate DIR to the end of REPOSITORY. */
- if (repository[0] == '\0')
- {
- char *new = xstrdup (dir);
- free (repository);
- repository = new;
- }
- else
- {
- char *new = xmalloc (strlen (repository) + strlen (dir) + 10);
- strcpy (new, repository);
- (void) strcat (new, "/");
- (void) strcat (new, dir);
- free (repository);
- repository = new;
- }
-
- if (!quiet && !current_parsed_root->isremote)
- error (0, 0, "Importing %s", repository);
-
- if ( CVS_CHDIR (dir) < 0)
- {
- ierrno = errno;
- fperrmsg (logfp, 0, ierrno, "ERROR: cannot chdir to %s", dir);
- error (0, ierrno, "ERROR: cannot chdir to %s", dir);
- err = 1;
- goto out;
- }
- if (!current_parsed_root->isremote && !isdir (repository))
- {
- rcs = xmalloc (strlen (repository) + sizeof (RCSEXT) + 5);
- (void) sprintf (rcs, "%s%s", repository, RCSEXT);
- if (isfile (repository) || isfile(rcs))
- {
- fperrmsg (logfp, 0, 0,
- "ERROR: %s is a file, should be a directory!",
- repository);
- error (0, 0, "ERROR: %s is a file, should be a directory!",
- repository);
- err = 1;
- goto out;
- }
- if (noexec == 0 && CVS_MKDIR (repository, 0777) < 0)
- {
- ierrno = errno;
- fperrmsg (logfp, 0, ierrno,
- "ERROR: cannot mkdir %s -- not added", repository);
- error (0, ierrno,
- "ERROR: cannot mkdir %s -- not added", repository);
- err = 1;
- goto out;
- }
- }
- err = import_descend (message, vtag, targc, targv);
- out:
- if (rcs != NULL)
- free (rcs);
- if ((cp = strrchr (repository, '/')) != NULL)
- *cp = '\0';
- else
- repository[0] = '\0';
- if (restore_cwd (&cwd, NULL))
- error_exit ();
- free_cwd (&cwd);
- return (err);
-}
OpenPOWER on IntegriCloud