summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/add.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1997-05-15 22:46:24 +0000
committerpeter <peter@FreeBSD.org>1997-05-15 22:46:24 +0000
commit4f40fe8334ad5f056e1d9105f23fe7ac859c39ba (patch)
tree3b2f0092fa216d9f61059ba94b7f10b5bacf9496 /contrib/cvs/src/add.c
parent8982e501c77217c860f79bba431f46a62b607a21 (diff)
downloadFreeBSD-src-4f40fe8334ad5f056e1d9105f23fe7ac859c39ba.zip
FreeBSD-src-4f40fe8334ad5f056e1d9105f23fe7ac859c39ba.tar.gz
Import of cvs-1.9.9-970515 onto vendor branch.
Obtained from: cyclic.com
Diffstat (limited to 'contrib/cvs/src/add.c')
-rw-r--r--contrib/cvs/src/add.c324
1 files changed, 233 insertions, 91 deletions
diff --git a/contrib/cvs/src/add.c b/contrib/cvs/src/add.c
index 82efefe..b7d5e5d 100644
--- a/contrib/cvs/src/add.c
+++ b/contrib/cvs/src/add.c
@@ -27,7 +27,7 @@
#include "cvs.h"
#include "savecwd.h"
-static int add_directory PROTO((char *repository, char *dir));
+static int add_directory PROTO((char *repository, List *, char *dir));
static int build_entry PROTO((char *repository, char *user, char *options,
char *message, List * entries, char *tag));
@@ -39,6 +39,47 @@ static const char *const add_usage[] =
NULL
};
+static char *combine_dir PROTO ((char *, char *));
+
+/* Given a directory DIR and a subdirectory within it, SUBDIR, combine
+ the two into a new directory name. Returns a newly malloc'd string.
+ For now this is a fairly simple affair, but perhaps it will want
+ to have grander ambitions in the context of VMS or others (or perhaps
+ not, perhaps that should all be hidden inside CVS_FOPEN and libc and so
+ on, and CVS should just see foo/bar/baz style pathnames). */
+static char *
+combine_dir (dir, subdir)
+ char *dir;
+ char *subdir;
+{
+ char *retval;
+ size_t dir_len;
+
+ dir_len = strlen (dir);
+ retval = xmalloc (dir_len + strlen (subdir) + 10);
+ if (dir_len >= 2
+ && dir[dir_len - 1] == '.'
+ && ISDIRSEP (dir[dir_len - 2]))
+ {
+ /* The dir name has an extraneous "." at the end.
+ I'm not completely sure that this is the best place
+ to strip it off--it is possible that Name_Repository
+ should do so, or it shouldn't be in the CVS/Repository
+ file in the first place. Fixing it here seems like
+ a safe, small change, but I'm not sure it catches
+ all the cases. */
+ strncpy (retval, dir, dir_len - 2);
+ retval[dir_len - 2] = '\0';
+ }
+ else
+ {
+ strcpy (retval, dir);
+ }
+ strcat (retval, "/");
+ strcat (retval, subdir);
+ return retval;
+}
+
int
add (argc, argv)
int argc;
@@ -62,7 +103,7 @@ add (argc, argv)
/* parse args */
optind = 1;
- while ((c = getopt (argc, argv, "k:m:")) != -1)
+ while ((c = getopt (argc, argv, "+k:m:")) != -1)
{
switch (c)
{
@@ -92,42 +133,61 @@ add (argc, argv)
#ifdef CLIENT_SUPPORT
if (client_active)
- {
+ {
int i;
start_server ();
ign_setup ();
if (options) send_arg(options);
option_with_arg ("-m", message);
for (i = 0; i < argc; ++i)
- /* FIXME: Does this erroneously call Create_Admin in error
- conditions which are only detected once the server gets its
- hands on things? */
- if (isdir (argv[i]))
+ /* FIXME: Does this erroneously call Create_Admin in error
+ conditions which are only detected once the server gets its
+ hands on things? */
+ if (isdir (argv[i]))
{
- char *tag;
- char *date;
- char *rcsdir = xmalloc (strlen (repository)
- + strlen (argv[i]) + 10);
+ char *tag;
+ char *date;
+ int nonbranch;
+ char *rcsdir;
- /* before we do anything else, see if we have any
- per-directory tags */
- ParseTag (&tag, &date);
+ /* before we do anything else, see if we have any
+ per-directory tags */
+ ParseTag (&tag, &date, &nonbranch);
- sprintf (rcsdir, "%s/%s", repository, argv[i]);
+ rcsdir = combine_dir (repository, argv[i]);
- Create_Admin (argv[i], argv[i], rcsdir, tag, date);
+ strip_trailing_slashes (argv[i]);
- if (tag)
- free (tag);
- if (date)
- free (date);
- free (rcsdir);
+ Create_Admin (argv[i], argv[i], rcsdir, tag, date, nonbranch);
+
+ if (tag)
+ free (tag);
+ if (date)
+ free (date);
+ free (rcsdir);
+
+ if (strchr (argv[i], '/') == NULL)
+ Subdir_Register ((List *) NULL, (char *) NULL, argv[i]);
+ else
+ {
+ char *cp, *b;
+
+ cp = xstrdup (argv[i]);
+ b = strrchr (cp, '/');
+ *b++ = '\0';
+ Subdir_Register ((List *) NULL, cp, b);
+ free (cp);
+ }
}
send_file_names (argc, argv, SEND_EXPAND_WILD);
- send_files (argc, argv, 0, 0);
+ /* FIXME: should be able to pass SEND_NO_CONTENTS, I think. */
+ send_files (argc, argv, 0, 0, SEND_BUILD_DIRS);
send_to_server ("add\012", 0);
+ if (message)
+ free (message);
+ free (repository);
return get_responses_and_close ();
- }
+ }
#endif
entries = Entries_Open (0);
@@ -136,7 +196,10 @@ add (argc, argv)
for (i = 0; i < argc; i++)
{
int begin_err = err;
+#ifdef SERVER_SUPPORT
int begin_added_files = added_files;
+#endif
+ struct file_info finfo;
user = argv[i];
strip_trailing_slashes (user);
@@ -148,8 +211,19 @@ add (argc, argv)
continue;
}
- vers = Version_TS (repository, options, (char *) NULL, (char *) NULL,
- user, 0, 0, entries, (RCSNode *) NULL);
+ memset (&finfo, 0, sizeof finfo);
+ finfo.file = user;
+ finfo.update_dir = "";
+ finfo.fullname = user;
+ finfo.repository = repository;
+ finfo.entries = entries;
+ finfo.rcs = NULL;
+
+ /* We pass force_tag_match as 1. If the directory has a
+ sticky branch tag, and there is already an RCS file which
+ does not have that tag, then the head revision is
+ meaningless to us. */
+ vers = Version_TS (&finfo, options, NULL, NULL, 1, 0);
if (vers->vn_user == NULL)
{
/* No entry available, ts_rcs is invalid */
@@ -168,7 +242,8 @@ add (argc, argv)
* See if a directory exists in the repository with
* the same name. If so, blow this request off.
*/
- char dname[PATH_MAX];
+ char *dname = xmalloc (strlen (repository) + strlen (user)
+ + 10);
(void) sprintf (dname, "%s/%s", repository, user);
if (isdir (dname))
{
@@ -179,29 +254,55 @@ add (argc, argv)
dname);
error (1, 0, "illegal filename overlap");
}
+ free (dname);
- /* There is a user file, so build the entry for it */
- if (build_entry (repository, user, vers->options,
- message, entries, vers->tag) != 0)
- err++;
- else
+ if (vers->options == NULL || *vers->options == '\0')
{
- added_files++;
- if (!quiet)
+ /* No options specified on command line (or in
+ rcs file if it existed, e.g. the file exists
+ on another branch). Check for a value from
+ the wrapper stuff. */
+ if (wrap_name_has (user, WRAP_RCSOPTION))
{
- if (vers->tag)
- error (0, 0, "\
+ if (vers->options)
+ free (vers->options);
+ vers->options = wrap_rcsoption (user, 1);
+ }
+ }
+
+ if (vers->nonbranch)
+ {
+ error (0, 0,
+ "cannot add file on non-branch tag %s",
+ vers->tag);
+ ++err;
+ }
+ else
+ {
+ /* There is a user file, so build the entry for it */
+ if (build_entry (repository, user, vers->options,
+ message, entries, vers->tag) != 0)
+ err++;
+ else
+ {
+ added_files++;
+ if (!quiet)
+ {
+ if (vers->tag)
+ error (0, 0, "\
scheduling %s `%s' for addition on branch `%s'",
- (wrap_name_has (user, WRAP_TOCVS)
- ? "wrapper"
- : "file"),
- user, vers->tag);
- else
- error (0, 0, "scheduling %s `%s' for addition",
- (wrap_name_has (user, WRAP_TOCVS)
- ? "wrapper"
- : "file"),
- user);
+ (wrap_name_has (user, WRAP_TOCVS)
+ ? "wrapper"
+ : "file"),
+ user, vers->tag);
+ else
+ error (0, 0,
+ "scheduling %s `%s' for addition",
+ (wrap_name_has (user, WRAP_TOCVS)
+ ? "wrapper"
+ : "file"),
+ user);
+ }
}
}
}
@@ -210,20 +311,38 @@ scheduling %s `%s' for addition on branch `%s'",
{
if (isdir (user) && !wrap_name_has (user, WRAP_TOCVS))
{
- error (0, 0, "the directory `%s' cannot be added because a file of the", user);
- error (1, 0, "same name already exists in the repository.");
+ error (0, 0, "\
+the directory `%s' cannot be added because a file of the", user);
+ error (1, 0, "\
+same name already exists in the repository.");
}
else
{
- if (vers->tag)
- error (0, 0, "file `%s' will be added on branch `%s' from version %s",
- user, vers->tag, vers->vn_rcs);
+ if (vers->nonbranch)
+ {
+ error (0, 0,
+ "cannot add file on non-branch tag %s",
+ vers->tag);
+ ++err;
+ }
else
- error (0, 0, "version %s of `%s' will be resurrected",
- vers->vn_rcs, user);
- Register (entries, user, "0", vers->ts_user, NULL,
- vers->tag, NULL, NULL);
- ++added_files;
+ {
+ if (vers->tag)
+ error (0, 0, "\
+file `%s' will be added on branch `%s' from version %s",
+ user, vers->tag, vers->vn_rcs);
+ else
+ /* I'm not sure that mentioning
+ vers->vn_rcs makes any sense here; I
+ can't think of a way to word the
+ message which is not confusing. */
+ error (0, 0, "\
+re-adding file %s (in place of dead revision %s)",
+ user, vers->vn_rcs);
+ Register (entries, user, "0", vers->ts_user, NULL,
+ vers->tag, NULL, NULL);
+ ++added_files;
+ }
}
}
else
@@ -259,8 +378,8 @@ scheduling %s `%s' for addition on branch `%s'",
* There is no RCS file, so somebody else must've removed
* it from under us
*/
- error (0, 0,
- "cannot resurrect %s; RCS file removed by second party", user);
+ error (0, 0, "\
+cannot resurrect %s; RCS file removed by second party", user);
err++;
}
else
@@ -298,7 +417,8 @@ scheduling %s `%s' for addition on branch `%s'",
else
{
/* The user file shouldn't be there */
- error (0, 0, "%s should be removed and is still there (or is back again)", user);
+ error (0, 0, "\
+%s should be removed and is still there (or is back again)", user);
err++;
}
}
@@ -316,7 +436,7 @@ scheduling %s `%s' for addition on branch `%s'",
&& isdir (user)
&& !wrap_name_has (user, WRAP_TOCVS))
{
- err += add_directory (repository, user);
+ err += add_directory (repository, entries, user);
continue;
}
#ifdef SERVER_SUPPORT
@@ -332,6 +452,7 @@ scheduling %s `%s' for addition on branch `%s'",
if (message)
free (message);
+ free (repository);
return (err);
}
@@ -344,14 +465,16 @@ scheduling %s `%s' for addition on branch `%s'",
* Returns 1 on failure, 0 on success.
*/
static int
-add_directory (repository, dir)
+add_directory (repository, entries, dir)
char *repository;
+ List *entries;
char *dir;
{
- char rcsdir[PATH_MAX];
+ char *rcsdir = NULL;
struct saved_cwd cwd;
- char message[PATH_MAX + 100];
+ char *message = NULL;
char *tag, *date;
+ int nonbranch;
if (strchr (dir, '/') != NULL)
{
@@ -366,12 +489,12 @@ add_directory (repository, dir)
}
/* before we do anything else, see if we have any per-directory tags */
- ParseTag (&tag, &date);
+ ParseTag (&tag, &date, &nonbranch);
/* now, remember where we were, so we can get back */
if (save_cwd (&cwd))
return (1);
- if (chdir (dir) < 0)
+ if ( CVS_CHDIR (dir) < 0)
{
error (0, errno, "cannot chdir to %s", dir);
return (1);
@@ -386,7 +509,7 @@ add_directory (repository, dir)
goto out;
}
- (void) sprintf (rcsdir, "%s/%s", repository, dir);
+ rcsdir = combine_dir (repository, dir);
if (isfile (rcsdir) && !isdir (rcsdir))
{
error (0, 0, "%s is not a directory; %s not added", rcsdir, dir);
@@ -394,6 +517,7 @@ add_directory (repository, dir)
}
/* setup the log message */
+ message = xmalloc (strlen (rcsdir) + 80);
(void) sprintf (message, "Directory %s added to the repository\n", rcsdir);
if (tag)
{
@@ -413,30 +537,27 @@ add_directory (repository, dir)
mode_t omask;
Node *p;
List *ulist;
+ struct logfile_info *li;
-#if 0
- char line[MAXLINELEN];
-
- (void) printf ("Add directory %s to the repository (y/n) [n] ? ",
- rcsdir);
- (void) fflush (stdout);
- clearerr (stdin);
- if (fgets (line, sizeof (line), stdin) == NULL ||
- (line[0] != 'y' && line[0] != 'Y'))
- {
- error (0, 0, "directory %s not added", rcsdir);
- goto out;
- }
-#endif
+ /* There used to be some code here which would prompt for
+ whether to add the directory. The details of that code had
+ bitrotted, but more to the point it can't work
+ client/server, doesn't ask in the right way for GUIs, etc.
+ A better way of making it harder to accidentally add
+ directories would be to have to add and commit directories
+ like for files. The code was #if 0'd at least since CVS 1.5. */
- omask = umask (cvsumask);
- if (CVS_MKDIR (rcsdir, 0777) < 0)
+ if (!noexec)
{
- error (0, errno, "cannot mkdir %s", rcsdir);
+ omask = umask (cvsumask);
+ if (CVS_MKDIR (rcsdir, 0777) < 0)
+ {
+ error (0, errno, "cannot mkdir %s", rcsdir);
+ (void) umask (omask);
+ goto out;
+ }
(void) umask (omask);
- goto out;
}
- (void) umask (omask);
/*
* Set up an update list with a single title node for Update_Logfile
@@ -446,28 +567,45 @@ add_directory (repository, dir)
p->type = UPDATE;
p->delproc = update_delproc;
p->key = xstrdup ("- New directory");
- p->data = (char *) T_TITLE;
+ li = (struct logfile_info *) xmalloc (sizeof (struct logfile_info));
+ li->type = T_TITLE;
+ li->tag = xstrdup (tag);
+ li->rev_old = li->rev_new = NULL;
+ p->data = (char *) li;
(void) addnode (ulist, p);
- Update_Logfile (rcsdir, message, (char *) NULL, (FILE *) NULL, ulist);
+ Update_Logfile (rcsdir, message, (FILE *) NULL, ulist);
dellist (&ulist);
}
#ifdef SERVER_SUPPORT
if (!server_active)
- Create_Admin (".", dir, rcsdir, tag, date);
+ Create_Admin (".", dir, rcsdir, tag, date, nonbranch);
#else
- Create_Admin (".", dir, rcsdir, tag, date);
+ Create_Admin (".", dir, rcsdir, tag, date, nonbranch);
#endif
if (tag)
free (tag);
if (date)
free (date);
+ if (restore_cwd (&cwd, NULL))
+ error_exit ();
+ free_cwd (&cwd);
+
+ Subdir_Register (entries, (char *) NULL, dir);
+
(void) printf ("%s", message);
+ free (rcsdir);
+ free (message);
+
+ return (0);
+
out:
if (restore_cwd (&cwd, NULL))
- exit (EXIT_FAILURE);
+ error_exit ();
free_cwd (&cwd);
+ if (rcsdir != NULL)
+ free (rcsdir);
return (0);
}
@@ -484,8 +622,8 @@ build_entry (repository, user, options, message, entries, tag)
List *entries;
char *tag;
{
- char fname[PATH_MAX];
- char line[MAXLINELEN];
+ char *fname;
+ char *line;
FILE *fp;
if (noexec)
@@ -496,19 +634,23 @@ build_entry (repository, user, options, message, entries, tag)
* file user,t. If the "message" argument is set, use it as the
* initial creation log (which typically describes the file).
*/
+ fname = xmalloc (strlen (user) + 80);
(void) sprintf (fname, "%s/%s%s", CVSADM, user, CVSEXT_LOG);
fp = open_file (fname, "w+");
if (message && fputs (message, fp) == EOF)
error (1, errno, "cannot write to %s", fname);
if (fclose(fp) == EOF)
error(1, errno, "cannot close %s", fname);
+ free (fname);
/*
* Create the entry now, since this allows the user to interrupt us above
* without needing to clean anything up (well, we could clean up the
* ,t file, but who cares).
*/
+ line = xmalloc (strlen (user) + 20);
(void) sprintf (line, "Initial %s", user);
Register (entries, user, "0", line, options, tag, (char *) 0, (char *) 0);
+ free (line);
return (0);
}
OpenPOWER on IntegriCloud