summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/add.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1998-01-26 03:09:57 +0000
committerpeter <peter@FreeBSD.org>1998-01-26 03:09:57 +0000
commite6e45661e44f15cb8c5c6f063080509bd910b98d (patch)
treea9812ba7ade0fde6f62c1626b45d522ba104c314 /contrib/cvs/src/add.c
parent571cfa0005d94d99d1341bf8ab02be04d4df5f9f (diff)
downloadFreeBSD-src-e6e45661e44f15cb8c5c6f063080509bd910b98d.zip
FreeBSD-src-e6e45661e44f15cb8c5c6f063080509bd910b98d.tar.gz
Import cvs-1.9.23 as at 19980123. There are a number of really nice
things fixed in here, including the '-ko' vs. -A problem with remote cvs which caused all files with -ko to be resent each time (which is damn painful over a modem, I can tell you). It also found a heap of stray empty directories that should have been pruned with the -P flag to cvs update but were not for some reason. It also has the fully integrated rcs and diff, so no more fork/exec overheads for rcs,ci,patch,diff,etc. This means that it parses the control data in the rcs files only once rather than twice or more. If the 'cvs diff' vs. Index thing is going to be fixed for future patch compatability, this is the place to do it.
Diffstat (limited to 'contrib/cvs/src/add.c')
-rw-r--r--contrib/cvs/src/add.c343
1 files changed, 218 insertions, 125 deletions
diff --git a/contrib/cvs/src/add.c b/contrib/cvs/src/add.c
index 9220930..ab667df 100644
--- a/contrib/cvs/src/add.c
+++ b/contrib/cvs/src/add.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.
*
* Add
*
@@ -26,8 +26,9 @@
#include "cvs.h"
#include "savecwd.h"
+#include "fileattr.h"
-static int add_directory PROTO((char *repository, List *, char *dir));
+static int add_directory PROTO ((struct file_info *finfo));
static int build_entry PROTO((char *repository, char *user, char *options,
char *message, List * entries, char *tag));
@@ -36,57 +37,16 @@ static const char *const add_usage[] =
"Usage: %s %s [-k rcs-kflag] [-m message] files...\n",
"\t-k\tUse \"rcs-kflag\" to add the file with the specified kflag.\n",
"\t-m\tUse \"message\" for the creation log.\n",
+ "(Specify the --help global option for a list of other help options)\n",
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;
char **argv;
{
char *message = NULL;
- char *user;
int i;
char *repository;
int c;
@@ -95,6 +55,7 @@ add (argc, argv)
char *options = NULL;
List *entries;
Vers_TS *vers;
+ struct saved_cwd cwd;
if (argc == 1 || argc == -1)
usage (add_usage);
@@ -128,17 +89,64 @@ add (argc, argv)
if (argc <= 0)
usage (add_usage);
- /* find the repository associated with our current dir */
- repository = Name_Repository ((char *) NULL, (char *) NULL);
+ /* First some sanity checks. I know that the CVS case is (sort of)
+ also handled by add_directory, but we need to check here so the
+ client won't get all confused in send_file_names. */
+ for (i = 0; i < argc; i++)
+ {
+ int skip_file = 0;
+
+ /* If it were up to me I'd probably make this a fatal error.
+ But some people are really fond of their "cvs add *", and
+ don't seem to object to the warnings.
+ Whatever. */
+ strip_trailing_slashes (argv[i]);
+ if (strcmp (argv[i], ".") == 0
+ || strcmp (argv[i], "..") == 0
+ || fncmp (argv[i], CVSADM) == 0)
+ {
+ error (0, 0, "cannot add special file `%s'; skipping", argv[i]);
+ skip_file = 1;
+ }
+
+ if (skip_file)
+ {
+ int j;
+
+ /* FIXME: We don't do anything about free'ing argv[i]. But
+ the problem is that it is only sometimes allocated (see
+ cvsrc.c). */
+
+ for (j = i; j < argc - 1; ++j)
+ argv[j] = argv[j + 1];
+ --argc;
+ /* Check the new argv[i] again. */
+ --i;
+ ++err;
+ }
+ }
#ifdef CLIENT_SUPPORT
if (client_active)
{
int i;
+
+ if (argc == 0)
+ /* We snipped out all the arguments in the above sanity
+ check. We can just forget the whole thing (and we
+ better, because if we fired up the server and passed it
+ nothing, it would spit back a usage message). */
+ return err;
+
start_server ();
ign_setup ();
if (options) send_arg(options);
option_with_arg ("-m", message);
+
+ repository = Name_Repository (NULL, NULL);
+ send_a_repository ("", repository, "");
+ free (repository);
+
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
@@ -149,16 +157,48 @@ add (argc, argv)
char *date;
int nonbranch;
char *rcsdir;
+ char *p;
+ char *update_dir;
+ /* This is some mungeable storage into which we can point
+ with p and/or update_dir. */
+ char *filedir;
+
+ if (save_cwd (&cwd))
+ error_exit ();
+
+ filedir = xstrdup (argv[i]);
+ p = last_component (filedir);
+ if (p == filedir)
+ {
+ update_dir = "";
+ }
+ else
+ {
+ p[-1] = '\0';
+ update_dir = filedir;
+ if (CVS_CHDIR (update_dir) < 0)
+ error (1, errno,
+ "could not chdir to %s", update_dir);
+ }
+
+ /* find the repository associated with our current dir */
+ repository = Name_Repository (NULL, update_dir);
/* before we do anything else, see if we have any
per-directory tags */
ParseTag (&tag, &date, &nonbranch);
- rcsdir = combine_dir (repository, argv[i]);
+ rcsdir = xmalloc (strlen (repository) + strlen (p) + 5);
+ sprintf (rcsdir, "%s/%s", repository, p);
+
+ Create_Admin (p, argv[i], rcsdir, tag, date,
+ nonbranch, 0);
- strip_trailing_slashes (argv[i]);
+ send_a_repository ("", repository, update_dir);
- Create_Admin (argv[i], argv[i], rcsdir, tag, date, nonbranch);
+ if (restore_cwd (&cwd, NULL))
+ error_exit ();
+ free_cwd (&cwd);
if (tag)
free (tag);
@@ -166,32 +206,24 @@ add (argc, argv)
free (date);
free (rcsdir);
- if (strchr (argv[i], '/') == NULL)
+ if (p == filedir)
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);
+ Subdir_Register ((List *) NULL, update_dir, p);
}
+ free (repository);
+ free (filedir);
}
send_file_names (argc, argv, SEND_EXPAND_WILD);
- /* FIXME: should be able to pass SEND_NO_CONTENTS, I think. */
- send_files (argc, argv, 0, 0, SEND_BUILD_DIRS);
+ send_files (argc, argv, 0, 0, SEND_BUILD_DIRS | SEND_NO_CONTENTS);
send_to_server ("add\012", 0);
if (message)
free (message);
- free (repository);
- return get_responses_and_close ();
+ return err + get_responses_and_close ();
}
#endif
- entries = Entries_Open (0);
-
/* walk the arg list adding files/dirs */
for (i = 0; i < argc; i++)
{
@@ -200,24 +232,42 @@ add (argc, argv)
int begin_added_files = added_files;
#endif
struct file_info finfo;
+ char *p;
+
+ memset (&finfo, 0, sizeof finfo);
- user = argv[i];
- strip_trailing_slashes (user);
- if (strchr (user, '/') != NULL)
+ if (save_cwd (&cwd))
+ error_exit ();
+
+ finfo.fullname = xstrdup (argv[i]);
+ p = last_component (argv[i]);
+ if (p == argv[i])
{
- error (0, 0,
- "cannot add files with '/' in their name; %s not added", user);
- err++;
- continue;
+ finfo.update_dir = "";
+ finfo.file = p;
+ }
+ else
+ {
+ p[-1] = '\0';
+ finfo.update_dir = argv[i];
+ finfo.file = p;
+ if (CVS_CHDIR (finfo.update_dir) < 0)
+ error (1, errno, "could not chdir to %s", finfo.update_dir);
}
- memset (&finfo, 0, sizeof finfo);
- finfo.file = user;
- finfo.update_dir = "";
- finfo.fullname = user;
+ /* Add wrappers for this directory. They exist only until
+ the next call to wrap_add_file. */
+ wrap_add_file (CVSDOTWRAPPER, 1);
+
+ finfo.rcs = NULL;
+
+ /* Find the repository associated with our current dir. */
+ repository = Name_Repository (NULL, finfo.update_dir);
+
+ entries = Entries_Open (0);
+
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
@@ -233,23 +283,25 @@ add (argc, argv)
if (vers->ts_user == NULL)
{
/* There is no user file either */
- error (0, 0, "nothing known about %s", user);
+ error (0, 0, "nothing known about %s", finfo.fullname);
err++;
}
- else if (!isdir (user) || wrap_name_has (user, WRAP_TOCVS))
+ else if (!isdir (finfo.file)
+ || wrap_name_has (finfo.file, WRAP_TOCVS))
{
/*
* See if a directory exists in the repository with
* the same name. If so, blow this request off.
*/
- char *dname = xmalloc (strlen (repository) + strlen (user)
+ char *dname = xmalloc (strlen (repository)
+ + strlen (finfo.file)
+ 10);
- (void) sprintf (dname, "%s/%s", repository, user);
+ (void) sprintf (dname, "%s/%s", repository, finfo.file);
if (isdir (dname))
{
error (0, 0,
"cannot add file `%s' since the directory",
- user);
+ finfo.fullname);
error (0, 0, "`%s' already exists in the repository",
dname);
error (1, 0, "illegal filename overlap");
@@ -262,11 +314,11 @@ add (argc, argv)
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 (wrap_name_has (finfo.file, WRAP_RCSOPTION))
{
if (vers->options)
free (vers->options);
- vers->options = wrap_rcsoption (user, 1);
+ vers->options = wrap_rcsoption (finfo.file, 1);
}
}
@@ -280,7 +332,7 @@ add (argc, argv)
else
{
/* There is a user file, so build the entry for it */
- if (build_entry (repository, user, vers->options,
+ if (build_entry (repository, finfo.file, vers->options,
message, entries, vers->tag) != 0)
err++;
else
@@ -291,17 +343,19 @@ add (argc, argv)
if (vers->tag)
error (0, 0, "\
scheduling %s `%s' for addition on branch `%s'",
- (wrap_name_has (user, WRAP_TOCVS)
+ (wrap_name_has (finfo.file,
+ WRAP_TOCVS)
? "wrapper"
: "file"),
- user, vers->tag);
+ finfo.fullname, vers->tag);
else
error (0, 0,
"scheduling %s `%s' for addition",
- (wrap_name_has (user, WRAP_TOCVS)
+ (wrap_name_has (finfo.file,
+ WRAP_TOCVS)
? "wrapper"
: "file"),
- user);
+ finfo.fullname);
}
}
}
@@ -309,10 +363,11 @@ scheduling %s `%s' for addition on branch `%s'",
}
else if (RCS_isdead (vers->srcfile, vers->vn_rcs))
{
- if (isdir (user) && !wrap_name_has (user, WRAP_TOCVS))
+ if (isdir (finfo.file)
+ && !wrap_name_has (finfo.file, WRAP_TOCVS))
{
error (0, 0, "\
-the directory `%s' cannot be added because a file of the", user);
+the directory `%s' cannot be added because a file of the", finfo.fullname);
error (1, 0, "\
same name already exists in the repository.");
}
@@ -330,7 +385,7 @@ same name already exists in the repository.");
if (vers->tag)
error (0, 0, "\
file `%s' will be added on branch `%s' from version %s",
- user, vers->tag, vers->vn_rcs);
+ finfo.fullname, vers->tag, vers->vn_rcs);
else
/* I'm not sure that mentioning
vers->vn_rcs makes any sense here; I
@@ -338,8 +393,9 @@ file `%s' will be added on branch `%s' from version %s",
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,
+ finfo.fullname, vers->vn_rcs);
+ Register (entries, finfo.file, "0", vers->ts_user,
+ NULL,
vers->tag, NULL, NULL);
++added_files;
}
@@ -351,7 +407,8 @@ re-adding file %s (in place of dead revision %s)",
* There is an RCS file already, so somebody else must've
* added it
*/
- error (0, 0, "%s added independently by second party", user);
+ error (0, 0, "%s added independently by second party",
+ finfo.fullname);
err++;
}
}
@@ -362,7 +419,7 @@ re-adding file %s (in place of dead revision %s)",
* An entry for a new-born file, ts_rcs is dummy, but that is
* inappropriate here
*/
- error (0, 0, "%s has already been entered", user);
+ error (0, 0, "%s has already been entered", finfo.fullname);
err++;
}
else if (vers->vn_user[0] == '-')
@@ -379,7 +436,7 @@ re-adding file %s (in place of dead revision %s)",
* it from under us
*/
error (0, 0, "\
-cannot resurrect %s; RCS file removed by second party", user);
+cannot resurrect %s; RCS file removed by second party", finfo.fullname);
err++;
}
else
@@ -389,12 +446,13 @@ cannot resurrect %s; RCS file removed by second party", user);
* There is an RCS file, so remove the "-" from the
* version number and restore the file
*/
- char *tmp = xmalloc (strlen (user) + 50);
+ char *tmp = xmalloc (strlen (finfo.file) + 50);
(void) strcpy (tmp, vers->vn_user + 1);
(void) strcpy (vers->vn_user, tmp);
- (void) sprintf (tmp, "Resurrected %s", user);
- Register (entries, user, vers->vn_user, tmp, vers->options,
+ (void) sprintf (tmp, "Resurrected %s", finfo.file);
+ Register (entries, finfo.file, vers->vn_user, tmp,
+ vers->options,
vers->tag, vers->date, vers->ts_conflict);
free (tmp);
@@ -404,12 +462,13 @@ cannot resurrect %s; RCS file removed by second party", user);
check the file out. */
if (update (2, argv + i - 1) == 0)
{
- error (0, 0, "%s, version %s, resurrected", user,
+ error (0, 0, "%s, version %s, resurrected",
+ finfo.fullname,
vers->vn_user);
}
else
{
- error (0, 0, "could not resurrect %s", user);
+ error (0, 0, "could not resurrect %s", finfo.fullname);
err++;
}
}
@@ -418,14 +477,15 @@ cannot resurrect %s; RCS file removed by second party", user);
{
/* The user file shouldn't be there */
error (0, 0, "\
-%s should be removed and is still there (or is back again)", user);
+%s should be removed and is still there (or is back again)", finfo.fullname);
err++;
}
}
else
{
/* A normal entry, ts_rcs is valid, so it must already be there */
- error (0, 0, "%s already exists, with version number %s", user,
+ error (0, 0, "%s already exists, with version number %s",
+ finfo.fullname,
vers->vn_user);
err++;
}
@@ -433,26 +493,34 @@ cannot resurrect %s; RCS file removed by second party", user);
/* passed all the checks. Go ahead and add it if its a directory */
if (begin_err == err
- && isdir (user)
- && !wrap_name_has (user, WRAP_TOCVS))
+ && isdir (finfo.file)
+ && !wrap_name_has (finfo.file, WRAP_TOCVS))
{
- err += add_directory (repository, entries, user);
- continue;
+ err += add_directory (&finfo);
}
+ else
+ {
#ifdef SERVER_SUPPORT
- if (server_active && begin_added_files != added_files)
- server_checked_in (user, ".", repository);
+ if (server_active && begin_added_files != added_files)
+ server_checked_in (finfo.file, finfo.update_dir, repository);
#endif
+ }
+ free (repository);
+ Entries_Close (entries);
+
+ if (restore_cwd (&cwd, NULL))
+ error_exit ();
+ free_cwd (&cwd);
+
+ free (finfo.fullname);
}
if (added_files)
- error (0, 0, "use 'cvs commit' to add %s permanently",
+ error (0, 0, "use '%s commit' to add %s permanently",
+ program_name,
(added_files == 1) ? "this file" : "these files");
- Entries_Close (entries);
-
if (message)
free (message);
- free (repository);
return (err);
}
@@ -465,24 +533,28 @@ cannot resurrect %s; RCS file removed by second party", user);
* Returns 1 on failure, 0 on success.
*/
static int
-add_directory (repository, entries, dir)
- char *repository;
- List *entries;
- char *dir;
+add_directory (finfo)
+ struct file_info *finfo;
{
+ char *repository = finfo->repository;
+ List *entries = finfo->entries;
+ char *dir = finfo->file;
+
char *rcsdir = NULL;
struct saved_cwd cwd;
char *message = NULL;
char *tag, *date;
int nonbranch;
+ char *attrs;
if (strchr (dir, '/') != NULL)
{
+ /* "Can't happen". */
error (0, 0,
"directory %s not added; must be a direct sub-directory", dir);
return (1);
}
- if (strcmp (dir, CVSADM) == 0)
+ if (fncmp (dir, CVSADM) == 0)
{
error (0, 0, "cannot add a `%s' directory", CVSADM);
return (1);
@@ -491,12 +563,18 @@ add_directory (repository, entries, dir)
/* before we do anything else, see if we have any per-directory tags */
ParseTag (&tag, &date, &nonbranch);
+ /* Remember the default attributes from this directory, so we can apply
+ them to the new directory. */
+ fileattr_startdir (repository);
+ attrs = fileattr_getall (NULL);
+ fileattr_free ();
+
/* now, remember where we were, so we can get back */
if (save_cwd (&cwd))
return (1);
if ( CVS_CHDIR (dir) < 0)
{
- error (0, errno, "cannot chdir to %s", dir);
+ error (0, errno, "cannot chdir to %s", finfo->fullname);
return (1);
}
#ifdef SERVER_SUPPORT
@@ -505,19 +583,24 @@ add_directory (repository, entries, dir)
if (isfile (CVSADM))
#endif
{
- error (0, 0, "%s/%s already exists", dir, CVSADM);
+ error (0, 0, "%s/%s already exists", finfo->fullname, CVSADM);
goto out;
}
- rcsdir = combine_dir (repository, dir);
+ rcsdir = xmalloc (strlen (repository) + strlen (dir) + 5);
+ sprintf (rcsdir, "%s/%s", repository, dir);
if (isfile (rcsdir) && !isdir (rcsdir))
{
- error (0, 0, "%s is not a directory; %s not added", rcsdir, dir);
+ error (0, 0, "%s is not a directory; %s not added", rcsdir,
+ finfo->fullname);
goto out;
}
/* setup the log message */
- message = xmalloc (strlen (rcsdir) + 80);
+ message = xmalloc (strlen (rcsdir)
+ + 80
+ + (tag == NULL ? 0 : strlen (tag) + 80)
+ + (date == NULL ? 0 : strlen (date) + 80));
(void) sprintf (message, "Directory %s added to the repository\n", rcsdir);
if (tag)
{
@@ -559,6 +642,15 @@ add_directory (repository, entries, dir)
(void) umask (omask);
}
+ /* Now set the default file attributes to the ones we inherited
+ from the parent directory. */
+ fileattr_startdir (rcsdir);
+ fileattr_setall (NULL, attrs);
+ fileattr_write ();
+ fileattr_free ();
+ if (attrs != NULL)
+ free (attrs);
+
/*
* Set up an update list with a single title node for Update_Logfile
*/
@@ -579,9 +671,9 @@ add_directory (repository, entries, dir)
#ifdef SERVER_SUPPORT
if (!server_active)
- Create_Admin (".", dir, rcsdir, tag, date, nonbranch);
+ Create_Admin (".", finfo->fullname, rcsdir, tag, date, nonbranch, 0);
#else
- Create_Admin (".", dir, rcsdir, tag, date, nonbranch);
+ Create_Admin (".", finfo->fullname, rcsdir, tag, date, nonbranch, 0);
#endif
if (tag)
free (tag);
@@ -594,7 +686,8 @@ add_directory (repository, entries, dir)
Subdir_Register (entries, (char *) NULL, dir);
- (void) printf ("%s", message);
+ cvs_output (message, 0);
+
free (rcsdir);
free (message);
OpenPOWER on IntegriCloud