mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
First round of the post-import cleanups...
This commit is contained in:
parent
271f76d028
commit
21eb9ed3e1
57 changed files with 6139 additions and 2901 deletions
|
|
@ -1,5 +1,5 @@
|
|||
# $Id: Makefile,v 1.5 1995/03/31 07:55:01 nate Exp $
|
||||
# $Id: Makefile,v 1.6 1995/04/14 15:15:27 nate Exp $
|
||||
|
||||
SUBDIR = lib cvs mkmodules cvsinit doc examples
|
||||
SUBDIR = lib cvs mkmodules contrib cvsbug cvsinit doc examples
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
|
|
|||
41
gnu/usr.bin/cvs/contrib/Makefile
Normal file
41
gnu/usr.bin/cvs/contrib/Makefile
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# $Id: Makefile,v 1.2 1995/07/25 00:31:51 bde Exp $
|
||||
|
||||
SCRIPTS= ccvs-rsh rcs2log clmerge cln_hist commit_prep cvs_acls cvscheck \
|
||||
log log_accum mfpipe rcs-to-cvs rcs2log rcslock sccs2rcs
|
||||
|
||||
FILES= README cvscheck.man cvshelp.man descend.man intro.doc
|
||||
|
||||
PCLCVS= ChangeLog INSTALL NEWS README \
|
||||
compile-all.el pcl-cvs-lucid.el pcl-cvs-lucid.elc pcl-cvs-startup.el \
|
||||
pcl-cvs.el pcl-cvs.elc pcl-cvs.texinfo
|
||||
|
||||
EXAMPDIR= /usr/share/examples/cvs
|
||||
PERLPATH= /usr/bin/perl
|
||||
CLEANFILES+= $(SCRIPTS)
|
||||
|
||||
.SUFFIXES: .sh .csh .pl
|
||||
|
||||
all: ${SCRIPTS}
|
||||
|
||||
.sh:
|
||||
cp $< $@
|
||||
|
||||
.csh:
|
||||
sed -e 's,xCSH_PATHx,/bin/csh,' $< > $@
|
||||
|
||||
.pl:
|
||||
sed -e 's,xPERL_PATHx,$(PERLPATH),' $< > $@
|
||||
|
||||
|
||||
afterinstall:
|
||||
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
|
||||
${SCRIPTS} ${DESTDIR}${EXAMPDIR}/contrib
|
||||
cd ${.CURDIR} ; \
|
||||
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 \
|
||||
${FILES} ${DESTDIR}${EXAMPDIR}/contrib
|
||||
cd ${.CURDIR}/pcl-cvs ; \
|
||||
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 \
|
||||
${PCLCVS} ${DESTDIR}${EXAMPDIR}/pcl-cvs
|
||||
|
||||
.include "../../Makefile.inc"
|
||||
.include <bsd.prog.mk>
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
# @(#) Id: dist-makefile,v 1.19 1993/05/31 22:43:45 ceder Exp
|
||||
# Makefile for pcl-cvs release 1.05.
|
||||
# Copyright (C) 1992, 1993 Per Cederqvist
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
# This is the directory in which the ELFILES and ELCFILES will be
|
||||
# installed.
|
||||
|
||||
lispdir = /usr/local/lib/elisp
|
||||
|
||||
# Where to install the info file.
|
||||
|
||||
prefix=/usr/local
|
||||
infodir = $(prefix)/info
|
||||
|
||||
# Used to byte-compile files.
|
||||
|
||||
EMACS=emacs
|
||||
|
||||
#
|
||||
# The rest of this file should not need to be modified.
|
||||
#
|
||||
|
||||
# Just in case...
|
||||
SHELL = /bin/sh
|
||||
|
||||
ELFILES = pcl-cvs.el pcl-cvs-lucid.el
|
||||
ELCFILES = pcl-cvs.elc pcl-cvs-lucid.elc
|
||||
INFOFILES = pcl-cvs
|
||||
TEXTMPS = pcl-cvs.aux pcl-cvs.log pcl-cvs.toc pcl-cvs.dvi pcl-cvs.cp \
|
||||
pcl-cvs.fn pcl-cvs.vr pcl-cvs.tp pcl-cvs.ky pcl-cvs.pg \
|
||||
pcl-cvs.cps pcl-cvs.fns pcl-cvs.kys pcl-cvs.pgs pcl-cvs.tps \
|
||||
pcl-cvs.vrs
|
||||
|
||||
INSTALL = install
|
||||
INSTALL_DATA = $(INSTALL)
|
||||
|
||||
elcfiles:
|
||||
$(EMACS) -batch -l ./compile-all.el -f compile-pcl-cvs
|
||||
|
||||
all: elcfiles info
|
||||
|
||||
# Don't install the info file yet, since it requires makeinfo
|
||||
# version 2.something (and version 1.something is distributed with emacs).
|
||||
#
|
||||
# install: install_elc install_info
|
||||
install: install_elc
|
||||
for i in $(ELFILES); do $(INSTALL_DATA) $$i $(lispdir)/$$i; done
|
||||
|
||||
install_elc: elcfiles
|
||||
for i in $(ELCFILES); do $(INSTALL_DATA) $$i $(lispdir)/$$i; done
|
||||
|
||||
install_info: pcl-cvs
|
||||
$(INSTALL_DATA) pcl-cvs $(infodir)/pcl-cvs
|
||||
|
||||
info pcl-cvs: pcl-cvs.texinfo
|
||||
makeinfo +fill-column=70 pcl-cvs.texinfo
|
||||
|
||||
pcl-cvs.dvi: pcl-cvs.texinfo
|
||||
tex pcl-cvs.texinfo
|
||||
tex pcl-cvs.texinfo
|
||||
-texindex pcl-cvs.cp pcl-cvs.fn pcl-cvs.vr pcl-cvs.tp pcl-cvs.ky \
|
||||
pcl-cvs.pg
|
||||
tex pcl-cvs.texinfo
|
||||
|
||||
mostlyclean clean realclean:
|
||||
rm -f *~ core $(ELCFILES) $(INFOFILES) $(TEXTMPS)
|
||||
|
||||
tags TAGS:
|
||||
etags *.el
|
||||
|
|
@ -1,18 +1,20 @@
|
|||
# $Id: Makefile,v 1.25 1995/03/22 19:39:45 nate Exp $
|
||||
# $Id: Makefile,v 1.10 1995/03/31 07:55:08 nate Exp $
|
||||
|
||||
PROG= cvs
|
||||
MAN1= cvs.1
|
||||
MAN5= cvs.5
|
||||
SRCS = add.c admin.c checkin.c checkout.c classify.c commit.c create_adm.c \
|
||||
cvsrc.c diff.c entries.c find_names.c history.c ignore.c import.c \
|
||||
lock.c log.c logmsg.c main.c modules.c no_diff.c parseinfo.c patch.c \
|
||||
rcs.c recurse.c release.c remove.c repos.c root.c rtag.c status.c \
|
||||
tag.c update.c vers_ts.c
|
||||
SRCS = add.c admin.c checkin.c checkout.c classify.c client.c commit.c \
|
||||
create_adm.c cvsrc.c diff.c entries.c expand_path.c find_names.c \
|
||||
history.c ignore.c import.c lock.c log.c login.c logmsg.c main.c \
|
||||
modules.c no_diff.c parseinfo.c patch.c rcs.c rcscmds.c recurse.c \
|
||||
release.c remove.c repos.c root.c rtag.c server.c status.c tag.c \
|
||||
update.c vers_ts.c wrapper.c
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../lib -DHAVE_CONFIG_H -DHAVE_TIMEZONE
|
||||
CFLAGS+= -I${.CURDIR}/../lib -DHAVE_CONFIG_H
|
||||
|
||||
DPADD+= ${LIBCVS} ${LIBGNUREGEX}
|
||||
LDADD+= -lcvs -lgnuregex
|
||||
|
||||
.include "../../Makefile.inc"
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
|
|
|
|||
|
|
@ -25,17 +25,18 @@
|
|||
*/
|
||||
|
||||
#include "cvs.h"
|
||||
#include "save-cwd.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)add.c 1.55 94/10/22 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)add.c 1.55 94/10/22 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static int add_directory PROTO((char *repository, char *dir));
|
||||
static int build_entry PROTO((char *repository, char *user, char *options,
|
||||
char *message, List * entries, char *tag));
|
||||
|
||||
static char *add_usage[] =
|
||||
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",
|
||||
|
|
@ -46,7 +47,7 @@ static char *add_usage[] =
|
|||
int
|
||||
add (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
char *message = NULL;
|
||||
char *user;
|
||||
|
|
@ -62,6 +63,8 @@ add (argc, argv)
|
|||
if (argc == 1 || argc == -1)
|
||||
usage (add_usage);
|
||||
|
||||
wrap_setup ();
|
||||
|
||||
/* parse args */
|
||||
optind = 1;
|
||||
while ((c = getopt (argc, argv, "k:m:")) != -1)
|
||||
|
|
@ -91,12 +94,54 @@ add (argc, argv)
|
|||
|
||||
/* find the repository associated with our current dir */
|
||||
repository = Name_Repository ((char *) NULL, (char *) NULL);
|
||||
entries = ParseEntries (0);
|
||||
|
||||
#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]))
|
||||
{
|
||||
char *tag;
|
||||
char *date;
|
||||
char *rcsdir = xmalloc (strlen (repository)
|
||||
+ strlen (argv[i]) + 10);
|
||||
|
||||
/* before we do anything else, see if we have any
|
||||
per-directory tags */
|
||||
ParseTag (&tag, &date);
|
||||
|
||||
sprintf (rcsdir, "%s/%s", repository, argv[i]);
|
||||
|
||||
Create_Admin (argv[i], argv[i], rcsdir, tag, date);
|
||||
|
||||
if (tag)
|
||||
free (tag);
|
||||
if (date)
|
||||
free (date);
|
||||
free (rcsdir);
|
||||
}
|
||||
send_files (argc, argv, 0, 0);
|
||||
if (fprintf (to_server, "add\n") < 0)
|
||||
error (1, errno, "writing to server");
|
||||
return get_responses_and_close ();
|
||||
}
|
||||
#endif
|
||||
|
||||
entries = Entries_Open (0);
|
||||
|
||||
/* walk the arg list adding files/dirs */
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
int begin_err = err;
|
||||
int begin_added_files = added_files;
|
||||
|
||||
user = argv[i];
|
||||
strip_trailing_slashes (user);
|
||||
|
|
@ -122,7 +167,7 @@ add (argc, argv)
|
|||
error (0, 0, "nothing known about %s", user);
|
||||
err++;
|
||||
}
|
||||
else if (!isdir (user))
|
||||
else if (!isdir (user) || wrap_name_has (user, WRAP_TOCVS))
|
||||
{
|
||||
/*
|
||||
* See if a directory exists in the repository with
|
||||
|
|
@ -143,15 +188,53 @@ add (argc, argv)
|
|||
/* There is a user file, so build the entry for it */
|
||||
if (build_entry (repository, user, vers->options,
|
||||
message, entries, vers->tag) != 0)
|
||||
err++;
|
||||
err++;
|
||||
else
|
||||
{
|
||||
added_files++;
|
||||
if (!quiet)
|
||||
error (0, 0, "scheduling file `%s' for addition", user);
|
||||
added_files++;
|
||||
if (!quiet)
|
||||
{
|
||||
#ifdef DEATH_SUPPORT
|
||||
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
|
||||
#endif /* DEATH_SUPPORT */
|
||||
error (0, 0, "scheduling %s `%s' for addition",
|
||||
(wrap_name_has (user, WRAP_TOCVS)
|
||||
? "wrapper"
|
||||
: "file"),
|
||||
user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DEATH_SUPPORT
|
||||
else if (RCS_isdead (vers->srcfile, vers->vn_rcs))
|
||||
{
|
||||
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.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vers->tag)
|
||||
error (0, 0, "file `%s' will be added on branch `%s' from version %s",
|
||||
user, vers->tag, vers->vn_rcs);
|
||||
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;
|
||||
}
|
||||
}
|
||||
#endif /* DEATH_SUPPORT */
|
||||
else
|
||||
{
|
||||
/*
|
||||
|
|
@ -206,6 +289,9 @@ add (argc, argv)
|
|||
free (tmp);
|
||||
|
||||
/* XXX - bugs here; this really resurrect the head */
|
||||
/* Note that this depends on the Register above actually
|
||||
having written Entries, or else it won't really
|
||||
check the file out. */
|
||||
if (update (2, argv + i - 1) == 0)
|
||||
{
|
||||
error (0, 0, "%s, version %s, resurrected", user,
|
||||
|
|
@ -235,16 +321,23 @@ add (argc, argv)
|
|||
freevers_ts (&vers);
|
||||
|
||||
/* passed all the checks. Go ahead and add it if its a directory */
|
||||
if (begin_err == err && isdir (user))
|
||||
if (begin_err == err
|
||||
&& isdir (user)
|
||||
&& !wrap_name_has (user, WRAP_TOCVS))
|
||||
{
|
||||
err += add_directory (repository, user);
|
||||
continue;
|
||||
}
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active && begin_added_files != added_files)
|
||||
server_checked_in (user, ".", repository);
|
||||
#endif
|
||||
}
|
||||
if (added_files)
|
||||
error (0, 0, "use 'cvs commit' to add %s permanently",
|
||||
(added_files == 1) ? "this file" : "these files");
|
||||
dellist (&entries);
|
||||
|
||||
Entries_Close (entries);
|
||||
|
||||
if (message)
|
||||
free (message);
|
||||
|
|
@ -264,7 +357,8 @@ add_directory (repository, dir)
|
|||
char *repository;
|
||||
char *dir;
|
||||
{
|
||||
char cwd[PATH_MAX], rcsdir[PATH_MAX];
|
||||
char rcsdir[PATH_MAX];
|
||||
struct saved_cwd cwd;
|
||||
char message[PATH_MAX + 100];
|
||||
char *tag, *date;
|
||||
|
||||
|
|
@ -274,9 +368,9 @@ add_directory (repository, dir)
|
|||
"directory %s not added; must be a direct sub-directory", dir);
|
||||
return (1);
|
||||
}
|
||||
if (strcmp (dir, CVSADM) == 0 || strcmp (dir, OCVSADM) == 0)
|
||||
if (strcmp (dir, CVSADM) == 0)
|
||||
{
|
||||
error (0, 0, "cannot add a `%s' or a `%s' directory", CVSADM, OCVSADM);
|
||||
error (0, 0, "cannot add a `%s' directory", CVSADM);
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
|
@ -284,20 +378,20 @@ add_directory (repository, dir)
|
|||
ParseTag (&tag, &date);
|
||||
|
||||
/* now, remember where we were, so we can get back */
|
||||
if (getwd (cwd) == NULL)
|
||||
{
|
||||
error (0, 0, "cannot get working directory: %s", cwd);
|
||||
if (save_cwd (&cwd))
|
||||
return (1);
|
||||
}
|
||||
if (chdir (dir) < 0)
|
||||
{
|
||||
error (0, errno, "cannot chdir to %s", dir);
|
||||
return (1);
|
||||
}
|
||||
if (isfile (CVSADM) || isfile (OCVSADM))
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (!server_active && isfile (CVSADM))
|
||||
#else
|
||||
if (isfile (CVSADM))
|
||||
#endif
|
||||
{
|
||||
error (0, 0,
|
||||
"%s/%s (or %s/%s) already exists", dir, CVSADM, dir, OCVSADM);
|
||||
error (0, 0, "%s/%s already exists", dir, CVSADM);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -344,14 +438,14 @@ add_directory (repository, dir)
|
|||
}
|
||||
#endif
|
||||
|
||||
omask = umask (2);
|
||||
if (mkdir (rcsdir, 0777) < 0)
|
||||
omask = umask (cvsumask);
|
||||
if (CVS_MKDIR (rcsdir, 0777) < 0)
|
||||
{
|
||||
error (0, errno, "cannot mkdir %s", rcsdir);
|
||||
(void) umask ((int) omask);
|
||||
(void) umask (omask);
|
||||
goto out;
|
||||
}
|
||||
(void) umask ((int) omask);
|
||||
(void) umask (omask);
|
||||
|
||||
/*
|
||||
* Set up an update list with a single title node for Update_Logfile
|
||||
|
|
@ -367,7 +461,12 @@ add_directory (repository, dir)
|
|||
dellist (&ulist);
|
||||
}
|
||||
|
||||
Create_Admin (".", rcsdir, tag, date);
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (!server_active)
|
||||
Create_Admin (".", dir, rcsdir, tag, date);
|
||||
#else
|
||||
Create_Admin (".", dir, rcsdir, tag, date);
|
||||
#endif
|
||||
if (tag)
|
||||
free (tag);
|
||||
if (date)
|
||||
|
|
@ -375,8 +474,9 @@ add_directory (repository, dir)
|
|||
|
||||
(void) printf ("%s", message);
|
||||
out:
|
||||
if (chdir (cwd) < 0)
|
||||
error (1, errno, "cannot chdir to %s", cwd);
|
||||
if (restore_cwd (&cwd, NULL))
|
||||
exit (1);
|
||||
free_cwd (&cwd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
@ -397,6 +497,8 @@ build_entry (repository, user, options, message, entries, tag)
|
|||
char line[MAXLINELEN];
|
||||
FILE *fp;
|
||||
|
||||
#ifndef DEATH_SUPPORT
|
||||
/* when using the rcs death support, this case is not a problem. */
|
||||
/*
|
||||
* There may be an old file with the same name in the Attic! This is,
|
||||
* perhaps, an awkward place to check for this, but other places are
|
||||
|
|
@ -409,21 +511,13 @@ build_entry (repository, user, options, message, entries, tag)
|
|||
repository, CVSATTIC);
|
||||
return (1);
|
||||
}
|
||||
#endif /* no DEATH_SUPPORT */
|
||||
|
||||
if (noexec)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* The options for the "add" command are store in the file CVS/user,p
|
||||
* XXX - no they are not!
|
||||
*/
|
||||
(void) sprintf (fname, "%s/%s%s", CVSADM, user, CVSEXT_OPT);
|
||||
fp = open_file (fname, "w+");
|
||||
if (fclose (fp) == EOF)
|
||||
error(1, errno, "cannot close %s", fname);
|
||||
|
||||
/*
|
||||
* And the requested log is read directly from the user and stored in the
|
||||
* The requested log is read directly from the user and stored in the
|
||||
* file user,t. If the "message" argument is set, use it as the
|
||||
* initial creation log (which typically describes the file).
|
||||
*/
|
||||
|
|
@ -436,8 +530,8 @@ build_entry (repository, user, options, message, entries, tag)
|
|||
|
||||
/*
|
||||
* 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 ,p
|
||||
* and ,t files, but who cares).
|
||||
* without needing to clean anything up (well, we could clean up the
|
||||
* ,t file, but who cares).
|
||||
*/
|
||||
(void) sprintf (line, "Initial %s", user);
|
||||
Register (entries, user, "0", line, options, tag, (char *) 0, (char *) 0);
|
||||
|
|
|
|||
|
|
@ -12,10 +12,13 @@
|
|||
*/
|
||||
|
||||
#include "cvs.h"
|
||||
#ifdef CVS_ADMIN_GROUP
|
||||
#include <grp.h>
|
||||
#endif
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)admin.c 1.20 94/09/30 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)admin.c 1.20 94/09/30 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static Dtype admin_dirproc PROTO((char *dir, char *repos, char *update_dir));
|
||||
|
|
@ -23,7 +26,7 @@ static int admin_fileproc PROTO((char *file, char *update_dir,
|
|||
char *repository, List *entries,
|
||||
List *srcfiles));
|
||||
|
||||
static char *admin_usage[] =
|
||||
static const char *const admin_usage[] =
|
||||
{
|
||||
"Usage: %s %s rcs-options files...\n",
|
||||
NULL
|
||||
|
|
@ -35,13 +38,42 @@ static char **av;
|
|||
int
|
||||
admin (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
int err;
|
||||
|
||||
#ifdef CVS_ADMIN_GROUP
|
||||
struct group *grp;
|
||||
#endif
|
||||
if (argc <= 1)
|
||||
usage (admin_usage);
|
||||
|
||||
#ifdef CVS_ADMIN_GROUP
|
||||
grp = getgrnam(CVS_ADMIN_GROUP);
|
||||
/* skip usage right check if group CVS_ADMIN_GROUP does not exist */
|
||||
if (grp != NULL)
|
||||
{
|
||||
char *me = getcaller();
|
||||
char **grnam = grp->gr_mem;
|
||||
int denied = 1;
|
||||
|
||||
while (*grnam)
|
||||
{
|
||||
if (strcmp(*grnam, me) == 0)
|
||||
{
|
||||
denied = 0;
|
||||
break;
|
||||
}
|
||||
grnam++;
|
||||
}
|
||||
|
||||
if (denied)
|
||||
error (1, 0, "usage is restricted to members of the group %s",
|
||||
CVS_ADMIN_GROUP);
|
||||
}
|
||||
#endif
|
||||
|
||||
wrap_setup ();
|
||||
|
||||
/* skip all optional arguments to see if we have any file names */
|
||||
for (ac = 1; ac < argc; ac++)
|
||||
if (argv[ac][0] != '-')
|
||||
|
|
@ -53,9 +85,36 @@ admin (argc, argv)
|
|||
if (ac == 0 || argc == 0)
|
||||
usage (admin_usage);
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* We're the client side. Fire up the remote server. */
|
||||
start_server ();
|
||||
|
||||
ign_setup ();
|
||||
|
||||
for (i = 0; i <= ac; ++i) /* XXX send -ko too with i = 0 */
|
||||
send_arg (av[i]);
|
||||
|
||||
#if 0
|
||||
/* FIXME: We shouldn't have to send current files, but I'm not sure
|
||||
whether it works. So send the files --
|
||||
it's slower but it works. */
|
||||
send_file_names (argc, argv);
|
||||
#else
|
||||
send_files (argc, argv, 0, 0);
|
||||
#endif
|
||||
if (fprintf (to_server, "admin\n") < 0)
|
||||
error (1, errno, "writing to server");
|
||||
return get_responses_and_close ();
|
||||
}
|
||||
#endif /* CLIENT_SUPPORT */
|
||||
|
||||
/* start the recursion processor */
|
||||
err = start_recursion (admin_fileproc, (int (*) ()) NULL, admin_dirproc,
|
||||
(int (*) ()) NULL, argc, argv, 0,
|
||||
err = start_recursion (admin_fileproc, (FILESDONEPROC) NULL, admin_dirproc,
|
||||
(DIRLEAVEPROC) NULL, argc, argv, 0,
|
||||
W_LOCAL, 0, 1, (char *) NULL, 1, 0);
|
||||
return (err);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,14 +18,16 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)checkin.c 1.48 94/10/07 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)checkin.c 1.48 94/10/07 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
int
|
||||
Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
|
||||
Checkin (type, file, update_dir, repository,
|
||||
rcs, rev, tag, options, message, entries)
|
||||
int type;
|
||||
char *file;
|
||||
char *update_dir;
|
||||
char *repository;
|
||||
char *rcs;
|
||||
char *rev;
|
||||
|
|
@ -37,8 +39,17 @@ Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
|
|||
char fname[PATH_MAX];
|
||||
Vers_TS *vers;
|
||||
int set_time;
|
||||
char *fullname;
|
||||
|
||||
(void) printf ("Checking in %s;\n", file);
|
||||
char *tocvsPath = NULL;
|
||||
|
||||
fullname = xmalloc (strlen (update_dir) + strlen (file) + 10);
|
||||
if (update_dir[0] == '\0')
|
||||
strcpy (fullname, file);
|
||||
else
|
||||
sprintf (fullname, "%s/%s", update_dir, file);
|
||||
|
||||
(void) printf ("Checking in %s;\n", fullname);
|
||||
(void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
|
||||
|
||||
/*
|
||||
|
|
@ -46,13 +57,28 @@ Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
|
|||
* modification times, then place a copy back in the original file name
|
||||
* for the checkin and checkout.
|
||||
*/
|
||||
|
||||
tocvsPath = wrap_tocvs_process_file (fullname);
|
||||
|
||||
if (!noexec)
|
||||
copy_file (file, fname);
|
||||
{
|
||||
if (tocvsPath)
|
||||
{
|
||||
copy_file (tocvsPath, fname);
|
||||
if (unlink_file_dir (file) < 0)
|
||||
if (! existence_error (errno))
|
||||
error (1, errno, "cannot remove %s", file);
|
||||
copy_file (tocvsPath, file);
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_file (file, fname);
|
||||
}
|
||||
}
|
||||
|
||||
run_setup ("%s%s -f %s%s", Rcsbin, RCS_CI,
|
||||
rev ? "-r" : "", rev ? rev : "");
|
||||
run_args ("-m%s", (*message == '\0' || strcmp(message, "\n") == 0) ?
|
||||
"*** empty log message ***\n" : message);
|
||||
run_args ("-m%s", make_message_rcslegal (message));
|
||||
run_arg (rcs);
|
||||
|
||||
switch (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL))
|
||||
|
|
@ -83,11 +109,14 @@ Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
|
|||
}
|
||||
else
|
||||
{
|
||||
(void) unlink_file (fname);
|
||||
if (unlink_file (fname) < 0)
|
||||
error (0, errno, "cannot remove %s", fname);
|
||||
/* sync up with the time from the RCS file */
|
||||
set_time = 1;
|
||||
}
|
||||
|
||||
wrap_fromcvs_process_file (file);
|
||||
|
||||
/*
|
||||
* If we want read-only files, muck the permissions here, before
|
||||
* getting the file time-stamp.
|
||||
|
|
@ -95,13 +124,15 @@ Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
|
|||
if (cvswrite == FALSE)
|
||||
xchmod (file, 0);
|
||||
|
||||
#ifndef DEATH_SUPPORT
|
||||
/* With death_support, files added with tags go into branches immediately. */
|
||||
|
||||
/* for added files with symbolic tags, need to add the tag too */
|
||||
if (type == 'A' && tag && !isdigit (*tag))
|
||||
{
|
||||
run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, tag, rev);
|
||||
run_arg (rcs);
|
||||
(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
|
||||
(void) RCS_settag(rcs, tag, rev);
|
||||
}
|
||||
#endif /* No DEATH_SUPPORT */
|
||||
|
||||
/* re-register with the new data */
|
||||
vers = Version_TS (repository, (char *) NULL, tag, (char *) NULL,
|
||||
|
|
@ -112,11 +143,21 @@ Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
|
|||
vers->options, vers->tag, vers->date, (char *) 0);
|
||||
history_write (type, (char *) 0, vers->vn_rcs, file, repository);
|
||||
freevers_ts (&vers);
|
||||
|
||||
if (tocvsPath)
|
||||
if (unlink_file_dir (tocvsPath) < 0)
|
||||
error (0, errno, "cannot remove %s", tocvsPath);
|
||||
|
||||
break;
|
||||
|
||||
case -1: /* fork failed */
|
||||
if (tocvsPath)
|
||||
if (unlink_file_dir (tocvsPath) < 0)
|
||||
error (0, errno, "cannot remove %s", tocvsPath);
|
||||
|
||||
if (!noexec)
|
||||
error (1, errno, "could not check in %s -- fork failed", file);
|
||||
error (1, errno, "could not check in %s -- fork failed",
|
||||
fullname);
|
||||
return (1);
|
||||
|
||||
default: /* ci failed */
|
||||
|
|
@ -125,10 +166,14 @@ Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
|
|||
* The checkin failed, for some unknown reason, so we restore the
|
||||
* original user file, print an error, and return an error
|
||||
*/
|
||||
if (tocvsPath)
|
||||
if (unlink_file_dir (tocvsPath) < 0)
|
||||
error (0, errno, "cannot remove %s", tocvsPath);
|
||||
|
||||
if (!noexec)
|
||||
{
|
||||
rename_file (fname, file);
|
||||
error (0, 0, "could not check in %s", file);
|
||||
error (0, 0, "could not check in %s", fullname);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
|
@ -140,10 +185,20 @@ Checkin (type, file, repository, rcs, rev, tag, options, message, entries)
|
|||
*/
|
||||
if (rev)
|
||||
{
|
||||
run_setup ("%s%s -q -u", Rcsbin, RCS);
|
||||
run_arg (rcs);
|
||||
(void) run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL);
|
||||
(void) RCS_unlock (rcs, NULL, 1);
|
||||
}
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
{
|
||||
if (set_time)
|
||||
/* Need to update the checked out file on the client side. */
|
||||
server_updated (file, update_dir, repository, SERVER_UPDATED,
|
||||
NULL, NULL);
|
||||
else
|
||||
server_checked_in (file, update_dir, repository);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,31 +36,30 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)checkout.c 1.78 94/10/07 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)checkout.c 1.78 94/10/07 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static char *findslash PROTO((char *start, char *p));
|
||||
static int build_dirs_and_chdir PROTO((char *dir, char *prepath, char *realdir,
|
||||
int sticky));
|
||||
static int checkout_proc PROTO((int *pargc, char *argv[], char *where,
|
||||
static int checkout_proc PROTO((int *pargc, char **argv, char *where,
|
||||
char *mwhere, char *mfile, int shorten,
|
||||
int local_specified, char *omodule,
|
||||
char *msg));
|
||||
static int safe_location PROTO((void));
|
||||
|
||||
static char *checkout_usage[] =
|
||||
static const char *const checkout_usage[] =
|
||||
{
|
||||
"Usage:\n %s %s [-ANPQcflnpqs] [-r rev | -D date] [-d dir] [-k kopt] modules...\n",
|
||||
"Usage:\n %s %s [-ANPcflnps] [-r rev | -D date] [-d dir] [-k kopt] modules...\n",
|
||||
"\t-A\tReset any sticky tags/date/kopts.\n",
|
||||
"\t-N\tDon't shorten module paths if -d specified.\n",
|
||||
"\t-P\tPrune empty directories.\n",
|
||||
"\t-Q\tReally quiet.\n",
|
||||
"\t-c\t\"cat\" the module database.\n",
|
||||
"\t-f\tForce a head revision match if tag/date not found.\n",
|
||||
"\t-l\tLocal directory only, not recursive\n",
|
||||
"\t-n\tDo not run module program (if any).\n",
|
||||
"\t-p\tCheck out files to standard output.\n",
|
||||
"\t-q\tSomewhat quiet.\n",
|
||||
"\t-s\tLike -c, but include module status.\n",
|
||||
"\t-r rev\tCheck out revision or tag. (implies -P)\n",
|
||||
"\t-D date\tCheck out revisions as of date. (implies -P)\n",
|
||||
|
|
@ -70,18 +69,17 @@ static char *checkout_usage[] =
|
|||
NULL
|
||||
};
|
||||
|
||||
static char *export_usage[] =
|
||||
static const char *const export_usage[] =
|
||||
{
|
||||
"Usage: %s %s [-NPQflnq] [-r rev | -D date] [-d dir] module...\n",
|
||||
"Usage: %s %s [-NPfln] [-r rev | -D date] [-d dir] [-k kopt] module...\n",
|
||||
"\t-N\tDon't shorten module paths if -d specified.\n",
|
||||
"\t-Q\tReally quiet.\n",
|
||||
"\t-f\tForce a head revision match if tag/date not found.\n",
|
||||
"\t-l\tLocal directory only, not recursive\n",
|
||||
"\t-n\tDo not run module program (if any).\n",
|
||||
"\t-q\tSomewhat quiet.\n",
|
||||
"\t-r rev\tCheck out revision or tag.\n",
|
||||
"\t-D date\tCheck out revisions as of date.\n",
|
||||
"\t-d dir\tCheck out into dir instead of module name.\n",
|
||||
"\t-k kopt\tUse RCS kopt -k option on checkout.\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -99,7 +97,7 @@ static char *preload_update_dir = NULL;
|
|||
int
|
||||
checkout (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
|
|
@ -109,21 +107,25 @@ checkout (argc, argv)
|
|||
int local = 0;
|
||||
int shorten = -1;
|
||||
char *where = NULL;
|
||||
char *valid_options, **valid_usage;
|
||||
char *valid_options;
|
||||
const char *const *valid_usage;
|
||||
enum mtype m_type;
|
||||
|
||||
/*
|
||||
* A smaller subset of options are allowed for the export command, which
|
||||
* is essentially like checkout, except that it hard-codes certain
|
||||
* options to be on (like -kv) and takes care to remove the CVS directory
|
||||
* when it has done its duty
|
||||
* options to be default (like -kv) and takes care to remove the CVS
|
||||
* directory when it has done its duty
|
||||
*/
|
||||
if (strcmp (command_name, "export") == 0)
|
||||
{
|
||||
valid_options = "Nnd:flRQqr:D:";
|
||||
m_type = EXPORT;
|
||||
valid_options = "Nnk:d:flRQqr:D:";
|
||||
valid_usage = export_usage;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_type = CHECKOUT;
|
||||
valid_options = "ANnk:d:flRpQqcsr:D:j:P";
|
||||
valid_usage = checkout_usage;
|
||||
}
|
||||
|
|
@ -132,6 +134,7 @@ checkout (argc, argv)
|
|||
usage (valid_usage);
|
||||
|
||||
ign_setup ();
|
||||
wrap_setup ();
|
||||
|
||||
optind = 1;
|
||||
while ((c = getopt (argc, argv, valid_options)) != -1)
|
||||
|
|
@ -153,10 +156,15 @@ checkout (argc, argv)
|
|||
run_module_prog = 0;
|
||||
break;
|
||||
case 'Q':
|
||||
really_quiet = 1;
|
||||
/* FALL THROUGH */
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
#ifdef SERVER_SUPPORT
|
||||
/* The CVS 1.5 client sends these options (in addition to
|
||||
Global_option requests), so we must ignore them. */
|
||||
if (!server_active)
|
||||
#endif
|
||||
error (1, 0,
|
||||
"-q or -Q must be specified before \"%s\"",
|
||||
command_name);
|
||||
break;
|
||||
case 'l':
|
||||
local = 1;
|
||||
|
|
@ -230,9 +238,102 @@ checkout (argc, argv)
|
|||
}
|
||||
if (tag && isdigit (tag[0]))
|
||||
error (1, 0, "tag `%s' must be a symbolic tag", tag);
|
||||
options = RCS_check_kflag ("v");/* -kv must be on */
|
||||
/*
|
||||
* mhy 950615: -kv doesn't work for binaries with RCS keywords.
|
||||
* Instead use the default provided in the RCS file (-ko for binaries).
|
||||
*/
|
||||
#if 0
|
||||
if (!options)
|
||||
options = RCS_check_kflag ("v");/* -kv is default */
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!safe_location()) {
|
||||
error(1, 0, "Cannot check out files into the repository itself");
|
||||
}
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active)
|
||||
{
|
||||
int expand_modules;
|
||||
|
||||
start_server ();
|
||||
|
||||
ign_setup ();
|
||||
|
||||
/* We have to expand names here because the "expand-modules"
|
||||
directive to the server has the side-effect of having the
|
||||
server send the check-in and update programs for the
|
||||
various modules/dirs requested. If we turn this off and
|
||||
simply request the names of the modules and directories (as
|
||||
below in !expand_modules), those files (CVS/Checking.prog
|
||||
or CVS/Update.prog) don't get created. Grrr. */
|
||||
|
||||
expand_modules = (!cat && !status && !pipeout
|
||||
&& supported_request ("expand-modules"));
|
||||
|
||||
if (expand_modules)
|
||||
{
|
||||
/* This is done here because we need to read responses
|
||||
from the server before we send the command checkout or
|
||||
export files. */
|
||||
|
||||
client_expand_modules (argc, argv, local);
|
||||
}
|
||||
|
||||
if (!run_module_prog) send_arg ("-n");
|
||||
if (local) send_arg ("-l");
|
||||
if (pipeout) send_arg ("-p");
|
||||
if (!force_tag_match) send_arg ("-f");
|
||||
if (aflag)
|
||||
send_arg("-A");
|
||||
if (!shorten)
|
||||
send_arg("-N");
|
||||
if (checkout_prune_dirs && strcmp (command_name, "export") != 0)
|
||||
send_arg("-P");
|
||||
client_prune_dirs = checkout_prune_dirs;
|
||||
if (cat)
|
||||
send_arg("-c");
|
||||
if (where != NULL)
|
||||
{
|
||||
option_with_arg ("-d", where);
|
||||
}
|
||||
if (status)
|
||||
send_arg("-s");
|
||||
if (strcmp (command_name, "export") != 0
|
||||
&& options != NULL
|
||||
&& options[0] != '\0')
|
||||
send_arg (options);
|
||||
option_with_arg ("-r", tag);
|
||||
if (date)
|
||||
client_senddate (date);
|
||||
if (join_rev1 != NULL)
|
||||
option_with_arg ("-j", join_rev1);
|
||||
if (join_rev2 != NULL)
|
||||
option_with_arg ("-j", join_rev2);
|
||||
|
||||
if (expand_modules)
|
||||
{
|
||||
client_send_expansions (local);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < argc; ++i)
|
||||
send_arg (argv[i]);
|
||||
client_nonexpanded_setup ();
|
||||
}
|
||||
|
||||
if (fprintf
|
||||
(to_server,
|
||||
strcmp (command_name, "export") == 0 ? "export\n" : "co\n")
|
||||
< 0)
|
||||
error (1, errno, "writing to server");
|
||||
|
||||
return get_responses_and_close ();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cat || status)
|
||||
{
|
||||
cat_module (status);
|
||||
|
|
@ -249,23 +350,29 @@ checkout (argc, argv)
|
|||
{
|
||||
char repository[PATH_MAX];
|
||||
|
||||
(void) mkdir (where, 0777);
|
||||
(void) CVS_MKDIR (where, 0777);
|
||||
if (chdir (where) < 0)
|
||||
error (1, errno, "cannot chdir to %s", where);
|
||||
preload_update_dir = xstrdup (where);
|
||||
where = (char *) NULL;
|
||||
if (!isfile (CVSADM) && !isfile (OCVSADM))
|
||||
if (!isfile (CVSADM))
|
||||
{
|
||||
(void) sprintf (repository, "%s/%s/%s", CVSroot, CVSROOTADM,
|
||||
CVSNULLREPOS);
|
||||
if (!isfile (repository))
|
||||
(void) mkdir (repository, 0777);
|
||||
{
|
||||
mode_t omask;
|
||||
omask = umask (cvsumask);
|
||||
(void) CVS_MKDIR (repository, 0777);
|
||||
(void) umask (omask);
|
||||
}
|
||||
|
||||
/* I'm not sure whether this check is redundant. */
|
||||
if (!isdir (repository))
|
||||
error (1, 0, "there is no repository %s", repository);
|
||||
|
||||
Create_Admin (".", repository, (char *) NULL, (char *) NULL);
|
||||
Create_Admin (".", where, repository,
|
||||
(char *) NULL, (char *) NULL);
|
||||
if (!noexec)
|
||||
{
|
||||
FILE *fp;
|
||||
|
|
@ -273,6 +380,10 @@ checkout (argc, argv)
|
|||
fp = open_file (CVSADM_ENTSTAT, "w+");
|
||||
if (fclose(fp) == EOF)
|
||||
error(1, errno, "cannot close %s", CVSADM_ENTSTAT);
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
server_set_entstat (preload_update_dir, repository);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -302,13 +413,34 @@ checkout (argc, argv)
|
|||
}
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
err += do_module (db, argv[i], CHECKOUT, "Updating", checkout_proc,
|
||||
err += do_module (db, argv[i], m_type, "Updating", checkout_proc,
|
||||
where, shorten, local, run_module_prog,
|
||||
(char *) NULL);
|
||||
close_module (db);
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
safe_location ()
|
||||
{
|
||||
char current[PATH_MAX];
|
||||
char hardpath[PATH_MAX+5];
|
||||
int x;
|
||||
|
||||
x = readlink(CVSroot, hardpath, sizeof hardpath - 1);
|
||||
if (x == -1)
|
||||
{
|
||||
strcpy(hardpath, CVSroot);
|
||||
}
|
||||
hardpath[x] = '\0';
|
||||
getwd (current);
|
||||
if (strncmp(current, hardpath, strlen(hardpath)) == 0)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* process_module calls us back here so we do the actual checkout stuff
|
||||
*/
|
||||
|
|
@ -317,7 +449,7 @@ static int
|
|||
checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
|
||||
local_specified, omodule, msg)
|
||||
int *pargc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
char *where;
|
||||
char *mwhere;
|
||||
char *mfile;
|
||||
|
|
@ -528,7 +660,7 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
|
|||
free (prepath);
|
||||
|
||||
/* set up the repository (or make sure the old one matches) */
|
||||
if (!isfile (CVSADM) && !isfile (OCVSADM))
|
||||
if (!isfile (CVSADM))
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
|
|
@ -538,10 +670,15 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
|
|||
if (!isdir (repository))
|
||||
error (1, 0, "there is no repository %s", repository);
|
||||
|
||||
Create_Admin (".", repository, (char *) NULL, (char *) NULL);
|
||||
Create_Admin (".", where, repository,
|
||||
(char *) NULL, (char *) NULL);
|
||||
fp = open_file (CVSADM_ENTSTAT, "w+");
|
||||
if (fclose(fp) == EOF)
|
||||
error(1, errno, "cannot close %s", CVSADM_ENTSTAT);
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
server_set_entstat (where, repository);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -549,7 +686,7 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
|
|||
if (!isdir (repository))
|
||||
error (1, 0, "there is no repository %s", repository);
|
||||
|
||||
Create_Admin (".", repository, tag, date);
|
||||
Create_Admin (".", where, repository, tag, date);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -558,7 +695,7 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
|
|||
|
||||
/* get the contents of the previously existing repository */
|
||||
repos = Name_Repository ((char *) NULL, preload_update_dir);
|
||||
if (strcmp (repository, repos) != 0)
|
||||
if (fncmp (repository, repos) != 0)
|
||||
{
|
||||
error (0, 0, "existing repository %s does not match %s",
|
||||
repos, repository);
|
||||
|
|
@ -620,7 +757,7 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
|
|||
List *entries;
|
||||
|
||||
/* we are only doing files, so register them */
|
||||
entries = ParseEntries (0);
|
||||
entries = Entries_Open (0);
|
||||
for (i = 1; i < *pargc; i++)
|
||||
{
|
||||
char line[MAXLINELEN];
|
||||
|
|
@ -639,7 +776,8 @@ checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
|
|||
}
|
||||
freevers_ts (&vers);
|
||||
}
|
||||
dellist (&entries);
|
||||
|
||||
Entries_Close (entries);
|
||||
}
|
||||
|
||||
/* Don't log "export", just regular "checkouts" */
|
||||
|
|
@ -698,32 +836,35 @@ build_dirs_and_chdir (dir, prepath, realdir, sticky)
|
|||
{
|
||||
*slash = '\0';
|
||||
*slash2 = '\0';
|
||||
(void) mkdir (cp, 0777);
|
||||
(void) CVS_MKDIR (cp, 0777);
|
||||
if (chdir (cp) < 0)
|
||||
{
|
||||
error (0, errno, "cannot chdir to %s", cp);
|
||||
return (1);
|
||||
}
|
||||
if (!isfile (CVSADM) && !isfile (OCVSADM) &&
|
||||
strcmp (command_name, "export") != 0)
|
||||
if (!isfile (CVSADM) && strcmp (command_name, "export") != 0)
|
||||
{
|
||||
(void) sprintf (repository, "%s/%s", prepath, path2);
|
||||
/* I'm not sure whether this check is redundant. */
|
||||
if (!isdir (repository))
|
||||
error (1, 0, "there is no repository %s", repository);
|
||||
Create_Admin (".", repository, sticky ? (char *) NULL : tag,
|
||||
Create_Admin (".", cp, repository, sticky ? (char *) NULL : tag,
|
||||
sticky ? (char *) NULL : date);
|
||||
if (!noexec)
|
||||
{
|
||||
fp = open_file (CVSADM_ENTSTAT, "w+");
|
||||
if (fclose(fp) == EOF)
|
||||
error(1, errno, "cannot close %s", CVSADM_ENTSTAT);
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
server_set_entstat (path, repository);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
*slash = '/';
|
||||
*slash2 = '/';
|
||||
}
|
||||
(void) mkdir (cp, 0777);
|
||||
(void) CVS_MKDIR (cp, 0777);
|
||||
if (chdir (cp) < 0)
|
||||
{
|
||||
error (0, errno, "cannot chdir to %s", cp);
|
||||
|
|
|
|||
|
|
@ -10,11 +10,17 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)classify.c 1.17 94/10/07 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)classify.c 1.17 94/10/07 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
static void sticky_ck PROTO((char *file, int aflag, Vers_TS * vers,
|
||||
List * entries,
|
||||
char *repository, char *update_dir));
|
||||
#else
|
||||
static void sticky_ck PROTO((char *file, int aflag, Vers_TS * vers, List * entries));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Classify the state of a file
|
||||
|
|
@ -73,6 +79,25 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
|
|||
ret = T_UNKNOWN;
|
||||
}
|
||||
}
|
||||
#ifdef DEATH_SUPPORT
|
||||
else if (RCS_isdead (vers->srcfile, vers->vn_rcs))
|
||||
{
|
||||
if (vers->ts_user == NULL)
|
||||
/*
|
||||
* Logically seems to me this should be T_UPTODATE.
|
||||
* But the joining code in update.c seems to expect
|
||||
* T_CHECKOUT, and that is what has traditionally been
|
||||
* returned for this case.
|
||||
*/
|
||||
ret = T_CHECKOUT;
|
||||
else
|
||||
{
|
||||
error (0, 0, "use `cvs add' to create an entry for %s",
|
||||
fullname);
|
||||
ret = T_UNKNOWN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
/* there is an rcs file */
|
||||
|
|
@ -133,8 +158,28 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
|
|||
if (vers->vn_rcs == NULL)
|
||||
/* There is no RCS file, added file */
|
||||
ret = T_ADDED;
|
||||
#ifdef DEATH_SUPPORT
|
||||
else if (RCS_isdead (vers->srcfile, vers->vn_rcs))
|
||||
/* we are resurrecting. */
|
||||
ret = T_ADDED;
|
||||
#endif /* DEATH_SUPPORT */
|
||||
else
|
||||
{
|
||||
#ifdef DEATH_SUPPORT
|
||||
if (vers->srcfile->flags & INATTIC
|
||||
&& vers->srcfile->flags & VALID)
|
||||
{
|
||||
/* This file has been added on some branch other than
|
||||
the one we are looking at. In the branch we are
|
||||
looking at, the file was already valid. */
|
||||
if (!really_quiet)
|
||||
error (0, 0,
|
||||
"conflict: %s has been added, but already exists",
|
||||
fullname);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* DEATH_SUPPORT */
|
||||
/*
|
||||
* There is an RCS file, so someone else must have checked
|
||||
* one in behind our back; conflict
|
||||
|
|
@ -143,6 +188,9 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
|
|||
error (0, 0,
|
||||
"conflict: %s created independently by second party",
|
||||
fullname);
|
||||
#ifdef DEATH_SUPPORT
|
||||
}
|
||||
#endif
|
||||
ret = T_CONFLICT;
|
||||
}
|
||||
}
|
||||
|
|
@ -282,7 +330,12 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
|
|||
ret = T_CHECKOUT;
|
||||
else
|
||||
{
|
||||
#ifdef SERVER_SUPPORT
|
||||
sticky_ck (file, aflag, vers, entries,
|
||||
repository, update_dir);
|
||||
#else
|
||||
sticky_ck (file, aflag, vers, entries);
|
||||
#endif
|
||||
ret = T_UPTODATE;
|
||||
}
|
||||
}
|
||||
|
|
@ -309,7 +362,12 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
|
|||
ret = T_NEEDS_MERGE;
|
||||
#else
|
||||
ret = T_MODIFIED;
|
||||
#ifdef SERVER_SUPPORT
|
||||
sticky_ck (file, aflag, vers, entries,
|
||||
repository, update_dir);
|
||||
#else
|
||||
sticky_ck (file, aflag, vers, entries);
|
||||
#endif /* SERVER_SUPPORT */
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
|
@ -352,7 +410,17 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
|
|||
/*
|
||||
* The user file is still unmodified, so just get it as well
|
||||
*/
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (strcmp (vers->entdata->options ?
|
||||
vers->entdata->options : "", vers->options) != 0
|
||||
|| (vers->srcfile != NULL
|
||||
&& (vers->srcfile->flags & INATTIC) != 0))
|
||||
ret = T_CHECKOUT;
|
||||
else
|
||||
ret = T_PATCH;
|
||||
#else
|
||||
ret = T_CHECKOUT;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -360,9 +428,21 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
|
|||
repository, update_dir))
|
||||
/* really modified, needs to merge */
|
||||
ret = T_NEEDS_MERGE;
|
||||
#ifdef SERVER_SUPPORT
|
||||
else if ((strcmp (vers->entdata->options ?
|
||||
vers->entdata->options : "", vers->options)
|
||||
!= 0)
|
||||
|| (vers->srcfile != NULL
|
||||
&& (vers->srcfile->flags & INATTIC) != 0))
|
||||
/* not really modified, check it out */
|
||||
ret = T_CHECKOUT;
|
||||
else
|
||||
ret = T_PATCH;
|
||||
#else
|
||||
else
|
||||
/* not really modified, check it out */
|
||||
ret = T_CHECKOUT;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -380,11 +460,19 @@ Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
|
|||
}
|
||||
|
||||
static void
|
||||
#ifdef SERVER_SUPPORT
|
||||
sticky_ck (file, aflag, vers, entries, repository, update_dir)
|
||||
#else
|
||||
sticky_ck (file, aflag, vers, entries)
|
||||
#endif
|
||||
char *file;
|
||||
int aflag;
|
||||
Vers_TS *vers;
|
||||
List *entries;
|
||||
#ifdef SERVER_SUPPORT
|
||||
char *repository;
|
||||
char *update_dir;
|
||||
#endif
|
||||
{
|
||||
if (aflag || vers->tag || vers->date)
|
||||
{
|
||||
|
|
@ -398,6 +486,19 @@ sticky_ck (file, aflag, vers, entries)
|
|||
{
|
||||
Register (entries, file, vers->vn_user, vers->ts_rcs,
|
||||
vers->options, vers->tag, vers->date, vers->ts_conflict);
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
{
|
||||
/* We need to update the entries line on the client side.
|
||||
It is possible we will later update it again via
|
||||
server_updated or some such, but that is OK. */
|
||||
server_update_entries
|
||||
(file, update_dir, repository,
|
||||
strcmp (vers->ts_rcs, vers->ts_user) == 0 ?
|
||||
SERVER_UPDATED : SERVER_MERGED);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,10 +15,11 @@
|
|||
*/
|
||||
|
||||
#include "cvs.h"
|
||||
#include "getline.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)commit.c 1.101 94/10/07 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)commit.c 1.101 94/10/07 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static Dtype check_direntproc PROTO((char *dir, char *repos, char *update_dir));
|
||||
|
|
@ -26,16 +27,17 @@ static int check_fileproc PROTO((char *file, char *update_dir, char *repository,
|
|||
List * entries, List * srcfiles));
|
||||
static int check_filesdoneproc PROTO((int err, char *repos, char *update_dir));
|
||||
static int checkaddfile PROTO((char *file, char *repository, char *tag,
|
||||
List *srcfiles));
|
||||
char *options, List *srcfiles));
|
||||
static Dtype commit_direntproc PROTO((char *dir, char *repos, char *update_dir));
|
||||
static int commit_dirleaveproc PROTO((char *dir, int err, char *update_dir));
|
||||
static int commit_fileproc PROTO((char *file, char *update_dir, char *repository,
|
||||
List * entries, List * srcfiles));
|
||||
static int commit_filesdoneproc PROTO((int err, char *repository, char *update_dir));
|
||||
static int finaladd PROTO((char *file, char *revision, char *tag, char *options,
|
||||
char *repository, List *entries));
|
||||
static int finaladd PROTO((char *file, char *revision, char *tag,
|
||||
char *options, char *update_dir,
|
||||
char *repository, List *entries));
|
||||
static int findmaxrev PROTO((Node * p, void *closure));
|
||||
static int fsortcmp PROTO((Node * p, Node * q));
|
||||
static int fsortcmp PROTO((const Node * p, const Node * q));
|
||||
static int lock_RCS PROTO((char *user, char *rcs, char *rev, char *repository));
|
||||
static int lock_filesdoneproc PROTO((int err, char *repository, char *update_dir));
|
||||
static int lockrcsfile PROTO((char *file, char *repository, char *rev));
|
||||
|
|
@ -64,7 +66,7 @@ struct master_lists
|
|||
List *cilist; /* list with commit_info structs */
|
||||
};
|
||||
|
||||
static int force_ci;
|
||||
static int force_ci = 0;
|
||||
static int got_message;
|
||||
static int run_module_prog = 1;
|
||||
static int aflag;
|
||||
|
|
@ -75,7 +77,7 @@ static List *mulist;
|
|||
static List *locklist;
|
||||
static char *message;
|
||||
|
||||
static char *commit_usage[] =
|
||||
static const char *const commit_usage[] =
|
||||
{
|
||||
"Usage: %s %s [-nRlf] [-m msg | -F logfile] [-r rev] files...\n",
|
||||
"\t-n\tDo not run the module program (if any).\n",
|
||||
|
|
@ -91,7 +93,7 @@ static char *commit_usage[] =
|
|||
int
|
||||
commit (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
int c;
|
||||
int err = 0;
|
||||
|
|
@ -188,7 +190,7 @@ commit (argc, argv)
|
|||
if (message)
|
||||
error (1, 0, "cannot specify both a message and a log file");
|
||||
|
||||
if ((logfd = open (logfile, O_RDONLY)) < 0)
|
||||
if ((logfd = open (logfile, O_RDONLY | OPEN_BINARY)) < 0)
|
||||
error (1, errno, "cannot open log file %s", logfile);
|
||||
|
||||
if (fstat(logfd, &statbuf) < 0)
|
||||
|
|
@ -203,17 +205,60 @@ commit (argc, argv)
|
|||
message[n] = '\0';
|
||||
}
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active)
|
||||
{
|
||||
/*
|
||||
* Do this now; don't ask for a log message if we can't talk to the
|
||||
* server. But if there is a syntax error in the options, give
|
||||
* an error message without connecting.
|
||||
*/
|
||||
start_server ();
|
||||
|
||||
ign_setup ();
|
||||
|
||||
/*
|
||||
* We do this once, not once for each directory as in normal CVS.
|
||||
* The protocol is designed this way. This is a feature.
|
||||
*
|
||||
* We could provide the lists of changed, modified, etc. files,
|
||||
* however. Our failure to do so is just laziness, not design.
|
||||
*/
|
||||
if (use_editor)
|
||||
do_editor (".", &message, (char *)NULL, (List *)NULL);
|
||||
|
||||
/* We always send some sort of message, even if empty. */
|
||||
option_with_arg ("-m", message);
|
||||
|
||||
if (local)
|
||||
send_arg("-l");
|
||||
if (force_ci)
|
||||
send_arg("-f");
|
||||
if (!run_module_prog)
|
||||
send_arg("-n");
|
||||
option_with_arg ("-r", tag);
|
||||
|
||||
send_files (argc, argv, local, 0);
|
||||
|
||||
if (fprintf (to_server, "ci\n") < 0)
|
||||
error (1, errno, "writing to server");
|
||||
return get_responses_and_close ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* XXX - this is not the perfect check for this */
|
||||
if (argc <= 0)
|
||||
write_dirtag = tag;
|
||||
|
||||
wrap_setup ();
|
||||
|
||||
/*
|
||||
* Run the recursion processor to find all the dirs to lock and lock all
|
||||
* the dirs
|
||||
*/
|
||||
locklist = getlist ();
|
||||
err = start_recursion ((int (*) ()) NULL, lock_filesdoneproc,
|
||||
(Dtype (*) ()) NULL, (int (*) ()) NULL, argc,
|
||||
err = start_recursion ((FILEPROC) NULL, lock_filesdoneproc,
|
||||
(DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, argc,
|
||||
argv, local, W_LOCAL, aflag, 0, (char *) NULL, 0,
|
||||
0);
|
||||
sortlist (locklist, fsortcmp);
|
||||
|
|
@ -229,7 +274,7 @@ commit (argc, argv)
|
|||
* Run the recursion processor to verify the files are all up-to-date
|
||||
*/
|
||||
err = start_recursion (check_fileproc, check_filesdoneproc,
|
||||
check_direntproc, (int (*) ()) NULL, argc,
|
||||
check_direntproc, (DIRLEAVEPROC) NULL, argc,
|
||||
argv, local, W_LOCAL, aflag, 0, (char *) NULL, 1,
|
||||
0);
|
||||
if (err)
|
||||
|
|
@ -261,7 +306,8 @@ commit (argc, argv)
|
|||
*/
|
||||
static int
|
||||
fsortcmp (p, q)
|
||||
Node *p, *q;
|
||||
const Node *p;
|
||||
const Node *q;
|
||||
{
|
||||
return (strcmp (p->key, q->key));
|
||||
}
|
||||
|
|
@ -395,14 +441,17 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
switch (status)
|
||||
{
|
||||
case T_CHECKOUT:
|
||||
#ifdef SERVER_SUPPORT
|
||||
case T_PATCH:
|
||||
#endif
|
||||
case T_NEEDS_MERGE:
|
||||
case T_CONFLICT:
|
||||
case T_REMOVE_ENTRY:
|
||||
if (update_dir[0] == '\0')
|
||||
error (0, 0, "Up-to-date check failed for `%s'", file);
|
||||
else
|
||||
error (0, 0, "Up-to-date check failed for `%s/%s'",
|
||||
update_dir, file);
|
||||
error (0, 0, "Up-to-date check failed for `%s'", file);
|
||||
freevers_ts (&vers);
|
||||
return (1);
|
||||
case T_MODIFIED:
|
||||
|
|
@ -463,9 +512,19 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
* If the timestamp on the file is the same as the
|
||||
* timestamp stored in the Entries file, we block the commit.
|
||||
*/
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
retcode = vers->ts_conflict[0] != '=';
|
||||
else {
|
||||
filestamp = time_stamp (file);
|
||||
retcode = strcmp (vers->ts_conflict, filestamp);
|
||||
free (filestamp);
|
||||
}
|
||||
#else
|
||||
filestamp = time_stamp (file);
|
||||
retcode = strcmp (vers->ts_conflict, filestamp);
|
||||
free (filestamp);
|
||||
#endif
|
||||
if (retcode == 0)
|
||||
{
|
||||
if (update_dir[0] == '\0')
|
||||
|
|
@ -484,10 +543,10 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
* If the timestamps differ, look for Conflict indicators
|
||||
* in the file to see if we should block the commit anyway
|
||||
*/
|
||||
run_setup ("%s -s", GREP);
|
||||
run_setup ("%s", GREP);
|
||||
run_arg (RCS_MERGE_PAT);
|
||||
run_arg (file);
|
||||
retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
|
||||
retcode = run_exec (RUN_TTY, DEVNULL, RUN_TTY, RUN_REALLY);
|
||||
|
||||
if (retcode == -1)
|
||||
{
|
||||
|
|
@ -532,7 +591,13 @@ check_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
{
|
||||
char rcs[PATH_MAX];
|
||||
|
||||
#ifdef DEATH_SUPPORT
|
||||
/* Don't look in the attic; if it exists there we will
|
||||
move it back out in checkaddfile. */
|
||||
sprintf(rcs, "%s/%s%s", repository, file, RCSEXT);
|
||||
#else
|
||||
locate_rcs (file, repository, rcs);
|
||||
#endif
|
||||
if (isreadable (rcs))
|
||||
{
|
||||
if (update_dir[0] == '\0')
|
||||
|
|
@ -676,7 +741,7 @@ precommit_proc (repository, filter)
|
|||
char *filter;
|
||||
{
|
||||
/* see if the filter is there, only if it's a full path */
|
||||
if (filter[0] == '/')
|
||||
if (isabsolute (filter))
|
||||
{
|
||||
char *s, *cp;
|
||||
|
||||
|
|
@ -797,12 +862,33 @@ commit_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
}
|
||||
else if (ci->status == T_ADDED)
|
||||
{
|
||||
if (checkaddfile (file, repository, ci->tag, srcfiles) != 0)
|
||||
if (checkaddfile (file, repository, ci->tag, ci->options,
|
||||
srcfiles) != 0)
|
||||
{
|
||||
fixaddfile (file, repository);
|
||||
err = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef DEATH_SUPPORT
|
||||
/* adding files with a tag, now means adding them on a branch.
|
||||
Since the branch test was done in check_fileproc for
|
||||
modified files, we need to stub it in again here. */
|
||||
|
||||
if (ci->tag) {
|
||||
locate_rcs (file, repository, rcs);
|
||||
ci->rev = RCS_whatbranch (file, ci->tag, srcfiles);
|
||||
err = Checkin ('A', file, update_dir, repository, rcs, ci->rev,
|
||||
ci->tag, ci->options, message, entries);
|
||||
if (err != 0)
|
||||
{
|
||||
unlockrcs (file, repository);
|
||||
fixbranch (file, repository, sbranch);
|
||||
}
|
||||
|
||||
ci->status = T_UPTODATE;
|
||||
}
|
||||
#endif /* DEATH_SUPPORT */
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -825,14 +911,15 @@ commit_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
|
||||
/* XXX - an added file with symbolic -r should add tag as well */
|
||||
err = finaladd (file, ci->rev ? ci->rev : xrev, ci->tag, ci->options,
|
||||
repository, entries);
|
||||
update_dir, repository, entries);
|
||||
if (xrev)
|
||||
free (xrev);
|
||||
}
|
||||
else if (ci->status == T_MODIFIED)
|
||||
{
|
||||
locate_rcs (file, repository, rcs);
|
||||
err = Checkin ('M', file, repository, rcs, ci->rev, ci->tag,
|
||||
err = Checkin ('M', file, update_dir, repository,
|
||||
rcs, ci->rev, ci->tag,
|
||||
ci->options, message, entries);
|
||||
if (err != 0)
|
||||
{
|
||||
|
|
@ -841,8 +928,19 @@ commit_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
}
|
||||
}
|
||||
else if (ci->status == T_REMOVED)
|
||||
{
|
||||
err = remove_file (file, repository, ci->tag, message,
|
||||
entries, srcfiles);
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active) {
|
||||
server_scratch_entry_only ();
|
||||
server_updated (file, update_dir, repository,
|
||||
/* Doesn't matter, it won't get checked. */
|
||||
SERVER_UPDATED, (struct stat *) NULL,
|
||||
(unsigned char *) NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
out:
|
||||
if (err != 0)
|
||||
|
|
@ -888,18 +986,23 @@ commit_filesdoneproc (err, repository, update_dir)
|
|||
|
||||
if (err == 0 && run_module_prog)
|
||||
{
|
||||
char *cp;
|
||||
FILE *fp;
|
||||
char line[MAXLINELEN];
|
||||
char *repository;
|
||||
|
||||
/* It is not an error if Checkin.prog does not exist. */
|
||||
if ((fp = fopen (CVSADM_CIPROG, "r")) != NULL)
|
||||
{
|
||||
if (fgets (line, sizeof (line), fp) != NULL)
|
||||
char *line;
|
||||
int line_length;
|
||||
size_t line_chars_allocated;
|
||||
char *repository;
|
||||
|
||||
line = NULL;
|
||||
line_chars_allocated = 0;
|
||||
line_length = getline (&line, &line_chars_allocated, fp);
|
||||
if (line_length > 0)
|
||||
{
|
||||
if ((cp = strrchr (line, '\n')) != NULL)
|
||||
*cp = '\0';
|
||||
/* Remove any trailing newline. */
|
||||
if (line[line_length - 1] == '\n')
|
||||
line[--line_length] = '\0';
|
||||
repository = Name_Repository ((char *) NULL, update_dir);
|
||||
run_setup ("%s %s", line, repository);
|
||||
(void) printf ("%s %s: Executing '", program_name,
|
||||
|
|
@ -909,7 +1012,21 @@ commit_filesdoneproc (err, repository, update_dir)
|
|||
(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
|
||||
free (repository);
|
||||
}
|
||||
(void) fclose (fp);
|
||||
else
|
||||
{
|
||||
if (ferror (fp))
|
||||
error (0, errno, "warning: error reading %s",
|
||||
CVSADM_CIPROG);
|
||||
}
|
||||
if (line != NULL)
|
||||
free (line);
|
||||
if (fclose (fp) < 0)
|
||||
error (0, errno, "warning: cannot close %s", CVSADM_CIPROG);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! existence_error (errno))
|
||||
error (0, errno, "warning: cannot open %s", CVSADM_CIPROG);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -968,7 +1085,14 @@ commit_dirleaveproc (dir, err, update_dir)
|
|||
{
|
||||
/* update the per-directory tag info */
|
||||
if (err == 0 && write_dirtag != NULL)
|
||||
{
|
||||
WriteTag ((char *) NULL, write_dirtag, (char *) NULL);
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
server_set_sticky (update_dir, Name_Repository (dir, update_dir),
|
||||
write_dirtag, (char *) NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
|
@ -1017,16 +1141,34 @@ remove_file (file, repository, tag, message, entries, srcfiles)
|
|||
char rcs[PATH_MAX];
|
||||
char *tmp;
|
||||
|
||||
#ifdef DEATH_SUPPORT
|
||||
int branch;
|
||||
char *lockflag;
|
||||
char *corev;
|
||||
char *rev;
|
||||
char *prev_rev;
|
||||
Node *p;
|
||||
RCSNode *rcsfile;
|
||||
|
||||
corev = NULL;
|
||||
rev = NULL;
|
||||
prev_rev = NULL;
|
||||
lockflag = 0;
|
||||
#endif /* DEATH_SUPPORT */
|
||||
|
||||
retcode = 0;
|
||||
|
||||
locate_rcs (file, repository, rcs);
|
||||
|
||||
#ifdef DEATH_SUPPORT
|
||||
branch = 0;
|
||||
if (tag && !(branch = RCS_isbranch (file, tag, srcfiles)))
|
||||
#else
|
||||
if (tag)
|
||||
#endif
|
||||
{
|
||||
/* a symbolic tag is specified; just remove the tag from the file */
|
||||
run_setup ("%s%s -q -N%s", Rcsbin, RCS, tag);
|
||||
run_arg (rcs);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL)) != 0)
|
||||
if ((retcode = RCS_deltag (rcs, tag, 1)) != 0)
|
||||
{
|
||||
if (!quiet)
|
||||
error (0, retcode == -1 ? errno : 0,
|
||||
|
|
@ -1036,7 +1178,126 @@ remove_file (file, repository, tag, message, entries, srcfiles)
|
|||
Scratch_Entry (entries, file);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef DEATH_SUPPORT
|
||||
/* we are removing the file from either the head or a branch */
|
||||
/* commit a new, dead revision. */
|
||||
|
||||
/* Print message indicating that file is going to be removed. */
|
||||
(void) printf ("Removing %s;\n", file);
|
||||
|
||||
rev = NULL;
|
||||
lockflag = "-l";
|
||||
if (branch)
|
||||
{
|
||||
char *branchname;
|
||||
|
||||
rev = RCS_whatbranch (file, tag, srcfiles);
|
||||
if (rev == NULL)
|
||||
{
|
||||
error (0, 0, "cannot find branch \"%s\".", tag);
|
||||
return (1);
|
||||
}
|
||||
|
||||
p = findnode (srcfiles, file);
|
||||
if (p == NULL)
|
||||
{
|
||||
error (0, 0, "boy, I'm confused.");
|
||||
return (1);
|
||||
}
|
||||
rcsfile = (RCSNode *) p->data;
|
||||
branchname = RCS_getbranch (rcsfile, rev, 1);
|
||||
if (branchname == NULL)
|
||||
{
|
||||
/* no revision exists on this branch. use the previous
|
||||
revision but do not lock. */
|
||||
corev = RCS_gettag (rcsfile, tag, 1, 0);
|
||||
prev_rev = xstrdup(rev);
|
||||
lockflag = "";
|
||||
} else
|
||||
{
|
||||
corev = xstrdup (rev);
|
||||
prev_rev = xstrdup(branchname);
|
||||
free (branchname);
|
||||
}
|
||||
|
||||
} else /* Not a branch */
|
||||
{
|
||||
|
||||
/* Get current head revision of file. */
|
||||
p = findnode (srcfiles, file);
|
||||
if (p == NULL)
|
||||
{
|
||||
error (0, 0, "could not find parsed rcsfile %s", file);
|
||||
return (1);
|
||||
}
|
||||
rcsfile = (RCSNode *) p->data;
|
||||
prev_rev = RCS_head (rcsfile);
|
||||
}
|
||||
|
||||
/* if removing without a tag or a branch, then make sure the default
|
||||
branch is the trunk. */
|
||||
if (!tag && !branch)
|
||||
{
|
||||
if (RCS_setbranch (rcs, NULL) != 0)
|
||||
{
|
||||
error (0, 0, "cannot change branch to default for %s",
|
||||
rcs);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active) {
|
||||
/* If this is the server, there will be a file sitting in the
|
||||
temp directory which is the kludgy way in which server.c
|
||||
tells time_stamp that the file is no longer around. Remove
|
||||
it so we can create temp files with that name (ignore errors). */
|
||||
unlink_file (file);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check something out. Generally this is the head. If we have a
|
||||
particular rev, then name it. except when creating a branch,
|
||||
lock the rev we're checking out. */
|
||||
run_setup ("%s%s %s %s%s %s", Rcsbin, RCS_CO,
|
||||
lockflag,
|
||||
rev ? "-r" : "",
|
||||
rev ? corev : "", rcs);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL))
|
||||
!= 0) {
|
||||
if (!quiet)
|
||||
error (0, retcode == -1 ? errno : 0,
|
||||
"failed to check out `%s'", rcs);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (corev != NULL)
|
||||
free (corev);
|
||||
|
||||
#ifdef DEATH_STATE
|
||||
run_setup ("%s%s -f -sdead %s%s", Rcsbin, RCS_CI, rev ? "-r" : "",
|
||||
#else
|
||||
run_setup ("%s%s -K %s%s", Rcsbin, RCS_CI, rev ? "-r" : "",
|
||||
#endif
|
||||
rev ? rev : "");
|
||||
run_args ("-m%s", make_message_rcslegal (message));
|
||||
run_arg (rcs);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL))
|
||||
!= 0) {
|
||||
if (!quiet)
|
||||
error (0, retcode == -1 ? errno : 0,
|
||||
"failed to commit dead revision for `%s'", rcs);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (rev != NULL)
|
||||
free (rev);
|
||||
|
||||
if (!branch)
|
||||
#else /* No DEATH_SUPPORT */
|
||||
else
|
||||
#endif /* No DEATH_SUPPORT */
|
||||
{
|
||||
/* this was the head; really move it into the Attic */
|
||||
tmp = xmalloc(strlen(repository) +
|
||||
|
|
@ -1046,31 +1307,56 @@ remove_file (file, repository, tag, message, entries, srcfiles)
|
|||
strlen(file) +
|
||||
sizeof(RCSEXT) + 1);
|
||||
(void) sprintf (tmp, "%s/%s", repository, CVSATTIC);
|
||||
omask = umask (2);
|
||||
(void) mkdir (tmp, 0777);
|
||||
omask = umask (cvsumask);
|
||||
(void) CVS_MKDIR (tmp, 0777);
|
||||
(void) umask (omask);
|
||||
(void) sprintf (tmp, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT);
|
||||
|
||||
#ifdef DEATH_SUPPORT
|
||||
if (strcmp (rcs, tmp) != 0
|
||||
&& rename (rcs, tmp) == -1
|
||||
&& (isreadable (rcs) || !isreadable (tmp)))
|
||||
{
|
||||
free(tmp);
|
||||
return (1);
|
||||
}
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
/* Print message that file was removed. */
|
||||
(void) printf ("%s <-- %s\n", rcs, file);
|
||||
(void) printf ("new revision: delete; ");
|
||||
(void) printf ("previous revision: %s\n", prev_rev);
|
||||
(void) printf ("done\n");
|
||||
free(prev_rev);
|
||||
|
||||
Scratch_Entry (entries, file);
|
||||
return (0);
|
||||
#else /* No DEATH_SUPPORT */
|
||||
|
||||
if ((strcmp (rcs, tmp) == 0 || rename (rcs, tmp) != -1) ||
|
||||
(!isreadable (rcs) && isreadable (tmp)))
|
||||
{
|
||||
Scratch_Entry (entries, file);
|
||||
/* FIXME: should free tmp. */
|
||||
return (0);
|
||||
}
|
||||
/* FIXME: should free tmp. */
|
||||
}
|
||||
return (1);
|
||||
#endif /* No DEATH_SUPPORT */
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the actual checkin for added files
|
||||
*/
|
||||
static int
|
||||
finaladd (file, rev, tag, options, repository, entries)
|
||||
finaladd (file, rev, tag, options, update_dir, repository, entries)
|
||||
char *file;
|
||||
char *rev;
|
||||
char *tag;
|
||||
char *options;
|
||||
char *update_dir;
|
||||
char *repository;
|
||||
List *entries;
|
||||
{
|
||||
|
|
@ -1079,12 +1365,10 @@ finaladd (file, rev, tag, options, repository, entries)
|
|||
char rcs[PATH_MAX];
|
||||
|
||||
locate_rcs (file, repository, rcs);
|
||||
ret = Checkin ('A', file, repository, rcs, rev, tag, options,
|
||||
ret = Checkin ('A', file, update_dir, repository, rcs, rev, tag, options,
|
||||
message, entries);
|
||||
if (ret == 0)
|
||||
{
|
||||
(void) sprintf (tmp, "%s/%s%s", CVSADM, file, CVSEXT_OPT);
|
||||
(void) unlink_file (tmp);
|
||||
(void) sprintf (tmp, "%s/%s%s", CVSADM, file, CVSEXT_LOG);
|
||||
(void) unlink_file (tmp);
|
||||
}
|
||||
|
|
@ -1105,10 +1389,8 @@ unlockrcs (file, repository)
|
|||
int retcode = 0;
|
||||
|
||||
locate_rcs (file, repository, rcs);
|
||||
run_setup ("%s%s -q -u", Rcsbin, RCS);
|
||||
run_arg (rcs);
|
||||
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
|
||||
if ((retcode = RCS_unlock (rcs, NULL, 0)) != 0)
|
||||
error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
|
||||
"could not unlock %s", rcs);
|
||||
}
|
||||
|
|
@ -1150,9 +1432,7 @@ fixbranch (file, repository, branch)
|
|||
if (branch != NULL && branch[0] != '\0')
|
||||
{
|
||||
locate_rcs (file, repository, rcs);
|
||||
run_setup ("%s%s -q -b%s", Rcsbin, RCS, branch);
|
||||
run_arg (rcs);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
|
||||
if ((retcode = RCS_setbranch (rcs, branch)) != 0)
|
||||
error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
|
||||
"cannot restore branch to %s for %s", branch, rcs);
|
||||
}
|
||||
|
|
@ -1165,24 +1445,26 @@ fixbranch (file, repository, branch)
|
|||
*/
|
||||
|
||||
static int
|
||||
checkaddfile (file, repository, tag, srcfiles)
|
||||
checkaddfile (file, repository, tag, options, srcfiles)
|
||||
char *file;
|
||||
char *repository;
|
||||
char *tag;
|
||||
char *options;
|
||||
List *srcfiles;
|
||||
{
|
||||
FILE *fp;
|
||||
char *cp;
|
||||
char rcs[PATH_MAX];
|
||||
char fname[PATH_MAX];
|
||||
mode_t omask;
|
||||
int retcode = 0;
|
||||
#ifdef DEATH_SUPPORT
|
||||
int newfile = 0;
|
||||
#endif
|
||||
|
||||
if (tag)
|
||||
{
|
||||
(void) sprintf(rcs, "%s/%s", repository, CVSATTIC);
|
||||
omask = umask (2);
|
||||
if (mkdir (rcs, 0777) != 0 && errno != EEXIST)
|
||||
omask = umask (cvsumask);
|
||||
if (CVS_MKDIR (rcs, 0777) != 0 && errno != EEXIST)
|
||||
error (1, errno, "cannot make directory `%s'", rcs);;
|
||||
(void) umask (omask);
|
||||
(void) sprintf (rcs, "%s/%s/%s%s", repository, CVSATTIC, file, RCSEXT);
|
||||
|
|
@ -1190,18 +1472,177 @@ checkaddfile (file, repository, tag, srcfiles)
|
|||
else
|
||||
locate_rcs (file, repository, rcs);
|
||||
|
||||
#ifdef DEATH_SUPPORT
|
||||
if (isreadable(rcs))
|
||||
{
|
||||
/* file has existed in the past. Prepare to resurrect. */
|
||||
char oldfile[PATH_MAX];
|
||||
char *rev;
|
||||
Node *p;
|
||||
RCSNode *rcsfile;
|
||||
|
||||
if (tag == NULL)
|
||||
{
|
||||
/* we are adding on the trunk, so move the file out of the
|
||||
Attic. */
|
||||
strcpy (oldfile, rcs);
|
||||
sprintf (rcs, "%s/%s%s", repository, file, RCSEXT);
|
||||
|
||||
if (strcmp (oldfile, rcs) == 0
|
||||
|| rename (oldfile, rcs) != 0
|
||||
|| isreadable (oldfile)
|
||||
|| !isreadable (rcs))
|
||||
{
|
||||
error (0, 0, "failed to move `%s' out of the attic.",
|
||||
file);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
p = findnode (srcfiles, file);
|
||||
if (p == NULL)
|
||||
{
|
||||
error (0, 0, "could not find parsed rcsfile %s", file);
|
||||
return (1);
|
||||
}
|
||||
|
||||
rcsfile = (RCSNode *) p->data;
|
||||
rev = RCS_getversion (rcsfile, tag, NULL, 1, 0);
|
||||
/* and lock it */
|
||||
if (lock_RCS (file, rcs, rev, repository)) {
|
||||
error (0, 0, "cannot lock `%s'.", rcs);
|
||||
free (rev);
|
||||
return (1);
|
||||
}
|
||||
|
||||
free (rev);
|
||||
} else {
|
||||
/* this is the first time we have ever seen this file; create
|
||||
an rcs file. */
|
||||
run_setup ("%s%s -i", Rcsbin, RCS);
|
||||
|
||||
(void) sprintf (fname, "%s/%s%s", CVSADM, file, CVSEXT_LOG);
|
||||
/* If the file does not exist, no big deal. In particular, the
|
||||
server does not (yet at least) create CVSEXT_LOG files. */
|
||||
if (isfile (fname))
|
||||
run_args ("-t%s/%s%s", CVSADM, file, CVSEXT_LOG);
|
||||
|
||||
/* Set RCS keyword expansion options. */
|
||||
if (options && options[0] == '-' && options[1] == 'k')
|
||||
run_arg (options);
|
||||
run_arg (rcs);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
|
||||
{
|
||||
error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
|
||||
"could not create %s", rcs);
|
||||
return (1);
|
||||
}
|
||||
newfile = 1;
|
||||
}
|
||||
|
||||
/* when adding a file for the first time, and using a tag, we need
|
||||
to create a dead revision on the trunk. */
|
||||
if (tag && newfile)
|
||||
{
|
||||
char tmp[PATH_MAX];
|
||||
|
||||
/* move the new file out of the way. */
|
||||
(void) sprintf (fname, "%s/%s%s", CVSADM, CVSPREFIX, file);
|
||||
rename_file (file, fname);
|
||||
copy_file (DEVNULL, file);
|
||||
|
||||
/* commit a dead revision. */
|
||||
(void) sprintf (tmp, "-mfile %s was initially added on branch %s.", file, tag);
|
||||
#ifdef DEATH_STATE
|
||||
run_setup ("%s%s -q -f -sdead", Rcsbin, RCS_CI);
|
||||
#else
|
||||
run_setup ("%s%s -q -K", Rcsbin, RCS_CI);
|
||||
#endif
|
||||
run_arg (tmp);
|
||||
run_arg (rcs);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
|
||||
{
|
||||
error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
|
||||
"could not create initial dead revision %s", rcs);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* put the new file back where it was */
|
||||
rename_file (fname, file);
|
||||
|
||||
/* and lock it once again. */
|
||||
if (lock_RCS (file, rcs, NULL, repository)) {
|
||||
error (0, 0, "cannot lock `%s'.", rcs);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (tag != NULL)
|
||||
{
|
||||
/* when adding with a tag, we need to stub a branch, if it
|
||||
doesn't already exist. */
|
||||
Node *p;
|
||||
RCSNode *rcsfile;
|
||||
|
||||
rcsfile = RCS_parse (file, repository);
|
||||
if (rcsfile == NULL)
|
||||
{
|
||||
error (0, 0, "could not read %s", rcs);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (!RCS_nodeisbranch (tag, rcsfile)) {
|
||||
/* branch does not exist. Stub it. */
|
||||
char *head;
|
||||
char *magicrev;
|
||||
|
||||
head = RCS_getversion (rcsfile, NULL, NULL, 0, 0);
|
||||
magicrev = RCS_magicrev (rcsfile, head);
|
||||
if ((retcode = RCS_settag(rcs, tag, magicrev)) != 0)
|
||||
{
|
||||
error (retcode == -1 ? 1 : 0, retcode == -1 ? errno : 0,
|
||||
"could not stub branch %s for %s", tag, rcs);
|
||||
return (1);
|
||||
}
|
||||
|
||||
freercsnode (&rcsfile);
|
||||
|
||||
/* reparse the file, then add it to our list. */
|
||||
rcsfile = RCS_parse (file, repository);
|
||||
if (rcsfile == NULL)
|
||||
{
|
||||
error (0, 0, "could not reparse %s", rcs);
|
||||
return (1);
|
||||
}
|
||||
|
||||
free (head);
|
||||
free (magicrev);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* lock the branch. (stubbed branches need not be locked.) */
|
||||
if (lock_RCS (file, rcs, NULL, repository)) {
|
||||
error (0, 0, "cannot lock `%s'.", rcs);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* add (replace) this rcs file to our list */
|
||||
p = findnode (srcfiles, file);
|
||||
|
||||
if (p != NULL)
|
||||
freercsnode((RCSNode **) &p->data);
|
||||
|
||||
delnode(p);
|
||||
|
||||
RCS_addnode (file, rcsfile, srcfiles);
|
||||
}
|
||||
#else /* No DEATH_SUPPORT */
|
||||
run_setup ("%s%s -i", Rcsbin, RCS);
|
||||
run_args ("-t%s/%s%s", CVSADM, file, CVSEXT_LOG);
|
||||
(void) sprintf (fname, "%s/%s%s", CVSADM, file, CVSEXT_OPT);
|
||||
fp = open_file (fname, "r");
|
||||
while (fgets (fname, sizeof (fname), fp) != NULL)
|
||||
{
|
||||
if ((cp = strrchr (fname, '\n')) != NULL)
|
||||
*cp = '\0';
|
||||
if (*fname)
|
||||
run_arg (fname);
|
||||
}
|
||||
(void) fclose (fp);
|
||||
/* Set RCS keyword expansion options. */
|
||||
if (options && options[0] == '-' && options[1] == 'k')
|
||||
run_arg (options);
|
||||
run_arg (rcs);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
|
||||
{
|
||||
|
|
@ -1209,6 +1650,7 @@ checkaddfile (file, repository, tag, srcfiles)
|
|||
"could not create %s", rcs);
|
||||
return (1);
|
||||
}
|
||||
#endif /* No DEATH_SUPPORT */
|
||||
|
||||
fix_rcs_modes (rcs, file);
|
||||
return (0);
|
||||
|
|
@ -1272,9 +1714,7 @@ lock_RCS (user, rcs, rev, repository)
|
|||
freercsnode (&rcsfile);
|
||||
if (branch != NULL)
|
||||
{
|
||||
run_setup ("%s%s -q -b", Rcsbin, RCS);
|
||||
run_arg (rcs);
|
||||
if (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) != 0)
|
||||
if (RCS_setbranch (rcs, NULL) != 0)
|
||||
{
|
||||
error (0, 0, "cannot change branch to default for %s",
|
||||
rcs);
|
||||
|
|
@ -1283,16 +1723,12 @@ lock_RCS (user, rcs, rev, repository)
|
|||
return (1);
|
||||
}
|
||||
}
|
||||
run_setup ("%s%s -q -l", Rcsbin, RCS);
|
||||
run_arg (rcs);
|
||||
err = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
|
||||
err = RCS_lock(rcs, NULL, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
run_setup ("%s%s -q -l%s", Rcsbin, RCS, rev ? rev : "");
|
||||
run_arg (rcs);
|
||||
(void) run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL);
|
||||
(void) RCS_lock(rcs, rev, 1);
|
||||
}
|
||||
|
||||
if (err == 0)
|
||||
|
|
|
|||
|
|
@ -14,13 +14,16 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)create_adm.c 1.28 94/09/23 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)create_adm.c 1.28 94/09/23 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
/* update_dir includes dir as its last component. */
|
||||
|
||||
void
|
||||
Create_Admin (dir, repository, tag, date)
|
||||
Create_Admin (dir, update_dir, repository, tag, date)
|
||||
char *dir;
|
||||
char *update_dir;
|
||||
char *repository;
|
||||
char *tag;
|
||||
char *date;
|
||||
|
|
@ -29,6 +32,18 @@ Create_Admin (dir, repository, tag, date)
|
|||
char *cp;
|
||||
char tmp[PATH_MAX];
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (trace)
|
||||
{
|
||||
char wd[PATH_MAX];
|
||||
getwd (wd);
|
||||
fprintf (stderr, "%c-> Create_Admin (%s, %s, %s, %s, %s) in %s\n",
|
||||
(server_active) ? 'S' : ' ',
|
||||
dir, update_dir, repository, tag ? tag : "",
|
||||
date ? date : "", wd);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (noexec)
|
||||
return;
|
||||
|
||||
|
|
@ -36,24 +51,9 @@ Create_Admin (dir, repository, tag, date)
|
|||
(void) sprintf (tmp, "%s/%s", dir, CVSADM);
|
||||
else
|
||||
(void) strcpy (tmp, CVSADM);
|
||||
|
||||
if (isfile (tmp))
|
||||
error (1, 0, "there is a version here already");
|
||||
else
|
||||
{
|
||||
if (dir != NULL)
|
||||
(void) sprintf (tmp, "%s/%s", dir, OCVSADM);
|
||||
else
|
||||
(void) strcpy (tmp, OCVSADM);
|
||||
error (1, 0, "there is a version in %s already", update_dir);
|
||||
|
||||
if (isfile (tmp))
|
||||
error (1, 0, "there is a version here already");
|
||||
}
|
||||
|
||||
if (dir != NULL)
|
||||
(void) sprintf (tmp, "%s/%s", dir, CVSADM);
|
||||
else
|
||||
(void) strcpy (tmp, CVSADM);
|
||||
make_directory (tmp);
|
||||
|
||||
#ifdef CVSADM_ROOT
|
||||
|
|
@ -65,7 +65,14 @@ Create_Admin (dir, repository, tag, date)
|
|||
(void) sprintf (tmp, "%s/%s", dir, CVSADM_REP);
|
||||
else
|
||||
(void) strcpy (tmp, CVSADM_REP);
|
||||
fout = open_file (tmp, "w+");
|
||||
fout = fopen (tmp, "w+");
|
||||
if (fout == NULL)
|
||||
{
|
||||
if (update_dir[0] == '\0')
|
||||
error (1, errno, "cannot open %s", tmp);
|
||||
else
|
||||
error (1, errno, "cannot open %s/%s", update_dir, CVSADM_REP);
|
||||
}
|
||||
cp = repository;
|
||||
strip_path (cp);
|
||||
|
||||
|
|
@ -84,20 +91,54 @@ Create_Admin (dir, repository, tag, date)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (fprintf (fout, "%s\n", cp) == EOF)
|
||||
error (1, errno, "write to %s failed", tmp);
|
||||
if (fprintf (fout, "%s\n", cp) < 0)
|
||||
{
|
||||
if (update_dir[0] == '\0')
|
||||
error (1, errno, "write to %s failed", tmp);
|
||||
else
|
||||
error (1, errno, "write to %s/%s failed", update_dir, CVSADM_REP);
|
||||
}
|
||||
if (fclose (fout) == EOF)
|
||||
error (1, errno, "cannot close %s", tmp);
|
||||
{
|
||||
if (update_dir[0] == '\0')
|
||||
error (1, errno, "cannot close %s", tmp);
|
||||
else
|
||||
error (1, errno, "cannot close %s/%s", update_dir, CVSADM_REP);
|
||||
}
|
||||
|
||||
/* now, do the Entries file */
|
||||
if (dir != NULL)
|
||||
(void) sprintf (tmp, "%s/%s", dir, CVSADM_ENT);
|
||||
else
|
||||
(void) strcpy (tmp, CVSADM_ENT);
|
||||
fout = open_file (tmp, "w+");
|
||||
fout = fopen (tmp, "w+");
|
||||
if (fout == NULL)
|
||||
{
|
||||
if (update_dir[0] == '\0')
|
||||
error (1, errno, "cannot open %s", tmp);
|
||||
else
|
||||
error (1, errno, "cannot open %s/%s", update_dir, CVSADM_ENT);
|
||||
}
|
||||
if (fclose (fout) == EOF)
|
||||
error (1, errno, "cannot close %s", tmp);
|
||||
{
|
||||
if (update_dir[0] == '\0')
|
||||
error (1, errno, "cannot close %s", tmp);
|
||||
else
|
||||
error (1, errno, "cannot close %s/%s", update_dir, CVSADM_ENT);
|
||||
}
|
||||
|
||||
/* Create a new CVS/Tag file */
|
||||
WriteTag (dir, tag, date);
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
server_set_sticky (update_dir, repository, tag, date);
|
||||
|
||||
if (trace)
|
||||
{
|
||||
fprintf (stderr, "%c<- Create_Admin\n",
|
||||
(server_active) ? 'S' : ' ');
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
.ds Rv \\$3
|
||||
.ds Dt \\$4
|
||||
..
|
||||
.Id $Id: cvs.1,v 1.1.1.2 1995/03/31 07:44:48 nate Exp $
|
||||
.Id $Id: cvs.1,v 1.7 1995/11/15 01:02:41 woods Exp $
|
||||
.TH CVS 1 "\*(Dt"
|
||||
.\" Full space in nroff; half space in troff
|
||||
.de SP
|
||||
|
|
@ -128,16 +128,28 @@ command).
|
|||
There are only two situations where you may omit
|
||||
.IR cvs_command :
|
||||
.` "cvs \-H"
|
||||
or
|
||||
.` "cvs --help"
|
||||
elicits a list of available commands, and
|
||||
.` "cvs \-v "
|
||||
.` "cvs \-v"
|
||||
or
|
||||
.` "cvs --version"
|
||||
displays version information on \fBcvs\fP itself.
|
||||
.SP
|
||||
.SH "CVS OPTIONS"
|
||||
As of release 1.6,
|
||||
.B cvs
|
||||
supports
|
||||
.SM GNU
|
||||
style long options as well as short options. Only
|
||||
a few long options are currently supported, these are listed in
|
||||
brackets after the short options whose functions they duplicate.
|
||||
.SP
|
||||
Use these options to control the overall
|
||||
.B cvs
|
||||
program:
|
||||
.TP
|
||||
.B \-H
|
||||
.B \-H [ --help ]
|
||||
Display usage information about the specified
|
||||
.I cvs_command
|
||||
(but do not actually execute the command). If you don't specify a
|
||||
|
|
@ -186,6 +198,11 @@ and the
|
|||
.SM EDITOR
|
||||
environment variables.
|
||||
.TP
|
||||
.B \-f
|
||||
Do not read the
|
||||
.B cvs
|
||||
startup file (\fI~/.cvsrc\fP).
|
||||
.TP
|
||||
.B \-l
|
||||
Do not log the
|
||||
.I cvs_command
|
||||
|
|
@ -213,7 +230,7 @@ Same effect as if the
|
|||
.SM CVSREAD
|
||||
environment variable is set.
|
||||
.TP
|
||||
.B \-v
|
||||
.B \-v [ --version ]
|
||||
Displays version and copyright information for
|
||||
.BR cvs .
|
||||
.TP
|
||||
|
|
@ -222,6 +239,16 @@ Makes new working files read-write (default).
|
|||
Overrides the setting of the
|
||||
.SM CVSREAD
|
||||
environment variable.
|
||||
.TP
|
||||
\fB\-z\fP \fIcompression\-level\fP
|
||||
When transferring files across the network use
|
||||
.B gzip
|
||||
with compression level \fIcompression\-level\fP to compress and
|
||||
de-compress data as it is transferred. Requires the presence of
|
||||
the
|
||||
.SM GNU
|
||||
.B gzip
|
||||
program in the current search path at both ends of the link.
|
||||
.SH "USAGE"
|
||||
Except when requesting general help with
|
||||
.` "cvs \-H",
|
||||
|
|
@ -237,6 +264,29 @@ However, many options are available across several commands.
|
|||
You can display a usage summary for each command by specifying the
|
||||
.B \-H
|
||||
option with the command.
|
||||
.SH "CVS STARTUP FILE"
|
||||
Normally, when CVS starts up, it reads the
|
||||
.I .cvsrc
|
||||
file from the home directory of the user reading it. This startup
|
||||
procedure can be turned off with the
|
||||
.B \-f
|
||||
flag.
|
||||
.SP
|
||||
The
|
||||
.I .cvsrc
|
||||
file lists CVS commands with a list of arguments, one command per
|
||||
line. For example, the following line in \fI.cvsrc\fP:
|
||||
.SP
|
||||
diff \-c
|
||||
.SP
|
||||
will mean that the
|
||||
.` "cvs diff"
|
||||
command will always be passed the \-c option in addition to any
|
||||
other options that are specified in the command line (in this case
|
||||
it will have the effect of producing context sensitive diffs for
|
||||
all executions of
|
||||
.` "cvs diff"
|
||||
).
|
||||
.SH "CVS COMMAND SUMMARY"
|
||||
Here are brief descriptions of all the
|
||||
.B cvs
|
||||
|
|
@ -343,7 +393,8 @@ file. (Does not change
|
|||
repository or working directory.)
|
||||
.TP
|
||||
.B tag
|
||||
Specify a symbolic tag for files in the repository. Tags the revisions
|
||||
Specify a symbolic tag for files in the repository. By default, tags
|
||||
the revisions
|
||||
that were last synchronized with your working directory. (Changes
|
||||
repository directly; uses working directory without changing it.)
|
||||
.TP
|
||||
|
|
@ -436,9 +487,9 @@ Alter the default
|
|||
processing of keywords; all the
|
||||
.B \-k
|
||||
options described in
|
||||
.BR rcs ( 1 )
|
||||
.BR co ( 1 )
|
||||
are available. The \fB\-k\fP option is available with the
|
||||
.BR add ", " checkout ", " diff ", "
|
||||
.BR add ", " checkout ", " diff ", " export ", "
|
||||
.BR rdiff ", and " update
|
||||
commands. Your \fIkflag\fP specification is ``sticky'' when you use
|
||||
it to create a private copy of a source file; that is, when you use
|
||||
|
|
@ -446,6 +497,15 @@ this option with the \fBcheckout\fP or \fBupdate\fP commands,
|
|||
\fBcvs\fP associates your selected \fIkflag\fP with the file, and
|
||||
continues to use it with future \fBupdate\fP commands on the same file
|
||||
until you specify otherwise.
|
||||
.SP
|
||||
Some of the more useful \fIkflag\fPs are \-ko and \-kb (for binary files,
|
||||
only compatible with
|
||||
.SM RCS
|
||||
version 5.7 or later), and \-kv which is useful for an
|
||||
.B export
|
||||
where you wish to retain keyword information after an
|
||||
.B import
|
||||
at some other site.
|
||||
.TP
|
||||
.B \-l
|
||||
Local; run only in current working directory, rather than recurring through
|
||||
|
|
@ -508,23 +568,6 @@ rather than writing them in the current directory. Available with the
|
|||
.BR checkout " and " update
|
||||
commands.
|
||||
.TP
|
||||
.B \-Q
|
||||
Causes the command to be
|
||||
.I really
|
||||
quiet; the command will generate output only for serious problems.
|
||||
Available with the following commands:
|
||||
.BR checkout ", " import ", " export ", "
|
||||
.BR rdiff ", " rtag ", "
|
||||
.BR tag ", and " update .
|
||||
.TP
|
||||
.B \-q
|
||||
Causes the command to be somewhat quiet; informational messages, such
|
||||
as reports of recursion through subdirectories, are suppressed.
|
||||
Available with the following commands:
|
||||
.BR checkout ", " import ", " export ", "
|
||||
.BR rtag ", "
|
||||
.BR tag ", and " update .
|
||||
.TP
|
||||
\fB\-r\fP \fItag\fP
|
||||
Use the revision specified by the
|
||||
.I tag
|
||||
|
|
@ -553,9 +596,9 @@ can be either a symbolic or numeric tag, in
|
|||
fashion.
|
||||
Specifying the
|
||||
.B \-q
|
||||
option along with the
|
||||
global option along with the
|
||||
.B \-r
|
||||
option is often useful, to suppress the warning messages when the
|
||||
command option is often useful, to suppress the warning messages when the
|
||||
.SM RCS
|
||||
file does not contain the specified tag.
|
||||
.B \-r
|
||||
|
|
@ -787,7 +830,7 @@ sure that it will be a sub-directory, and that
|
|||
will show the relative path leading to each file as it is extracted into
|
||||
your private work area (unless you specify the
|
||||
.B \-Q
|
||||
option).
|
||||
global option).
|
||||
.SP
|
||||
Running
|
||||
.` "cvs checkout"
|
||||
|
|
@ -805,11 +848,11 @@ The
|
|||
permitted with
|
||||
.` "cvs checkout"
|
||||
include the standard command options
|
||||
.BR \-P ", " \-Q ", " \-f ", "
|
||||
.BR \-P ", " \-f ", "
|
||||
.BI \-k " kflag"
|
||||
\&,
|
||||
.BR \-l ", " \-n ", " \-p ", "
|
||||
.BR \-q ", " \-r
|
||||
.BR \-r
|
||||
.IR tag ", and"
|
||||
.BI \-D " date"\c
|
||||
\&.
|
||||
|
|
@ -1068,7 +1111,7 @@ differ from the corresponding revision in the source repository
|
|||
.I you
|
||||
have changed), or that differ from the revision specified.
|
||||
.TP
|
||||
\fBexport\fP [\-\fBf\|lNnQq\fP] \fB\-r\fP \fIrev\fP\||\|\fB\-D\fP \fIdate\fP [\fB\-d\fP \fIdir\fP] \fImodule\fP.\|.\|.
|
||||
\fBexport\fP [\-\fBf\|lNnQq\fP] \fB\-r\fP \fIrev\fP\||\|\fB\-D\fP \fIdate\fP [\fB\-d\fP \fIdir\fP] [\fB\-k\fP \fIkflag\fP] \fImodule\fP.\|.\|.
|
||||
.I Requires:
|
||||
repository.
|
||||
.br
|
||||
|
|
@ -1098,7 +1141,7 @@ These have the same meanings as the same options in
|
|||
.SP
|
||||
The
|
||||
.B \-kv
|
||||
option is always set when
|
||||
option is useful when
|
||||
.B export
|
||||
is used.
|
||||
This causes any
|
||||
|
|
@ -1106,7 +1149,10 @@ This causes any
|
|||
keywords to be expanded such that an
|
||||
.B import
|
||||
done at some other site will not lose the keyword revision information.
|
||||
There is no way to override this.
|
||||
Other \fIkflag\fPs may be used with
|
||||
.` "cvs export"
|
||||
and are described in
|
||||
.BR co ( 1 ).
|
||||
.TP
|
||||
\fBhistory\fP [\fB\-\fP\fIreport\fP] [\fB\-\fP\fIflags\fP] [\fB\-\fP\fIoptions args\fP] [\fIfiles\fP.\|.\|.]
|
||||
.I Requires:
|
||||
|
|
@ -1310,9 +1356,9 @@ least one \fIreleasetag\fP to identify the files at the leaves created
|
|||
each time you execute
|
||||
.` "cvs import".
|
||||
.SP
|
||||
Three of the standard
|
||||
One of the standard
|
||||
.B cvs
|
||||
command options are available: \fB\-Q\fP, \fB\-q\fP, and \fB\-m\fP
|
||||
command options is available: \fB\-m\fP
|
||||
\fImessage\fP. If you do not specify a logging message with
|
||||
\fB\-m\fP, your editor is invoked (as with \fBcommit\fP) to allow you
|
||||
to enter one.
|
||||
|
|
@ -1411,8 +1457,8 @@ version \fIvn\fP (the expansion format changed with
|
|||
.SM RCS
|
||||
version 5).
|
||||
.SP
|
||||
The standard option \fIflags\fP \fB\-f\fP, \fB\-l\fP, \fB\-Q\fP, and
|
||||
\fB\-q\fP are available with this command. There are also several
|
||||
The standard option \fIflags\fP \fB\-f\fP, and \fB\-l\fP
|
||||
are available with this command. There are also several
|
||||
special options flags:
|
||||
.SP
|
||||
If you use the
|
||||
|
|
@ -1543,6 +1589,17 @@ should not be removed, but the
|
|||
option is available as a means to remove completely obsolete symbolic names
|
||||
if necessary (as might be the case for an Alpha release, say).
|
||||
.SP
|
||||
.` "cvs rtag"
|
||||
will not move a tag that already exists. With the \fB\-F\fP option,
|
||||
however,
|
||||
.` "cvs rtag"
|
||||
will re-locate any instance of \fIsymbolic_tag\fP that already exists
|
||||
on that file to the new repository versions. Without the \fB\-F\fP
|
||||
option, attempting to use
|
||||
.` "cvs rtag"
|
||||
to apply a tag that already exists on that file will produce an error
|
||||
message.
|
||||
.SP
|
||||
The \fB-b\fP option makes the tag a ``branch'' tag, allowing
|
||||
concurrent, isolated development.
|
||||
This is most useful for creating a patch to a previously released software
|
||||
|
|
@ -1564,9 +1621,6 @@ is specified; a typical use is to send electronic mail to a group of
|
|||
interested parties. If you want to bypass that program, use the
|
||||
standard \fB\-n\fP option.
|
||||
.SP
|
||||
The standard options \fB\-Q\fP and \fB\-q\fP are also available with
|
||||
this command.
|
||||
.SP
|
||||
Use the
|
||||
.B \-a
|
||||
option to have
|
||||
|
|
@ -1578,7 +1632,7 @@ The tag is removed from these files, which makes it convenient to re-use a
|
|||
symbolic tag as development continues (and files get removed from the
|
||||
up-coming distribution).
|
||||
.TP
|
||||
\fBstatus\fP [\fB\-lR\fP] [\fB\-v\fP] [\fIfiles\fP\|.\|.\|.]
|
||||
\fBstatus\fP [\fB\-lRqQ\fP] [\fB\-v\fP] [\fIfiles\fP\|.\|.\|.]
|
||||
.I Requires:
|
||||
working directory, repository.
|
||||
.br
|
||||
|
|
@ -1609,7 +1663,7 @@ option causes the symbolic tags for the
|
|||
.SM RCS
|
||||
file to be displayed as well.
|
||||
.TP
|
||||
\fBtag\fP [\fB\-lQqR\fP] [\fB\-b\fP] [\fB\-d\fP] \fIsymbolic_tag\fP [\fIfiles\fP\|.\|.\|.\|]
|
||||
\fBtag\fP [\fB\-lQqR\fP] [\fB\-F\fP] [\fB\-b\fP] [\fB\-d\fP] [\fB\-r\fP \fItag\fP | \fB\-D\fP \fIdate\fP] [\fB\-f\fP] \fIsymbolic_tag\fP [\fIfiles\fP\|.\|.\|.\|]
|
||||
.I Requires:
|
||||
working directory, repository.
|
||||
.br
|
||||
|
|
@ -1621,9 +1675,7 @@ repository.
|
|||
.br
|
||||
Use this command to assign symbolic tags to the nearest repository
|
||||
versions to your working sources. The tags are applied immediately to
|
||||
the repository, as with \fBrtag\fP, but the versions are supplied
|
||||
implicitly by the \fBcvs\fP records of your working files' history
|
||||
rather than applied explicitly.
|
||||
the repository, as with \fBrtag\fP.
|
||||
.SP
|
||||
One use for tags is to record a ``snapshot'' of the current sources
|
||||
when the software freeze date of a project arrives. As bugs are fixed
|
||||
|
|
@ -1633,13 +1685,28 @@ of the release need be re-tagged.
|
|||
The symbolic tags are meant to permanently record which revisions of which
|
||||
files were used in creating a software distribution.
|
||||
The
|
||||
.B checkout
|
||||
.BR checkout ,
|
||||
.B export
|
||||
and
|
||||
.B update
|
||||
commands allow you to extract an exact copy of a tagged release at any time in
|
||||
the future, regardless of whether files have been changed, added, or removed
|
||||
since the release was tagged.
|
||||
.SP
|
||||
You can use the standard \fB\-r\fP and \fB\-D\fP options to tag only those
|
||||
files that already contain a certain tag. This method would be used
|
||||
to rename a tag: tag only the files identified by the old tag, then delete the
|
||||
old tag, leaving the new tag on exactly the same files as the old tag.
|
||||
.SP
|
||||
Specifying the \fB\-f\fP flag in addition to the \fB\-r\fP or \fB\-D\fP
|
||||
flags will tag those files named on the command line even if they do not
|
||||
contain the old tag or did not exist on the specified date.
|
||||
.SP
|
||||
By default (without a \fB\-r\fP or \fB\-D\fP flag)
|
||||
the versions to be tagged are supplied
|
||||
implicitly by the \fBcvs\fP records of your working files' history
|
||||
rather than applied explicitly.
|
||||
.SP
|
||||
If you use
|
||||
.` "cvs tag \-d \fIsymbolic_tag\fP\|.\|.\|.",
|
||||
the
|
||||
|
|
@ -1649,6 +1716,17 @@ instead of being added. \fIWarning\fP: Be very certain of your ground
|
|||
before you delete a tag; doing this effectively discards some
|
||||
historical information, which may later turn out to have been valuable.
|
||||
.SP
|
||||
.` "cvs tag"
|
||||
will not move a tag that already exists. With the \fB\-F\fP option,
|
||||
however,
|
||||
.` "cvs tag"
|
||||
will re-locate any instance of \fIsymbolic_tag\fP that already exists
|
||||
on that file to the new repository versions. Without the \fB\-F\fP
|
||||
option, attempting to use
|
||||
.` "cvs tag"
|
||||
to apply a tag that already exists on that file will produce an error
|
||||
message.
|
||||
.SP
|
||||
The \fB-b\fP option makes the tag a ``branch'' tag, allowing
|
||||
concurrent, isolated development.
|
||||
This is most useful for creating a patch to a previously released software
|
||||
|
|
@ -1834,7 +1912,7 @@ Use
|
|||
to avoid ignoring any files at all.
|
||||
.SP
|
||||
The standard \fBcvs\fP command options \fB\-f\fP, \fB\-k\fP,
|
||||
\fB\-l\fP, \fB\-P\fP, \fB\-p\fP, \fB\-Q\fP, \fB\-q\fP, and \fB\-r\fP
|
||||
\fB\-l\fP, \fB\-P\fP, \fB\-p\fP, and \fB\-r\fP
|
||||
are also available with \fBupdate\fP.
|
||||
.RE
|
||||
.SH "FILES"
|
||||
|
|
@ -1844,6 +1922,27 @@ supporting files, see
|
|||
.BR cvs ( 5 ).
|
||||
.LP
|
||||
.I
|
||||
Files in home directories:
|
||||
.TP
|
||||
\&.cvsrc
|
||||
The
|
||||
.B cvs
|
||||
initialisation file. Lines in this file can be used to specify default
|
||||
options for each
|
||||
.B cvs
|
||||
command. For example the line
|
||||
.` "diff \-c"
|
||||
will ensure that
|
||||
.` "cvs diff"
|
||||
is always passed the
|
||||
.B \-c
|
||||
option in addition to any other options passed on the command line.
|
||||
.TP
|
||||
\&.cvswrappers
|
||||
Specifies wrappers to be used in addition to those specified in the
|
||||
CVSROOT/cvswrappers file in the repository.
|
||||
.LP
|
||||
.I
|
||||
Files in working directories:
|
||||
.TP
|
||||
CVS
|
||||
|
|
@ -1862,6 +1961,21 @@ CVS/Entries.Static
|
|||
Flag: do not add more entries on
|
||||
.` "cvs update".
|
||||
.TP
|
||||
CVS/Root
|
||||
Pathname to the repository (
|
||||
.SM CVSROOT
|
||||
) location at the time of checkout. This file is used instead
|
||||
of the
|
||||
.SM CVSROOT
|
||||
environment variable if the environment variable is not
|
||||
set. A warning message will be issued when the contents of this
|
||||
file and the
|
||||
.SM CVSROOT
|
||||
environment variable differ. The file may be over-ridden by the
|
||||
presence of the
|
||||
.SM CVS_IGNORE_REMOTE_ROOT
|
||||
environment variable.
|
||||
.TP
|
||||
CVS/Repository
|
||||
Pathname to the corresponding directory in the source repository.
|
||||
.TP
|
||||
|
|
@ -1896,28 +2010,44 @@ Records programs for filtering
|
|||
.` "cvs commit"
|
||||
requests.
|
||||
.TP
|
||||
CVSROOT/history
|
||||
Log file of \fBcvs\fP transactions.
|
||||
.TP
|
||||
CVSROOT/modules,v
|
||||
Definitions for modules in this repository.
|
||||
.TP
|
||||
CVSROOT/loginfo,v
|
||||
Records programs for piping
|
||||
.` "cvs commit"
|
||||
log entries.
|
||||
.TP
|
||||
CVSROOT/rcsinfo,v
|
||||
Records pathnames to templates used during a
|
||||
.` "cvs commit"
|
||||
operation.
|
||||
CVSROOT/cvswrappers,v
|
||||
Records
|
||||
.B cvs
|
||||
wrapper commands to be used when checking files into and out of the
|
||||
repository. Wrappers allow the file or directory to be processed
|
||||
on the way in and out of CVS. The intended uses are many, one
|
||||
possible use would be to reformat a C file before the file is checked
|
||||
in, so all of the code in the repository looks the same.
|
||||
.TP
|
||||
CVSROOT/editinfo,v
|
||||
Records programs for editing/validating
|
||||
.` "cvs commit"
|
||||
log entries.
|
||||
.TP
|
||||
Attic
|
||||
CVSROOT/history
|
||||
Log file of \fBcvs\fP transactions.
|
||||
.TP
|
||||
CVSROOT/loginfo,v
|
||||
Records programs for piping
|
||||
.` "cvs commit"
|
||||
log entries.
|
||||
.TP
|
||||
CVSROOT/modules,v
|
||||
Definitions for modules in this repository.
|
||||
.TP
|
||||
CVSROOT/rcsinfo,v
|
||||
Records pathnames to templates used during a
|
||||
.` "cvs commit"
|
||||
operation.
|
||||
.TP
|
||||
CVSROOT/taginfo,v
|
||||
Records programs for validating/logging
|
||||
.` "cvs tag"
|
||||
and
|
||||
.` "cvs rtag"
|
||||
operations.
|
||||
.TP
|
||||
MODULE/Attic
|
||||
Directory for removed source files.
|
||||
.TP
|
||||
#cvs.lock
|
||||
|
|
@ -1982,7 +2112,37 @@ environment variable is used instead.
|
|||
If
|
||||
.SM EDITOR
|
||||
is not set either, the default is
|
||||
.BR vi .
|
||||
.BR /usr/ucb/vi .
|
||||
.TP
|
||||
.SM CVS_IGNORE_REMOTE_ROOT
|
||||
If this variable is set then
|
||||
.B cvs
|
||||
will ignore all references to remote repositories in the CVS/Root file.
|
||||
.TP
|
||||
.SM CVS_RSH
|
||||
.B cvs
|
||||
uses the contents of this variable to determine the name of the
|
||||
remote shell command to use when starting a
|
||||
.B cvs
|
||||
server. If this variable is not set then
|
||||
.` "rsh"
|
||||
is used.
|
||||
.TP
|
||||
.SM CVS_SERVER
|
||||
.B cvs
|
||||
uses the contents of this variable to determine the name of the
|
||||
.B cvs
|
||||
server command. If this variable is not set then
|
||||
.` "cvs"
|
||||
is used.
|
||||
.TP
|
||||
.SM CVSWRAPPERS
|
||||
This variable is used by the
|
||||
.` "cvswrappers"
|
||||
script to determine the name of the wrapper file, in addition to the
|
||||
wrappers defaults contained in the repository
|
||||
.SM (CVSROOT/cvswrappers)
|
||||
and the user's home directory (~/.cvswrappers).
|
||||
.SH "AUTHORS"
|
||||
.TP
|
||||
Dick Grune
|
||||
|
|
@ -2011,6 +2171,8 @@ shell script (the ancestor of
|
|||
.BR ci ( 1 ),
|
||||
.BR co ( 1 ),
|
||||
.BR cvs ( 5 ),
|
||||
.BR cvsbug ( 8 ),
|
||||
.BR cvsinit ( 8 ),
|
||||
.BR diff ( 1 ),
|
||||
.BR grep ( 1 ),
|
||||
.BR mkmodules ( 1 ),
|
||||
|
|
|
|||
|
|
@ -21,16 +21,20 @@
|
|||
#ifdef _AIX
|
||||
#pragma alloca
|
||||
#else /* not _AIX */
|
||||
#ifdef ALLOCA_IN_STDLIB
|
||||
/* then we need do nothing */
|
||||
#else
|
||||
char *alloca ();
|
||||
#endif /* not ALLOCA_IN_STDLIB */
|
||||
#endif /* not _AIX */
|
||||
#endif /* not HAVE_ALLOCA_H */
|
||||
#endif /* not __GNUC__ */
|
||||
|
||||
#if __STDC__
|
||||
#define CONST const
|
||||
/* Changed from if __STDC__ to ifdef __STDC__ because of Sun's acc compiler */
|
||||
|
||||
#ifdef __STDC__
|
||||
#define PTR void *
|
||||
#else
|
||||
#define CONST
|
||||
#define PTR char *
|
||||
#endif
|
||||
|
||||
|
|
@ -44,17 +48,29 @@ char *alloca ();
|
|||
#endif
|
||||
|
||||
#if __GNUC__ == 2
|
||||
#define USE(var) static char sizeof##var = sizeof(sizeof##var) + sizeof(var);
|
||||
#define USE(var) static const char sizeof##var = sizeof(sizeof##var) + sizeof(var)
|
||||
#else
|
||||
#define USE(var)
|
||||
#define USE(var) static const char standalone_semis_illegal_sigh
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Under OS/2, <stdio.h> doesn't define popen()/pclose(). */
|
||||
#ifdef USE_OWN_POPEN
|
||||
#include "popen.h"
|
||||
#endif
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
extern void exit ();
|
||||
extern char *getenv();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
|
|
@ -62,7 +78,13 @@ char *alloca ();
|
|||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#include <fnmatch.h> /* This is supposed to be available on Posix systems */
|
||||
#ifdef SERVER_SUPPORT
|
||||
/* If the system doesn't provide strerror, it won't be declared in
|
||||
string.h. */
|
||||
char *strerror ();
|
||||
#endif
|
||||
|
||||
#include <fnmatch.h> /* This is supposed to be available on Posix systems */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <pwd.h>
|
||||
|
|
@ -79,6 +101,18 @@ extern int errno;
|
|||
#include "system.h"
|
||||
|
||||
#include "hash.h"
|
||||
#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
|
||||
#include "server.h"
|
||||
#include "client.h"
|
||||
#endif
|
||||
|
||||
#ifdef AUTH_CLIENT_SUPPORT
|
||||
extern int use_authenticating_server;
|
||||
void connect_to_pserver();
|
||||
# ifndef CVS_AUTH_PORT
|
||||
# define CVS_AUTH_PORT 2401
|
||||
# endif /* CVS_AUTH_PORT */
|
||||
#endif /* AUTH_CLIENT_SUPPORT */
|
||||
|
||||
#ifdef MY_NDBM
|
||||
#include "myndbm.h"
|
||||
|
|
@ -90,6 +124,11 @@ extern int errno;
|
|||
#include "getopt.h"
|
||||
#include "wait.h"
|
||||
|
||||
/* Define to enable alternate death support (which uses the RCS state). */
|
||||
#define DEATH_STATE 1
|
||||
|
||||
#define DEATH_SUPPORT 1
|
||||
|
||||
#include "rcs.h"
|
||||
|
||||
|
||||
|
|
@ -111,16 +150,17 @@ extern int errno;
|
|||
/*
|
||||
* Copyright (c) 1992, Brian Berliner and Jeff Polk
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
* Definitions for the CVS Administrative directory and the files it contains.
|
||||
* Here as #define's to make changing the names a simple task.
|
||||
*/
|
||||
#define CVSADM "CVS"
|
||||
#define CVSADM_ENT "CVS/Entries"
|
||||
#define CVSADM_ENTBAK "CVS/Entries.Backup"
|
||||
#define CVSADM_ENTLOG "CVS/Entries.Log"
|
||||
#define CVSADM_ENTSTAT "CVS/Entries.Static"
|
||||
#define CVSADM_REP "CVS/Repository"
|
||||
#define CVSADM_ROOT "CVS/Root"
|
||||
|
|
@ -128,14 +168,6 @@ extern int errno;
|
|||
#define CVSADM_UPROG "CVS/Update.prog"
|
||||
#define CVSADM_TAG "CVS/Tag"
|
||||
|
||||
/*
|
||||
* The following are obsolete and are maintained here only so that they can be
|
||||
* cleaned up during the transition
|
||||
*/
|
||||
#define OCVSADM "CVS.adm" /* for CVS 1.2 and earlier */
|
||||
#define CVSADM_FILE "CVS/Files"
|
||||
#define CVSADM_MOD "CVS/Mod"
|
||||
|
||||
/*
|
||||
* Definitions for the CVSROOT Administrative directory and the files it
|
||||
* contains. This directory is created as a sub-directory of the $CVSROOT
|
||||
|
|
@ -147,33 +179,36 @@ extern int errno;
|
|||
#define CVSROOTADM_LOGINFO "loginfo"
|
||||
#define CVSROOTADM_RCSINFO "rcsinfo"
|
||||
#define CVSROOTADM_COMMITINFO "commitinfo"
|
||||
#define CVSROOTADM_TAGINFO "taginfo"
|
||||
#define CVSROOTADM_EDITINFO "editinfo"
|
||||
#define CVSROOTADM_HISTORY "history"
|
||||
#define CVSROOTADM_IGNORE "cvsignore"
|
||||
#define CVSROOTADM_CHECKOUTLIST "checkoutlist"
|
||||
#define CVSROOTADM_WRAPPER "cvswrappers"
|
||||
#define CVSNULLREPOS "Emptydir" /* an empty directory */
|
||||
|
||||
/* support for the modules file (CVSROOTADM_MODULES) */
|
||||
#define CVSMODULE_OPTS "ad:i:lo:s:t:u:"/* options in modules file */
|
||||
#define CVSMODULE_OPTS "ad:i:lo:e:s:t:u:"/* options in modules file */
|
||||
#define CVSMODULE_SPEC '&' /* special delimiter */
|
||||
|
||||
/*
|
||||
* The following are obsolete and are maintained here only so that they can be
|
||||
* cleaned up during the transition
|
||||
*/
|
||||
#define OCVSROOTADM "CVSROOT.adm" /* for CVS 1.2 and earlier */
|
||||
|
||||
/* Other CVS file names */
|
||||
|
||||
/* Files go in the attic if the head main branch revision is dead,
|
||||
otherwise they go in the regular repository directories. The whole
|
||||
concept of having an attic is sort of a relic from before death
|
||||
support but on the other hand, it probably does help the speed of
|
||||
some operations (such as main branch checkouts and updates). */
|
||||
#define CVSATTIC "Attic"
|
||||
|
||||
#define CVSLCK "#cvs.lock"
|
||||
#define CVSTFL "#cvs.tfl"
|
||||
#define CVSRFL "#cvs.rfl"
|
||||
#define CVSWFL "#cvs.wfl"
|
||||
#define CVSRFLPAT "#cvs.rfl.*" /* wildcard expr to match read locks */
|
||||
#define CVSEXT_OPT ",p"
|
||||
#define CVSEXT_LOG ",t"
|
||||
#define CVSPREFIX ",,"
|
||||
#define CVSDOTIGNORE ".cvsignore"
|
||||
#define CVSDOTWRAPPER ".cvswrappers"
|
||||
|
||||
/* miscellaneous CVS defines */
|
||||
#define CVSEDITPREFIX "CVS: "
|
||||
|
|
@ -181,7 +216,9 @@ extern int errno;
|
|||
#define CVSLCKSLEEP 30 /* wait 30 seconds before retrying */
|
||||
#define CVSBRANCH "1.1.1" /* RCS branch used for vendor srcs */
|
||||
#define BAKPREFIX ".#" /* when rcsmerge'ing */
|
||||
#ifndef DEVNULL
|
||||
#define DEVNULL "/dev/null"
|
||||
#endif
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
|
@ -202,18 +239,23 @@ extern int errno;
|
|||
/* #define RCSBIN_DFLT Set by config.h */
|
||||
|
||||
#define EDITOR1_ENV "CVSEDITOR" /* which editor to use */
|
||||
#define EDITOR2_ENV "EDITOR" /* which editor to use */
|
||||
#define EDITOR2_ENV "VISUAL" /* which editor to use */
|
||||
#define EDITOR3_ENV "EDITOR" /* which editor to use */
|
||||
/* #define EDITOR_DFLT Set by config.h */
|
||||
|
||||
#define CVSROOT_ENV "CVSROOT" /* source directory root */
|
||||
#define CVSROOT_DFLT NULL /* No dflt; must set for checkout */
|
||||
|
||||
#define IGNORE_ENV "CVSIGNORE" /* More files to ignore */
|
||||
#define WRAPPER_ENV "CVSWRAPPERS" /* name of the wrapper file */
|
||||
|
||||
#define CVSUMASK_ENV "CVSUMASK" /* Effective umask for repository */
|
||||
/* #define CVSUMASK_DFLT Set by config.h */
|
||||
|
||||
/*
|
||||
* If the beginning of the Repository matches the following string, strip it
|
||||
* so that the output to the logfile does not contain a full pathname.
|
||||
*
|
||||
*
|
||||
* If the CVSROOT environment variable is set, it overrides this define.
|
||||
*/
|
||||
#define REPOS_STRIP "/master/"
|
||||
|
|
@ -229,10 +271,23 @@ extern int errno;
|
|||
#define MAXLISTLEN 40000 /* For [A-Z]list holders */
|
||||
#define MAXDATELEN 50 /* max length for a date */
|
||||
|
||||
/* structure of a entry record */
|
||||
struct entnode
|
||||
{
|
||||
char *user;
|
||||
char *version;
|
||||
char *timestamp;
|
||||
char *options;
|
||||
char *tag;
|
||||
char *date;
|
||||
char *conflict;
|
||||
};
|
||||
typedef struct entnode Entnode;
|
||||
|
||||
/* The type of request that is being done in do_module() */
|
||||
enum mtype
|
||||
{
|
||||
CHECKOUT, TAG, PATCH
|
||||
CHECKOUT, TAG, PATCH, EXPORT
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -251,6 +306,9 @@ enum classify_type
|
|||
T_REMOVED, /* R (removed file) list */
|
||||
T_REMOVE_ENTRY, /* W (removed entry) list */
|
||||
T_UPTODATE, /* File is up-to-date */
|
||||
#ifdef SERVER_SUPPORT
|
||||
T_PATCH, /* P Like C, but can patch */
|
||||
#endif
|
||||
T_TITLE /* title for node type */
|
||||
};
|
||||
typedef enum classify_type Ctype;
|
||||
|
|
@ -258,7 +316,7 @@ typedef enum classify_type Ctype;
|
|||
/*
|
||||
* a struct vers_ts contains all the information about a file including the
|
||||
* user and rcs file names, and the version checked out and the head.
|
||||
*
|
||||
*
|
||||
* this is usually obtained from a call to Version_TS which takes a tag argument
|
||||
* for the RCS file if desired
|
||||
*/
|
||||
|
|
@ -266,15 +324,16 @@ struct vers_ts
|
|||
{
|
||||
char *vn_user; /* rcs version user file derives from
|
||||
* it can have the following special
|
||||
* values:
|
||||
* empty = no user file
|
||||
* values:
|
||||
* empty = no user file
|
||||
* 0 = user file is new
|
||||
* -vers = user file to be removed */
|
||||
char *vn_rcs; /* the version for the rcs file
|
||||
* (tag version?) */
|
||||
char *vn_tag; /* the symbolic tag name */
|
||||
char *ts_user; /* the timestamp for the user file */
|
||||
char *ts_rcs; /* the user timestamp from entries */
|
||||
char *options; /* opts from Entries file
|
||||
char *options; /* opts from Entries file
|
||||
* (keyword expansion) */
|
||||
char *ts_conflict; /* Holds time_stamp of conflict */
|
||||
char *tag; /* tag stored in the Entries file */
|
||||
|
|
@ -285,7 +344,7 @@ struct vers_ts
|
|||
typedef struct vers_ts Vers_TS;
|
||||
|
||||
/*
|
||||
* structure used for list-private storage by ParseEntries() and
|
||||
* structure used for list-private storage by Entries_Open() and
|
||||
* Version_TS().
|
||||
*/
|
||||
struct stickydirtag
|
||||
|
|
@ -296,15 +355,6 @@ struct stickydirtag
|
|||
char *options;
|
||||
};
|
||||
|
||||
/* flags for run_exec(), the fast system() for CVS */
|
||||
#define RUN_NORMAL 0x0000 /* no special behaviour */
|
||||
#define RUN_COMBINED 0x0001 /* stdout is duped to stderr */
|
||||
#define RUN_REALLY 0x0002 /* do the exec, even if noexec is on */
|
||||
#define RUN_STDOUT_APPEND 0x0004 /* append to stdout, don't truncate */
|
||||
#define RUN_STDERR_APPEND 0x0008 /* append to stderr, don't truncate */
|
||||
#define RUN_SIGIGNORE 0x0010 /* ignore interrupts for command */
|
||||
#define RUN_TTY (char *)0 /* for the benefit of lint */
|
||||
|
||||
/* Flags for find_{names,dirs} routines */
|
||||
#define W_LOCAL 0x01 /* look for files locally */
|
||||
#define W_REPOS 0x02 /* look for files in the repository */
|
||||
|
|
@ -320,7 +370,7 @@ enum direnter_type
|
|||
};
|
||||
typedef enum direnter_type Dtype;
|
||||
|
||||
extern char *program_name, *command_name;
|
||||
extern char *program_name, *program_path, *command_name;
|
||||
extern char *Rcsbin, *Editor, *CVSroot;
|
||||
#ifdef CVSADM_ROOT
|
||||
extern char *CVSADM_Root;
|
||||
|
|
@ -330,17 +380,29 @@ extern char *CurDir;
|
|||
extern int really_quiet, quiet;
|
||||
extern int use_editor;
|
||||
extern int cvswrite;
|
||||
extern mode_t cvsumask;
|
||||
|
||||
extern int trace; /* Show all commands */
|
||||
extern int noexec; /* Don't modify disk anywhere */
|
||||
extern int logoff; /* Don't write history entry */
|
||||
|
||||
extern char hostname[];
|
||||
|
||||
/* Externs that are included directly in the CVS sources */
|
||||
int RCS_settag PROTO((const char *, const char *, const char *));
|
||||
int RCS_deltag PROTO((const char *, const char *, int));
|
||||
int RCS_setbranch PROTO((const char *, const char *));
|
||||
int RCS_lock PROTO((const char *, const char *, int));
|
||||
int RCS_unlock PROTO((const char *, const char *, int));
|
||||
int RCS_merge PROTO((const char *, const char *, const char *, const char *));
|
||||
|
||||
#include "error.h"
|
||||
|
||||
DBM *open_module PROTO((void));
|
||||
FILE *Fopen PROTO((char *name, char *mode));
|
||||
FILE *open_file PROTO((char *name, char *mode));
|
||||
FILE *open_file PROTO((const char *, const char *));
|
||||
List *Find_Dirs PROTO((char *repository, int which));
|
||||
List *ParseEntries PROTO((int aflag));
|
||||
void Entries_Close PROTO((List *entries));
|
||||
List *Entries_Open PROTO((int aflag));
|
||||
char *Make_Date PROTO((char *rawdate));
|
||||
char *Name_Repository PROTO((char *dir, char *update_dir));
|
||||
#ifdef CVSADM_ROOT
|
||||
|
|
@ -354,29 +416,37 @@ char *getcaller PROTO((void));
|
|||
char *time_stamp PROTO((char *file));
|
||||
char *xmalloc PROTO((size_t bytes));
|
||||
char *xrealloc PROTO((char *ptr, size_t bytes));
|
||||
char *xstrdup PROTO((char *str));
|
||||
char *xstrdup PROTO((const char *str));
|
||||
void strip_trailing_newlines PROTO((char *str));
|
||||
int No_Difference PROTO((char *file, Vers_TS * vers, List * entries,
|
||||
char *repository, char *update_dir));
|
||||
int Parse_Info PROTO((char *infofile, char *repository, int PROTO((*callproc)) PROTO(()), int all));
|
||||
typedef int (*CALLPROC) PROTO((char *repository, char *value));
|
||||
int Parse_Info PROTO((char *infofile, char *repository, CALLPROC callproc, int all));
|
||||
int Reader_Lock PROTO((char *xrepository));
|
||||
int SIG_register PROTO((int sig, RETSIGTYPE PROTO((*fn)) PROTO(())));
|
||||
typedef RETSIGTYPE (*SIGCLEANUPPROC) PROTO(());
|
||||
int SIG_register PROTO((int sig, SIGCLEANUPPROC sigcleanup));
|
||||
int Writer_Lock PROTO((List * list));
|
||||
int ign_name PROTO((char *name));
|
||||
int isdir PROTO((char *file));
|
||||
int isfile PROTO((char *file));
|
||||
int islink PROTO((char *file));
|
||||
int isreadable PROTO((char *file));
|
||||
int iswritable PROTO((char *file));
|
||||
int isdir PROTO((const char *file));
|
||||
int isfile PROTO((const char *file));
|
||||
int islink PROTO((const char *file));
|
||||
int isreadable PROTO((const char *file));
|
||||
int iswritable PROTO((const char *file));
|
||||
int isaccessible PROTO((const char *file, const int mode));
|
||||
int isabsolute PROTO((const char *filename));
|
||||
char *last_component PROTO((char *path));
|
||||
|
||||
int joining PROTO((void));
|
||||
int link_file PROTO((char *from, char *to));
|
||||
int numdots PROTO((char *s));
|
||||
int run_exec PROTO((char *stin, char *stout, char *sterr, int flags));
|
||||
int unlink_file PROTO((char *f));
|
||||
int numdots PROTO((const char *s));
|
||||
int unlink_file PROTO((const char *f));
|
||||
int unlink_file_dir PROTO((const char *f));
|
||||
int update PROTO((int argc, char *argv[]));
|
||||
int xcmp PROTO((char *file1, char *file2));
|
||||
int xcmp PROTO((const char *file1, const char *file2));
|
||||
int yesno PROTO((void));
|
||||
void *valloc PROTO((size_t bytes));
|
||||
time_t get_date PROTO((char *date, struct timeb *now));
|
||||
void Create_Admin PROTO((char *dir, char *repository, char *tag, char *date));
|
||||
void Create_Admin PROTO((char *dir, char *update_dir,
|
||||
char *repository, char *tag, char *date));
|
||||
void Lock_Cleanup PROTO((void));
|
||||
void ParseTag PROTO((char **tagp, char **datep));
|
||||
void Scratch_Entry PROTO((List * list, char *fname));
|
||||
|
|
@ -384,8 +454,8 @@ void WriteTag PROTO((char *dir, char *tag, char *date));
|
|||
void cat_module PROTO((int status));
|
||||
void check_entries PROTO((char *dir));
|
||||
void close_module PROTO((DBM * db));
|
||||
void copy_file PROTO((char *from, char *to));
|
||||
void error PROTO((int status, int errnum, char *message,...));
|
||||
void copy_file PROTO((const char *from, const char *to));
|
||||
void (*error_set_cleanup PROTO((void (*) (void)))) PROTO ((void));
|
||||
void fperror PROTO((FILE * fp, int status, int errnum, char *message,...));
|
||||
void free_names PROTO((int *pargc, char *argv[]));
|
||||
void freevers_ts PROTO((Vers_TS ** versp));
|
||||
|
|
@ -395,20 +465,18 @@ void ign_setup PROTO((void));
|
|||
void ign_dir_add PROTO((char *name));
|
||||
int ignore_directory PROTO((char *name));
|
||||
void line2argv PROTO((int *pargc, char *argv[], char *line));
|
||||
void make_directories PROTO((char *name));
|
||||
void make_directory PROTO((char *name));
|
||||
void rename_file PROTO((char *from, char *to));
|
||||
void run_arg PROTO((char *s));
|
||||
void run_args PROTO((char *fmt,...));
|
||||
void run_print PROTO((FILE * fp));
|
||||
void run_setup PROTO((char *fmt,...));
|
||||
void make_directories PROTO((const char *name));
|
||||
void make_directory PROTO((const char *name));
|
||||
void rename_file PROTO((const char *from, const char *to));
|
||||
void strip_path PROTO((char *path));
|
||||
void strip_trailing_slashes PROTO((char *path));
|
||||
void update_delproc PROTO((Node * p));
|
||||
void usage PROTO((char **cpp));
|
||||
void usage PROTO((const char *const *cpp));
|
||||
void xchmod PROTO((char *fname, int writable));
|
||||
int Checkin PROTO((int type, char *file, char *repository, char *rcs, char *rev,
|
||||
char *tag, char *options, char *message, List *entries));
|
||||
char *xgetwd PROTO((void));
|
||||
int Checkin PROTO((int type, char *file, char *update_dir,
|
||||
char *repository, char *rcs, char *rev,
|
||||
char *tag, char *options, char *message, List *entries));
|
||||
Ctype Classify_File PROTO((char *file, char *tag, char *date, char *options,
|
||||
int force_tag_match, int aflag, char *repository,
|
||||
List *entries, List *srcfiles, Vers_TS **versp,
|
||||
|
|
@ -424,11 +492,21 @@ Vers_TS *Version_TS PROTO((char *repository, char *options, char *tag,
|
|||
int set_time, List * entries, List * xfiles));
|
||||
void do_editor PROTO((char *dir, char **messagep,
|
||||
char *repository, List * changes));
|
||||
|
||||
typedef int (*CALLBACKPROC) PROTO((int *pargc, char *argv[], char *where,
|
||||
char *mwhere, char *mfile, int horten, int local_specified,
|
||||
char *omodule, char *msg));
|
||||
typedef int (*FILEPROC) PROTO((char *file, char *update_dir, char *repository,
|
||||
List * entries, List * srcfiles));
|
||||
typedef int (*FILESDONEPROC) PROTO((int err, char *repository, char *update_dir));
|
||||
typedef Dtype (*DIRENTPROC) PROTO((char *dir, char *repos, char *update_dir));
|
||||
typedef int (*DIRLEAVEPROC) PROTO((char *dir, int err, char *update_dir));
|
||||
|
||||
int do_module PROTO((DBM * db, char *mname, enum mtype m_type, char *msg,
|
||||
int PROTO((*callback_proc)) (), char *where, int shorten,
|
||||
int local_specified, int run_module_prog, char *extra_arg));
|
||||
int do_recursion PROTO((int PROTO((*xfileproc)) (), int PROTO((*xfilesdoneproc)) (),
|
||||
Dtype PROTO((*xdirentproc)) (), int PROTO((*xdirleaveproc)) (),
|
||||
CALLBACKPROC callback_proc, char *where, int shorten,
|
||||
int local_specified, int run_module_prog, char *extra_arg));
|
||||
int do_recursion PROTO((FILEPROC xfileproc, FILESDONEPROC xfilesdoneproc,
|
||||
DIRENTPROC xdirentproc, DIRLEAVEPROC xdirleaveproc,
|
||||
Dtype xflags, int xwhich, int xaflag, int xreadlock,
|
||||
int xdosrcs));
|
||||
int do_update PROTO((int argc, char *argv[], char *xoptions, char *xtag,
|
||||
|
|
@ -437,11 +515,56 @@ int do_update PROTO((int argc, char *argv[], char *xoptions, char *xtag,
|
|||
char *xjoin_rev1, char *xjoin_rev2, char *preload_update_dir));
|
||||
void history_write PROTO((int type, char *update_dir, char *revs, char *name,
|
||||
char *repository));
|
||||
int start_recursion PROTO((int PROTO((*fileproc)) (), int PROTO((*filesdoneproc)) (),
|
||||
Dtype PROTO((*direntproc)) (), int PROTO((*dirleaveproc)) (),
|
||||
int start_recursion PROTO((FILEPROC fileproc, FILESDONEPROC filesdoneproc,
|
||||
DIRENTPROC direntproc, DIRLEAVEPROC dirleaveproc,
|
||||
int argc, char *argv[], int local, int which,
|
||||
int aflag, int readlock, char *update_preload,
|
||||
int dosrcs, int wd_is_repos));
|
||||
void SIG_beginCrSect PROTO((void));
|
||||
void SIG_endCrSect PROTO((void));
|
||||
void read_cvsrc PROTO((int *argc, char ***argv));
|
||||
|
||||
char *make_message_rcslegal PROTO((char *message));
|
||||
|
||||
/* flags for run_exec(), the fast system() for CVS */
|
||||
#define RUN_NORMAL 0x0000 /* no special behaviour */
|
||||
#define RUN_COMBINED 0x0001 /* stdout is duped to stderr */
|
||||
#define RUN_REALLY 0x0002 /* do the exec, even if noexec is on */
|
||||
#define RUN_STDOUT_APPEND 0x0004 /* append to stdout, don't truncate */
|
||||
#define RUN_STDERR_APPEND 0x0008 /* append to stderr, don't truncate */
|
||||
#define RUN_SIGIGNORE 0x0010 /* ignore interrupts for command */
|
||||
#define RUN_TTY (char *)0 /* for the benefit of lint */
|
||||
|
||||
void run_arg PROTO((const char *s));
|
||||
void run_print PROTO((FILE * fp));
|
||||
#ifdef HAVE_VPRINTF
|
||||
void run_setup PROTO((const char *fmt,...));
|
||||
void run_args PROTO((const char *fmt,...));
|
||||
#else
|
||||
void run_setup ();
|
||||
void run_args ();
|
||||
#endif
|
||||
int run_exec PROTO((char *stin, char *stout, char *sterr, int flags));
|
||||
|
||||
/* other similar-minded stuff from run.c. */
|
||||
FILE *Popen PROTO((const char *, const char *));
|
||||
int piped_child PROTO((char **, int *, int *));
|
||||
void close_on_exec PROTO((int));
|
||||
int filter_stream_through_program PROTO((int, int, char **, pid_t *));
|
||||
|
||||
pid_t waitpid PROTO((pid_t, int *, int));
|
||||
|
||||
/* Wrappers. */
|
||||
|
||||
typedef enum { WRAP_MERGE, WRAP_COPY } WrapMergeMethod;
|
||||
typedef enum { WRAP_TOCVS, WRAP_FROMCVS, WRAP_CONFLICT } WrapMergeHas;
|
||||
|
||||
void wrap_setup PROTO((void));
|
||||
int wrap_name_has PROTO((const char *name,WrapMergeHas has));
|
||||
char *wrap_tocvs_process_file PROTO((const char *fileName));
|
||||
int wrap_merge_is_copy PROTO((const char *fileName));
|
||||
char *wrap_fromcvs_process_file PROTO((const char *fileName));
|
||||
/* Pathname expansion */
|
||||
char *expand_path PROTO((char *name));
|
||||
void wrap_add_file PROTO((const char *file,int temp));
|
||||
void wrap_add PROTO((char *line,int temp));
|
||||
|
|
|
|||
|
|
@ -10,10 +10,11 @@
|
|||
|
||||
|
||||
#include "cvs.h"
|
||||
#include "getline.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)cvsrc.c 1.9 94/09/30 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)cvsrc.c 1.9 94/09/30 $";
|
||||
USE(rcsid);
|
||||
#endif /* lint */
|
||||
|
||||
/* this file is to be found in the user's home directory */
|
||||
|
|
@ -25,7 +26,6 @@ char cvsrc[] = CVSRC_FILENAME;
|
|||
|
||||
#define GROW 10
|
||||
|
||||
extern char *getenv ();
|
||||
extern char *strtok ();
|
||||
|
||||
void
|
||||
|
|
@ -37,10 +37,13 @@ read_cvsrc (argc, argv)
|
|||
char *homeinit;
|
||||
FILE *cvsrcfile;
|
||||
|
||||
char linebuf [MAXLINELEN];
|
||||
|
||||
char *line;
|
||||
int line_length;
|
||||
size_t line_chars_allocated;
|
||||
|
||||
char *optstart;
|
||||
|
||||
int command_len;
|
||||
int found = 0;
|
||||
|
||||
int i;
|
||||
|
|
@ -73,7 +76,7 @@ read_cvsrc (argc, argv)
|
|||
|
||||
/* if it can't be read, there's no point to continuing */
|
||||
|
||||
if (access (homeinit, R_OK) != 0)
|
||||
if (!isreadable (homeinit))
|
||||
{
|
||||
free (homeinit);
|
||||
return;
|
||||
|
|
@ -81,15 +84,20 @@ read_cvsrc (argc, argv)
|
|||
|
||||
/* now scan the file until we find the line for the command in question */
|
||||
|
||||
line = NULL;
|
||||
line_chars_allocated = 0;
|
||||
command_len = strlen (command_name);
|
||||
cvsrcfile = open_file (homeinit, "r");
|
||||
while (fgets (linebuf, MAXLINELEN, cvsrcfile))
|
||||
while ((line_length = getline (&line, &line_chars_allocated, cvsrcfile))
|
||||
>= 0)
|
||||
{
|
||||
/* skip over comment lines */
|
||||
if (linebuf[0] == '#')
|
||||
if (line[0] == '#')
|
||||
continue;
|
||||
|
||||
/* stop if we match the current command */
|
||||
if (!strncmp (linebuf, (*argv)[0], strlen ((*argv)[0])))
|
||||
if (!strncmp (line, command_name, command_len)
|
||||
&& isspace (*(line + command_len)))
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
|
|
@ -101,8 +109,8 @@ read_cvsrc (argc, argv)
|
|||
if (found)
|
||||
{
|
||||
/* skip over command in the options line */
|
||||
optstart = strtok(linebuf+strlen((*argv)[0]), "\t \n");
|
||||
|
||||
optstart = strtok (line + command_len, "\t \n");
|
||||
|
||||
do
|
||||
{
|
||||
new_argv [new_argc] = xstrdup (optstart);
|
||||
|
|
@ -121,9 +129,12 @@ read_cvsrc (argc, argv)
|
|||
}
|
||||
|
||||
}
|
||||
while (optstart = strtok (NULL, "\t \n"));
|
||||
while ((optstart = strtok (NULL, "\t \n")) != NULL);
|
||||
}
|
||||
|
||||
if (line != NULL)
|
||||
free (line);
|
||||
|
||||
/* now copy the remaining arguments */
|
||||
|
||||
for (i=1; i < *argc; i++)
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)diff.c 1.61 94/10/22 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)diff.c 1.61 94/10/22 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static Dtype diff_dirproc PROTO((char *dir, char *pos_repos, char *update_dir));
|
||||
|
|
@ -33,12 +33,19 @@ static void diff_mark_errors PROTO((int err));
|
|||
static char *diff_rev1, *diff_rev2;
|
||||
static char *diff_date1, *diff_date2;
|
||||
static char *use_rev1, *use_rev2;
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
/* Revision of the user file, if it is unchanged from something in the
|
||||
repository and we want to use that fact. */
|
||||
static char *user_file_rev;
|
||||
#endif
|
||||
|
||||
static char *options;
|
||||
static char opts[PATH_MAX];
|
||||
static int diff_errors;
|
||||
static int empty_files = 0;
|
||||
|
||||
static char *diff_usage[] =
|
||||
static const char *const diff_usage[] =
|
||||
{
|
||||
"Usage: %s %s [-lN] [rcsdiff-options]\n",
|
||||
#ifdef CVS_DIFFDATE
|
||||
|
|
@ -58,7 +65,7 @@ static char *diff_usage[] =
|
|||
int
|
||||
diff (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
char tmp[50];
|
||||
int c, err = 0;
|
||||
|
|
@ -73,6 +80,11 @@ diff (argc, argv)
|
|||
* intercept the -r arguments for doing revision diffs; and -l/-R for a
|
||||
* non-recursive/recursive diff.
|
||||
*/
|
||||
#ifdef SERVER_SUPPORT
|
||||
/* Need to be able to do this command more than once (according to
|
||||
the protocol spec, even if the current client doesn't use it). */
|
||||
opts[0] = '\0';
|
||||
#endif
|
||||
optind = 1;
|
||||
while ((c = getopt (argc, argv,
|
||||
"abcdefhilnpqtuw0123456789BHNQRTC:D:F:I:L:V:k:r:")) != -1)
|
||||
|
|
@ -150,10 +162,63 @@ diff (argc, argv)
|
|||
if (!options)
|
||||
options = xstrdup ("");
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active) {
|
||||
/* We're the client side. Fire up the remote server. */
|
||||
start_server ();
|
||||
|
||||
ign_setup ();
|
||||
|
||||
if (local)
|
||||
send_arg("-l");
|
||||
if (empty_files)
|
||||
send_arg("-N");
|
||||
send_option_string (opts);
|
||||
if (diff_rev1)
|
||||
option_with_arg ("-r", diff_rev1);
|
||||
if (diff_date1)
|
||||
client_senddate (diff_date1);
|
||||
if (diff_rev2)
|
||||
option_with_arg ("-r", diff_rev2);
|
||||
if (diff_date2)
|
||||
client_senddate (diff_date2);
|
||||
|
||||
#if 0
|
||||
/* FIXME: We shouldn't have to send current files to diff two revs, but it
|
||||
doesn't work yet and I haven't debugged it. So send the files --
|
||||
it's slower but it works. gnu@cygnus.com Apr94 */
|
||||
|
||||
/* Idea: often times the changed region of a file is relatively small.
|
||||
It would be cool if the client could just divide the file into 4k
|
||||
blocks or whatever and send hash values for the blocks. Send hash
|
||||
values for blocks aligned with the beginning of the file and the
|
||||
end of the file. Then the server can tell how much of the head and
|
||||
tail of the file is unchanged. Well, hash collisions will screw
|
||||
things up, but MD5 has 128 bits of hash value... */
|
||||
|
||||
/* Send the current files unless diffing two revs from the archive */
|
||||
if (diff_rev2 == NULL && diff_date2 == NULL)
|
||||
send_files (argc, argv, local);
|
||||
else
|
||||
send_file_names (argc, argv);
|
||||
#else
|
||||
send_files (argc, argv, local, 0);
|
||||
#endif
|
||||
|
||||
if (fprintf (to_server, "diff\n") < 0)
|
||||
error (1, errno, "writing to server");
|
||||
err = get_responses_and_close ();
|
||||
free (options);
|
||||
return (err);
|
||||
}
|
||||
#endif
|
||||
|
||||
which = W_LOCAL;
|
||||
if (diff_rev2 != NULL || diff_date2 != NULL)
|
||||
which |= W_REPOS | W_ATTIC;
|
||||
|
||||
wrap_setup ();
|
||||
|
||||
/* start the recursion processor */
|
||||
err = start_recursion (diff_fileproc, diff_filesdoneproc, diff_dirproc,
|
||||
diff_dirleaveproc, argc, argv, local,
|
||||
|
|
@ -185,7 +250,12 @@ diff_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
DIFF_NEITHER
|
||||
} empty_file = DIFF_NEITHER;
|
||||
char tmp[L_tmpnam+1];
|
||||
char *tocvsPath;
|
||||
char fname[PATH_MAX];
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
user_file_rev = 0;
|
||||
#endif
|
||||
vers = Version_TS (repository, (char *) NULL, (char *) NULL, (char *) NULL,
|
||||
file, 1, 0, entries, srcfiles);
|
||||
|
||||
|
|
@ -243,6 +313,15 @@ diff_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
diff_mark_errors (err);
|
||||
return (err);
|
||||
}
|
||||
#ifdef SERVER_SUPPORT
|
||||
else if (!strcmp (vers->ts_user, vers->ts_rcs))
|
||||
{
|
||||
/* The user file matches some revision in the repository
|
||||
Diff against the repository (for remote CVS, we might not
|
||||
have a copy of the user file around). */
|
||||
user_file_rev = vers->vn_user;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -252,6 +331,11 @@ diff_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
return (0);
|
||||
}
|
||||
|
||||
#ifdef DEATH_SUPPORT
|
||||
/* FIXME: Check whether use_rev1 and use_rev2 are dead and deal
|
||||
accordingly. */
|
||||
#endif
|
||||
|
||||
/* Output an "Index:" line for patch to use */
|
||||
(void) fflush (stdout);
|
||||
if (update_dir[0])
|
||||
|
|
@ -260,6 +344,19 @@ diff_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
(void) printf ("Index: %s\n", file);
|
||||
(void) fflush (stdout);
|
||||
|
||||
tocvsPath = wrap_tocvs_process_file(file);
|
||||
if (tocvsPath)
|
||||
{
|
||||
/* Backup the current version of the file to CVS/,,filename */
|
||||
sprintf(fname,"%s/%s%s",CVSADM, CVSPREFIX, file);
|
||||
if (unlink_file_dir (fname) < 0)
|
||||
if (! existence_error (errno))
|
||||
error (1, errno, "cannot remove %s", file);
|
||||
rename_file (file, fname);
|
||||
/* Copy the wrapped file to the current directory then go to work */
|
||||
copy_file (tocvsPath, file);
|
||||
}
|
||||
|
||||
if (empty_file == DIFF_ADDED || empty_file == DIFF_REMOVED)
|
||||
{
|
||||
(void) printf ("===================================================================\nRCS file: %s\n",
|
||||
|
|
@ -320,6 +417,17 @@ diff_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
break;
|
||||
}
|
||||
|
||||
if (tocvsPath)
|
||||
{
|
||||
if (unlink_file_dir (file) < 0)
|
||||
if (! existence_error (errno))
|
||||
error (1, errno, "cannot remove %s", file);
|
||||
|
||||
rename_file (fname,file);
|
||||
if (unlink_file (tocvsPath) < 0)
|
||||
error (1, errno, "cannot remove %s", file);
|
||||
}
|
||||
|
||||
if (empty_file == DIFF_REMOVED)
|
||||
(void) unlink (tmp);
|
||||
|
||||
|
|
@ -342,6 +450,8 @@ diff_mark_errors (err)
|
|||
|
||||
/*
|
||||
* Print a warm fuzzy message when we enter a dir
|
||||
*
|
||||
* Don't try to diff directories that don't exist! -- DW
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static Dtype
|
||||
|
|
@ -351,6 +461,11 @@ diff_dirproc (dir, pos_repos, update_dir)
|
|||
char *update_dir;
|
||||
{
|
||||
/* XXX - check for dirs we don't want to process??? */
|
||||
|
||||
/* YES ... for instance dirs that don't exist!!! -- DW */
|
||||
if (!isdir (dir) )
|
||||
return (R_SKIP_ALL);
|
||||
|
||||
if (!quiet)
|
||||
error (0, 0, "Diffing %s", update_dir);
|
||||
return (R_PROCESS);
|
||||
|
|
@ -414,8 +529,11 @@ diff_file_nodiff (file, repository, entries, srcfiles, vers)
|
|||
diff_date1, file, 1, 0, entries, srcfiles);
|
||||
if (xvers->vn_rcs == NULL)
|
||||
{
|
||||
if (diff_rev1)
|
||||
error (0, 0, "tag %s is not in file %s", diff_rev1, file);
|
||||
/* Don't gripe if it doesn't exist, just ignore! */
|
||||
if (! isfile (file))
|
||||
/* null statement */ ;
|
||||
else if (diff_rev1)
|
||||
error (0, 0, "tag %s is not in file %s", diff_rev1, file);
|
||||
else
|
||||
error (0, 0, "no revision for date %s in file %s",
|
||||
diff_date1, file);
|
||||
|
|
@ -436,7 +554,10 @@ diff_file_nodiff (file, repository, entries, srcfiles, vers)
|
|||
diff_date2, file, 1, 0, entries, srcfiles);
|
||||
if (xvers->vn_rcs == NULL)
|
||||
{
|
||||
if (diff_rev1)
|
||||
/* Don't gripe if it doesn't exist, just ignore! */
|
||||
if (! isfile (file))
|
||||
/* null statement */ ;
|
||||
else if (diff_rev1)
|
||||
error (0, 0, "tag %s is not in file %s", diff_rev2, file);
|
||||
else
|
||||
error (0, 0, "no revision for date %s in file %s",
|
||||
|
|
@ -455,6 +576,24 @@ diff_file_nodiff (file, repository, entries, srcfiles, vers)
|
|||
return (1);
|
||||
}
|
||||
}
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (user_file_rev)
|
||||
{
|
||||
/* drop user_file_rev into first unused use_rev */
|
||||
if (!use_rev1)
|
||||
use_rev1 = xstrdup (user_file_rev);
|
||||
else if (!use_rev2)
|
||||
use_rev2 = xstrdup (user_file_rev);
|
||||
/* and if not, it wasn't needed anyhow */
|
||||
user_file_rev = 0;
|
||||
}
|
||||
|
||||
/* now, see if we really need to do the diff */
|
||||
if (use_rev1 && use_rev2)
|
||||
{
|
||||
return (strcmp (use_rev1, use_rev2) == 0);
|
||||
}
|
||||
#endif /* SERVER_SUPPORT */
|
||||
if (use_rev1 == NULL || strcmp (use_rev1, vers->vn_user) == 0)
|
||||
{
|
||||
if (strcmp (vers->ts_rcs, vers->ts_user) == 0 &&
|
||||
|
|
|
|||
|
|
@ -12,53 +12,81 @@
|
|||
*/
|
||||
|
||||
#include "cvs.h"
|
||||
#include "getline.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)entries.c 1.44 94/10/07 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)entries.c 1.44 94/10/07 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static Node *AddEntryNode PROTO((List * list, char *name, char *version,
|
||||
char *timestamp, char *options, char *tag,
|
||||
char *date, char *conflict));
|
||||
static Node *AddEntryNode PROTO((List * list, Entnode *entnode));
|
||||
|
||||
static Entnode *fgetentent PROTO((FILE *));
|
||||
static int fputentent PROTO((FILE *, Entnode *));
|
||||
|
||||
static FILE *entfile;
|
||||
static char *entfilename; /* for error messages */
|
||||
|
||||
/*
|
||||
* Construct an Entnode
|
||||
*/
|
||||
Entnode *
|
||||
Entnode_Create(user, vn, ts, options, tag, date, ts_conflict)
|
||||
const char *user;
|
||||
const char *vn;
|
||||
const char *ts;
|
||||
const char *options;
|
||||
const char *tag;
|
||||
const char *date;
|
||||
const char *ts_conflict;
|
||||
{
|
||||
Entnode *ent;
|
||||
|
||||
/* Note that timestamp and options must be non-NULL */
|
||||
ent = (Entnode *) xmalloc (sizeof (Entnode));
|
||||
ent->user = xstrdup (user);
|
||||
ent->version = xstrdup (vn);
|
||||
ent->timestamp = xstrdup (ts ? ts : "");
|
||||
ent->options = xstrdup (options ? options : "");
|
||||
ent->tag = xstrdup (tag);
|
||||
ent->date = xstrdup (date);
|
||||
ent->conflict = xstrdup (ts_conflict);
|
||||
|
||||
return ent;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destruct an Entnode
|
||||
*/
|
||||
void
|
||||
Entnode_Destroy (ent)
|
||||
Entnode *ent;
|
||||
{
|
||||
free (ent->user);
|
||||
free (ent->version);
|
||||
free (ent->timestamp);
|
||||
free (ent->options);
|
||||
if (ent->tag)
|
||||
free (ent->tag);
|
||||
if (ent->date)
|
||||
free (ent->date);
|
||||
if (ent->conflict)
|
||||
free (ent->conflict);
|
||||
free (ent);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out the line associated with a node of an entries file
|
||||
*/
|
||||
static int write_ent_proc PROTO ((Node *, void *));
|
||||
static int
|
||||
write_ent_proc (node, closure)
|
||||
Node *node;
|
||||
void *closure;
|
||||
{
|
||||
Entnode *p;
|
||||
|
||||
p = (Entnode *) node->data;
|
||||
if (fprintf (entfile, "/%s/%s/%s", node->key, p->version,
|
||||
p->timestamp) == EOF)
|
||||
error (1, errno, "cannot write %s", entfilename);
|
||||
if (p->conflict)
|
||||
{
|
||||
if (fprintf (entfile, "+%s", p->conflict) == EOF)
|
||||
error (1, errno, "cannot write %s", entfilename);
|
||||
}
|
||||
if (fprintf (entfile, "/%s/", p->options) == EOF)
|
||||
if (fputentent(entfile, (Entnode *) node->data))
|
||||
error (1, errno, "cannot write %s", entfilename);
|
||||
|
||||
if (p->tag)
|
||||
{
|
||||
if (fprintf (entfile, "T%s\n", p->tag) == EOF)
|
||||
error (1, errno, "cannot write %s", entfilename);
|
||||
}
|
||||
else if (p->date)
|
||||
{
|
||||
if (fprintf (entfile, "D%s\n", p->date) == EOF)
|
||||
error (1, errno, "cannot write %s", entfilename);
|
||||
}
|
||||
else if (fprintf (entfile, "\n") == EOF)
|
||||
error (1, errno, "cannot write %s", entfilename);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
@ -79,6 +107,9 @@ write_entries (list)
|
|||
|
||||
/* now, atomically (on systems that support it) rename it */
|
||||
rename_file (entfilename, CVSADM_ENT);
|
||||
|
||||
/* now, remove the log file */
|
||||
unlink_file (CVSADM_ENTLOG);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -92,12 +123,21 @@ Scratch_Entry (list, fname)
|
|||
Node *node;
|
||||
|
||||
if (trace)
|
||||
#ifdef SERVER_SUPPORT
|
||||
(void) fprintf (stderr, "%c-> Scratch_Entry(%s)\n",
|
||||
(server_active) ? 'S' : ' ', fname);
|
||||
#else
|
||||
(void) fprintf (stderr, "-> Scratch_Entry(%s)\n", fname);
|
||||
#endif
|
||||
|
||||
/* hashlookup to see if it is there */
|
||||
if ((node = findnode (list, fname)) != NULL)
|
||||
{
|
||||
delnode (node); /* delete the node */
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
server_scratch (fname);
|
||||
#endif
|
||||
if (!noexec)
|
||||
write_entries (list); /* re-write the file */
|
||||
}
|
||||
|
|
@ -118,45 +158,43 @@ Register (list, fname, vn, ts, options, tag, date, ts_conflict)
|
|||
char *date;
|
||||
char *ts_conflict;
|
||||
{
|
||||
int should_write_file = !noexec;
|
||||
Entnode *entnode;
|
||||
Node *node;
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
{
|
||||
server_register (fname, vn, ts, options, tag, date, ts_conflict);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (trace)
|
||||
{
|
||||
(void) fprintf (stderr, "-> Register(%s, %s, %s%s%s, %s, %s %s)\n",
|
||||
fname, vn, ts,
|
||||
#ifdef SERVER_SUPPORT
|
||||
(void) fprintf (stderr, "%c-> Register(%s, %s, %s%s%s, %s, %s %s)\n",
|
||||
(server_active) ? 'S' : ' ',
|
||||
fname, vn, ts ? ts : "",
|
||||
ts_conflict ? "+" : "", ts_conflict ? ts_conflict : "",
|
||||
options, tag ? tag : "", date ? date : "");
|
||||
options, tag ? tag : "", date ? date : "");
|
||||
#else
|
||||
(void) fprintf (stderr, "-> Register(%s, %s, %s%s%s, %s, %s %s)\n",
|
||||
fname, vn, ts ? ts : "",
|
||||
ts_conflict ? "+" : "", ts_conflict ? ts_conflict : "",
|
||||
options, tag ? tag : "", date ? date : "");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* was it already there? */
|
||||
if ((node = findnode (list, fname)) != NULL)
|
||||
entnode = Entnode_Create(fname, vn, ts, options, tag, date, ts_conflict);
|
||||
node = AddEntryNode (list, entnode);
|
||||
|
||||
if (!noexec)
|
||||
{
|
||||
/* take it out */
|
||||
delnode (node);
|
||||
entfile = open_file (CVSADM_ENTLOG, "a");
|
||||
|
||||
write_ent_proc (node, NULL);
|
||||
|
||||
/* add the new one and re-write the file */
|
||||
(void) AddEntryNode (list, fname, vn, ts, options, tag,
|
||||
date, ts_conflict);
|
||||
|
||||
if (should_write_file)
|
||||
write_entries (list);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* add the new one */
|
||||
node = AddEntryNode (list, fname, vn, ts, options, tag,
|
||||
date, ts_conflict);
|
||||
|
||||
if (should_write_file)
|
||||
{
|
||||
/* append it to the end */
|
||||
entfilename = CVSADM_ENT;
|
||||
entfile = open_file (entfilename, "a");
|
||||
(void) write_ent_proc (node, NULL);
|
||||
if (fclose (entfile) == EOF)
|
||||
error (1, errno, "error closing %s", entfilename);
|
||||
}
|
||||
if (fclose (entfile) == EOF)
|
||||
error (1, errno, "error closing %s", CVSADM_ENTLOG);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -179,24 +217,138 @@ freesdt (p)
|
|||
free ((char *) sdtp);
|
||||
}
|
||||
|
||||
static Entnode *
|
||||
fgetentent(fpin)
|
||||
FILE *fpin;
|
||||
{
|
||||
Entnode *ent;
|
||||
char *line;
|
||||
size_t line_chars_allocated;
|
||||
register char *cp;
|
||||
char *user, *vn, *ts, *options;
|
||||
char *tag_or_date, *tag, *date, *ts_conflict;
|
||||
|
||||
line = NULL;
|
||||
line_chars_allocated = 0;
|
||||
|
||||
ent = NULL;
|
||||
while (getline (&line, &line_chars_allocated, fpin) > 0)
|
||||
{
|
||||
if (line[0] != '/')
|
||||
continue;
|
||||
|
||||
user = line + 1;
|
||||
if ((cp = strchr (user, '/')) == NULL)
|
||||
continue;
|
||||
*cp++ = '\0';
|
||||
vn = cp;
|
||||
if ((cp = strchr (vn, '/')) == NULL)
|
||||
continue;
|
||||
*cp++ = '\0';
|
||||
ts = cp;
|
||||
if ((cp = strchr (ts, '/')) == NULL)
|
||||
continue;
|
||||
*cp++ = '\0';
|
||||
options = cp;
|
||||
if ((cp = strchr (options, '/')) == NULL)
|
||||
continue;
|
||||
*cp++ = '\0';
|
||||
tag_or_date = cp;
|
||||
if ((cp = strchr (tag_or_date, '\n')) == NULL)
|
||||
continue;
|
||||
*cp = '\0';
|
||||
tag = (char *) NULL;
|
||||
date = (char *) NULL;
|
||||
if (*tag_or_date == 'T')
|
||||
tag = tag_or_date + 1;
|
||||
else if (*tag_or_date == 'D')
|
||||
date = tag_or_date + 1;
|
||||
|
||||
if ((ts_conflict = strchr (ts, '+')))
|
||||
*ts_conflict++ = '\0';
|
||||
|
||||
/*
|
||||
* XXX - Convert timestamp from old format to new format.
|
||||
*
|
||||
* If the timestamp doesn't match the file's current
|
||||
* mtime, we'd have to generate a string that doesn't
|
||||
* match anyways, so cheat and base it on the existing
|
||||
* string; it doesn't have to match the same mod time.
|
||||
*
|
||||
* For an unmodified file, write the correct timestamp.
|
||||
*/
|
||||
{
|
||||
struct stat sb;
|
||||
if (strlen (ts) > 30 && stat (user, &sb) == 0)
|
||||
{
|
||||
char *c = ctime (&sb.st_mtime);
|
||||
|
||||
if (!strncmp (ts + 25, c, 24))
|
||||
ts = time_stamp (user);
|
||||
else
|
||||
{
|
||||
ts += 24;
|
||||
ts[0] = '*';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ent = Entnode_Create(user, vn, ts, options, tag, date, ts_conflict);
|
||||
break;
|
||||
}
|
||||
|
||||
free (line);
|
||||
return ent;
|
||||
}
|
||||
|
||||
static int
|
||||
fputentent(fp, p)
|
||||
FILE *fp;
|
||||
Entnode *p;
|
||||
{
|
||||
if (fprintf (fp, "/%s/%s/%s", p->user, p->version, p->timestamp) < 0)
|
||||
return 1;
|
||||
if (p->conflict)
|
||||
{
|
||||
if (fprintf (fp, "+%s", p->conflict) < 0)
|
||||
return 1;
|
||||
}
|
||||
if (fprintf (fp, "/%s/", p->options) < 0)
|
||||
return 1;
|
||||
|
||||
if (p->tag)
|
||||
{
|
||||
if (fprintf (fp, "T%s\n", p->tag) < 0)
|
||||
return 1;
|
||||
}
|
||||
else if (p->date)
|
||||
{
|
||||
if (fprintf (fp, "D%s\n", p->date) < 0)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fprintf (fp, "\n") < 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the entries file into a list, hashing on the file name.
|
||||
*/
|
||||
List *
|
||||
ParseEntries (aflag)
|
||||
Entries_Open (aflag)
|
||||
int aflag;
|
||||
{
|
||||
List *entries;
|
||||
char line[MAXLINELEN];
|
||||
char *cp, *user, *vn, *ts, *options;
|
||||
char *tag_or_date, *tag, *date, *ts_conflict;
|
||||
Entnode *ent;
|
||||
char *dirtag, *dirdate;
|
||||
int lineno = 0;
|
||||
int do_rewrite = 0;
|
||||
FILE *fpin;
|
||||
|
||||
vn = ts = options = tag = date = ts_conflict = 0;
|
||||
|
||||
/* get a fresh list... */
|
||||
entries = getlist ();
|
||||
|
||||
|
|
@ -220,89 +372,28 @@ ParseEntries (aflag)
|
|||
entries->list->delproc = freesdt;
|
||||
}
|
||||
|
||||
again:
|
||||
fpin = fopen (CVSADM_ENT, "r");
|
||||
if (fpin == NULL)
|
||||
error (0, errno, "cannot open %s for reading", CVSADM_ENT);
|
||||
else
|
||||
{
|
||||
while (fgets (line, sizeof (line), fpin) != NULL)
|
||||
while ((ent = fgetentent (fpin)) != NULL)
|
||||
{
|
||||
lineno++;
|
||||
if (line[0] == '/')
|
||||
{
|
||||
user = line + 1;
|
||||
if ((cp = strchr (user, '/')) == NULL)
|
||||
continue;
|
||||
*cp++ = '\0';
|
||||
vn = cp;
|
||||
if ((cp = strchr (vn, '/')) == NULL)
|
||||
continue;
|
||||
*cp++ = '\0';
|
||||
ts = cp;
|
||||
if ((cp = strchr (ts, '/')) == NULL)
|
||||
continue;
|
||||
*cp++ = '\0';
|
||||
options = cp;
|
||||
if ((cp = strchr (options, '/')) == NULL)
|
||||
continue;
|
||||
*cp++ = '\0';
|
||||
tag_or_date = cp;
|
||||
if ((cp = strchr (tag_or_date, '\n')) == NULL)
|
||||
continue;
|
||||
*cp = '\0';
|
||||
tag = (char *) NULL;
|
||||
date = (char *) NULL;
|
||||
if (*tag_or_date == 'T')
|
||||
tag = tag_or_date + 1;
|
||||
else if (*tag_or_date == 'D')
|
||||
date = tag_or_date + 1;
|
||||
|
||||
if (ts_conflict = strchr (ts, '+'))
|
||||
*ts_conflict++ = '\0';
|
||||
|
||||
/*
|
||||
* XXX - Convert timestamp from old format to new format.
|
||||
*
|
||||
* If the timestamp doesn't match the file's current
|
||||
* mtime, we'd have to generate a string that doesn't
|
||||
* match anyways, so cheat and base it on the existing
|
||||
* string; it doesn't have to match the same mod time.
|
||||
*
|
||||
* For an unmodified file, write the correct timestamp.
|
||||
*/
|
||||
{
|
||||
struct stat sb;
|
||||
if (strlen (ts) > 30 && stat (user, &sb) == 0)
|
||||
{
|
||||
extern char *ctime ();
|
||||
char *c = ctime (&sb.st_mtime);
|
||||
|
||||
if (!strncmp (ts + 25, c, 24))
|
||||
ts = time_stamp (user);
|
||||
else
|
||||
{
|
||||
ts += 24;
|
||||
ts[0] = '*';
|
||||
}
|
||||
do_rewrite = 1;
|
||||
}
|
||||
}
|
||||
|
||||
(void) AddEntryNode (entries, user, vn, ts, options, tag,
|
||||
date, ts_conflict);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* try conversion only on first line */
|
||||
if (lineno == 1)
|
||||
{
|
||||
(void) fclose (fpin);
|
||||
check_entries ((char *) NULL);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
(void) AddEntryNode (entries, ent);
|
||||
}
|
||||
|
||||
fclose (fpin);
|
||||
}
|
||||
|
||||
fpin = fopen (CVSADM_ENTLOG, "r");
|
||||
if (fpin != NULL)
|
||||
{
|
||||
while ((ent = fgetentent (fpin)) != NULL)
|
||||
{
|
||||
(void) AddEntryNode (entries, ent);
|
||||
}
|
||||
do_rewrite = 1;
|
||||
fclose (fpin);
|
||||
}
|
||||
|
||||
if (do_rewrite && !noexec)
|
||||
|
|
@ -318,92 +409,22 @@ ParseEntries (aflag)
|
|||
return (entries);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look at the entries file to determine if it is in the old entries format.
|
||||
* If so, convert it to the new format.
|
||||
*/
|
||||
void
|
||||
check_entries (dir)
|
||||
char *dir;
|
||||
Entries_Close(list)
|
||||
List *list;
|
||||
{
|
||||
FILE *fpin, *fpout;
|
||||
char tmp[MAXLINELEN];
|
||||
char line[MAXLINELEN];
|
||||
char entname[MAXLINELEN];
|
||||
char entbak[MAXLINELEN];
|
||||
char *cp, *user, *rev, *ts, *opt;
|
||||
|
||||
if (dir != NULL)
|
||||
if (list)
|
||||
{
|
||||
(void) sprintf (entname, "%s/%s", dir, CVSADM_ENT);
|
||||
(void) sprintf (entbak, "%s/%s", dir, CVSADM_ENTBAK);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void) strcpy (entname, CVSADM_ENT);
|
||||
(void) strcpy (entbak, CVSADM_ENTBAK);
|
||||
}
|
||||
|
||||
fpin = open_file (entname, "r");
|
||||
if (fgets (line, sizeof (line), fpin) == NULL)
|
||||
{
|
||||
(void) fclose (fpin);
|
||||
return;
|
||||
}
|
||||
(void) fclose (fpin);
|
||||
if (line[0] != '/')
|
||||
{
|
||||
rename_file (entname, entbak);
|
||||
fpin = open_file (entbak, "r");
|
||||
fpout = open_file (entname, "w+");
|
||||
while (fgets (line, sizeof (line), fpin) != NULL)
|
||||
{
|
||||
if (line[0] == '/')
|
||||
{
|
||||
if (fputs (line, fpout) == EOF)
|
||||
error (1, errno, "cannot write %s", CVSADM_ENT);
|
||||
continue;
|
||||
}
|
||||
rev = line;
|
||||
if ((ts = strchr (line, '|')) == NULL)
|
||||
continue;
|
||||
*ts++ = '\0';
|
||||
if ((user = strrchr (ts, ' ')) == NULL)
|
||||
continue;
|
||||
*user++ = '\0';
|
||||
if ((cp = strchr (user, '|')) == NULL)
|
||||
continue;
|
||||
*cp = '\0';
|
||||
opt = "";
|
||||
#ifdef HAVE_RCS5
|
||||
#ifdef HAD_RCS4
|
||||
opt = "-V4";
|
||||
#endif
|
||||
#endif
|
||||
if (fprintf (fpout, "/%s/%s/%s/%s/\n", user, rev, ts, opt) == EOF)
|
||||
error (1, errno, "cannot write %s", CVSADM_ENT);
|
||||
if (!noexec)
|
||||
{
|
||||
if (isfile (CVSADM_ENTLOG))
|
||||
write_entries (list);
|
||||
}
|
||||
(void) fclose (fpin);
|
||||
if (fclose (fpout) == EOF)
|
||||
error (1, errno, "cannot close %s", entname);
|
||||
|
||||
/* clean up any old Files or Mod files */
|
||||
if (dir != NULL)
|
||||
(void) sprintf (tmp, "%s/%s", dir, CVSADM_FILE);
|
||||
else
|
||||
(void) strcpy (tmp, CVSADM_FILE);
|
||||
if (isfile (tmp))
|
||||
(void) unlink (tmp);
|
||||
|
||||
if (dir != NULL)
|
||||
(void) sprintf (tmp, "%s/%s", dir, CVSADM_MOD);
|
||||
else
|
||||
(void) strcpy (tmp, CVSADM_MOD);
|
||||
if (isfile (tmp))
|
||||
(void) unlink (tmp);
|
||||
dellist(&list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Free up the memory associated with the data section of an ENTRIES type
|
||||
* node
|
||||
|
|
@ -415,16 +436,7 @@ Entries_delproc (node)
|
|||
Entnode *p;
|
||||
|
||||
p = (Entnode *) node->data;
|
||||
free (p->version);
|
||||
free (p->timestamp);
|
||||
free (p->options);
|
||||
if (p->tag)
|
||||
free (p->tag);
|
||||
if (p->date)
|
||||
free (p->date);
|
||||
if (p->conflict)
|
||||
free (p->conflict);
|
||||
free ((char *) p);
|
||||
Entnode_Destroy(p);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -432,18 +444,18 @@ Entries_delproc (node)
|
|||
* list
|
||||
*/
|
||||
static Node *
|
||||
AddEntryNode (list, name, version, timestamp, options, tag, date, conflict)
|
||||
AddEntryNode (list, entdata)
|
||||
List *list;
|
||||
char *name;
|
||||
char *version;
|
||||
char *timestamp;
|
||||
char *options;
|
||||
char *tag;
|
||||
char *date;
|
||||
char *conflict;
|
||||
Entnode *entdata;
|
||||
{
|
||||
Node *p;
|
||||
Entnode *entdata;
|
||||
|
||||
/* was it already there? */
|
||||
if ((p = findnode (list, entdata->user)) != NULL)
|
||||
{
|
||||
/* take it out */
|
||||
delnode (p);
|
||||
}
|
||||
|
||||
/* get a node and fill in the regular stuff */
|
||||
p = getnode ();
|
||||
|
|
@ -451,25 +463,14 @@ AddEntryNode (list, name, version, timestamp, options, tag, date, conflict)
|
|||
p->delproc = Entries_delproc;
|
||||
|
||||
/* this one gets a key of the name for hashing */
|
||||
p->key = xstrdup (name);
|
||||
|
||||
/* malloc the data parts and fill them in */
|
||||
p->data = xmalloc (sizeof (Entnode));
|
||||
entdata = (Entnode *) p->data;
|
||||
entdata->version = xstrdup (version);
|
||||
entdata->timestamp = xstrdup (timestamp);
|
||||
entdata->options = xstrdup (options);
|
||||
if (entdata->options == NULL)
|
||||
entdata->options = xstrdup ("");/* must be non-NULL */
|
||||
entdata->conflict = xstrdup (conflict);
|
||||
entdata->tag = xstrdup (tag);
|
||||
entdata->date = xstrdup (date);
|
||||
/* FIXME This results in duplicated data --- the hash package shouldn't
|
||||
assume that the key is dynamically allocated. The user's free proc
|
||||
should be responsible for freeing the key. */
|
||||
p->key = xstrdup (entdata->user);
|
||||
p->data = (char *) entdata;
|
||||
|
||||
/* put the node into the list */
|
||||
if (addnode (list, p) != 0)
|
||||
error (0, 0, "Duplicate filename in entries file (%s) -- ignored",
|
||||
name);
|
||||
|
||||
addnode (list, p);
|
||||
return (p);
|
||||
}
|
||||
|
||||
|
|
@ -498,19 +499,19 @@ WriteTag (dir, tag, date)
|
|||
fout = open_file (tmp, "w+");
|
||||
if (tag)
|
||||
{
|
||||
if (fprintf (fout, "T%s\n", tag) == EOF)
|
||||
if (fprintf (fout, "T%s\n", tag) < 0)
|
||||
error (1, errno, "write to %s failed", tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fprintf (fout, "D%s\n", date) == EOF)
|
||||
if (fprintf (fout, "D%s\n", date) < 0)
|
||||
error (1, errno, "write to %s failed", tmp);
|
||||
}
|
||||
if (fclose (fout) == EOF)
|
||||
error (1, errno, "cannot close %s", tmp);
|
||||
}
|
||||
else
|
||||
if (unlink_file (tmp) < 0 && errno != ENOENT)
|
||||
if (unlink_file (tmp) < 0 && ! existence_error (errno))
|
||||
error (1, errno, "cannot remove %s", tmp);
|
||||
}
|
||||
|
||||
|
|
@ -523,8 +524,6 @@ ParseTag (tagp, datep)
|
|||
char **datep;
|
||||
{
|
||||
FILE *fp;
|
||||
char line[MAXLINELEN];
|
||||
char *cp;
|
||||
|
||||
if (tagp)
|
||||
*tagp = (char *) NULL;
|
||||
|
|
@ -533,15 +532,24 @@ ParseTag (tagp, datep)
|
|||
fp = fopen (CVSADM_TAG, "r");
|
||||
if (fp)
|
||||
{
|
||||
if (fgets (line, sizeof (line), fp) != NULL)
|
||||
char *line;
|
||||
int line_length;
|
||||
size_t line_chars_allocated;
|
||||
|
||||
line = NULL;
|
||||
line_chars_allocated = 0;
|
||||
|
||||
if ((line_length = getline (&line, &line_chars_allocated, fp)) > 0)
|
||||
{
|
||||
if ((cp = strrchr (line, '\n')) != NULL)
|
||||
*cp = '\0';
|
||||
/* Remove any trailing newline. */
|
||||
if (line[line_length - 1] == '\n')
|
||||
line[--line_length] = '\0';
|
||||
if (*line == 'T' && tagp)
|
||||
*tagp = xstrdup (line + 1);
|
||||
else if (*line == 'D' && datep)
|
||||
*datep = xstrdup (line + 1);
|
||||
}
|
||||
(void) fclose (fp);
|
||||
free (line);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)find_names.c 1.45 94/10/22 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)find_names.c 1.45 94/10/22 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static int find_dirs PROTO((char *dir, List * list, int checkadm));
|
||||
|
|
@ -31,6 +31,7 @@ static List *filelist;
|
|||
/*
|
||||
* add the key from entry on entries list to the files list
|
||||
*/
|
||||
static int add_entries_proc PROTO((Node *, void *));
|
||||
static int
|
||||
add_entries_proc (node, closure)
|
||||
Node *node;
|
||||
|
|
@ -49,9 +50,11 @@ add_entries_proc (node, closure)
|
|||
/*
|
||||
* compare two files list node (for sort)
|
||||
*/
|
||||
static int fsortcmp PROTO ((const Node *, const Node *));
|
||||
static int
|
||||
fsortcmp (p, q)
|
||||
Node *p, *q;
|
||||
const Node *p;
|
||||
const Node *q;
|
||||
{
|
||||
return (strcmp (p->key, q->key));
|
||||
}
|
||||
|
|
@ -74,8 +77,7 @@ Find_Names (repository, which, aflag, optentries)
|
|||
if (which & W_LOCAL)
|
||||
{
|
||||
/* parse the entries file (if it exists) */
|
||||
entries = ParseEntries (aflag);
|
||||
|
||||
entries = Entries_Open (aflag);
|
||||
if (entries != NULL)
|
||||
{
|
||||
/* walk the entries file adding elements to the files list */
|
||||
|
|
@ -85,7 +87,7 @@ Find_Names (repository, which, aflag, optentries)
|
|||
if (optentries != NULL)
|
||||
*optentries = entries;
|
||||
else
|
||||
dellist (&entries);
|
||||
Entries_Close (entries);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -258,12 +260,7 @@ find_dirs (dir, list, checkadm)
|
|||
/* check for new style */
|
||||
(void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, CVSADM);
|
||||
if (!isdir (tmp))
|
||||
{
|
||||
/* and old style */
|
||||
(void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, OCVSADM);
|
||||
if (!isdir (tmp))
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* put it in the list */
|
||||
|
|
|
|||
|
|
@ -179,8 +179,8 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)history.c 1.33 94/09/21 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)history.c 1.33 94/09/21 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static struct hrec
|
||||
|
|
@ -201,7 +201,7 @@ static struct hrec
|
|||
static char *fill_hrec PROTO((char *line, struct hrec * hr));
|
||||
static int accept_hrec PROTO((struct hrec * hr, struct hrec * lr));
|
||||
static int select_hrec PROTO((struct hrec * hr));
|
||||
static int sort_order PROTO((CONST PTR l, CONST PTR r));
|
||||
static int sort_order PROTO((const PTR l, const PTR r));
|
||||
static int within PROTO((char *find, char *string));
|
||||
static time_t date_and_time PROTO((char *date_str));
|
||||
static void expand_modules PROTO((void));
|
||||
|
|
@ -268,11 +268,9 @@ static char **mod_list; /* Ptr to array of ptrs to module names */
|
|||
static int mod_max; /* Number of elements allocated */
|
||||
static int mod_count; /* Number of elements used */
|
||||
|
||||
static int histsize;
|
||||
static char *histdata;
|
||||
static char *histfile; /* Ptr to the history file name */
|
||||
|
||||
static char *history_usg[] =
|
||||
static const char *const history_usg[] =
|
||||
{
|
||||
"Usage: %s %s [-report] [-flags] [-options args] [files...]\n\n",
|
||||
" Reports:\n",
|
||||
|
|
@ -307,12 +305,12 @@ static char *history_usg[] =
|
|||
*/
|
||||
static int
|
||||
sort_order (l, r)
|
||||
CONST PTR l;
|
||||
CONST PTR r;
|
||||
const PTR l;
|
||||
const PTR r;
|
||||
{
|
||||
int i;
|
||||
CONST struct hrec *left = (CONST struct hrec *) l;
|
||||
CONST struct hrec *right = (CONST struct hrec *) r;
|
||||
const struct hrec *left = (const struct hrec *) l;
|
||||
const struct hrec *right = (const struct hrec *) r;
|
||||
|
||||
if (user_sort) /* If Sort by username, compare users */
|
||||
{
|
||||
|
|
@ -531,6 +529,62 @@ history (argc, argv)
|
|||
else if (report_count > 1)
|
||||
error (1, 0, "Only one report type allowed from: \"-Tcomx\".");
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active)
|
||||
{
|
||||
struct file_list_str *f1;
|
||||
char **mod;
|
||||
|
||||
/* We're the client side. Fire up the remote server. */
|
||||
start_server ();
|
||||
|
||||
ign_setup ();
|
||||
|
||||
if (tag_report)
|
||||
send_arg("-T");
|
||||
if (all_users)
|
||||
send_arg("-a");
|
||||
if (modified)
|
||||
send_arg("-c");
|
||||
if (last_entry)
|
||||
send_arg("-l");
|
||||
if (v_checkout)
|
||||
send_arg("-o");
|
||||
if (working)
|
||||
send_arg("-w");
|
||||
if (histfile)
|
||||
send_arg("-X");
|
||||
if (since_date)
|
||||
option_with_arg ("-D", asctime (gmtime (&since_date)));
|
||||
if (backto[0] != '\0')
|
||||
option_with_arg ("-b", backto);
|
||||
for (f1 = file_list; f1 < &file_list[file_count]; ++f1)
|
||||
{
|
||||
if (f1->l_file[0] == '*')
|
||||
option_with_arg ("-p", f1->l_file + 1);
|
||||
else
|
||||
option_with_arg ("-f", f1->l_file);
|
||||
}
|
||||
if (module_report)
|
||||
send_arg("-m");
|
||||
for (mod = mod_list; mod < &mod_list[mod_count]; ++mod)
|
||||
option_with_arg ("-n", *mod);
|
||||
if (since_rev != NULL)
|
||||
option_with_arg ("-r", since_rev);
|
||||
if (since_tag != NULL)
|
||||
option_with_arg ("-t", since_tag);
|
||||
for (mod = user_list; mod < &user_list[user_count]; ++mod)
|
||||
option_with_arg ("-u", *mod);
|
||||
if (extract)
|
||||
option_with_arg ("-x", rec_types);
|
||||
option_with_arg ("-z", tz_name);
|
||||
|
||||
if (fprintf (to_server, "history\n") < 0)
|
||||
error (1, errno, "writing to server");
|
||||
return get_responses_and_close ();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (all_users)
|
||||
save_user ("");
|
||||
|
||||
|
|
@ -621,7 +675,8 @@ history_write (type, update_dir, revs, name, repository)
|
|||
{
|
||||
char fname[PATH_MAX], workdir[PATH_MAX], homedir[PATH_MAX];
|
||||
static char username[20]; /* !!! Should be global */
|
||||
FILE *fp;
|
||||
int fd;
|
||||
char *line;
|
||||
char *slash = "", *cp, *cp2, *repos;
|
||||
int i;
|
||||
static char *tilde = "";
|
||||
|
|
@ -638,8 +693,17 @@ history_write (type, update_dir, revs, name, repository)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!(fp = Fopen (fname, "a"))) /* Some directory not there! */
|
||||
if (trace)
|
||||
#ifdef SERVER_SUPPORT
|
||||
fprintf (stderr, "%c-> fopen(%s,a)\n",
|
||||
(server_active) ? 'S' : ' ', fname);
|
||||
#else
|
||||
fprintf (stderr, "-> fopen(%s,a)\n", fname);
|
||||
#endif
|
||||
if (noexec)
|
||||
return;
|
||||
if ((fd = open (fname, O_WRONLY | O_APPEND | O_CREAT, 0666)) < 0)
|
||||
error (1, errno, "cannot open history file: %s", fname);
|
||||
|
||||
repos = Short_Repository (repository);
|
||||
|
||||
|
|
@ -747,10 +811,23 @@ history_write (type, update_dir, revs, name, repository)
|
|||
(void) sprintf ((cp + 1), "*%x", i);
|
||||
}
|
||||
|
||||
if (fprintf (fp, "%c%08x|%s|%s|%s|%s|%s\n", type, time ((time_t *) NULL),
|
||||
username, workdir, repos, revs ? revs : "", name) == EOF)
|
||||
if (!revs)
|
||||
revs = "";
|
||||
line = xmalloc (strlen (username) + strlen (workdir) + strlen (repos)
|
||||
+ strlen (revs) + strlen (name) + 100);
|
||||
sprintf (line, "%c%08lx|%s|%s|%s|%s|%s\n",
|
||||
type, (long) time ((time_t *) NULL),
|
||||
username, workdir, repos, revs, name);
|
||||
|
||||
/* Lessen some race conditions on non-Posix-compliant hosts. */
|
||||
if (lseek (fd, (off_t) 0, SEEK_END) == -1)
|
||||
error (1, errno, "cannot seek to end of history file: %s", fname);
|
||||
|
||||
if (write (fd, line, strlen (line)) < 0)
|
||||
error (1, errno, "cannot write to history file: %s", fname);
|
||||
(void) fclose (fp);
|
||||
free (line);
|
||||
if (close (fd) != 0)
|
||||
error (1, errno, "cannot close history file: %s", fname);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -931,8 +1008,7 @@ read_hrecs (fname)
|
|||
/* Exactly enough space for lines data */
|
||||
if (!(i = st_buf.st_size))
|
||||
error (1, 0, "history file is empty");
|
||||
histdata = cp = xmalloc (i + 2);
|
||||
histsize = i;
|
||||
cp = xmalloc (i + 2);
|
||||
|
||||
if (read (fd, cp, i) != i)
|
||||
error (1, errno, "cannot read log file");
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)ignore.c 1.16 94/09/24 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)ignore.c 1.16 94/09/24 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -27,7 +27,7 @@ static int ign_size; /* This many slots available (plus
|
|||
static int ign_hold; /* Index where first "temporary" item
|
||||
* is held */
|
||||
|
||||
char *ign_default = ". .. core RCSLOG tags TAGS RCS SCCS .make.state .nse_depinfo #* .#* cvslog.* ,* CVS* .del-* *.a *.o *.so *.Z *~ *.old *.elc *.ln *.bak *.BAK *.orig *.rej";
|
||||
const char *ign_default = ". .. core RCSLOG tags TAGS RCS SCCS .make.state .nse_depinfo #* .#* cvslog.* ,* CVS* .del-* *.a *.o *.so *.Z *~ *.old *.elc *.ln *.bak *.BAK *.orig *.rej";
|
||||
|
||||
#define IGN_GROW 16 /* grow the list by 16 elements at a
|
||||
* time */
|
||||
|
|
@ -41,7 +41,6 @@ char *ign_default = ". .. core RCSLOG tags TAGS RCS SCCS .make.state .nse_depinf
|
|||
void
|
||||
ign_setup ()
|
||||
{
|
||||
extern char *getenv ();
|
||||
struct passwd *pw;
|
||||
char file[PATH_MAX];
|
||||
char *tmp;
|
||||
|
|
@ -51,17 +50,26 @@ ign_setup ()
|
|||
ign_add (tmp, 0);
|
||||
free (tmp);
|
||||
|
||||
/* Then add entries found in repository, if it exists */
|
||||
(void) sprintf (file, "%s/%s/%s", CVSroot, CVSROOTADM, CVSROOTADM_IGNORE);
|
||||
if (isfile (file))
|
||||
#ifdef CLIENT_SUPPORT
|
||||
/* Chances are we should have some way to provide this feature
|
||||
client/server, but I'm not sure how (surely not by introducing
|
||||
another network turnaround to each operation--perhaps by
|
||||
putting a file in the CVS directory on checkout, or with some
|
||||
sort of "slave cvsroot" on the client). */
|
||||
if (!client_active)
|
||||
#endif
|
||||
{
|
||||
/* Then add entries found in repository, if it exists */
|
||||
(void) sprintf (file, "%s/%s/%s", CVSroot, CVSROOTADM,
|
||||
CVSROOTADM_IGNORE);
|
||||
ign_add_file (file, 0);
|
||||
}
|
||||
|
||||
/* Then add entries found in home dir, (if user has one) and file exists */
|
||||
if ((pw = (struct passwd *) getpwuid (getuid ())) && pw->pw_dir)
|
||||
{
|
||||
(void) sprintf (file, "%s/%s", pw->pw_dir, CVSDOTIGNORE);
|
||||
if (isfile (file))
|
||||
ign_add_file (file, 0);
|
||||
ign_add_file (file, 0);
|
||||
}
|
||||
|
||||
/* Then add entries found in CVSIGNORE environment variable. */
|
||||
|
|
@ -118,11 +126,17 @@ ign_add_file (file, hold)
|
|||
}
|
||||
|
||||
/* load the file */
|
||||
if (!(fp = fopen (file, "r")))
|
||||
fp = fopen (file, "r");
|
||||
if (fp == NULL)
|
||||
{
|
||||
if (! existence_error (errno))
|
||||
error (0, errno, "cannot open %s", file);
|
||||
return;
|
||||
}
|
||||
while (fgets (line, sizeof (line), fp))
|
||||
ign_add (line, hold);
|
||||
(void) fclose (fp);
|
||||
if (fclose (fp) < 0)
|
||||
error (0, errno, "cannot close %s", file);
|
||||
}
|
||||
|
||||
/* Parse a line of space-separated wildcards and add them to the list. */
|
||||
|
|
|
|||
|
|
@ -17,10 +17,11 @@
|
|||
*/
|
||||
|
||||
#include "cvs.h"
|
||||
#include "save-cwd.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)import.c 1.63 94/09/30 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)import.c 1.63 94/09/30 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
#define FILE_HOLDER ".#cvsxxx"
|
||||
|
|
@ -40,8 +41,6 @@ static int process_import_file PROTO((char *message, char *vfile, char *vtag,
|
|||
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 str2expmode PROTO((char const* expstring));
|
||||
static int strn2expmode PROTO((char const* expstring, size_t n));
|
||||
|
||||
static int repos_len;
|
||||
static char vhead[50];
|
||||
|
|
@ -52,37 +51,23 @@ static int conflicts;
|
|||
static int use_file_modtime;
|
||||
static char *keyword_opt = NULL;
|
||||
|
||||
static char *import_usage[] =
|
||||
static const char *const import_usage[] =
|
||||
{
|
||||
"Usage: %s %s [-Qq] [-d] [-k subst] [-I ign] [-m msg] [-b branch]\n",
|
||||
" repository vendor-tag release-tags...\n",
|
||||
"\t-Q\tReally quiet.\n",
|
||||
"\t-q\tSomewhat quiet.\n",
|
||||
"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",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *keyword_usage[] =
|
||||
{
|
||||
"%s %s: invalid RCS keyword expansion mode\n",
|
||||
"Valid expansion modes include:\n",
|
||||
" -kkv\tGenerate keywords using the default form.\n",
|
||||
" -kkvl\tLike -kkv, except locker's name inserted.\n",
|
||||
" -kk\tGenerate only keyword names in keyword strings.\n",
|
||||
" -kv\tGenerate only keyword values in keyword strings.\n",
|
||||
" -ko\tGenerate the old keyword string (no changes from checked in file).\n",
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
import (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
char *message = NULL;
|
||||
char tmpfile[L_tmpnam+1];
|
||||
|
|
@ -95,18 +80,24 @@ import (argc, argv)
|
|||
usage (import_usage);
|
||||
|
||||
ign_setup ();
|
||||
wrap_setup ();
|
||||
|
||||
(void) strcpy (vbranch, CVSBRANCH);
|
||||
optind = 1;
|
||||
while ((c = getopt (argc, argv, "Qqdb:m:I:k:")) != -1)
|
||||
while ((c = getopt (argc, argv, "Qqdb:m:I:k:W:")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'Q':
|
||||
really_quiet = 1;
|
||||
/* FALL THROUGH */
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
#ifdef SERVER_SUPPORT
|
||||
/* The CVS 1.5 client sends these options (in addition to
|
||||
Global_option requests), so we must ignore them. */
|
||||
if (!server_active)
|
||||
#endif
|
||||
error (1, 0,
|
||||
"-q or -Q must be specified before \"%s\"",
|
||||
command_name);
|
||||
break;
|
||||
case 'd':
|
||||
use_file_modtime = 1;
|
||||
|
|
@ -126,10 +117,14 @@ import (argc, argv)
|
|||
ign_add (optarg, 0);
|
||||
break;
|
||||
case 'k':
|
||||
if (str2expmode(optarg) != -1)
|
||||
keyword_opt = optarg;
|
||||
else
|
||||
usage (keyword_usage);
|
||||
/* 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:
|
||||
|
|
@ -146,7 +141,7 @@ import (argc, argv)
|
|||
RCS_check_tag (argv[i]);
|
||||
|
||||
/* XXX - this should be a module, not just a pathname */
|
||||
if (argv[0][0] != '/')
|
||||
if (! isabsolute (argv[0]))
|
||||
{
|
||||
if (CVSroot == NULL)
|
||||
{
|
||||
|
|
@ -177,6 +172,17 @@ import (argc, argv)
|
|||
(void) strcpy (vhead, vbranch);
|
||||
cp = strrchr (vhead, '.');
|
||||
*cp = '\0';
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active)
|
||||
{
|
||||
/* Do this now; don't ask for a log message if we can't talk to the
|
||||
server. But if there is a syntax error in the options, give
|
||||
an error message without connecting. */
|
||||
start_server ();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (use_editor)
|
||||
{
|
||||
do_editor ((char *) NULL, &message, repository,
|
||||
|
|
@ -196,11 +202,45 @@ import (argc, argv)
|
|||
message = nm;
|
||||
}
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active)
|
||||
{
|
||||
int err;
|
||||
|
||||
ign_setup ();
|
||||
|
||||
if (use_file_modtime)
|
||||
send_arg("-d");
|
||||
|
||||
if (vbranch[0] != '\0')
|
||||
option_with_arg ("-b", vbranch);
|
||||
if (message)
|
||||
option_with_arg ("-m", message);
|
||||
if (keyword_opt != NULL)
|
||||
option_with_arg ("-k", keyword_opt);
|
||||
|
||||
{
|
||||
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 (fprintf (to_server, "import\n") < 0)
|
||||
error (1, errno, "writing to server");
|
||||
err += get_responses_and_close ();
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Make all newly created directories writable. Should really use a more
|
||||
* sophisticated security mechanism here.
|
||||
*/
|
||||
(void) umask (2);
|
||||
(void) umask (cvsumask);
|
||||
make_directories (repository);
|
||||
|
||||
/* Create the logfile that will be logged upon completion */
|
||||
|
|
@ -254,6 +294,10 @@ import (argc, argv)
|
|||
dellist (&ulist);
|
||||
(void) fclose (logfp);
|
||||
|
||||
/* Make sure the temporary file goes away, even on systems that don't let
|
||||
you delete a file that's in use. */
|
||||
unlink (tmpfile);
|
||||
|
||||
if (message)
|
||||
free (message);
|
||||
|
||||
|
|
@ -273,10 +317,11 @@ import_descend (message, vtag, targc, targv)
|
|||
DIR *dirp;
|
||||
struct dirent *dp;
|
||||
int err = 0;
|
||||
int has_dirs = 0;
|
||||
List *dirlist = NULL;
|
||||
|
||||
/* first, load up any per-directory ignore lists */
|
||||
ign_add_file (CVSDOTIGNORE, 1);
|
||||
wrap_add_file (CVSDOTWRAPPER, 1);
|
||||
|
||||
if ((dirp = opendir (".")) == NULL)
|
||||
{
|
||||
|
|
@ -290,49 +335,75 @@ import_descend (message, vtag, targc, targv)
|
|||
continue;
|
||||
if (ign_name (dp->d_name))
|
||||
{
|
||||
#ifdef SERVER_SUPPORT
|
||||
/* CVS directories are created by server.c because it doesn't
|
||||
special-case import. So don't print a message about them.
|
||||
Do print a message about other ignored files (although
|
||||
most of these will get ignored on the client side). */
|
||||
if (server_active && strcmp (dp->d_name, CVSADM) == 0)
|
||||
continue;
|
||||
#endif
|
||||
add_log ('I', dp->d_name);
|
||||
continue;
|
||||
}
|
||||
if (isdir (dp->d_name))
|
||||
|
||||
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 &&
|
||||
#endif
|
||||
islink (dp->d_name))
|
||||
{
|
||||
has_dirs = 1;
|
||||
add_log ('L', dp->d_name);
|
||||
err++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (islink (dp->d_name))
|
||||
{
|
||||
add_log ('L', dp->d_name);
|
||||
err++;
|
||||
}
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active)
|
||||
err += client_process_import_file (message, dp->d_name,
|
||||
vtag, targc, targv,
|
||||
repository);
|
||||
else
|
||||
{
|
||||
#endif
|
||||
err += process_import_file (message, dp->d_name,
|
||||
vtag, targc, targv);
|
||||
}
|
||||
}
|
||||
}
|
||||
(void) closedir (dirp);
|
||||
}
|
||||
if (has_dirs)
|
||||
|
||||
if (dirlist != NULL)
|
||||
{
|
||||
if ((dirp = opendir (".")) == NULL)
|
||||
err++;
|
||||
else
|
||||
Node *head, *p;
|
||||
|
||||
head = dirlist->list;
|
||||
for (p = head->next; p != head; p = p->next)
|
||||
{
|
||||
while ((dp = readdir (dirp)) != NULL)
|
||||
{
|
||||
if (!strcmp(".", dp->d_name) || !strcmp("..", dp->d_name))
|
||||
continue;
|
||||
if (!isdir (dp->d_name) || ign_name (dp->d_name))
|
||||
continue;
|
||||
err += import_descend_dir (message, dp->d_name,
|
||||
vtag, targc, targv);
|
||||
/* need to re-load .cvsignore after each dir traversal */
|
||||
ign_add_file (CVSDOTIGNORE, 1);
|
||||
}
|
||||
(void) closedir (dirp);
|
||||
err += import_descend_dir (message, p->key, vtag, targc, targv);
|
||||
}
|
||||
|
||||
dellist(&dirlist);
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
|
@ -392,10 +463,16 @@ update_rcs_file (message, vfile, vtag, targc, targv, inattic)
|
|||
int letter;
|
||||
int ierrno;
|
||||
char *tmpdir;
|
||||
char *tocvsPath;
|
||||
|
||||
vers = Version_TS (repository, (char *) NULL, vbranch, (char *) NULL, vfile,
|
||||
1, 0, (List *) NULL, (List *) NULL);
|
||||
#ifdef DEATH_SUPPORT
|
||||
if (vers->vn_rcs != NULL
|
||||
&& !RCS_isdead(vers->srcfile, vers->vn_rcs))
|
||||
#else
|
||||
if (vers->vn_rcs != NULL)
|
||||
#endif
|
||||
{
|
||||
char xtmpfile[PATH_MAX];
|
||||
int different;
|
||||
|
|
@ -435,7 +512,13 @@ update_rcs_file (message, vfile, vtag, targc, targv, inattic)
|
|||
(void) unlink_file (xtmpfile);
|
||||
return (1);
|
||||
}
|
||||
|
||||
tocvsPath = wrap_tocvs_process_file (vfile);
|
||||
different = xcmp (xtmpfile, vfile);
|
||||
if (tocvsPath)
|
||||
if (unlink_file_dir (tocvsPath) < 0)
|
||||
error (0, errno, "cannot remove %s", tocvsPath);
|
||||
|
||||
(void) unlink_file (xtmpfile);
|
||||
if (!different)
|
||||
{
|
||||
|
|
@ -488,7 +571,8 @@ add_rev (message, rcs, vfile, vers)
|
|||
char *vers;
|
||||
{
|
||||
int locked, status, ierrno;
|
||||
int retcode = 0;
|
||||
char *tocvsPath;
|
||||
struct stat vfile_stat;
|
||||
|
||||
if (noexec)
|
||||
return (0);
|
||||
|
|
@ -496,39 +580,43 @@ add_rev (message, rcs, vfile, vers)
|
|||
locked = 0;
|
||||
if (vers != NULL)
|
||||
{
|
||||
run_setup ("%s%s -q -l%s", Rcsbin, RCS, vbranch);
|
||||
run_arg (rcs);
|
||||
if ((retcode = run_exec (RUN_TTY, DEVNULL, DEVNULL, RUN_NORMAL)) == 0)
|
||||
locked = 1;
|
||||
else if (retcode == -1)
|
||||
/* 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);
|
||||
}
|
||||
locked = 1;
|
||||
}
|
||||
if (link_file (vfile, FILE_HOLDER) < 0)
|
||||
{
|
||||
if (errno == EEXIST)
|
||||
{
|
||||
(void) unlink_file (FILE_HOLDER);
|
||||
(void) link_file (vfile, FILE_HOLDER);
|
||||
}
|
||||
else
|
||||
{
|
||||
ierrno = errno;
|
||||
fperror (logfp, 0, ierrno, "ERROR: cannot create link to %s", vfile);
|
||||
error (0, ierrno, "ERROR: cannot create link to %s", vfile);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
run_setup ("%s%s -q -f -r%s", Rcsbin, RCS_CI, vbranch);
|
||||
run_args ("-m%s", message);
|
||||
tocvsPath = wrap_tocvs_process_file (vfile);
|
||||
|
||||
/* We used to deposit the revision with -r; RCS would delete the
|
||||
working file, but we'd keep a hard link to it, and rename it
|
||||
back after running RCS (ooh, atomicity). However, that
|
||||
strategy doesn't work on operating systems without hard links
|
||||
(like Windows NT). Instead, let's deposit it using -u, and
|
||||
restore its permission bits afterwards. This also means the
|
||||
file always exists under its own name. */
|
||||
if (! tocvsPath)
|
||||
stat (vfile, &vfile_stat);
|
||||
|
||||
run_setup ("%s%s -q -f %s%s", Rcsbin, RCS_CI,
|
||||
(tocvsPath ? "-r" : "-u"),
|
||||
vbranch);
|
||||
run_args ("-m%s", make_message_rcslegal (message));
|
||||
if (use_file_modtime)
|
||||
run_arg ("-d");
|
||||
run_arg (tocvsPath == NULL ? vfile : tocvsPath);
|
||||
run_arg (rcs);
|
||||
status = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
|
||||
ierrno = errno;
|
||||
rename_file (FILE_HOLDER, vfile);
|
||||
|
||||
/* Restore the permissions on vfile. */
|
||||
if (! tocvsPath)
|
||||
chmod (vfile, vfile_stat.st_mode);
|
||||
|
||||
if (status)
|
||||
{
|
||||
if (!noexec)
|
||||
|
|
@ -538,9 +626,7 @@ add_rev (message, rcs, vfile, vers)
|
|||
}
|
||||
if (locked)
|
||||
{
|
||||
run_setup ("%s%s -q -u%s", Rcsbin, RCS, vbranch);
|
||||
run_arg (rcs);
|
||||
(void) run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
|
||||
(void) RCS_unlock(rcs, vbranch, 0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
|
@ -568,9 +654,7 @@ add_tags (rcs, vfile, vtag, targc, targv)
|
|||
if (noexec)
|
||||
return (0);
|
||||
|
||||
run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, vtag, vbranch);
|
||||
run_arg (rcs);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
|
||||
if ((retcode = RCS_settag(rcs, vtag, vbranch)) != 0)
|
||||
{
|
||||
ierrno = errno;
|
||||
fperror (logfp, 0, retcode == -1 ? ierrno : 0,
|
||||
|
|
@ -583,9 +667,7 @@ add_tags (rcs, vfile, vtag, targc, targv)
|
|||
1, 0, (List *) NULL, (List *) NULL);
|
||||
for (i = 0; i < targc; i++)
|
||||
{
|
||||
run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, targv[i], vers->vn_rcs);
|
||||
run_arg (rcs);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
|
||||
if ((retcode = RCS_settag (rcs, targv[i], vers->vn_rcs)) != 0)
|
||||
{
|
||||
ierrno = errno;
|
||||
fperror (logfp, 0, retcode == -1 ? ierrno : 0,
|
||||
|
|
@ -606,7 +688,7 @@ struct compair
|
|||
char *suffix, *comlead;
|
||||
};
|
||||
|
||||
struct compair comtable[] =
|
||||
static const struct compair comtable[] =
|
||||
{
|
||||
|
||||
/*
|
||||
|
|
@ -616,83 +698,89 @@ struct compair comtable[] =
|
|||
* suffix during initial ci (see InitAdmin()). Comment leaders are needed for
|
||||
* languages without multiline comments; for others they are optional.
|
||||
*/
|
||||
"a", "-- ", /* Ada */
|
||||
"ada", "-- ",
|
||||
"adb", "-- ",
|
||||
"asm", ";; ", /* assembler (MS-DOS) */
|
||||
"ads", "-- ", /* Ada */
|
||||
"bat", ":: ", /* batch (MS-DOS) */
|
||||
"body", "-- ", /* Ada */
|
||||
"c", " * ", /* C */
|
||||
"c++", "// ", /* C++ in all its infinite guises */
|
||||
"cc", "// ",
|
||||
"cpp", "// ",
|
||||
"cxx", "// ",
|
||||
"cl", ";;; ", /* Common Lisp */
|
||||
"cmd", ":: ", /* command (OS/2) */
|
||||
"cmf", "c ", /* CM Fortran */
|
||||
"cs", " * ", /* C* */
|
||||
"csh", "# ", /* shell */
|
||||
"e", "# ", /* efl */
|
||||
"epsf", "% ", /* encapsulated postscript */
|
||||
"epsi", "% ", /* encapsulated postscript */
|
||||
"el", "; ", /* Emacs Lisp */
|
||||
"f", "c ", /* Fortran */
|
||||
"for", "c ",
|
||||
"h", " * ", /* C-header */
|
||||
"hh", "// ", /* C++ header */
|
||||
"hpp", "// ",
|
||||
"hxx", "// ",
|
||||
"in", "# ", /* for Makefile.in */
|
||||
"l", " * ", /* lex (conflict between lex and
|
||||
{"a", "-- "}, /* Ada */
|
||||
{"ada", "-- "},
|
||||
{"adb", "-- "},
|
||||
{"asm", ";; "}, /* assembler (MS-DOS) */
|
||||
{"ads", "-- "}, /* Ada */
|
||||
{"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 */
|
||||
{"e", "# "}, /* efl */
|
||||
{"epsf", "% "}, /* encapsulated postscript */
|
||||
{"epsi", "% "}, /* encapsulated postscript */
|
||||
{"el", "; "}, /* Emacs Lisp */
|
||||
{"f", "c "}, /* Fortran */
|
||||
{"for", "c "},
|
||||
{"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,
|
||||
{"mac", ";; "}, /* macro (DEC-10, MS-DOS, PDP-11,
|
||||
* VMS, etc) */
|
||||
"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 */
|
||||
"r", "# ", /* ratfor */
|
||||
"red", "% ", /* psl/rlisp */
|
||||
{"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 */
|
||||
{"red", "% "}, /* psl/rlisp */
|
||||
#ifdef sparc
|
||||
"s", "! ", /* assembler */
|
||||
{"s", "! "}, /* assembler */
|
||||
#endif
|
||||
#ifdef mc68000
|
||||
"s", "| ", /* assembler */
|
||||
{"s", "| "}, /* assembler */
|
||||
#endif
|
||||
#ifdef pdp11
|
||||
"s", "/ ", /* assembler */
|
||||
{"s", "/ "}, /* assembler */
|
||||
#endif
|
||||
#ifdef vax
|
||||
"s", "# ", /* assembler */
|
||||
{"s", "# "}, /* assembler */
|
||||
#endif
|
||||
#ifdef __ksr__
|
||||
"s", "# ", /* assembler */
|
||||
"S", "# ", /* Macro assembler */
|
||||
{"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; */
|
||||
{"sh", "# "}, /* shell */
|
||||
{"sl", "% "}, /* psl */
|
||||
{"spec", "-- "}, /* Ada */
|
||||
{"tex", "% "}, /* tex */
|
||||
{"y", " * "}, /* yacc */
|
||||
{"ye", " * "}, /* yacc-efl */
|
||||
{"yr", " * "}, /* yacc-ratfor */
|
||||
#ifdef SYSTEM_COMMENT_TABLE
|
||||
SYSTEM_COMMENT_TABLE
|
||||
#endif
|
||||
{"", "# "}, /* default for empty suffix */
|
||||
{NULL, "# "} /* default for unknown suffix; */
|
||||
/* must always be last */
|
||||
};
|
||||
|
||||
|
|
@ -748,17 +836,27 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
|
|||
char altdate2[50];
|
||||
#endif
|
||||
char *author, *buf;
|
||||
int i, mode, ierrno, err = 0;
|
||||
int i, ierrno, err = 0;
|
||||
mode_t mode;
|
||||
char *tocvsPath;
|
||||
char *userfile;
|
||||
|
||||
if (noexec)
|
||||
return (0);
|
||||
|
||||
/* open the user file first, before we change the RCS files... */
|
||||
fpuser = fopen (user, "r");
|
||||
#ifdef LINES_CRLF_TERMINATED
|
||||
/* There exits a port of RCS to such a system that stores files with
|
||||
straight newlines. If we ever reach this point on such a system,
|
||||
we'll need to decide what to do with the open_file call below. */
|
||||
abort ();
|
||||
#endif
|
||||
tocvsPath = wrap_tocvs_process_file (user);
|
||||
userfile = (tocvsPath == NULL ? user : tocvsPath);
|
||||
fpuser = fopen (userfile, "r");
|
||||
if (fpuser == NULL) {
|
||||
/* not fatal, continue the import */
|
||||
fperror (logfp, 0, errno, "ERROR: cannot read file %s", user);
|
||||
error (0, errno, "ERROR: cannot read file %s", user);
|
||||
/* not fatal, continue import */
|
||||
fperror (logfp, 0, errno, "ERROR: cannot read file %s", userfile);
|
||||
error (0, errno, "ERROR: cannot read file %s", userfile);
|
||||
goto read_error;
|
||||
}
|
||||
fprcs = fopen (rcs, "w+");
|
||||
|
|
@ -770,33 +868,33 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
|
|||
/*
|
||||
* putadmin()
|
||||
*/
|
||||
if (fprintf (fprcs, "head %s;\n", vhead) == EOF ||
|
||||
fprintf (fprcs, "branch %s;\n", vbranch) == EOF ||
|
||||
fprintf (fprcs, "access ;\n") == EOF ||
|
||||
fprintf (fprcs, "symbols ") == EOF)
|
||||
if (fprintf (fprcs, "head %s;\n", vhead) < 0 ||
|
||||
fprintf (fprcs, "branch %s;\n", vbranch) < 0 ||
|
||||
fprintf (fprcs, "access ;\n") < 0 ||
|
||||
fprintf (fprcs, "symbols ") < 0)
|
||||
{
|
||||
goto write_error;
|
||||
}
|
||||
|
||||
for (i = targc - 1; i >= 0; i--) /* RCS writes the symbols backwards */
|
||||
if (fprintf (fprcs, "%s:%s.1 ", targv[i], vbranch) == EOF)
|
||||
if (fprintf (fprcs, "%s:%s.1 ", targv[i], vbranch) < 0)
|
||||
goto write_error;
|
||||
|
||||
if (fprintf (fprcs, "%s:%s;\n", vtag, vbranch) == EOF ||
|
||||
fprintf (fprcs, "locks ; strict;\n") == EOF ||
|
||||
if (fprintf (fprcs, "%s:%s;\n", vtag, vbranch) < 0 ||
|
||||
fprintf (fprcs, "locks ; strict;\n") < 0 ||
|
||||
/* XXX - make sure @@ processing works in the RCS file */
|
||||
fprintf (fprcs, "comment @%s@;\n", get_comment (user)) == EOF)
|
||||
fprintf (fprcs, "comment @%s@;\n", get_comment (user)) < 0)
|
||||
{
|
||||
goto write_error;
|
||||
}
|
||||
|
||||
if (keyword_opt != NULL)
|
||||
if (fprintf (fprcs, "expand @%s@;\n", keyword_opt) == EOF)
|
||||
if (fprintf (fprcs, "expand @%s@;\n", keyword_opt) < 0)
|
||||
{
|
||||
goto write_error;
|
||||
}
|
||||
|
||||
if (fprintf (fprcs, "\n") == EOF)
|
||||
if (fprintf (fprcs, "\n") < 0)
|
||||
goto write_error;
|
||||
|
||||
/*
|
||||
|
|
@ -833,28 +931,28 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
|
|||
#endif
|
||||
author = getcaller ();
|
||||
|
||||
if (fprintf (fprcs, "\n%s\n", vhead) == EOF ||
|
||||
if (fprintf (fprcs, "\n%s\n", vhead) < 0 ||
|
||||
fprintf (fprcs, "date %s; author %s; state Exp;\n",
|
||||
altdate1, author) == EOF ||
|
||||
fprintf (fprcs, "branches %s.1;\n", vbranch) == EOF ||
|
||||
fprintf (fprcs, "next ;\n") == EOF ||
|
||||
fprintf (fprcs, "\n%s.1\n", vbranch) == EOF ||
|
||||
altdate1, author) < 0 ||
|
||||
fprintf (fprcs, "branches %s.1;\n", vbranch) < 0 ||
|
||||
fprintf (fprcs, "next ;\n") < 0 ||
|
||||
fprintf (fprcs, "\n%s.1\n", vbranch) < 0 ||
|
||||
fprintf (fprcs, "date %s; author %s; state Exp;\n",
|
||||
altdate2, author) == EOF ||
|
||||
fprintf (fprcs, "branches ;\n") == EOF ||
|
||||
fprintf (fprcs, "next ;\n\n") == EOF ||
|
||||
altdate2, author) < 0 ||
|
||||
fprintf (fprcs, "branches ;\n") < 0 ||
|
||||
fprintf (fprcs, "next ;\n\n") < 0 ||
|
||||
/*
|
||||
* putdesc()
|
||||
*/
|
||||
fprintf (fprcs, "\ndesc\n") == EOF ||
|
||||
fprintf (fprcs, "@@\n\n\n") == EOF ||
|
||||
fprintf (fprcs, "\ndesc\n") < 0 ||
|
||||
fprintf (fprcs, "@@\n\n\n") < 0 ||
|
||||
/*
|
||||
* putdelta()
|
||||
*/
|
||||
fprintf (fprcs, "\n%s\n", vhead) == EOF ||
|
||||
fprintf (fprcs, "log\n") == EOF ||
|
||||
fprintf (fprcs, "@Initial revision\n@\n") == EOF ||
|
||||
fprintf (fprcs, "text\n@") == EOF)
|
||||
fprintf (fprcs, "\n%s\n", vhead) < 0 ||
|
||||
fprintf (fprcs, "log\n") < 0 ||
|
||||
fprintf (fprcs, "@Initial revision\n@\n") < 0 ||
|
||||
fprintf (fprcs, "text\n@") < 0)
|
||||
{
|
||||
goto write_error;
|
||||
}
|
||||
|
|
@ -867,19 +965,19 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
|
|||
buf = xmalloc ((int) size);
|
||||
if (fread (buf, (int) size, 1, fpuser) != 1)
|
||||
error (1, errno, "cannot read file %s for copying", user);
|
||||
if (expand_at_signs (buf, size, fprcs) == EOF)
|
||||
if (expand_at_signs (buf, size, fprcs) < 0)
|
||||
{
|
||||
free (buf);
|
||||
goto write_error;
|
||||
}
|
||||
free (buf);
|
||||
}
|
||||
if (fprintf (fprcs, "@\n\n") == EOF ||
|
||||
fprintf (fprcs, "\n%s.1\n", vbranch) == EOF ||
|
||||
fprintf (fprcs, "log\n@") == EOF ||
|
||||
expand_at_signs (message, (off_t) strlen (message), fprcs) == EOF ||
|
||||
fprintf (fprcs, "@\ntext\n") == EOF ||
|
||||
fprintf (fprcs, "@@\n") == EOF)
|
||||
if (fprintf (fprcs, "@\n\n") < 0 ||
|
||||
fprintf (fprcs, "\n%s.1\n", vbranch) < 0 ||
|
||||
fprintf (fprcs, "log\n@") < 0 ||
|
||||
expand_at_signs (message, (off_t) strlen (message), fprcs) < 0 ||
|
||||
fprintf (fprcs, "@\ntext\n") < 0 ||
|
||||
fprintf (fprcs, "@@\n") < 0)
|
||||
{
|
||||
goto write_error;
|
||||
}
|
||||
|
|
@ -891,11 +989,16 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
|
|||
(void) fclose (fpuser);
|
||||
|
||||
/*
|
||||
* Fix the modes on the RCS files. They must maintain the same modes as
|
||||
* the original user file, except that all write permissions must be
|
||||
* 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 & ~(S_IWRITE | S_IWGRP | S_IWOTH);
|
||||
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;
|
||||
|
|
@ -904,6 +1007,9 @@ add_rcs_file (message, rcs, user, vtag, targc, targv)
|
|||
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);
|
||||
return (err);
|
||||
|
||||
write_error:
|
||||
|
|
@ -920,11 +1026,17 @@ write_error_noclose:
|
|||
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);
|
||||
|
||||
return (err + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sigh.. need to expand @ signs into double @ signs
|
||||
* 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.
|
||||
*/
|
||||
static int
|
||||
expand_at_signs (buf, size, fp)
|
||||
|
|
@ -934,11 +1046,15 @@ expand_at_signs (buf, size, fp)
|
|||
{
|
||||
char *cp, *end;
|
||||
|
||||
errno = 0;
|
||||
for (cp = buf, end = buf + size; cp < end; cp++)
|
||||
{
|
||||
if (*cp == '@')
|
||||
(void) putc ('@', fp);
|
||||
if (putc (*cp, fp) == EOF)
|
||||
{
|
||||
if (putc ('@', fp) == EOF && errno != 0)
|
||||
return EOF;
|
||||
}
|
||||
if (putc (*cp, fp) == EOF && errno != 0)
|
||||
return (EOF);
|
||||
}
|
||||
return (1);
|
||||
|
|
@ -986,16 +1102,15 @@ import_descend_dir (message, dir, vtag, targc, targv)
|
|||
int targc;
|
||||
char *targv[];
|
||||
{
|
||||
char cwd[PATH_MAX];
|
||||
struct saved_cwd cwd;
|
||||
char *cp;
|
||||
int ierrno, err;
|
||||
|
||||
if (islink (dir))
|
||||
return (0);
|
||||
if (getwd (cwd) == NULL)
|
||||
if (save_cwd (&cwd))
|
||||
{
|
||||
fperror (logfp, 0, 0, "ERROR: cannot get working directory: %s", cwd);
|
||||
error (0, 0, "ERROR: cannot get working directory: %s", cwd);
|
||||
fperror (logfp, 0, 0, "ERROR: cannot get working directory");
|
||||
return (1);
|
||||
}
|
||||
if (repository[0] == '\0')
|
||||
|
|
@ -1005,8 +1120,20 @@ import_descend_dir (message, dir, vtag, targc, targv)
|
|||
(void) strcat (repository, "/");
|
||||
(void) strcat (repository, dir);
|
||||
}
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (!quiet && !client_active)
|
||||
#else
|
||||
if (!quiet)
|
||||
#endif
|
||||
#ifdef SERVER_SUPPORT
|
||||
/* Needs to go on stdout, not stderr, to avoid being interspersed
|
||||
with the add_log messages. */
|
||||
printf ("%s %s: Importing %s\n",
|
||||
program_name, command_name, repository);
|
||||
#else
|
||||
error (0, 0, "Importing %s", repository);
|
||||
#endif
|
||||
|
||||
if (chdir (dir) < 0)
|
||||
{
|
||||
ierrno = errno;
|
||||
|
|
@ -1015,7 +1142,11 @@ import_descend_dir (message, dir, vtag, targc, targv)
|
|||
err = 1;
|
||||
goto out;
|
||||
}
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (!client_active && !isdir (repository))
|
||||
#else
|
||||
if (!isdir (repository))
|
||||
#endif
|
||||
{
|
||||
if (isfile (repository))
|
||||
{
|
||||
|
|
@ -1026,7 +1157,7 @@ import_descend_dir (message, dir, vtag, targc, targv)
|
|||
err = 1;
|
||||
goto out;
|
||||
}
|
||||
if (noexec == 0 && mkdir (repository, 0777) < 0)
|
||||
if (noexec == 0 && CVS_MKDIR (repository, 0777) < 0)
|
||||
{
|
||||
ierrno = errno;
|
||||
fperror (logfp, 0, ierrno,
|
||||
|
|
@ -1043,40 +1174,8 @@ import_descend_dir (message, dir, vtag, targc, targv)
|
|||
*cp = '\0';
|
||||
else
|
||||
repository[0] = '\0';
|
||||
if (chdir (cwd) < 0)
|
||||
error (1, errno, "cannot chdir to %s", cwd);
|
||||
if (restore_cwd (&cwd, NULL))
|
||||
exit (1);
|
||||
free_cwd (&cwd);
|
||||
return (err);
|
||||
}
|
||||
|
||||
/* the following code is taken from code in rcs/src/rcssyn.c, and returns a
|
||||
* positive value if 'expstring' contains a valid RCS expansion token for
|
||||
* the -k option. If an invalid expansion is named, then return -1.
|
||||
*/
|
||||
|
||||
char const *const expand_names[] = {
|
||||
/* These must agree with *_EXPAND in rcs/src/rcsbase.h. */
|
||||
"kv","kvl","k","v","o",
|
||||
0
|
||||
};
|
||||
|
||||
static int
|
||||
str2expmode(s)
|
||||
char const *s;
|
||||
/* Yield expand mode corresponding to S, or -1 if bad. */
|
||||
{
|
||||
return strn2expmode(s, strlen(s));
|
||||
}
|
||||
|
||||
static int
|
||||
strn2expmode(s, n)
|
||||
char const *s;
|
||||
size_t n;
|
||||
{
|
||||
char const *const *p;
|
||||
|
||||
for (p = expand_names; *p; ++p)
|
||||
if (memcmp(*p,s,n) == 0 && !(*p)[n])
|
||||
return p - expand_names;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,31 +13,30 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)lock.c 1.50 94/09/30 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)lock.c 1.50 94/09/30 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
extern char *ctime ();
|
||||
|
||||
static int readers_exist PROTO((char *repository));
|
||||
static int set_lock PROTO((char *lockdir, int will_wait, char *repository));
|
||||
static int set_lock PROTO((char *repository, int will_wait));
|
||||
static void clear_lock PROTO((void));
|
||||
static void set_lockers_name PROTO((struct stat *statp));
|
||||
static int set_writelock_proc PROTO((Node * p, void *closure));
|
||||
static int unlock_proc PROTO((Node * p, void *closure));
|
||||
static int write_lock PROTO((char *repository));
|
||||
static void unlock PROTO((char *repository));
|
||||
static void lock_wait PROTO((char *repository));
|
||||
static int Check_Owner PROTO((char *lockdir));
|
||||
|
||||
static char lockers_name[20];
|
||||
static char *repository;
|
||||
static char readlock[PATH_MAX], writelock[PATH_MAX];
|
||||
static char readlock[PATH_MAX], writelock[PATH_MAX], masterlock[PATH_MAX];
|
||||
static int cleanup_lckdir;
|
||||
static List *locklist;
|
||||
|
||||
#define L_OK 0 /* success */
|
||||
#define L_ERROR 1 /* error condition */
|
||||
#define L_LOCK_OWNED 2 /* lock already owned by us */
|
||||
#define L_LOCKED 3 /* lock owned by someone else */
|
||||
#define L_LOCKED 2 /* lock owned by someone else */
|
||||
|
||||
/*
|
||||
* Clean up all outstanding locks
|
||||
|
|
@ -80,19 +79,18 @@ unlock (repository)
|
|||
char *repository;
|
||||
{
|
||||
char tmp[PATH_MAX];
|
||||
struct stat sb;
|
||||
|
||||
if (readlock[0] != '\0')
|
||||
{
|
||||
(void) sprintf (tmp, "%s/%s", repository, readlock);
|
||||
if (unlink (tmp) < 0 && errno != ENOENT)
|
||||
if (unlink (tmp) < 0 && ! existence_error (errno))
|
||||
error (0, errno, "failed to remove lock %s", tmp);
|
||||
}
|
||||
|
||||
if (writelock[0] != '\0')
|
||||
{
|
||||
(void) sprintf (tmp, "%s/%s", repository, writelock);
|
||||
if (unlink (tmp) < 0 && errno != ENOENT)
|
||||
if (unlink (tmp) < 0 && ! existence_error (errno))
|
||||
error (0, errno, "failed to remove lock %s", tmp);
|
||||
}
|
||||
|
||||
|
|
@ -101,21 +99,53 @@ unlock (repository)
|
|||
* lead to the limitation that one user ID should not be committing
|
||||
* files into the same Repository directory at the same time. Oh well.
|
||||
*/
|
||||
(void) sprintf (tmp, "%s/%s", repository, CVSLCK);
|
||||
if (stat (tmp, &sb) != -1 && sb.st_uid == geteuid () &&
|
||||
(writelock[0] != '\0' || (readlock[0] != '\0' && cleanup_lckdir)))
|
||||
if (writelock[0] != '\0' || (readlock[0] != '\0' && cleanup_lckdir))
|
||||
{
|
||||
(void) rmdir (tmp);
|
||||
(void) sprintf (tmp, "%s/%s", repository, CVSLCK);
|
||||
if (Check_Owner(tmp))
|
||||
{
|
||||
#ifdef AFSCVS
|
||||
char rmuidlock[PATH_MAX];
|
||||
sprintf(rmuidlock, "rm -f %s/uidlock%d", tmp, geteuid() );
|
||||
system(rmuidlock);
|
||||
#endif
|
||||
(void) rmdir (tmp);
|
||||
}
|
||||
}
|
||||
cleanup_lckdir = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since some systems don't define this...
|
||||
* Check the owner of a lock. Returns 1 if we own it, 0 otherwise.
|
||||
*/
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 256
|
||||
static int
|
||||
Check_Owner(lockdir)
|
||||
char *lockdir;
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
#ifdef AFSCVS
|
||||
/* In the Andrew File System (AFS), user ids from stat don't match
|
||||
those from geteuid(). The AFSCVS code can deal with either AFS or
|
||||
non-AFS repositories; the non-AFSCVS code is faster. */
|
||||
char uidlock[PATH_MAX];
|
||||
|
||||
/* Check if the uidlock is in the lock directory */
|
||||
sprintf(uidlock, "%s/uidlock%d", lockdir, geteuid() );
|
||||
if( stat(uidlock, &sb) != -1)
|
||||
return 1; /* The file exists, therefore we own the lock */
|
||||
else
|
||||
return 0; /* The file didn't exist or some other error.
|
||||
* Assume that we don't own it.
|
||||
*/
|
||||
#else
|
||||
if (stat (lockdir, &sb) != -1 && sb.st_uid == geteuid ())
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
#endif
|
||||
} /* end Check_Owner() */
|
||||
|
||||
|
||||
/*
|
||||
* Create a lock file for readers
|
||||
|
|
@ -127,18 +157,10 @@ Reader_Lock (xrepository)
|
|||
int err = 0;
|
||||
FILE *fp;
|
||||
char tmp[PATH_MAX];
|
||||
#ifdef HAVE_LONG_FILE_NAMES
|
||||
char hostname[MAXHOSTNAMELEN];
|
||||
#endif
|
||||
|
||||
if (noexec)
|
||||
return (0);
|
||||
|
||||
#ifdef HAVE_LONG_FILE_NAMES
|
||||
memset(hostname, 0, sizeof(hostname));
|
||||
gethostname(hostname, sizeof(hostname) - 1);
|
||||
#endif
|
||||
|
||||
/* we only do one directory at a time for read locks! */
|
||||
if (repository != NULL)
|
||||
{
|
||||
|
|
@ -158,13 +180,7 @@ Reader_Lock (xrepository)
|
|||
/* remember what we're locking (for lock_cleanup) */
|
||||
repository = xrepository;
|
||||
|
||||
/* make sure we clean up on error */
|
||||
(void) SIG_register (SIGHUP, Lock_Cleanup);
|
||||
(void) SIG_register (SIGINT, Lock_Cleanup);
|
||||
(void) SIG_register (SIGQUIT, Lock_Cleanup);
|
||||
(void) SIG_register (SIGPIPE, Lock_Cleanup);
|
||||
(void) SIG_register (SIGTERM, Lock_Cleanup);
|
||||
|
||||
#ifdef BOGUS_UNLESS_PROVEN_OTHERWISE
|
||||
/* make sure we can write the repository */
|
||||
(void) sprintf (tmp,
|
||||
#ifdef HAVE_LONG_FILE_NAMES
|
||||
|
|
@ -178,16 +194,16 @@ Reader_Lock (xrepository)
|
|||
error (0, errno, "cannot create read lock in repository `%s'",
|
||||
xrepository);
|
||||
readlock[0] = '\0';
|
||||
if (unlink (tmp) < 0 && errno != ENOENT)
|
||||
if (unlink (tmp) < 0 && ! existence_error (errno))
|
||||
error (0, errno, "failed to remove lock %s", tmp);
|
||||
return (1);
|
||||
}
|
||||
if (unlink (tmp) < 0)
|
||||
error (0, errno, "failed to remove lock %s", tmp);
|
||||
#endif
|
||||
|
||||
/* get the lock dir for our own */
|
||||
(void) sprintf (tmp, "%s/%s", xrepository, CVSLCK);
|
||||
if (set_lock (tmp, 1, xrepository) != L_OK)
|
||||
if (set_lock (xrepository, 1) != L_OK)
|
||||
{
|
||||
error (0, 0, "failed to obtain dir lock in repository `%s'",
|
||||
xrepository);
|
||||
|
|
@ -206,9 +222,7 @@ Reader_Lock (xrepository)
|
|||
}
|
||||
|
||||
/* free the lock dir */
|
||||
(void) sprintf (tmp, "%s/%s", xrepository, CVSLCK);
|
||||
if (rmdir (tmp) < 0)
|
||||
error (0, errno, "failed to remove lock dir `%s'", tmp);
|
||||
clear_lock();
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
|
@ -294,14 +308,6 @@ write_lock (repository)
|
|||
int status;
|
||||
FILE *fp;
|
||||
char tmp[PATH_MAX];
|
||||
#ifdef HAVE_LONG_FILE_NAMES
|
||||
char hostname[MAXHOSTNAMELEN];
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LONG_FILE_NAMES
|
||||
memset(hostname, 0, sizeof(hostname));
|
||||
gethostname(hostname, sizeof(hostname) - 1);
|
||||
#endif
|
||||
|
||||
if (writelock[0] == '\0')
|
||||
(void) sprintf (writelock,
|
||||
|
|
@ -312,13 +318,7 @@ write_lock (repository)
|
|||
#endif
|
||||
getpid());
|
||||
|
||||
/* make sure we clean up on error */
|
||||
(void) SIG_register (SIGHUP, Lock_Cleanup);
|
||||
(void) SIG_register (SIGINT, Lock_Cleanup);
|
||||
(void) SIG_register (SIGQUIT, Lock_Cleanup);
|
||||
(void) SIG_register (SIGPIPE, Lock_Cleanup);
|
||||
(void) SIG_register (SIGTERM, Lock_Cleanup);
|
||||
|
||||
#ifdef BOGUS_UNLESS_PROVEN_OTHERWISE
|
||||
/* make sure we can write the repository */
|
||||
(void) sprintf (tmp,
|
||||
#ifdef HAVE_LONG_FILE_NAMES
|
||||
|
|
@ -331,17 +331,17 @@ write_lock (repository)
|
|||
{
|
||||
error (0, errno, "cannot create write lock in repository `%s'",
|
||||
repository);
|
||||
if (unlink (tmp) < 0 && errno != ENOENT)
|
||||
if (unlink (tmp) < 0 && ! existence_error (errno))
|
||||
error (0, errno, "failed to remove lock %s", tmp);
|
||||
return (L_ERROR);
|
||||
}
|
||||
if (unlink (tmp) < 0)
|
||||
error (0, errno, "failed to remove lock %s", tmp);
|
||||
#endif
|
||||
|
||||
/* make sure the lock dir is ours (not necessarily unique to us!) */
|
||||
(void) sprintf (tmp, "%s/%s", repository, CVSLCK);
|
||||
status = set_lock (tmp, 0, repository);
|
||||
if (status == L_OK || status == L_LOCK_OWNED)
|
||||
status = set_lock (repository, 0);
|
||||
if (status == L_OK)
|
||||
{
|
||||
/* we now own a writer - make sure there are no readers */
|
||||
if (readers_exist (repository))
|
||||
|
|
@ -349,8 +349,7 @@ write_lock (repository)
|
|||
/* clean up the lock dir if we created it */
|
||||
if (status == L_OK)
|
||||
{
|
||||
if (rmdir (tmp) < 0)
|
||||
error (0, errno, "failed to remove lock dir `%s'", tmp);
|
||||
clear_lock();
|
||||
}
|
||||
|
||||
/* indicate we failed due to read locks instead of error */
|
||||
|
|
@ -363,15 +362,13 @@ write_lock (repository)
|
|||
{
|
||||
int xerrno = errno;
|
||||
|
||||
if (unlink (tmp) < 0 && errno != ENOENT)
|
||||
if (unlink (tmp) < 0 && ! existence_error (errno))
|
||||
error (0, errno, "failed to remove lock %s", tmp);
|
||||
|
||||
/* free the lock dir if we created it */
|
||||
if (status == L_OK)
|
||||
{
|
||||
(void) sprintf (tmp, "%s/%s", repository, CVSLCK);
|
||||
if (rmdir (tmp) < 0)
|
||||
error (0, errno, "failed to remove lock dir `%s'", tmp);
|
||||
clear_lock();
|
||||
}
|
||||
|
||||
/* return the error */
|
||||
|
|
@ -428,9 +425,7 @@ again:
|
|||
*/
|
||||
if (now >= (sb.st_ctime + CVSLCKAGE) && unlink (line) != -1)
|
||||
{
|
||||
if (closedir (dirp) < 0)
|
||||
error (0, errno,
|
||||
"error closing directory %s", repository);
|
||||
(void) closedir (dirp);
|
||||
goto again;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -445,8 +440,7 @@ again:
|
|||
if (errno != 0)
|
||||
error (0, errno, "error reading directory %s", repository);
|
||||
|
||||
if (closedir (dirp) < 0)
|
||||
error (0, errno, "error closing directory %s", repository);
|
||||
closedir (dirp);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
|
@ -466,7 +460,7 @@ set_lockers_name (statp)
|
|||
(void) strcpy (lockers_name, pw->pw_name);
|
||||
}
|
||||
else
|
||||
(void) sprintf (lockers_name, "uid%d", statp->st_uid);
|
||||
(void) sprintf (lockers_name, "uid%lu", (unsigned long) statp->st_uid);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -475,16 +469,18 @@ set_lockers_name (statp)
|
|||
* seconds old, just try to remove the directory.
|
||||
*/
|
||||
static int
|
||||
set_lock (lockdir, will_wait, repository)
|
||||
char *lockdir;
|
||||
int will_wait;
|
||||
set_lock (repository, will_wait)
|
||||
char *repository;
|
||||
int will_wait;
|
||||
{
|
||||
struct stat sb;
|
||||
mode_t omask;
|
||||
#ifdef CVS_FUDGELOCKS
|
||||
time_t now;
|
||||
#endif
|
||||
|
||||
(void) sprintf (masterlock, "%s/%s", repository, CVSLCK);
|
||||
|
||||
/*
|
||||
* Note that it is up to the callers of set_lock() to arrange for signal
|
||||
* handlers that do the appropriate things, like remove the lock
|
||||
|
|
@ -493,14 +489,39 @@ set_lock (lockdir, will_wait, repository)
|
|||
cleanup_lckdir = 0;
|
||||
for (;;)
|
||||
{
|
||||
int status = -1;
|
||||
omask = umask (cvsumask);
|
||||
SIG_beginCrSect ();
|
||||
if (mkdir (lockdir, 0777) == 0)
|
||||
if (CVS_MKDIR (masterlock, 0777) == 0)
|
||||
{
|
||||
#ifdef AFSCVS
|
||||
char uidlock[PATH_MAX];
|
||||
FILE *fp;
|
||||
|
||||
sprintf(uidlock, "%s/uidlock%d", masterlock, geteuid() );
|
||||
if ((fp = fopen(uidlock, "w+")) == NULL)
|
||||
{
|
||||
/* We failed to create the uidlock,
|
||||
so rm masterlock and leave */
|
||||
rmdir(masterlock);
|
||||
SIG_endCrSect ();
|
||||
status = L_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We successfully created the uid lock, so close the file */
|
||||
fclose(fp);
|
||||
#endif
|
||||
cleanup_lckdir = 1;
|
||||
SIG_endCrSect ();
|
||||
return (L_OK);
|
||||
status = L_OK;
|
||||
goto out;
|
||||
}
|
||||
SIG_endCrSect ();
|
||||
out:
|
||||
(void) umask (omask);
|
||||
if (status != -1)
|
||||
return status;
|
||||
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
|
|
@ -514,24 +535,16 @@ set_lock (lockdir, will_wait, repository)
|
|||
* stat the dir - if it is non-existent, re-try the loop since
|
||||
* someone probably just removed it (thus releasing the lock)
|
||||
*/
|
||||
if (stat (lockdir, &sb) < 0)
|
||||
if (stat (masterlock, &sb) < 0)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
if (existence_error (errno))
|
||||
continue;
|
||||
|
||||
error (0, errno, "couldn't stat lock directory `%s'", lockdir);
|
||||
error (0, errno, "couldn't stat lock directory `%s'", masterlock);
|
||||
return (L_ERROR);
|
||||
}
|
||||
|
||||
/*
|
||||
* if we already own the lock, go ahead and return 1 which means it
|
||||
* existed but we owned it
|
||||
*/
|
||||
if (sb.st_uid == geteuid () && !will_wait)
|
||||
return (L_LOCK_OWNED);
|
||||
|
||||
#ifdef CVS_FUDGELOCKS
|
||||
|
||||
/*
|
||||
* If the create time of the directory is more than CVSLCKAGE seconds
|
||||
* ago, try to clean-up the lock directory, and if successful, just
|
||||
|
|
@ -540,7 +553,13 @@ set_lock (lockdir, will_wait, repository)
|
|||
(void) time (&now);
|
||||
if (now >= (sb.st_ctime + CVSLCKAGE))
|
||||
{
|
||||
if (rmdir (lockdir) >= 0)
|
||||
#ifdef AFSCVS
|
||||
/* Remove the uidlock first */
|
||||
char rmuidlock[PATH_MAX];
|
||||
sprintf(rmuidlock, "rm -f %s/uidlock%d", masterlock, geteuid() );
|
||||
system(rmuidlock);
|
||||
#endif
|
||||
if (rmdir (masterlock) >= 0)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -555,6 +574,24 @@ set_lock (lockdir, will_wait, repository)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear master lock. We don't have to recompute the lock name since
|
||||
* clear_lock is never called except after a successful set_lock().
|
||||
*/
|
||||
static void
|
||||
clear_lock()
|
||||
{
|
||||
#ifdef AFSCVS
|
||||
/* Remove the uidlock first */
|
||||
char rmuidlock[PATH_MAX];
|
||||
sprintf(rmuidlock, "rm -f %s/uidlock%d", masterlock, geteuid() );
|
||||
system(rmuidlock);
|
||||
#endif
|
||||
if (rmdir (masterlock) < 0)
|
||||
error (0, errno, "failed to remove lock dir `%s'", masterlock);
|
||||
cleanup_lckdir = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print out a message that the lock is still held, then sleep a while.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@
|
|||
*
|
||||
* Print Log Information
|
||||
*
|
||||
* This line exists solely to test some pcl-cvs/ChangeLog stuff. You
|
||||
* can delete it, if indeed it's still here when you read it. -Karl
|
||||
*
|
||||
* Prints the RCS "log" (rlog) information for the specified files. With no
|
||||
* argument, prints the log information for all the files in the directory
|
||||
* (recursive by default).
|
||||
|
|
@ -15,30 +18,30 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)log.c 1.44 94/09/30 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)log.c 1.44 94/09/30 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static Dtype log_dirproc PROTO((char *dir, char *repository, char *update_dir));
|
||||
static int log_fileproc PROTO((char *file, char *update_dir, char *repository,
|
||||
List * entries, List * srcfiles));
|
||||
|
||||
static char options[PATH_MAX];
|
||||
|
||||
static char *log_usage[] =
|
||||
static const char *const log_usage[] =
|
||||
{
|
||||
"Usage: %s %s [-l] [rlog-options] [files...]\n",
|
||||
"\t-l\tLocal directory only, no recursion.\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int ac;
|
||||
static char **av;
|
||||
|
||||
int
|
||||
cvslog (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
int i;
|
||||
int numopt = 1;
|
||||
int err = 0;
|
||||
int local = 0;
|
||||
|
||||
|
|
@ -48,34 +51,49 @@ cvslog (argc, argv)
|
|||
/*
|
||||
* All 'log' command options except -l are passed directly on to 'rlog'
|
||||
*/
|
||||
options[0] = '\0'; /* Assume none */
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (argv[i][0] == '-' || argv[i][0] == '\0')
|
||||
{
|
||||
numopt++;
|
||||
switch (argv[i][1])
|
||||
{
|
||||
case 'l':
|
||||
local = 1;
|
||||
break;
|
||||
default:
|
||||
(void) strcat (options, " ");
|
||||
(void) strcat (options, argv[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
argc -= numopt;
|
||||
argv += numopt;
|
||||
for (i = 1; i < argc && argv[i][0] == '-'; i++)
|
||||
if (argv[i][1] == 'l')
|
||||
local = 1;
|
||||
|
||||
err = start_recursion (log_fileproc, (int (*) ()) NULL, log_dirproc,
|
||||
(int (*) ()) NULL, argc, argv, local,
|
||||
wrap_setup ();
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active) {
|
||||
/* We're the local client. Fire up the remote server. */
|
||||
start_server ();
|
||||
|
||||
ign_setup ();
|
||||
|
||||
for (i = 1; i < argc && argv[i][0] == '-'; i++)
|
||||
send_arg (argv[i]);
|
||||
|
||||
#if 0
|
||||
/* FIXME: We shouldn't have to send current files to get log entries, but it
|
||||
doesn't work yet and I haven't debugged it. So send the files --
|
||||
it's slower but it works. gnu@cygnus.com Apr94 */
|
||||
send_file_names (argc - i, argv + i);
|
||||
#else
|
||||
send_files (argc - i, argv + i, local, 0);
|
||||
#endif
|
||||
|
||||
if (fprintf (to_server, "log\n") < 0)
|
||||
error (1, errno, "writing to server");
|
||||
err = get_responses_and_close ();
|
||||
return err;
|
||||
}
|
||||
|
||||
ac = argc;
|
||||
av = argv;
|
||||
#endif
|
||||
|
||||
err = start_recursion (log_fileproc, (FILESDONEPROC) NULL, log_dirproc,
|
||||
(DIRLEAVEPROC) NULL, argc - i, argv + i, local,
|
||||
W_LOCAL | W_REPOS | W_ATTIC, 0, 1,
|
||||
(char *) NULL, 1, 0);
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do an rlog on a file
|
||||
*/
|
||||
|
|
@ -117,8 +135,23 @@ log_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
return (1);
|
||||
}
|
||||
|
||||
run_setup ("%s%s %s", Rcsbin, RCS_RLOG, options);
|
||||
run_setup ("%s%s", Rcsbin, RCS_RLOG);
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < ac && av[i][0] == '-'; i++)
|
||||
if (av[i][1] != 'l')
|
||||
run_arg (av[i]);
|
||||
}
|
||||
run_arg (rcsfile->path);
|
||||
|
||||
if (*update_dir)
|
||||
{
|
||||
char *workfile = xmalloc (strlen (update_dir) + strlen (file) + 2);
|
||||
sprintf (workfile, "%s/%s", update_dir, file);
|
||||
run_arg (workfile);
|
||||
free (workfile);
|
||||
}
|
||||
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_REALLY)) == -1)
|
||||
{
|
||||
error (1, errno, "fork failed for rlog on %s", file);
|
||||
|
|
|
|||
|
|
@ -7,18 +7,11 @@
|
|||
*/
|
||||
|
||||
#include "cvs.h"
|
||||
#include "getline.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)logmsg.c 1.48 94/09/29 $";
|
||||
USE(rcsid)
|
||||
#endif
|
||||
|
||||
/* this is slightly dangerous, since it could conflict with other systems'
|
||||
* own prototype.
|
||||
*/
|
||||
#if 0
|
||||
/* Which is why I'll nuke this */
|
||||
extern int gethostname PROTO((char *name, int len));
|
||||
static const char rcsid[] = "$CVSid: @(#)logmsg.c 1.48 94/09/29 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static int find_type PROTO((Node * p, void *closure));
|
||||
|
|
@ -33,7 +26,7 @@ static void setup_tmpfile PROTO((FILE * xfp, char *xprefix, List * changes));
|
|||
static int editinfo_proc PROTO((char *repository, char *template));
|
||||
|
||||
static FILE *fp;
|
||||
static char *strlist;
|
||||
static char *str_list;
|
||||
static char *editinfo_editor;
|
||||
static Ctype type;
|
||||
|
||||
|
|
@ -137,7 +130,10 @@ do_editor (dir, messagep, repository, changes)
|
|||
List *changes;
|
||||
{
|
||||
static int reuse_log_message = 0;
|
||||
char line[MAXLINELEN], fname[L_tmpnam+1];
|
||||
char *line;
|
||||
int line_length;
|
||||
size_t line_chars_allocated;
|
||||
char fname[L_tmpnam+1];
|
||||
struct stat pre_stbuf, post_stbuf;
|
||||
int retcode = 0;
|
||||
char *p;
|
||||
|
|
@ -171,7 +167,7 @@ do_editor (dir, messagep, repository, changes)
|
|||
(void) fprintf (fp,
|
||||
"%sEnter Log. Lines beginning with `%s' are removed automatically\n%s\n",
|
||||
CVSEDITPREFIX, CVSEDITPREFIX, CVSEDITPREFIX);
|
||||
if (dir != NULL)
|
||||
if (dir != NULL && *dir)
|
||||
(void) fprintf (fp, "%sCommitting in %s\n%s\n", CVSEDITPREFIX,
|
||||
dir, CVSEDITPREFIX);
|
||||
if (changes != NULL)
|
||||
|
|
@ -181,7 +177,8 @@ do_editor (dir, messagep, repository, changes)
|
|||
CVSEDITPREFIX);
|
||||
|
||||
/* finish off the temp file */
|
||||
(void) fclose (fp);
|
||||
if (fclose (fp) == EOF)
|
||||
error (1, errno, "%s", fname);
|
||||
if (stat (fname, &pre_stbuf) == -1)
|
||||
pre_stbuf.st_mtime = 0;
|
||||
|
||||
|
|
@ -214,25 +211,34 @@ do_editor (dir, messagep, repository, changes)
|
|||
*messagep = NULL;
|
||||
else
|
||||
{
|
||||
*messagep = (char *) xmalloc (post_stbuf.st_size);
|
||||
*messagep = (char *) xmalloc (post_stbuf.st_size + 1);
|
||||
*messagep[0] = '\0';
|
||||
}
|
||||
|
||||
/* !!! XXX FIXME: fgets is broken. This should not have any line
|
||||
length limits. */
|
||||
line = NULL;
|
||||
line_chars_allocated = 0;
|
||||
|
||||
if (*messagep)
|
||||
{
|
||||
p = *messagep;
|
||||
while (fgets (line, sizeof (line), fp) != NULL)
|
||||
while (1)
|
||||
{
|
||||
line_length = getline (&line, &line_chars_allocated, fp);
|
||||
if (line_length == -1)
|
||||
{
|
||||
if (ferror (fp))
|
||||
error (0, errno, "warning: cannot read %s", fname);
|
||||
break;
|
||||
}
|
||||
if (strncmp (line, CVSEDITPREFIX, sizeof (CVSEDITPREFIX) - 1) == 0)
|
||||
continue;
|
||||
(void) strcpy (p, line);
|
||||
p += strlen (line);
|
||||
p += line_length;
|
||||
}
|
||||
}
|
||||
(void) fclose (fp);
|
||||
if (fclose (fp) < 0)
|
||||
error (0, errno, "warning: cannot close %s", fname);
|
||||
|
||||
if (pre_stbuf.st_mtime == post_stbuf.st_mtime ||
|
||||
*messagep == NULL ||
|
||||
strcmp (*messagep, "\n") == 0)
|
||||
|
|
@ -243,9 +249,9 @@ do_editor (dir, messagep, repository, changes)
|
|||
(void) printf ("a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs\n");
|
||||
(void) printf ("Action: (continue) ");
|
||||
(void) fflush (stdout);
|
||||
*line = '\0';
|
||||
(void) fgets (line, sizeof (line), stdin);
|
||||
if (*line == '\0' || *line == '\n' || *line == 'c' || *line == 'C')
|
||||
line_length = getline (&line, &line_chars_allocated, stdin);
|
||||
if (line_length <= 0
|
||||
|| *line == '\n' || *line == 'c' || *line == 'C')
|
||||
break;
|
||||
if (*line == 'a' || *line == 'A')
|
||||
error (1, 0, "aborted by user");
|
||||
|
|
@ -259,7 +265,10 @@ do_editor (dir, messagep, repository, changes)
|
|||
(void) printf ("Unknown input\n");
|
||||
}
|
||||
}
|
||||
(void) unlink_file (fname);
|
||||
if (line)
|
||||
free (line);
|
||||
if (unlink_file (fname) < 0)
|
||||
error (0, errno, "warning: cannot remove temp file %s", fname);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -275,7 +284,6 @@ rcsinfo_proc (repository, template)
|
|||
{
|
||||
static char *last_template;
|
||||
FILE *tfp;
|
||||
char line[MAXLINELEN];
|
||||
|
||||
/* nothing to do if the last one included is the same as this one */
|
||||
if (last_template && strcmp (last_template, template) == 0)
|
||||
|
|
@ -286,14 +294,22 @@ rcsinfo_proc (repository, template)
|
|||
|
||||
if ((tfp = fopen (template, "r")) != NULL)
|
||||
{
|
||||
while (fgets (line, sizeof (line), tfp) != NULL)
|
||||
char *line;
|
||||
size_t line_chars_allocated;
|
||||
|
||||
while (getline (&line, &line_chars_allocated, tfp) >= 0)
|
||||
(void) fputs (line, fp);
|
||||
(void) fclose (tfp);
|
||||
if (ferror (tfp))
|
||||
error (0, errno, "warning: cannot read %s", template);
|
||||
if (fclose (tfp) < 0)
|
||||
error (0, errno, "warning: cannot close %s", template);
|
||||
if (line)
|
||||
free (line);
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
error (0, 0, "Couldn't open rcsinfo template file %s", template);
|
||||
error (0, errno, "Couldn't open rcsinfo template file %s", template);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
|
@ -334,9 +350,9 @@ Update_Logfile (repository, xmessage, xrevision, xlogfp, xchanges)
|
|||
srepos = Short_Repository (repository);
|
||||
|
||||
/* allocate a chunk of memory to hold the title string */
|
||||
if (!strlist)
|
||||
strlist = xmalloc (MAXLISTLEN);
|
||||
strlist[0] = '\0';
|
||||
if (!str_list)
|
||||
str_list = xmalloc (MAXLISTLEN);
|
||||
str_list[0] = '\0';
|
||||
|
||||
type = T_TITLE;
|
||||
(void) walklist (changes, title_proc, NULL);
|
||||
|
|
@ -346,12 +362,12 @@ Update_Logfile (repository, xmessage, xrevision, xlogfp, xchanges)
|
|||
(void) walklist (changes, title_proc, NULL);
|
||||
type = T_REMOVED;
|
||||
(void) walklist (changes, title_proc, NULL);
|
||||
title = xmalloc (strlen (srepos) + strlen (strlist) + 1 + 2); /* for 's */
|
||||
(void) sprintf (title, "'%s%s'", srepos, strlist);
|
||||
title = xmalloc (strlen (srepos) + strlen (str_list) + 1 + 2); /* for 's */
|
||||
(void) sprintf (title, "'%s%s'", srepos, str_list);
|
||||
|
||||
/* to be nice, free up this chunk of memory */
|
||||
free (strlist);
|
||||
strlist = (char *) NULL;
|
||||
free (str_list);
|
||||
str_list = (char *) NULL;
|
||||
|
||||
/* call Parse_Info to do the actual logfile updates */
|
||||
(void) Parse_Info (CVSROOTADM_LOGINFO, repository, update_logfile_proc, 1);
|
||||
|
|
@ -373,7 +389,7 @@ update_logfile_proc (repository, filter)
|
|||
}
|
||||
|
||||
/*
|
||||
* concatenate each name onto strlist
|
||||
* concatenate each name onto str_list
|
||||
*/
|
||||
static int
|
||||
title_proc (p, closure)
|
||||
|
|
@ -382,8 +398,8 @@ title_proc (p, closure)
|
|||
{
|
||||
if (p->data == (char *) type)
|
||||
{
|
||||
(void) strcat (strlist, " ");
|
||||
(void) strcat (strlist, p->key);
|
||||
(void) strcat (str_list, " ");
|
||||
(void) strcat (str_list, p->key);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
|
@ -409,12 +425,13 @@ logfile_write (repository, filter, title, message, revision, logfp, changes)
|
|||
FILE *logfp;
|
||||
List *changes;
|
||||
{
|
||||
char cwd[PATH_MAX], host[MAXHOSTNAMELEN];
|
||||
char cwd[PATH_MAX];
|
||||
FILE *pipefp, *Popen ();
|
||||
char *prog = xmalloc (MAXPROGLEN);
|
||||
char *cp;
|
||||
int c;
|
||||
|
||||
/* XXX <woods@web.net> -- this is gross, ugly, and a hack! FIXME! */
|
||||
/*
|
||||
* A maximum of 6 %s arguments are supported in the filter
|
||||
*/
|
||||
|
|
@ -426,10 +443,8 @@ logfile_write (repository, filter, title, message, revision, logfp, changes)
|
|||
free (prog);
|
||||
return (1);
|
||||
}
|
||||
if (gethostname (host, sizeof (host)) < 0)
|
||||
(void) strcpy (host, "(unknown)");
|
||||
(void) fprintf (pipefp, "Update of %s\n", repository);
|
||||
(void) fprintf (pipefp, "In directory %s:%s\n\n", host,
|
||||
(void) fprintf (pipefp, "In directory %s:%s\n\n", hostname,
|
||||
((cp = getwd (cwd)) != NULL) ? cp : cwd);
|
||||
if (revision && *revision)
|
||||
(void) fprintf (pipefp, "Revision/Branch: %s\n\n", revision);
|
||||
|
|
@ -438,7 +453,7 @@ logfile_write (repository, filter, title, message, revision, logfp, changes)
|
|||
if (logfp != (FILE *) 0)
|
||||
{
|
||||
(void) fprintf (pipefp, "Status:\n");
|
||||
(void) rewind (logfp);
|
||||
rewind (logfp);
|
||||
while ((c = getc (logfp)) != EOF)
|
||||
(void) putc ((char) c, pipefp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
* commit Checks files into the repository
|
||||
* diff Runs diffs between revisions
|
||||
* log Prints "rlog" information for files
|
||||
* login Record user, host, repos, password
|
||||
* add Adds an entry to the repository
|
||||
* remove Removes an entry from the repository
|
||||
* status Status info on the revisions
|
||||
|
|
@ -35,16 +36,40 @@
|
|||
#include "cvs.h"
|
||||
#include "patchlevel.h"
|
||||
|
||||
#ifndef lint
|
||||
char rcsid[] = "$CVSid: @(#)main.c 1.78 94/10/07 $\n";
|
||||
USE(rcsid)
|
||||
#if HAVE_KERBEROS
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <krb.h>
|
||||
#ifndef HAVE_KRB_GET_ERR_TEXT
|
||||
#define krb_get_err_text(status) krb_err_txt[status]
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern char *getenv ();
|
||||
#ifndef lint
|
||||
static const char rcsid[] = "$CVSid: @(#)main.c 1.78 94/10/07 $\n";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
char *program_name;
|
||||
char *command_name = "";
|
||||
char *program_path;
|
||||
/*
|
||||
* Initialize comamnd_name to "cvs" so that the first call to
|
||||
* read_cvsrc tries to find global cvs options.
|
||||
*/
|
||||
char *command_name = "cvs";
|
||||
|
||||
/*
|
||||
* Since some systems don't define this...
|
||||
*/
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 256
|
||||
#endif
|
||||
|
||||
char hostname[MAXHOSTNAMELEN];
|
||||
|
||||
#ifdef AUTH_CLIENT_SUPPORT
|
||||
int use_authenticating_server = FALSE;
|
||||
#endif /* AUTH_CLIENT_SUPPORT */
|
||||
int use_editor = TRUE;
|
||||
int use_cvsrc = TRUE;
|
||||
int cvswrite = !CVSREAD_DFLT;
|
||||
|
|
@ -53,6 +78,7 @@ int quiet = FALSE;
|
|||
int trace = FALSE;
|
||||
int noexec = FALSE;
|
||||
int logoff = FALSE;
|
||||
mode_t cvsumask = UMASK_DFLT;
|
||||
|
||||
char *CurDir;
|
||||
|
||||
|
|
@ -77,6 +103,9 @@ int diff PROTO((int argc, char **argv));
|
|||
int history PROTO((int argc, char **argv));
|
||||
int import PROTO((int argc, char **argv));
|
||||
int cvslog PROTO((int argc, char **argv));
|
||||
#ifdef AUTH_CLIENT_SUPPORT
|
||||
int login PROTO((int argc, char **argv));
|
||||
#endif /* AUTH_CLIENT_SUPPORT */
|
||||
int patch PROTO((int argc, char **argv));
|
||||
int release PROTO((int argc, char **argv));
|
||||
int cvsremove PROTO((int argc, char **argv));
|
||||
|
|
@ -85,41 +114,69 @@ int status PROTO((int argc, char **argv));
|
|||
int tag PROTO((int argc, char **argv));
|
||||
int update PROTO((int argc, char **argv));
|
||||
|
||||
struct cmd
|
||||
const struct cmd
|
||||
{
|
||||
char *fullname; /* Full name of the function (e.g. "commit") */
|
||||
char *nick1; /* alternate name (e.g. "ci") */
|
||||
char *nick2; /* another alternate names (e.g. "ci") */
|
||||
int (*func) (); /* Function takes (argc, argv) arguments. */
|
||||
#ifdef CLIENT_SUPPORT
|
||||
int (*client_func) (); /* Function to do it via the protocol. */
|
||||
#endif
|
||||
} cmds[] =
|
||||
|
||||
{
|
||||
{ "add", "ad", "new", add },
|
||||
{ "admin", "adm", "rcs", admin },
|
||||
{ "checkout", "co", "get", checkout },
|
||||
{ "commit", "ci", "com", commit },
|
||||
{ "diff", "di", "dif", diff },
|
||||
{ "export", "exp", "ex", checkout },
|
||||
{ "history", "hi", "his", history },
|
||||
{ "import", "im", "imp", import },
|
||||
{ "log", "lo", "rlog", cvslog },
|
||||
{ "rdiff", "patch", "pa", patch },
|
||||
{ "release", "re", "rel", release },
|
||||
{ "remove", "rm", "delete", cvsremove },
|
||||
{ "status", "st", "stat", status },
|
||||
{ "rtag", "rt", "rfreeze", rtag },
|
||||
{ "tag", "ta", "freeze", tag },
|
||||
{ "update", "up", "upd", update },
|
||||
{ NULL, NULL, NULL, NULL },
|
||||
#ifdef CLIENT_SUPPORT
|
||||
#define CMD_ENTRY(n1, n2, n3, f1, f2) { n1, n2, n3, f1, f2 }
|
||||
#else
|
||||
#define CMD_ENTRY(n1, n2, n3, f1, f2) { n1, n2, n3, f1 }
|
||||
#endif
|
||||
|
||||
CMD_ENTRY("add", "ad", "new", add, client_add),
|
||||
#ifndef CVS_NOADMIN
|
||||
CMD_ENTRY("admin", "adm", "rcs", admin, client_admin),
|
||||
#endif
|
||||
CMD_ENTRY("checkout", "co", "get", checkout, client_checkout),
|
||||
CMD_ENTRY("commit", "ci", "com", commit, client_commit),
|
||||
CMD_ENTRY("diff", "di", "dif", diff, client_diff),
|
||||
CMD_ENTRY("export", "exp", "ex", checkout, client_export),
|
||||
CMD_ENTRY("history", "hi", "his", history, client_history),
|
||||
CMD_ENTRY("import", "im", "imp", import, client_import),
|
||||
CMD_ENTRY("log", "lo", "rlog", cvslog, client_log),
|
||||
#ifdef AUTH_CLIENT_SUPPORT
|
||||
CMD_ENTRY("login", "logon", "lgn", login, login),
|
||||
#endif /* AUTH_CLIENT_SUPPORT */
|
||||
CMD_ENTRY("rdiff", "patch", "pa", patch, client_rdiff),
|
||||
CMD_ENTRY("release", "re", "rel", release, client_release),
|
||||
CMD_ENTRY("remove", "rm", "delete", cvsremove, client_remove),
|
||||
CMD_ENTRY("status", "st", "stat", status, client_status),
|
||||
CMD_ENTRY("rtag", "rt", "rfreeze", rtag, client_rtag),
|
||||
CMD_ENTRY("tag", "ta", "freeze", tag, client_tag),
|
||||
CMD_ENTRY("update", "up", "upd", update, client_update),
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
/*
|
||||
* The client_func is also server because we might have picked up a
|
||||
* CVSROOT environment variable containing a colon. The client will send
|
||||
* the real root later.
|
||||
*/
|
||||
CMD_ENTRY("server", "server", "server", server, server),
|
||||
#endif
|
||||
CMD_ENTRY(NULL, NULL, NULL, NULL, NULL),
|
||||
|
||||
#undef CMD_ENTRY
|
||||
};
|
||||
|
||||
static char *usg[] =
|
||||
static const char *const usg[] =
|
||||
{
|
||||
"Usage: %s [cvs-options] command [command-options] [files...]\n",
|
||||
" Where 'cvs-options' are:\n",
|
||||
" -H Displays Usage information for command\n",
|
||||
" -Q Cause CVS to be really quiet.\n",
|
||||
" -q Cause CVS to be somewhat quiet.\n",
|
||||
#ifdef AUTH_CLIENT_SUPPORT
|
||||
" -a Use the authenticating server, not rsh.\n",
|
||||
#endif /* AUTH_CLIENT_SUPPORT */
|
||||
" -r Make checked-out files read-only\n",
|
||||
" -w Make checked-out files read-write (default)\n",
|
||||
" -l Turn History logging off\n",
|
||||
|
|
@ -130,6 +187,9 @@ static char *usg[] =
|
|||
" -e editor Use 'editor' for editing log information\n",
|
||||
" -d CVS_root Overrides $CVSROOT as the root of the CVS tree\n",
|
||||
" -f Do not use the ~/.cvsrc file\n",
|
||||
#ifdef CLIENT_SUPPORT
|
||||
" -z # Use 'gzip -#' for net traffic if possible.\n",
|
||||
#endif
|
||||
"\n",
|
||||
" and where 'command' is:\n",
|
||||
" add Adds a new file/directory to the repository\n",
|
||||
|
|
@ -141,6 +201,9 @@ static char *usg[] =
|
|||
" import Import sources into CVS, using vendor branches\n",
|
||||
" export Export sources from CVS, similar to checkout\n",
|
||||
" log Prints out 'rlog' information for files\n",
|
||||
#ifdef AUTH_CLIENT_SUPPORT
|
||||
" login Prompt for password for authenticating server.\n",
|
||||
#endif /* AUTH_CLIENT_SUPPORT */
|
||||
" rdiff 'patch' format diffs between releases\n",
|
||||
" release Indicate that a Module is no longer in use\n",
|
||||
" remove Removes an entry from the repository\n",
|
||||
|
|
@ -157,29 +220,61 @@ main_cleanup ()
|
|||
exit (1);
|
||||
}
|
||||
|
||||
static void
|
||||
error_cleanup ()
|
||||
{
|
||||
Lock_Cleanup();
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
server_cleanup (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
extern char *version_string;
|
||||
char *cp;
|
||||
struct cmd *cm;
|
||||
int c, help = FALSE, err = 0;
|
||||
extern char *config_string;
|
||||
char *cp, *end;
|
||||
const struct cmd *cm;
|
||||
int c, err = 0;
|
||||
static int help = FALSE, version_flag = FALSE;
|
||||
int rcsbin_update_env, cvs_update_env = 0;
|
||||
char tmp[PATH_MAX];
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"help", 0, &help, TRUE},
|
||||
{"version", 0, &version_flag, TRUE},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
/* `getopt_long' stores the option index here, but right now we
|
||||
don't use it. */
|
||||
int option_index = 0;
|
||||
|
||||
error_set_cleanup (error_cleanup);
|
||||
|
||||
/* The IBM TCP/IP library under OS/2 needs to be initialized: */
|
||||
#ifdef NEED_CALL_SOCKINIT
|
||||
if (SockInit () != TRUE)
|
||||
{
|
||||
fprintf (stderr, "SockInit() failed!\n");
|
||||
exit (1);
|
||||
}
|
||||
#endif /* NEED_CALL_SOCKINIT */
|
||||
|
||||
/*
|
||||
* Just save the last component of the path for error messages
|
||||
*/
|
||||
if ((program_name = strrchr (argv[0], '/')) == NULL)
|
||||
program_name = argv[0];
|
||||
else
|
||||
program_name++;
|
||||
program_path = xstrdup (argv[0]);
|
||||
program_name = last_component (argv[0]);
|
||||
|
||||
CurDir = xmalloc (PATH_MAX);
|
||||
#ifndef SERVER_SUPPORT
|
||||
if (!getwd (CurDir))
|
||||
error (1, 0, "cannot get working directory: %s", CurDir);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Query the environment variables up-front, so that
|
||||
|
|
@ -196,6 +291,8 @@ main (argc, argv)
|
|||
Editor = cp;
|
||||
else if ((cp = getenv (EDITOR2_ENV)) != NULL)
|
||||
Editor = cp;
|
||||
else if ((cp = getenv (EDITOR3_ENV)) != NULL)
|
||||
Editor = cp;
|
||||
if ((cp = getenv (CVSROOT_ENV)) != NULL)
|
||||
{
|
||||
CVSroot = cp;
|
||||
|
|
@ -203,12 +300,36 @@ main (argc, argv)
|
|||
}
|
||||
if (getenv (CVSREAD_ENV) != NULL)
|
||||
cvswrite = FALSE;
|
||||
|
||||
optind = 1;
|
||||
while ((c = getopt (argc, argv, "Qqrwtnlvb:e:d:Hf")) != -1)
|
||||
if ((cp = getenv (CVSUMASK_ENV)) != NULL)
|
||||
{
|
||||
/* FIXME: Should be accepting symbolic as well as numeric mask. */
|
||||
cvsumask = strtol (cp, &end, 8) & 0777;
|
||||
if (*end != '\0')
|
||||
error (1, errno, "invalid umask value in %s (%s)",
|
||||
CVSUMASK_ENV, cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan cvsrc file for global options.
|
||||
*/
|
||||
read_cvsrc(&argc, &argv);
|
||||
|
||||
/* This has the effect of setting getopt's ordering to REQUIRE_ORDER,
|
||||
which is what we need to distinguish between global options and
|
||||
command options. FIXME: It would appear to be possible to do this
|
||||
much less kludgily by passing "+" as the first character to the
|
||||
option string we pass to getopt_long. */
|
||||
optind = 1;
|
||||
|
||||
while ((c = getopt_long
|
||||
(argc, argv, "Qqrawtnlvb:e:d:Hfz:", long_options, &option_index))
|
||||
!= EOF)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
{
|
||||
case 0:
|
||||
/* getopt_long took care of setting the flag. */
|
||||
break;
|
||||
case 'Q':
|
||||
really_quiet = TRUE;
|
||||
/* FALL THROUGH */
|
||||
|
|
@ -218,6 +339,11 @@ main (argc, argv)
|
|||
case 'r':
|
||||
cvswrite = FALSE;
|
||||
break;
|
||||
#ifdef AUTH_CLIENT_SUPPORT
|
||||
case 'a':
|
||||
use_authenticating_server = TRUE;
|
||||
break;
|
||||
#endif /* AUTH_CLIENT_SUPPORT */
|
||||
case 'w':
|
||||
cvswrite = TRUE;
|
||||
break;
|
||||
|
|
@ -230,11 +356,7 @@ main (argc, argv)
|
|||
logoff = TRUE;
|
||||
break;
|
||||
case 'v':
|
||||
(void) fputs (version_string, stdout);
|
||||
(void) sprintf (tmp, "Patch Level: %d\n", PATCHLEVEL);
|
||||
(void) fputs (tmp, stdout);
|
||||
(void) fputs ("\nCopyright (c) 1993-1994 Brian Berliner\nCopyright (c) 1993-1994 david d `zoo' zuhn\nCopyright (c) 1992, Brian Berliner and Jeff Polk\nCopyright (c) 1989-1992, Brian Berliner\n\nCVS may be copied only under the terms of the GNU General Public License,\na copy of which can be found with the CVS distribution kit.\n", stdout);
|
||||
exit (0);
|
||||
version_flag = TRUE;
|
||||
break;
|
||||
case 'b':
|
||||
Rcsbin = optarg;
|
||||
|
|
@ -254,55 +376,181 @@ main (argc, argv)
|
|||
case 'f':
|
||||
use_cvsrc = FALSE;
|
||||
break;
|
||||
#ifdef CLIENT_SUPPORT
|
||||
case 'z':
|
||||
gzip_level = atoi (optarg);
|
||||
if (gzip_level <= 0 || gzip_level > 9)
|
||||
error (1, 0,
|
||||
"gzip compression level must be between 1 and 9");
|
||||
break;
|
||||
#endif
|
||||
case '?':
|
||||
default:
|
||||
usage (usg);
|
||||
usage (usg);
|
||||
}
|
||||
}
|
||||
|
||||
if (version_flag == TRUE)
|
||||
{
|
||||
(void) fputs (version_string, stdout);
|
||||
(void) fputs (config_string, stdout);
|
||||
(void) sprintf (tmp, "Patch Level: %d\n", PATCHLEVEL);
|
||||
(void) fputs (tmp, stdout);
|
||||
(void) fputs ("\n", stdout);
|
||||
(void) fputs ("Copyright (c) 1993-1994 Brian Berliner\n", stdout);
|
||||
(void) fputs ("Copyright (c) 1993-1994 david d `zoo' zuhn\n", stdout);
|
||||
(void) fputs ("Copyright (c) 1992, Brian Berliner and Jeff Polk\n", stdout);
|
||||
(void) fputs ("Copyright (c) 1989-1992, Brian Berliner\n", stdout);
|
||||
(void) fputs ("\n", stdout);
|
||||
(void) fputs ("CVS may be copied only under the terms of the GNU General Public License,\n", stdout);
|
||||
(void) fputs ("a copy of which can be found with the CVS distribution kit.\n", stdout);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc < 1)
|
||||
usage (usg);
|
||||
|
||||
#ifdef HAVE_KERBEROS
|
||||
/* If we are invoked with a single argument "kserver", then we are
|
||||
running as Kerberos server as root. Do the authentication as
|
||||
the very first thing, to minimize the amount of time we are
|
||||
running as root. */
|
||||
if (strcmp (argv[0], "kserver") == 0)
|
||||
{
|
||||
int status;
|
||||
char instance[INST_SZ];
|
||||
struct sockaddr_in peer;
|
||||
struct sockaddr_in laddr;
|
||||
int len;
|
||||
KTEXT_ST ticket;
|
||||
AUTH_DAT auth;
|
||||
char version[KRB_SENDAUTH_VLEN];
|
||||
Key_schedule sched;
|
||||
char user[ANAME_SZ];
|
||||
struct passwd *pw;
|
||||
|
||||
strcpy (instance, "*");
|
||||
len = sizeof peer;
|
||||
if (getpeername (STDIN_FILENO, (struct sockaddr *) &peer, &len) < 0
|
||||
|| getsockname (STDIN_FILENO, (struct sockaddr *) &laddr,
|
||||
&len) < 0)
|
||||
{
|
||||
printf ("E Fatal error, aborting.\n\
|
||||
error %s getpeername or getsockname failed\n", strerror (errno));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
status = krb_recvauth (KOPT_DO_MUTUAL, STDIN_FILENO, &ticket, "rcmd",
|
||||
instance, &peer, &laddr, &auth, "", sched,
|
||||
version);
|
||||
if (status != KSUCCESS)
|
||||
{
|
||||
printf ("E Fatal error, aborting.\n\
|
||||
error 0 kerberos: %s\n", krb_get_err_text(status));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* Get the local name. */
|
||||
status = krb_kntoln (&auth, user);
|
||||
if (status != KSUCCESS)
|
||||
{
|
||||
printf ("E Fatal error, aborting.\n\
|
||||
error 0 kerberos: can't get local name: %s\n", krb_get_err_text(status));
|
||||
exit (1);
|
||||
}
|
||||
|
||||
pw = getpwnam (user);
|
||||
if (pw == NULL)
|
||||
{
|
||||
printf ("E Fatal error, aborting.\n\
|
||||
error 0 %s: no such user\n", user);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
initgroups (pw->pw_name, pw->pw_gid);
|
||||
setgid (pw->pw_gid);
|
||||
setuid (pw->pw_uid);
|
||||
/* Inhibit access by randoms. Don't want people randomly
|
||||
changing our temporary tree before we check things in. */
|
||||
umask (077);
|
||||
|
||||
#if HAVE_PUTENV
|
||||
/* Set LOGNAME and USER in the environment, in case they are
|
||||
already set to something else. */
|
||||
{
|
||||
char *env;
|
||||
|
||||
env = xmalloc (sizeof "LOGNAME=" + strlen (user));
|
||||
(void) sprintf (env, "LOGNAME=%s", user);
|
||||
(void) putenv (env);
|
||||
|
||||
env = xmalloc (sizeof "USER=" + strlen (user));
|
||||
(void) sprintf (env, "USER=%s", user);
|
||||
(void) putenv (env);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Pretend we were invoked as a plain server. */
|
||||
argv[0] = "server";
|
||||
}
|
||||
#endif /* HAVE_KERBEROS */
|
||||
|
||||
|
||||
#if defined(AUTH_SERVER_SUPPORT) && defined(SERVER_SUPPORT)
|
||||
if (strcmp (argv[0], "pserver") == 0)
|
||||
{
|
||||
/* Gets username and password from client, authenticates, then
|
||||
switches to run as that user and sends an ACK back to the
|
||||
client. */
|
||||
authenticate_connection ();
|
||||
|
||||
/* Pretend we were invoked as a plain server. */
|
||||
argv[0] = "server";
|
||||
}
|
||||
#endif /* AUTH_SERVER_SUPPORT && SERVER_SUPPORT */
|
||||
|
||||
|
||||
#ifdef CVSADM_ROOT
|
||||
/*
|
||||
* See if we are able to find a 'better' value for CVSroot in the
|
||||
* CVSADM_ROOT directory.
|
||||
*/
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (strcmp (argv[0], "server") == 0 && CVSroot == NULL)
|
||||
CVSADM_Root = NULL;
|
||||
else
|
||||
CVSADM_Root = Name_Root((char *) NULL, (char *) NULL);
|
||||
#else /* No SERVER_SUPPORT */
|
||||
CVSADM_Root = Name_Root((char *) NULL, (char *) NULL);
|
||||
#endif /* No SERVER_SUPPORT */
|
||||
if (CVSADM_Root != NULL)
|
||||
{
|
||||
if (CVSroot == NULL)
|
||||
if (CVSroot == NULL || !cvs_update_env)
|
||||
{
|
||||
CVSroot = CVSADM_Root;
|
||||
cvs_update_env = 1; /* need to update environment */
|
||||
}
|
||||
#ifdef CLIENT_SUPPORT
|
||||
else if (!getenv ("CVS_IGNORE_REMOTE_ROOT"))
|
||||
#else
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* Now for the hard part, compare the two directories. If they
|
||||
* are not identical, then abort this command.
|
||||
*/
|
||||
if ((strcmp (CVSroot, CVSADM_Root) != 0) &&
|
||||
if ((fncmp (CVSroot, CVSADM_Root) != 0) &&
|
||||
!same_directories(CVSroot, CVSADM_Root))
|
||||
{
|
||||
error (0, 0, "%s value for CVS Root found in %s",
|
||||
CVSADM_Root, CVSADM_ROOT);
|
||||
if (cvs_update_env)
|
||||
{
|
||||
error (0, 0, "does not match command line -d %s setting",
|
||||
CVSroot);
|
||||
error (1, 0,
|
||||
"you may wish to try the cvs command again without the -d option ");
|
||||
}
|
||||
else
|
||||
{
|
||||
error (0, 0,
|
||||
"does not match CVSROOT environment value of %s",
|
||||
CVSroot);
|
||||
error (1, 0,
|
||||
"you may wish to unsetenv CVSROOT and try again");
|
||||
}
|
||||
error (0, 0, "%s value for CVS Root found in %s",
|
||||
CVSADM_Root, CVSADM_ROOT);
|
||||
error (0, 0, "does not match command line -d %s setting",
|
||||
CVSroot);
|
||||
error (1, 0,
|
||||
"you may wish to try the cvs command again without the -d option ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -322,6 +570,9 @@ main (argc, argv)
|
|||
* we assume that we can't work in the repository.
|
||||
* BUT, only if the history file exists.
|
||||
*/
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (strcmp (command_name, "server") != 0 || CVSroot != NULL)
|
||||
#endif
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
int save_errno;
|
||||
|
|
@ -330,16 +581,23 @@ main (argc, argv)
|
|||
error (1, 0, "You don't have a %s environment variable",
|
||||
CVSROOT_ENV);
|
||||
(void) sprintf (path, "%s/%s", CVSroot, CVSROOTADM);
|
||||
if (access (path, R_OK | X_OK))
|
||||
if (!isaccessible (path, R_OK | X_OK))
|
||||
{
|
||||
save_errno = errno;
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (strchr (CVSroot, ':') == NULL)
|
||||
{
|
||||
#endif
|
||||
error (0, 0,
|
||||
"Sorry, you don't have sufficient access to %s", CVSroot);
|
||||
error (1, save_errno, "%s", path);
|
||||
#ifdef CLIENT_SUPPORT
|
||||
}
|
||||
#endif
|
||||
}
|
||||
(void) strcat (path, "/");
|
||||
(void) strcat (path, CVSROOTADM_HISTORY);
|
||||
if (isfile (path) && access (path, R_OK | W_OK))
|
||||
if (isfile (path) && !isaccessible (path, R_OK | W_OK))
|
||||
{
|
||||
save_errno = errno;
|
||||
error (0, 0,
|
||||
|
|
@ -349,6 +607,16 @@ main (argc, argv)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (strcmp (command_name, "server") == 0)
|
||||
/* This is only used for writing into the history file. Might
|
||||
be nice to have hostname and/or remote path, on the other hand
|
||||
I'm not sure whether it is worth the trouble. */
|
||||
strcpy (CurDir, "<remote>");
|
||||
else if (!getwd (CurDir))
|
||||
error (1, 0, "cannot get working directory: %s", CurDir);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PUTENV
|
||||
/* Now, see if we should update the environment with the Rcsbin value */
|
||||
if (cvs_update_env)
|
||||
|
|
@ -404,11 +672,30 @@ main (argc, argv)
|
|||
else
|
||||
{
|
||||
command_name = cm->fullname; /* Global pointer for later use */
|
||||
|
||||
/* make sure we clean up on error */
|
||||
#ifdef SIGHUP
|
||||
(void) SIG_register (SIGHUP, main_cleanup);
|
||||
(void) SIG_register (SIGHUP, Lock_Cleanup);
|
||||
#endif
|
||||
#ifdef SIGINT
|
||||
(void) SIG_register (SIGINT, main_cleanup);
|
||||
(void) SIG_register (SIGINT, Lock_Cleanup);
|
||||
#endif
|
||||
#ifdef SIGQUIT
|
||||
(void) SIG_register (SIGQUIT, main_cleanup);
|
||||
(void) SIG_register (SIGQUIT, Lock_Cleanup);
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
(void) SIG_register (SIGPIPE, main_cleanup);
|
||||
(void) SIG_register (SIGPIPE, Lock_Cleanup);
|
||||
#endif
|
||||
#ifdef SIGTERM
|
||||
(void) SIG_register (SIGTERM, main_cleanup);
|
||||
(void) SIG_register (SIGTERM, Lock_Cleanup);
|
||||
#endif
|
||||
|
||||
gethostname(hostname, sizeof (hostname));
|
||||
|
||||
#ifdef HAVE_SETVBUF
|
||||
/*
|
||||
|
|
@ -422,8 +709,19 @@ main (argc, argv)
|
|||
if (use_cvsrc)
|
||||
read_cvsrc(&argc, &argv);
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
/* If cvsroot contains a colon, try to do it via the protocol. */
|
||||
{
|
||||
char *p = CVSroot == NULL ? NULL : strchr (CVSroot, ':');
|
||||
if (p)
|
||||
err = (*(cm->client_func)) (argc, argv);
|
||||
else
|
||||
err = (*(cm->func)) (argc, argv);
|
||||
}
|
||||
#else /* No CLIENT_SUPPORT */
|
||||
err = (*(cm->func)) (argc, argv);
|
||||
|
||||
#endif /* No CLIENT_SUPPORT */
|
||||
}
|
||||
/*
|
||||
* If the command's error count is modulo 256, we need to change it
|
||||
|
|
@ -462,7 +760,7 @@ Make_Date (rawdate)
|
|||
|
||||
void
|
||||
usage (cpp)
|
||||
register char **cpp;
|
||||
register const char *const *cpp;
|
||||
{
|
||||
(void) fprintf (stderr, *cpp++, program_name, command_name);
|
||||
for (; *cpp; cpp++)
|
||||
|
|
|
|||
|
|
@ -21,10 +21,11 @@
|
|||
*/
|
||||
|
||||
#include "cvs.h"
|
||||
#include "save-cwd.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)modules.c 1.62 94/09/29 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)modules.c 1.62 94/09/29 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
struct sortrec
|
||||
|
|
@ -35,7 +36,7 @@ struct sortrec
|
|||
char *comment;
|
||||
};
|
||||
|
||||
static int sort_order PROTO((CONST PTR l, CONST PTR r));
|
||||
static int sort_order PROTO((const PTR l, const PTR r));
|
||||
static void save_d PROTO((char *k, int ks, char *d, int ds));
|
||||
|
||||
|
||||
|
|
@ -83,7 +84,7 @@ do_module (db, mname, m_type, msg, callback_proc, where,
|
|||
char *mname;
|
||||
enum mtype m_type;
|
||||
char *msg;
|
||||
int (*callback_proc) ();
|
||||
CALLBACKPROC callback_proc;
|
||||
char *where;
|
||||
int shorten;
|
||||
int local_specified;
|
||||
|
|
@ -92,26 +93,39 @@ do_module (db, mname, m_type, msg, callback_proc, where,
|
|||
{
|
||||
char *checkin_prog = NULL;
|
||||
char *checkout_prog = NULL;
|
||||
char *export_prog = NULL;
|
||||
char *tag_prog = NULL;
|
||||
char *update_prog = NULL;
|
||||
char cwd[PATH_MAX];
|
||||
struct saved_cwd cwd;
|
||||
char line[MAXLINELEN];
|
||||
char *xmodargv[MAXFILEPERDIR];
|
||||
int modargc;
|
||||
int xmodargc;
|
||||
char **modargv;
|
||||
char *xmodargv[MAXFILEPERDIR];
|
||||
char *value;
|
||||
char *zvalue;
|
||||
char *mwhere = NULL;
|
||||
char *mfile = NULL;
|
||||
char *spec_opt = NULL;
|
||||
char xvalue[PATH_MAX];
|
||||
int modargc, alias = 0;
|
||||
int alias = 0;
|
||||
datum key, val;
|
||||
char *cp;
|
||||
int c, err = 0;
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (trace)
|
||||
{
|
||||
fprintf (stderr, "%c-> do_module (%s, %s, %s, %s)\n",
|
||||
(server_active) ? 'S' : ' ',
|
||||
mname, msg, where ? where : "",
|
||||
extra_arg ? extra_arg : "");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* remember where we start */
|
||||
if (getwd (cwd) == NULL)
|
||||
error (1, 0, "cannot get current working directory: %s", cwd);
|
||||
if (save_cwd (&cwd))
|
||||
exit (1);
|
||||
|
||||
/* if this is a directory to ignore, add it to that list */
|
||||
if (mname[0] == '!' && mname[1] != '\0')
|
||||
|
|
@ -329,18 +343,24 @@ do_module (db, mname, m_type, msg, callback_proc, where,
|
|||
err++;
|
||||
goto out;
|
||||
}
|
||||
if (!isfile (CVSADM) && !isfile (OCVSADM))
|
||||
if (!isfile (CVSADM))
|
||||
{
|
||||
char nullrepos[PATH_MAX];
|
||||
|
||||
(void) sprintf (nullrepos, "%s/%s/%s", CVSroot,
|
||||
CVSROOTADM, CVSNULLREPOS);
|
||||
if (!isfile (nullrepos))
|
||||
(void) mkdir (nullrepos, 0777);
|
||||
{
|
||||
mode_t omask;
|
||||
omask = umask (cvsumask);
|
||||
(void) CVS_MKDIR (nullrepos, 0777);
|
||||
(void) umask (omask);
|
||||
}
|
||||
if (!isdir (nullrepos))
|
||||
error (1, 0, "there is no repository %s", nullrepos);
|
||||
|
||||
Create_Admin (".", nullrepos, (char *) NULL, (char *) NULL);
|
||||
Create_Admin (".", dir,
|
||||
nullrepos, (char *) NULL, (char *) NULL);
|
||||
if (!noexec)
|
||||
{
|
||||
FILE *fp;
|
||||
|
|
@ -348,6 +368,10 @@ do_module (db, mname, m_type, msg, callback_proc, where,
|
|||
fp = open_file (CVSADM_ENTSTAT, "w+");
|
||||
if (fclose (fp) == EOF)
|
||||
error (1, errno, "cannot close %s", CVSADM_ENTSTAT);
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
server_set_entstat (dir, nullrepos);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
out:
|
||||
|
|
@ -372,7 +396,8 @@ do_module (db, mname, m_type, msg, callback_proc, where,
|
|||
(void) sprintf (line, "%s %s", "XXX", value);
|
||||
|
||||
/* turn the line into an argv[] array */
|
||||
line2argv (&modargc, xmodargv, line);
|
||||
line2argv (&xmodargc, xmodargv, line);
|
||||
modargc = xmodargc;
|
||||
modargv = xmodargv;
|
||||
|
||||
/* parse the args */
|
||||
|
|
@ -397,6 +422,9 @@ do_module (db, mname, m_type, msg, callback_proc, where,
|
|||
case 'o':
|
||||
checkout_prog = optarg;
|
||||
break;
|
||||
case 'e':
|
||||
export_prog = optarg;
|
||||
break;
|
||||
case 't':
|
||||
tag_prog = optarg;
|
||||
break;
|
||||
|
|
@ -451,8 +479,12 @@ do_module (db, mname, m_type, msg, callback_proc, where,
|
|||
err += callback_proc (&modargc, modargv, where, mwhere, mfile, shorten,
|
||||
local_specified, mname, msg);
|
||||
|
||||
/* clean up */
|
||||
free_names (&modargc, modargv);
|
||||
#if 0
|
||||
/* FIXME: I've fixed this so that the correct arguments are called,
|
||||
but now this fails because there is code below this point that
|
||||
uses optarg values extracted from the arg vector. */
|
||||
free_names (&xmodargc, xmodargv);
|
||||
#endif
|
||||
|
||||
/* if there were special include args, process them now */
|
||||
|
||||
|
|
@ -495,6 +527,16 @@ do_module (db, mname, m_type, msg, callback_proc, where,
|
|||
}
|
||||
|
||||
/* write out the checkin/update prog files if necessary */
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (err == 0 && !noexec && m_type == CHECKOUT && server_expanding)
|
||||
{
|
||||
if (checkin_prog != NULL)
|
||||
server_prog (where ? where : mname, checkin_prog, PROG_CHECKIN);
|
||||
if (update_prog != NULL)
|
||||
server_prog (where ? where : mname, update_prog, PROG_UPDATE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (err == 0 && !noexec && m_type == CHECKOUT && run_module_prog)
|
||||
{
|
||||
FILE *fp;
|
||||
|
|
@ -516,23 +558,26 @@ do_module (db, mname, m_type, msg, callback_proc, where,
|
|||
}
|
||||
|
||||
/* cd back to where we started */
|
||||
if (chdir (cwd) < 0)
|
||||
error (1, errno, "failed chdir to %s!", cwd);
|
||||
if (restore_cwd (&cwd, NULL))
|
||||
exit (1);
|
||||
free_cwd (&cwd);
|
||||
|
||||
/* run checkout or tag prog if appropriate */
|
||||
if (err == 0 && run_module_prog)
|
||||
{
|
||||
if ((m_type == TAG && tag_prog != NULL) ||
|
||||
(m_type == CHECKOUT && checkout_prog != NULL))
|
||||
(m_type == CHECKOUT && checkout_prog != NULL) ||
|
||||
(m_type == EXPORT && export_prog != NULL))
|
||||
{
|
||||
/*
|
||||
* If a relative pathname is specified as the checkout or
|
||||
* tag proc, try to tack on the current "where" value.
|
||||
* If a relative pathname is specified as the checkout, tag
|
||||
* or export proc, try to tack on the current "where" value.
|
||||
* if we can't find a matching program, just punt and use
|
||||
* whatever is specified in the modules file.
|
||||
*/
|
||||
char real_prog[PATH_MAX];
|
||||
char *prog = (m_type == TAG ? tag_prog : checkout_prog);
|
||||
char *prog = (m_type == TAG ? tag_prog :
|
||||
(m_type == CHECKOUT ? checkout_prog : export_prog));
|
||||
char *real_where = (where != NULL ? where : mwhere);
|
||||
|
||||
if ((*prog != '/') && (*prog != '.'))
|
||||
|
|
@ -594,7 +639,10 @@ static struct sortrec *s_head;
|
|||
static int s_max = 0; /* Number of elements allocated */
|
||||
static int s_count = 0; /* Number of elements used */
|
||||
|
||||
static int Status;
|
||||
static int Status; /* Nonzero if the user is
|
||||
interested in status
|
||||
information as well as
|
||||
module name */
|
||||
static char def_status[] = "NONE";
|
||||
|
||||
/* Sort routine for qsort:
|
||||
|
|
@ -604,12 +652,12 @@ static char def_status[] = "NONE";
|
|||
*/
|
||||
static int
|
||||
sort_order (l, r)
|
||||
CONST PTR l;
|
||||
CONST PTR r;
|
||||
const PTR l;
|
||||
const PTR r;
|
||||
{
|
||||
int i;
|
||||
CONST struct sortrec *left = (CONST struct sortrec *) l;
|
||||
CONST struct sortrec *right = (CONST struct sortrec *) r;
|
||||
const struct sortrec *left = (const struct sortrec *) l;
|
||||
const struct sortrec *right = (const struct sortrec *) r;
|
||||
|
||||
if (Status)
|
||||
{
|
||||
|
|
@ -700,6 +748,9 @@ save_d (k, ks, d, ds)
|
|||
s_count++;
|
||||
}
|
||||
|
||||
/* Print out the module database as we know it. If STATUS is
|
||||
non-zero, print out status information for each module. */
|
||||
|
||||
void
|
||||
cat_module (status)
|
||||
int status;
|
||||
|
|
@ -827,5 +878,7 @@ cat_module (status)
|
|||
*cp++ = '\0';
|
||||
(void) printf ("%s\n", cp2);
|
||||
}
|
||||
|
||||
free_names(&moduleargc, moduleargv);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)no_diff.c 1.39 94/10/07 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)no_diff.c 1.39 94/10/07 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
int
|
||||
|
|
@ -34,6 +34,7 @@ No_Difference (file, vers, entries, repository, update_dir)
|
|||
int ret;
|
||||
char *ts, *options;
|
||||
int retcode = 0;
|
||||
char *tocvsPath;
|
||||
|
||||
if (!vers->srcfile || !vers->srcfile->path)
|
||||
return (-1); /* different since we couldn't tell */
|
||||
|
|
@ -48,20 +49,39 @@ No_Difference (file, vers, entries, repository, update_dir)
|
|||
run_arg (vers->srcfile->path);
|
||||
if ((retcode = run_exec (RUN_TTY, tmpnam (tmp), RUN_TTY, RUN_REALLY)) == 0)
|
||||
{
|
||||
#if 0
|
||||
/* Why would we want to munge the modes? And only if the timestamps
|
||||
are different? And even for commands like "cvs status"???? */
|
||||
if (!iswritable (file)) /* fix the modes as a side effect */
|
||||
xchmod (file, 1);
|
||||
#endif
|
||||
|
||||
tocvsPath = wrap_tocvs_process_file (file);
|
||||
|
||||
/* do the byte by byte compare */
|
||||
if (xcmp (file, tmp) == 0)
|
||||
if (xcmp (tocvsPath == NULL ? file : tocvsPath, tmp) == 0)
|
||||
{
|
||||
#if 0
|
||||
/* Why would we want to munge the modes? And only if the
|
||||
timestamps are different? And even for commands like
|
||||
"cvs status"???? */
|
||||
if (cvswrite == FALSE) /* fix the modes as a side effect */
|
||||
xchmod (file, 0);
|
||||
#endif
|
||||
|
||||
/* no difference was found, so fix the entries file */
|
||||
ts = time_stamp (file);
|
||||
Register (entries, file,
|
||||
vers->vn_user ? vers->vn_user : vers->vn_rcs, ts,
|
||||
options, vers->tag, vers->date, (char *) 0);
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
{
|
||||
/* We need to update the entries line on the client side. */
|
||||
server_update_entries
|
||||
(file, update_dir, repository, SERVER_UPDATED);
|
||||
}
|
||||
#endif
|
||||
free (ts);
|
||||
|
||||
/* update the entdata pointer in the vers_ts structure */
|
||||
|
|
@ -72,10 +92,25 @@ No_Difference (file, vers, entries, repository, update_dir)
|
|||
}
|
||||
else
|
||||
ret = 1; /* files were really different */
|
||||
if (tocvsPath)
|
||||
{
|
||||
/* Need to call unlink myself because the noexec variable
|
||||
* has been set to 1. */
|
||||
if (trace)
|
||||
(void) fprintf (stderr, "%c-> unlink (%s)\n",
|
||||
#ifdef SERVER_SUPPORT
|
||||
(server_active) ? 'S' : ' ',
|
||||
#else
|
||||
' ',
|
||||
#endif
|
||||
tocvsPath);
|
||||
if (unlink (tocvsPath) < 0)
|
||||
error (0, errno, "could not remove %s", tocvsPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (update_dir[0] == '\0')
|
||||
if (update_dir[0] == '\0')
|
||||
error (0, retcode == -1 ? errno : 0,
|
||||
"could not check out revision %s of %s",
|
||||
vers->vn_user, file);
|
||||
|
|
@ -87,7 +122,12 @@ No_Difference (file, vers, entries, repository, update_dir)
|
|||
}
|
||||
|
||||
if (trace)
|
||||
(void) fprintf (stderr, "-> unlink(%s)\n", tmp);
|
||||
#ifdef SERVER_SUPPORT
|
||||
(void) fprintf (stderr, "%c-> unlink2 (%s)\n",
|
||||
(server_active) ? 'S' : ' ', tmp);
|
||||
#else
|
||||
(void) fprintf (stderr, "-> unlink (%s)\n", tmp);
|
||||
#endif
|
||||
if (unlink (tmp) < 0)
|
||||
error (0, errno, "could not remove %s", tmp);
|
||||
free (options);
|
||||
|
|
|
|||
|
|
@ -53,26 +53,30 @@
|
|||
|
||||
/*
|
||||
* The "diff" program to execute when creating patch output. This "diff"
|
||||
* must support the "-c" option for context diffing. Specify a full pathname
|
||||
* if your site wants to use a particular diff. If you are using the GNU
|
||||
* version of diff (version 1.15 or later), this should be "diff -a".
|
||||
* must support the "-c" option for context diffing. Specify a full
|
||||
* pathname if your site wants to use a particular diff. If you are
|
||||
* using the GNU version of diff (version 1.15 or later), this should
|
||||
* be "diff -a".
|
||||
*
|
||||
* NOTE: this program is only used for the ``patch'' sub-command. The other
|
||||
* commands use rcsdiff which will use whatever version of diff was specified
|
||||
* NOTE: this program is only used for the ``patch'' sub-command (and
|
||||
* for ``update'' if you are using the server). The other commands
|
||||
* use rcsdiff which will use whatever version of diff was specified
|
||||
* when rcsdiff was built on your system.
|
||||
*/
|
||||
|
||||
#ifndef DIFF
|
||||
#define DIFF "diff"
|
||||
#define DIFF "/usr/bin/diff -a"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The "grep" program to execute when checking to see if a merged file had
|
||||
* any conflicts. This "grep" must support the "-s" option and a standard
|
||||
* any conflicts. This "grep" must support a standard basic
|
||||
* regular expression as an argument. Specify a full pathname if your site
|
||||
* wants to use a particular grep.
|
||||
*/
|
||||
|
||||
#ifndef GREP
|
||||
#define GREP "grep"
|
||||
#define GREP "grep"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -92,6 +96,15 @@
|
|||
#define SORT "sort"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The "patch" program to run when using the CVS server and accepting
|
||||
* patches across the network. Specify a full pathname if your site
|
||||
* wants to use a particular patch.
|
||||
*/
|
||||
#ifndef PATCH_PROGRAM
|
||||
#define PATCH_PROGRAM "patch"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* By default, RCS programs are executed with the shell or through execlp(),
|
||||
* so the user's PATH environment variable is searched. If you'd like to
|
||||
|
|
@ -119,6 +132,30 @@
|
|||
#define EDITOR_DFLT "vi"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The default umask to use when creating or otherwise setting file or
|
||||
* directory permissions in the repository. Must be a value in the
|
||||
* range of 0 through 0777. For example, a value of 002 allows group
|
||||
* rwx access and world rx access; a value of 007 allows group rwx
|
||||
* access but no world access. This value is overridden by the value
|
||||
* of the CVSUMASK environment variable, which is interpreted as an
|
||||
* octal number.
|
||||
*/
|
||||
#ifndef UMASK_DFLT
|
||||
#define UMASK_DFLT 002
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The cvs admin command is restricted to the members of the group
|
||||
* CVS_ADMIN_GROUP. If this group does not exist, all users are
|
||||
* allowed to run cvs admin. To disable the cvs admin for all users,
|
||||
* create an empty group CVS_ADMIN_GROUP. To disable access control for
|
||||
* cvs admin, comment out the define below.
|
||||
*/
|
||||
#ifndef CVS_ADMIN_GROUP
|
||||
#define CVS_ADMIN_GROUP "cvsadmin"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The Repository file holds the path to the directory within the source
|
||||
* repository that contains the RCS ,v files for each CVS working directory.
|
||||
|
|
@ -174,6 +211,19 @@
|
|||
#define CVS_BADROOT
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The "cvs admin" command allows people to get around most of the logging
|
||||
* and info procedures within CVS. For exmaple, "cvs tag tagname filename"
|
||||
* will perform some validity checks on the tag, while "cvs admin -Ntagname"
|
||||
* will not perform those checks. For this reason, some sites may wish to
|
||||
* disable the admin function completely.
|
||||
*
|
||||
* To disable the admin function, uncomment the lines below.
|
||||
*/
|
||||
#ifndef CVS_NOADMIN
|
||||
/* #define CVS_NOADMIN */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The "cvs diff" command accepts all the single-character options that GNU
|
||||
* diff (1.15) accepts. Except -D. GNU diff uses -D as a way to put
|
||||
|
|
@ -186,6 +236,40 @@
|
|||
#define CVS_DIFFDATE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* define this to enable the SETXID support (see FAQ 4D.13)
|
||||
*/
|
||||
#ifndef SETXID_SUPPORT
|
||||
/* #define SETXID_SUPPORT */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The authenticated client/server is under construction. Don't
|
||||
* define either of these unless you're testing them, in which case
|
||||
* you're me and you already know that.
|
||||
*/
|
||||
/* #undef AUTH_CLIENT_SUPPORT */
|
||||
/* #undef AUTH_SERVER_SUPPORT */
|
||||
|
||||
/*
|
||||
* If you are working with a large remote repository and a 'cvs checkout' is
|
||||
* swamping your network and memory, define these to enable flow control.
|
||||
* You will end up with even less guarantees of a consistant checkout,
|
||||
* but that may be better than no checkout at all. The master server process
|
||||
* will monitor how far it is getting behind, if it reaches the high water
|
||||
* mark, it will signal the child process to stop generating data when
|
||||
* convenient (ie: no locks are held, currently at the beginning of a
|
||||
* new directory). Once the buffer has drained sufficiently to reach the
|
||||
* low water mark, it will be signalled to start again.
|
||||
* -- EXPERIMENTAL! -- A better solution may be in the works.
|
||||
* You may override the default hi/low watermarks here too.
|
||||
*/
|
||||
#ifndef SERVER_FLOWCONTROL
|
||||
# define SERVER_FLOWCONTROL
|
||||
# define SERVER_HI_WATER (2 * 1024 * 1024)
|
||||
# define SERVER_LO_WATER (1 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
/* End of CVS configuration section */
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -9,20 +9,22 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)parseinfo.c 1.18 94/09/23 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)parseinfo.c 1.18 94/09/23 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Parse the INFOFILE file for the specified REPOSITORY. Invoke CALLPROC for
|
||||
* each line in the file that matches the REPOSITORY.
|
||||
* the first line in the file that matches the REPOSITORY, or if ALL != 0, any lines
|
||||
* matching "ALL", or if no lines match, the last line matching "DEFAULT".
|
||||
*
|
||||
* Return 0 for success, -1 if there was not an INFOFILE, and >0 for failure.
|
||||
*/
|
||||
int
|
||||
Parse_Info (infofile, repository, callproc, all)
|
||||
char *infofile;
|
||||
char *repository;
|
||||
int (*callproc) ();
|
||||
CALLPROC callproc;
|
||||
int all;
|
||||
{
|
||||
int err = 0;
|
||||
|
|
@ -30,9 +32,10 @@ Parse_Info (infofile, repository, callproc, all)
|
|||
char infopath[PATH_MAX];
|
||||
char line[MAXLINELEN];
|
||||
char *default_value = NULL;
|
||||
char *expanded_value= NULL;
|
||||
int callback_done, line_number;
|
||||
char *cp, *exp, *value, *srepos;
|
||||
CONST char *regex_err;
|
||||
const char *regex_err;
|
||||
|
||||
if (CVSroot == NULL)
|
||||
{
|
||||
|
|
@ -50,6 +53,10 @@ Parse_Info (infofile, repository, callproc, all)
|
|||
/* strip off the CVSROOT if repository was absolute */
|
||||
srepos = Short_Repository (repository);
|
||||
|
||||
if (trace)
|
||||
(void) fprintf (stderr, "-> ParseInfo(%s, %s, %s)\n",
|
||||
infopath, srepos, all ? "ALL" : "not ALL");
|
||||
|
||||
/* search the info file for lines that match */
|
||||
callback_done = line_number = 0;
|
||||
while (fgets (line, sizeof (line), fp_info) != NULL)
|
||||
|
|
@ -91,6 +98,16 @@ Parse_Info (infofile, repository, callproc, all)
|
|||
if ((cp = strrchr (value, '\n')) != NULL)
|
||||
*cp = '\0';
|
||||
|
||||
expanded_value = expand_path (value);
|
||||
if (!expanded_value)
|
||||
{
|
||||
error (0, 0,
|
||||
"Invalid environmental variable at line %d in file %s",
|
||||
line_number, infofile);
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, exp points to the regular expression, and value
|
||||
* points to the value to call the callback routine with. Evaluate
|
||||
|
|
@ -101,25 +118,29 @@ Parse_Info (infofile, repository, callproc, all)
|
|||
/* save the default value so we have it later if we need it */
|
||||
if (strcmp (exp, "DEFAULT") == 0)
|
||||
{
|
||||
default_value = xstrdup (value);
|
||||
default_value = xstrdup (expanded_value);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* For a regular expression of "ALL", do the callback always We may
|
||||
* execute lots of ALL callbacks in addition to one regular matching
|
||||
* execute lots of ALL callbacks in addition to *one* regular matching
|
||||
* callback or default
|
||||
*/
|
||||
if (strcmp (exp, "ALL") == 0)
|
||||
{
|
||||
if (all)
|
||||
err += callproc (repository, value);
|
||||
err += callproc (repository, expanded_value);
|
||||
else
|
||||
error(0, 0, "Keyword `ALL' is ignored at line %d in %s file",
|
||||
line_number, infofile);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (callback_done)
|
||||
/* only first matching, plus "ALL"'s */
|
||||
continue;
|
||||
|
||||
/* see if the repository matched this regular expression */
|
||||
if ((regex_err = re_comp (exp)) != NULL)
|
||||
{
|
||||
|
|
@ -128,10 +149,10 @@ Parse_Info (infofile, repository, callproc, all)
|
|||
continue;
|
||||
}
|
||||
if (re_exec (srepos) == 0)
|
||||
continue; /* no match */
|
||||
continue; /* no match */
|
||||
|
||||
/* it did, so do the callback and note that we did one */
|
||||
err += callproc (repository, value);
|
||||
err += callproc (repository, expanded_value);
|
||||
callback_done = 1;
|
||||
}
|
||||
(void) fclose (fp_info);
|
||||
|
|
@ -143,6 +164,8 @@ Parse_Info (infofile, repository, callproc, all)
|
|||
/* free up space if necessary */
|
||||
if (default_value != NULL)
|
||||
free (default_value);
|
||||
if (expanded_value != NULL)
|
||||
free (expanded_value);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,17 +13,18 @@
|
|||
*/
|
||||
|
||||
#include "cvs.h"
|
||||
#include "getline.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)patch.c 1.57 94/09/30 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)patch.c 1.57 94/09/30 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static RETSIGTYPE patch_cleanup PROTO((void));
|
||||
static Dtype patch_dirproc PROTO((char *dir, char *repos, char *update_dir));
|
||||
static int patch_fileproc PROTO((char *file, char *update_dir, char *repository,
|
||||
List * entries, List * srcfiles));
|
||||
static int patch_proc PROTO((int *pargc, char *argv[], char *xwhere,
|
||||
static int patch_proc PROTO((int *pargc, char **argv, char *xwhere,
|
||||
char *mwhere, char *mfile, int shorten,
|
||||
int local_specified, char *mname, char *msg));
|
||||
|
||||
|
|
@ -39,11 +40,10 @@ static char *date2 = NULL;
|
|||
static char tmpfile1[L_tmpnam+1], tmpfile2[L_tmpnam+1], tmpfile3[L_tmpnam+1];
|
||||
static int unidiff = 0;
|
||||
|
||||
static char *patch_usage[] =
|
||||
static const char *const patch_usage[] =
|
||||
{
|
||||
"Usage: %s %s [-Qflq] [-c|-u] [-s|-t] [-V %%d]\n",
|
||||
"Usage: %s %s [-fl] [-c|-u] [-s|-t] [-V %%d]\n",
|
||||
" -r rev|-D date [-r rev2 | -D date2] modules...\n",
|
||||
"\t-Q\tReally quiet.\n",
|
||||
"\t-f\tForce a head revision match if tag/date not found.\n",
|
||||
"\t-l\tLocal directory only, not recursive\n",
|
||||
"\t-c\tContext diffs (default)\n",
|
||||
|
|
@ -59,7 +59,7 @@ static char *patch_usage[] =
|
|||
int
|
||||
patch (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
register int i;
|
||||
int c;
|
||||
|
|
@ -75,10 +75,15 @@ patch (argc, argv)
|
|||
switch (c)
|
||||
{
|
||||
case 'Q':
|
||||
really_quiet = 1;
|
||||
/* FALL THROUGH */
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
#ifdef SERVER_SUPPORT
|
||||
/* The CVS 1.5 client sends these options (in addition to
|
||||
Global_option requests), so we must ignore them. */
|
||||
if (!server_active)
|
||||
#endif
|
||||
error (1, 0,
|
||||
"-q or -Q must be specified before \"%s\"",
|
||||
command_name);
|
||||
break;
|
||||
case 'f':
|
||||
force_tag_match = 0;
|
||||
|
|
@ -162,12 +167,64 @@ patch (argc, argv)
|
|||
if (options == NULL)
|
||||
options = xstrdup ("");
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active)
|
||||
{
|
||||
/* We're the client side. Fire up the remote server. */
|
||||
start_server ();
|
||||
|
||||
ign_setup ();
|
||||
|
||||
if (local)
|
||||
send_arg("-l");
|
||||
if (force_tag_match)
|
||||
send_arg("-f");
|
||||
if (toptwo_diffs)
|
||||
send_arg("-t");
|
||||
if (patch_short)
|
||||
send_arg("-s");
|
||||
if (unidiff)
|
||||
send_arg("-u");
|
||||
|
||||
if (rev1)
|
||||
option_with_arg ("-r", rev1);
|
||||
if (date1)
|
||||
client_senddate (date1);
|
||||
if (rev2)
|
||||
option_with_arg ("-r", rev2);
|
||||
if (date2)
|
||||
client_senddate (date2);
|
||||
if (options[0] != '\0')
|
||||
send_arg (options);
|
||||
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < argc; ++i)
|
||||
send_arg (argv[i]);
|
||||
}
|
||||
|
||||
if (fprintf (to_server, "rdiff\n") < 0)
|
||||
error (1, errno, "writing to server");
|
||||
return get_responses_and_close ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* clean up if we get a signal */
|
||||
#ifdef SIGHUP
|
||||
(void) SIG_register (SIGHUP, patch_cleanup);
|
||||
#endif
|
||||
#ifdef SIGINT
|
||||
(void) SIG_register (SIGINT, patch_cleanup);
|
||||
#endif
|
||||
#ifdef SIGQUIT
|
||||
(void) SIG_register (SIGQUIT, patch_cleanup);
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
(void) SIG_register (SIGPIPE, patch_cleanup);
|
||||
#endif
|
||||
#ifdef SIGTERM
|
||||
(void) SIG_register (SIGTERM, patch_cleanup);
|
||||
#endif
|
||||
|
||||
db = open_module ();
|
||||
for (i = 0; i < argc; i++)
|
||||
|
|
@ -188,7 +245,7 @@ static int
|
|||
patch_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified,
|
||||
mname, msg)
|
||||
int *pargc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
char *xwhere;
|
||||
char *mwhere;
|
||||
char *mfile;
|
||||
|
|
@ -255,8 +312,8 @@ patch_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified,
|
|||
which = W_REPOS;
|
||||
|
||||
/* start the recursion processor */
|
||||
err = start_recursion (patch_fileproc, (int (*) ()) NULL, patch_dirproc,
|
||||
(int (*) ()) NULL, *pargc - 1, argv + 1, local,
|
||||
err = start_recursion (patch_fileproc, (FILESDONEPROC) NULL, patch_dirproc,
|
||||
(DIRLEAVEPROC) NULL, *pargc - 1, argv + 1, local,
|
||||
which, 0, 1, where, 1, 1);
|
||||
|
||||
return (err);
|
||||
|
|
@ -286,7 +343,9 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
int isattic = 0;
|
||||
int retcode = 0;
|
||||
char file1[PATH_MAX], file2[PATH_MAX], strippath[PATH_MAX];
|
||||
char line1[MAXLINELEN], line2[MAXLINELEN];
|
||||
char *line1, *line2;
|
||||
size_t line1_chars_allocated;
|
||||
size_t line2_chars_allocated;
|
||||
char *cp1, *cp2, *commap;
|
||||
FILE *fp;
|
||||
|
||||
|
|
@ -304,7 +363,7 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
if (isattic && rev2 == NULL && date2 == NULL)
|
||||
vers_head = NULL;
|
||||
else
|
||||
vers_head = RCS_getversion (rcsfile, rev2, date2, force_tag_match);
|
||||
vers_head = RCS_getversion (rcsfile, rev2, date2, force_tag_match, 0);
|
||||
|
||||
if (toptwo_diffs)
|
||||
{
|
||||
|
|
@ -322,7 +381,7 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
return (1);
|
||||
}
|
||||
}
|
||||
vers_tag = RCS_getversion (rcsfile, rev1, date1, force_tag_match);
|
||||
vers_tag = RCS_getversion (rcsfile, rev1, date1, force_tag_match, 0);
|
||||
|
||||
if (vers_tag == NULL && (vers_head == NULL || isattic))
|
||||
return (0); /* nothing known about specified revs */
|
||||
|
|
@ -336,8 +395,21 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
if (vers_tag == NULL)
|
||||
(void) printf ("%s is new; current revision %s\n", rcs, vers_head);
|
||||
else if (vers_head == NULL)
|
||||
#ifdef DEATH_SUPPORT
|
||||
{
|
||||
(void) printf ("%s is removed; not included in ", rcs);
|
||||
if (rev2 != NULL)
|
||||
(void) printf ("release tag %s", rev2);
|
||||
else if (date2 != NULL)
|
||||
(void) printf ("release date %s", date2);
|
||||
else
|
||||
(void) printf ("current release");
|
||||
(void) printf ("\n");
|
||||
}
|
||||
#else
|
||||
(void) printf ("%s is removed; not included in release %s\n",
|
||||
rcs, rev2 ? rev2 : date2);
|
||||
#endif
|
||||
else
|
||||
(void) printf ("%s changed from revision %s to %s\n",
|
||||
rcs, vers_tag, vers_head);
|
||||
|
|
@ -396,6 +468,12 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
run_setup ("%s -%c", DIFF, unidiff ? 'u' : 'c');
|
||||
run_arg (tmpfile1);
|
||||
run_arg (tmpfile2);
|
||||
|
||||
line1 = NULL;
|
||||
line1_chars_allocated = 0;
|
||||
line2 = NULL;
|
||||
line2_chars_allocated = 0;
|
||||
|
||||
switch (run_exec (RUN_TTY, tmpfile3, RUN_TTY, RUN_NORMAL))
|
||||
{
|
||||
case -1: /* fork/wait failure */
|
||||
|
|
@ -419,8 +497,8 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
(void) fflush (stdout);
|
||||
|
||||
fp = open_file (tmpfile3, "r");
|
||||
if (fgets (line1, sizeof (line1), fp) == NULL ||
|
||||
fgets (line2, sizeof (line2), fp) == NULL)
|
||||
if (getline (&line1, &line1_chars_allocated, fp) < 0 ||
|
||||
getline (&line2, &line2_chars_allocated, fp) < 0)
|
||||
{
|
||||
error (0, errno, "failed to read diff file header %s for %s",
|
||||
tmpfile3, rcs);
|
||||
|
|
@ -488,14 +566,19 @@ patch_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
if (update_dir[0] != '\0')
|
||||
(void) printf ("%s/", update_dir);
|
||||
(void) printf ("%s%s", rcs, cp2);
|
||||
while (fgets (line1, sizeof (line1), fp) != NULL)
|
||||
(void) printf ("%s", line1);
|
||||
/* spew the rest of the diff out */
|
||||
while (getline (&line1, &line1_chars_allocated, fp) >= 0)
|
||||
(void) fputs (line1, stdout);
|
||||
(void) fclose (fp);
|
||||
break;
|
||||
default:
|
||||
error (0, 0, "diff failed for %s", rcs);
|
||||
}
|
||||
out:
|
||||
if (line1)
|
||||
free (line1);
|
||||
if (line2)
|
||||
free (line2);
|
||||
(void) unlink_file (tmpfile1);
|
||||
(void) unlink_file (tmpfile2);
|
||||
(void) unlink_file (tmpfile3);
|
||||
|
|
|
|||
|
|
@ -8,14 +8,15 @@
|
|||
* manipulation
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)rcs.c 1.40 94/10/07 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)rcs.c 1.40 94/10/07 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static RCSNode *RCS_parsercsfile_i PROTO((FILE * fp, char *rcsfile));
|
||||
static RCSNode *RCS_parsercsfile_i PROTO((FILE * fp, const char *rcsfile));
|
||||
static char *RCS_getdatebranch PROTO((RCSNode * rcs, char *date, char *branch));
|
||||
static int getrcskey PROTO((FILE * fp, char **keyp, char **valp));
|
||||
static int parse_rcs_proc PROTO((Node * file, void *closure));
|
||||
|
|
@ -56,7 +57,7 @@ static const char spacetab[] = {
|
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 - 0xff */
|
||||
};
|
||||
|
||||
#define whitespace(c) (spacetab[c] != 0)
|
||||
#define whitespace(c) (spacetab[(unsigned char)c] != 0)
|
||||
|
||||
/*
|
||||
* Parse all the rcs files specified and return a list
|
||||
|
|
@ -108,7 +109,7 @@ parse_rcs_proc (file, closure)
|
|||
|
||||
void
|
||||
RCS_addnode (file, rcs, list)
|
||||
char *file;
|
||||
const char *file;
|
||||
RCSNode *rcs;
|
||||
List *list;
|
||||
{
|
||||
|
|
@ -128,13 +129,19 @@ RCS_addnode (file, rcs, list)
|
|||
*/
|
||||
RCSNode *
|
||||
RCS_parse (file, repos)
|
||||
char *file;
|
||||
char *repos;
|
||||
const char *file;
|
||||
const char *repos;
|
||||
{
|
||||
RCSNode *rcs;
|
||||
FILE *fp;
|
||||
char rcsfile[PATH_MAX];
|
||||
|
||||
#ifdef LINES_CRLF_TERMINATED
|
||||
/* Some ports of RCS to Windows NT write RCS files with newline-
|
||||
delimited lines. We would need to pass fopen a "binary" flag. */
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
(void) sprintf (rcsfile, "%s/%s%s", repos, file, RCSEXT);
|
||||
if ((fp = fopen (rcsfile, "r")) != NULL)
|
||||
{
|
||||
|
|
@ -145,6 +152,17 @@ RCS_parse (file, repos)
|
|||
fclose (fp);
|
||||
return (rcs);
|
||||
}
|
||||
else if (! existence_error (errno))
|
||||
{
|
||||
error (0, errno, "cannot open %s", rcsfile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef LINES_CRLF_TERMINATED
|
||||
/* Some ports of RCS to Windows NT write RCS files with newline-
|
||||
delimited lines. We would need to pass fopen a "binary" flag. */
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
(void) sprintf (rcsfile, "%s/%s/%s%s", repos, CVSATTIC, file, RCSEXT);
|
||||
if ((fp = fopen (rcsfile, "r")) != NULL)
|
||||
|
|
@ -159,6 +177,11 @@ RCS_parse (file, repos)
|
|||
fclose (fp);
|
||||
return (rcs);
|
||||
}
|
||||
else if (! existence_error (errno))
|
||||
{
|
||||
error (0, errno, "cannot open %s", rcsfile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
|
@ -173,6 +196,12 @@ RCS_parsercsfile (rcsfile)
|
|||
FILE *fp;
|
||||
RCSNode *rcs;
|
||||
|
||||
#ifdef LINES_CRLF_TERMINATED
|
||||
/* Some ports of RCS to Windows NT write RCS files with newline-
|
||||
delimited lines. We would need to pass fopen a "binary" flag. */
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
/* open the rcsfile */
|
||||
if ((fp = fopen (rcsfile, "r")) == NULL)
|
||||
{
|
||||
|
|
@ -186,19 +215,15 @@ RCS_parsercsfile (rcsfile)
|
|||
return (rcs);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do the real work of parsing an RCS file
|
||||
*/
|
||||
*/
|
||||
static RCSNode *
|
||||
RCS_parsercsfile_i (fp, rcsfile)
|
||||
FILE *fp;
|
||||
char *rcsfile;
|
||||
const char *rcsfile;
|
||||
{
|
||||
Node *q, *r;
|
||||
RCSNode *rdata;
|
||||
RCSVers *vnode;
|
||||
int n;
|
||||
char *cp;
|
||||
char *key, *value;
|
||||
|
||||
/* make a node */
|
||||
|
|
@ -206,6 +231,87 @@ RCS_parsercsfile_i (fp, rcsfile)
|
|||
memset ((char *) rdata, 0, sizeof (RCSNode));
|
||||
rdata->refcount = 1;
|
||||
rdata->path = xstrdup (rcsfile);
|
||||
|
||||
/* Process HEAD and BRANCH keywords from the RCS header.
|
||||
*
|
||||
* Most cvs operatations on the main branch don't need any more
|
||||
* information. Those that do call XXX to completely parse the
|
||||
* RCS file. */
|
||||
|
||||
if (getrcskey (fp, &key, &value) == -1 || key == NULL)
|
||||
goto l_error;
|
||||
|
||||
if (strcmp (RCSHEAD, key) == 0 && value != NULL)
|
||||
rdata->head = xstrdup (value);
|
||||
|
||||
if (getrcskey (fp, &key, &value) == -1 || key == NULL)
|
||||
goto l_error;
|
||||
|
||||
if (strcmp (RCSBRANCH, key) == 0 && value != NULL)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
rdata->branch = xstrdup (value);
|
||||
if ((numdots (rdata->branch) & 1) != 0)
|
||||
{
|
||||
/* turn it into a branch if it's a revision */
|
||||
cp = strrchr (rdata->branch, '.');
|
||||
*cp = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
rdata->flags |= PARTIAL;
|
||||
return rdata;
|
||||
|
||||
l_error:
|
||||
if (!really_quiet)
|
||||
{
|
||||
if (ferror(fp))
|
||||
{
|
||||
error (1, 0, "error reading `%s'", rcsfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
error (0, 0, "`%s' does not appear to be a valid rcs file",
|
||||
rcsfile);
|
||||
}
|
||||
}
|
||||
freercsnode (&rdata);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Do the real work of parsing an RCS file
|
||||
*
|
||||
* There are no allowances for error here.
|
||||
*/
|
||||
void
|
||||
RCS_reparsercsfile (rdata)
|
||||
RCSNode *rdata;
|
||||
{
|
||||
FILE *fp;
|
||||
char *rcsfile;
|
||||
|
||||
Node *q, *r;
|
||||
RCSVers *vnode;
|
||||
int n;
|
||||
char *cp;
|
||||
char *key, *value;
|
||||
|
||||
rcsfile = rdata->path;
|
||||
|
||||
#ifdef LINES_CRLF_TERMINATED
|
||||
/* Some ports of RCS to Windows NT write RCS files with newline-
|
||||
delimited lines. We would need to pass fopen a "binary" flag. */
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
fp = fopen(rcsfile, "r");
|
||||
if (fp == NULL)
|
||||
error (1, 0, "unable to reopen `%s'", rcsfile);
|
||||
|
||||
/* make a node */
|
||||
rdata->versions = getlist ();
|
||||
rdata->dates = getlist ();
|
||||
|
||||
|
|
@ -221,40 +327,17 @@ RCS_parsercsfile_i (fp, rcsfile)
|
|||
or we had trouble reading the file. */
|
||||
if (getrcskey (fp, &key, &value) == -1 || key == NULL)
|
||||
{
|
||||
|
||||
if (!really_quiet)
|
||||
if (ferror(fp))
|
||||
{
|
||||
if (ferror(fp))
|
||||
{
|
||||
error (1, 0, "error reading `%s'", rcsfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
error (0, 0, "`%s' does not appear to be a valid rcs file",
|
||||
rcsfile);
|
||||
}
|
||||
error (1, 0, "error reading `%s'", rcsfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
error (1, 0, "`%s' does not appear to be a valid rcs file",
|
||||
rcsfile);
|
||||
}
|
||||
freercsnode (&rdata);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* process it */
|
||||
if (strcmp (RCSHEAD, key) == 0 && value != NULL)
|
||||
{
|
||||
rdata->head = xstrdup (value);
|
||||
continue;
|
||||
}
|
||||
if (strcmp (RCSBRANCH, key) == 0 && value != NULL)
|
||||
{
|
||||
rdata->branch = xstrdup (value);
|
||||
if ((numdots (rdata->branch) & 1) != 0)
|
||||
{
|
||||
/* turn it into a branch if it's a revision */
|
||||
cp = strrchr (rdata->branch, '.');
|
||||
*cp = '\0';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (strcmp (RCSSYMBOLS, key) == 0)
|
||||
{
|
||||
if (value != NULL)
|
||||
|
|
@ -264,6 +347,12 @@ RCS_parsercsfile_i (fp, rcsfile)
|
|||
}
|
||||
}
|
||||
|
||||
if (strcmp (RCSEXPAND, key) == 0)
|
||||
{
|
||||
rdata->expand = xstrdup (value);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* check key for '.''s and digits (probably a rev) if it is a
|
||||
* revision, we are done with the headers and are down to the
|
||||
|
|
@ -312,6 +401,17 @@ RCS_parsercsfile_i (fp, rcsfile)
|
|||
|
||||
/* throw away the state field */
|
||||
(void) getrcskey (fp, &key, &value);
|
||||
#ifdef DEATH_SUPPORT
|
||||
/* Accept this regardless of DEATH_STATE, so that we can read
|
||||
repositories created with different versions of CVS. */
|
||||
if (strcmp (key, "state") != 0)
|
||||
error (1, 0, "\
|
||||
unable to parse rcs file; `state' not in the expected place");
|
||||
if (strcmp (value, "dead") == 0)
|
||||
{
|
||||
vnode->dead = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* fill in the date field */
|
||||
r->key = vnode->date = xstrdup (date);
|
||||
|
|
@ -335,6 +435,15 @@ RCS_parsercsfile_i (fp, rcsfile)
|
|||
*/
|
||||
while ((n = getrcskey (fp, &key, &value)) >= 0)
|
||||
{
|
||||
#ifdef DEATH_SUPPORT
|
||||
/* Enable use of repositories created with a CVS which defines
|
||||
DEATH_SUPPORT and not DEATH_STATE. */
|
||||
if (strcmp(key, RCSDEAD) == 0)
|
||||
{
|
||||
vnode->dead = 1;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* if we have a revision, break and do it */
|
||||
for (cp = key; (isdigit (*cp) || *cp == '.') && *cp != '\0'; cp++)
|
||||
/* do nothing */ ;
|
||||
|
|
@ -354,7 +463,8 @@ RCS_parsercsfile_i (fp, rcsfile)
|
|||
break;
|
||||
}
|
||||
|
||||
return (rdata);
|
||||
fclose (fp);
|
||||
rdata->flags &= ~PARTIAL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -390,6 +500,8 @@ freercsnode (rnodep)
|
|||
dellist (&(*rnodep)->symbols);
|
||||
if ((*rnodep)->symbols_data != (char *) NULL)
|
||||
free ((*rnodep)->symbols_data);
|
||||
if ((*rnodep)->expand != NULL)
|
||||
free ((*rnodep)->expand);
|
||||
if ((*rnodep)->head != (char *) NULL)
|
||||
free ((*rnodep)->head);
|
||||
if ((*rnodep)->branch != (char *) NULL)
|
||||
|
|
@ -435,17 +547,17 @@ null_delproc (p)
|
|||
* space or semicolon
|
||||
* o if key == "desc" then key and data are NULL and return -1
|
||||
* o if key wasn't terminated by a semicolon, skip white space and fill
|
||||
* in value with everything up to a semicolon o compress all whitespace
|
||||
* down to a single space
|
||||
* in value with everything up to a semicolon
|
||||
* o compress all whitespace down to a single space
|
||||
* o if a word starts with @, do funky rcs processing
|
||||
* o strip whitespace off end of value or set value to NULL if it empty
|
||||
* o return 0 since we found something besides "desc"
|
||||
*/
|
||||
|
||||
static char *key = NULL;
|
||||
static int keysize = 0;
|
||||
static char *value = NULL;
|
||||
static int valsize = 0;
|
||||
static size_t keysize = 0;
|
||||
static size_t valsize = 0;
|
||||
|
||||
#define ALLOCINCR 1024
|
||||
|
||||
|
|
@ -457,11 +569,9 @@ getrcskey (fp, keyp, valp)
|
|||
{
|
||||
char *cur, *max;
|
||||
int c;
|
||||
int funky = 0;
|
||||
int white = 1;
|
||||
|
||||
/* skip leading whitespace */
|
||||
while (1)
|
||||
do
|
||||
{
|
||||
c = getc (fp);
|
||||
if (c == EOF)
|
||||
|
|
@ -470,25 +580,22 @@ getrcskey (fp, keyp, valp)
|
|||
*valp = (char *) NULL;
|
||||
return (-1);
|
||||
}
|
||||
if (!whitespace (c))
|
||||
break;
|
||||
}
|
||||
} while (whitespace (c));
|
||||
|
||||
/* fill in key */
|
||||
cur = key;
|
||||
max = key + keysize;
|
||||
while (!whitespace (c) && c != ';')
|
||||
{
|
||||
if (cur < max)
|
||||
*cur++ = c;
|
||||
else
|
||||
if (cur >= max)
|
||||
{
|
||||
key = xrealloc (key, keysize + ALLOCINCR);
|
||||
cur = key + keysize;
|
||||
keysize += ALLOCINCR;
|
||||
max = key + keysize;
|
||||
*cur++ = c;
|
||||
}
|
||||
*cur++ = c;
|
||||
|
||||
c = getc (fp);
|
||||
if (c == EOF)
|
||||
{
|
||||
|
|
@ -504,7 +611,6 @@ getrcskey (fp, keyp, valp)
|
|||
keysize += ALLOCINCR;
|
||||
max = key + keysize;
|
||||
}
|
||||
|
||||
*cur = '\0';
|
||||
|
||||
/* if we got "desc", we are done with the file */
|
||||
|
|
@ -515,6 +621,18 @@ getrcskey (fp, keyp, valp)
|
|||
return (-1);
|
||||
}
|
||||
|
||||
/* skip whitespace between key and val */
|
||||
while (whitespace (c))
|
||||
{
|
||||
c = getc (fp);
|
||||
if (c == EOF)
|
||||
{
|
||||
*keyp = (char *) NULL;
|
||||
*valp = (char *) NULL;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* if we ended key with a semicolon, there is no value */
|
||||
if (c == ';')
|
||||
{
|
||||
|
|
@ -524,33 +642,25 @@ getrcskey (fp, keyp, valp)
|
|||
}
|
||||
|
||||
/* otherwise, there might be a value, so fill it in */
|
||||
(void) ungetc (c, fp);
|
||||
cur = value;
|
||||
max = value + valsize;
|
||||
|
||||
/* process the value */
|
||||
for (;;)
|
||||
{
|
||||
/* get a character */
|
||||
c = getc (fp);
|
||||
if (c == EOF)
|
||||
/* handle RCS "strings" */
|
||||
if (c == '@')
|
||||
{
|
||||
*keyp = (char *) NULL;
|
||||
*valp = (char *) NULL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* if we are in funky mode, do the rest of this string */
|
||||
if (funky)
|
||||
{
|
||||
|
||||
/*
|
||||
* funky mode processing does the following: o @@ means one @ o
|
||||
* all other characters are literal up to a single @ (including
|
||||
* ';')
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
c = getc (fp);
|
||||
if (c == EOF)
|
||||
{
|
||||
*keyp = (char *) NULL;
|
||||
*valp = (char *) NULL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (c == '@')
|
||||
{
|
||||
c = getc (fp);
|
||||
|
|
@ -560,16 +670,11 @@ getrcskey (fp, keyp, valp)
|
|||
*valp = (char *) NULL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (c != '@')
|
||||
{
|
||||
/* @ followed by non @ turns off funky mode */
|
||||
funky = 0;
|
||||
break;
|
||||
}
|
||||
/* otherwise, we already ate one @ so copy the other one */
|
||||
}
|
||||
|
||||
/* put the character on the value (maybe allocating space) */
|
||||
if (cur >= max)
|
||||
{
|
||||
value = xrealloc (value, valsize + ALLOCINCR);
|
||||
|
|
@ -578,6 +683,13 @@ getrcskey (fp, keyp, valp)
|
|||
max = value + valsize;
|
||||
}
|
||||
*cur++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
/* compress whitespace down to a single space */
|
||||
if (whitespace (c))
|
||||
{
|
||||
do {
|
||||
c = getc (fp);
|
||||
if (c == EOF)
|
||||
{
|
||||
|
|
@ -585,45 +697,8 @@ getrcskey (fp, keyp, valp)
|
|||
*valp = (char *) NULL;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (whitespace (c));
|
||||
|
||||
/* if we got the semi-colon we are done with the entire value */
|
||||
if (c == ';')
|
||||
break;
|
||||
|
||||
/* process the character we got */
|
||||
if (white && c == '@')
|
||||
{
|
||||
|
||||
/*
|
||||
* if we are starting a word with an '@', enable funky processing
|
||||
*/
|
||||
white = 0; /* you can't be funky and white :-) */
|
||||
funky = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
* we put the character on the list, compressing all whitespace
|
||||
* to a single space
|
||||
*/
|
||||
|
||||
/* whitespace with white set means compress it out */
|
||||
if (white && whitespace (c))
|
||||
continue;
|
||||
|
||||
if (whitespace (c))
|
||||
{
|
||||
/* make c a space and set white */
|
||||
white = 1;
|
||||
c = ' ';
|
||||
}
|
||||
else
|
||||
white = 0;
|
||||
|
||||
/* put the char on the end of value (maybe allocating space) */
|
||||
if (cur >= max)
|
||||
{
|
||||
value = xrealloc (value, valsize + ALLOCINCR);
|
||||
|
|
@ -631,17 +706,13 @@ getrcskey (fp, keyp, valp)
|
|||
valsize += ALLOCINCR;
|
||||
max = value + valsize;
|
||||
}
|
||||
*cur++ = c;
|
||||
*cur++ = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
/* if the last char was white space, take it off */
|
||||
if (white && cur != value)
|
||||
cur--;
|
||||
/* if we got a semi-colon we are done with the entire value */
|
||||
if (c == ';')
|
||||
break;
|
||||
|
||||
/* terminate the string */
|
||||
if (cur)
|
||||
{
|
||||
if (cur >= max)
|
||||
{
|
||||
value = xrealloc (value, valsize + ALLOCINCR);
|
||||
|
|
@ -649,9 +720,27 @@ getrcskey (fp, keyp, valp)
|
|||
valsize += ALLOCINCR;
|
||||
max = value + valsize;
|
||||
}
|
||||
*cur = '\0';
|
||||
*cur++ = c;
|
||||
|
||||
c = getc (fp);
|
||||
if (c == EOF)
|
||||
{
|
||||
*keyp = (char *) NULL;
|
||||
*valp = (char *) NULL;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* terminate the string */
|
||||
if (cur >= max)
|
||||
{
|
||||
value = xrealloc (value, valsize + ALLOCINCR);
|
||||
cur = value + valsize;
|
||||
valsize += ALLOCINCR;
|
||||
max = value + valsize;
|
||||
}
|
||||
*cur = '\0';
|
||||
|
||||
/* if the string is empty, make it null */
|
||||
if (value && *value != '\0')
|
||||
*valp = value;
|
||||
|
|
@ -746,15 +835,15 @@ do_branches (list, val)
|
|||
* The result is returned; null-string if error.
|
||||
*/
|
||||
char *
|
||||
RCS_getversion (rcs, tag, date, force_tag_match)
|
||||
RCS_getversion (rcs, tag, date, force_tag_match, return_both)
|
||||
RCSNode *rcs;
|
||||
char *tag;
|
||||
char *date;
|
||||
int force_tag_match;
|
||||
int return_both;
|
||||
{
|
||||
/* make sure we have something to look at... */
|
||||
if (rcs == NULL)
|
||||
return ((char *) NULL);
|
||||
assert (rcs != NULL);
|
||||
|
||||
if (tag && date)
|
||||
{
|
||||
|
|
@ -764,7 +853,7 @@ RCS_getversion (rcs, tag, date, force_tag_match)
|
|||
* first lookup the tag; if that works, turn the revision into
|
||||
* a branch and lookup the date.
|
||||
*/
|
||||
tagrev = RCS_gettag (rcs, tag, force_tag_match);
|
||||
tagrev = RCS_gettag (rcs, tag, force_tag_match, 0);
|
||||
if (tagrev == NULL)
|
||||
return ((char *) NULL);
|
||||
|
||||
|
|
@ -775,7 +864,7 @@ RCS_getversion (rcs, tag, date, force_tag_match)
|
|||
return (rev);
|
||||
}
|
||||
else if (tag)
|
||||
return (RCS_gettag (rcs, tag, force_tag_match));
|
||||
return (RCS_gettag (rcs, tag, force_tag_match, return_both));
|
||||
else if (date)
|
||||
return (RCS_getdate (rcs, date, force_tag_match));
|
||||
else
|
||||
|
|
@ -792,22 +881,29 @@ RCS_getversion (rcs, tag, date, force_tag_match)
|
|||
* If the matched tag is a branch tag, find the head of the branch.
|
||||
*/
|
||||
char *
|
||||
RCS_gettag (rcs, tag, force_tag_match)
|
||||
RCS_gettag (rcs, symtag, force_tag_match, return_both)
|
||||
RCSNode *rcs;
|
||||
char *tag;
|
||||
char *symtag;
|
||||
int force_tag_match;
|
||||
int return_both;
|
||||
{
|
||||
Node *p;
|
||||
char *tag = symtag;
|
||||
|
||||
/* make sure we have something to look at... */
|
||||
if (rcs == NULL)
|
||||
return ((char *) NULL);
|
||||
assert (rcs != NULL);
|
||||
|
||||
/* XXX this is probably not necessary, --jtc */
|
||||
if (rcs->flags & PARTIAL)
|
||||
RCS_reparsercsfile (rcs);
|
||||
|
||||
/* If tag is "HEAD", special case to get head RCS revision */
|
||||
if (tag && (strcmp (tag, TAG_HEAD) == 0 || *tag == '\0'))
|
||||
#if 0 /* This #if 0 is only in the Cygnus code. Why? Death support? */
|
||||
if (force_tag_match && (rcs->flags & VALID) && (rcs->flags & INATTIC))
|
||||
return ((char *) NULL); /* head request for removed file */
|
||||
else
|
||||
#endif
|
||||
return (RCS_head (rcs));
|
||||
|
||||
if (!isdigit (tag[0]))
|
||||
|
|
@ -895,7 +991,25 @@ RCS_gettag (rcs, tag, force_tag_match)
|
|||
else
|
||||
p = findnode (rcs->versions, tag);
|
||||
if (p != NULL)
|
||||
return (xstrdup (tag));
|
||||
{
|
||||
/*
|
||||
* we have found a numeric revision for the revision tag.
|
||||
* To support expanding the RCS keyword Name, return both
|
||||
* the numeric tag and the supplied tag (which might be
|
||||
* symbolic). They are separated with a ':' which is not
|
||||
* a valid tag char. The variable return_both is only set
|
||||
* if this function is called through Version_TS ->
|
||||
* RCS_getversion.
|
||||
*/
|
||||
if (return_both)
|
||||
{
|
||||
char *both = xmalloc(strlen(tag) + 2 + strlen(symtag));
|
||||
sprintf(both, "%s:%s", tag, symtag);
|
||||
return both;
|
||||
}
|
||||
else
|
||||
return (xstrdup (tag));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The revision wasn't there, so return the head or NULL */
|
||||
|
|
@ -1124,8 +1238,10 @@ RCS_getbranch (rcs, tag, force_tag_match)
|
|||
char *cp;
|
||||
|
||||
/* make sure we have something to look at... */
|
||||
if (rcs == NULL)
|
||||
return ((char *) NULL);
|
||||
assert (rcs != NULL);
|
||||
|
||||
if (rcs->flags & PARTIAL)
|
||||
RCS_reparsercsfile (rcs);
|
||||
|
||||
/* find out if the tag contains a dot, or is on the trunk */
|
||||
cp = strrchr (tag, '.');
|
||||
|
|
@ -1233,16 +1349,14 @@ RCS_head (rcs)
|
|||
RCSNode *rcs;
|
||||
{
|
||||
/* make sure we have something to look at... */
|
||||
if (rcs == NULL)
|
||||
return ((char *) NULL);
|
||||
|
||||
if (rcs->branch)
|
||||
return (RCS_getbranch (rcs, rcs->branch, 1));
|
||||
assert (rcs != NULL);
|
||||
|
||||
/*
|
||||
* NOTE: we call getbranch with force_tag_match set to avoid any
|
||||
* possibility of recursion
|
||||
*/
|
||||
if (rcs->branch)
|
||||
return (RCS_getbranch (rcs, rcs->branch, 1));
|
||||
else
|
||||
return (xstrdup (rcs->head));
|
||||
}
|
||||
|
|
@ -1263,8 +1377,10 @@ RCS_getdate (rcs, date, force_tag_match)
|
|||
RCSVers *vers = NULL;
|
||||
|
||||
/* make sure we have something to look at... */
|
||||
if (rcs == NULL)
|
||||
return ((char *) NULL);
|
||||
assert (rcs != NULL);
|
||||
|
||||
if (rcs->flags & PARTIAL)
|
||||
RCS_reparsercsfile (rcs);
|
||||
|
||||
/* if the head is on a branch, try the branch first */
|
||||
if (rcs->branch != NULL)
|
||||
|
|
@ -1347,6 +1463,12 @@ RCS_getdatebranch (rcs, date, branch)
|
|||
return (NULL);
|
||||
}
|
||||
*cp = '\0'; /* turn it into a revision */
|
||||
|
||||
assert (rcs != NULL);
|
||||
|
||||
if (rcs->flags & PARTIAL)
|
||||
RCS_reparsercsfile (rcs);
|
||||
|
||||
p = findnode (rcs->versions, xrev);
|
||||
free (xrev);
|
||||
if (p == NULL)
|
||||
|
|
@ -1427,8 +1549,10 @@ RCS_getrevtime (rcs, rev, date, fudge)
|
|||
RCSVers *vers;
|
||||
|
||||
/* make sure we have something to look at... */
|
||||
if (rcs == NULL)
|
||||
return (revdate);
|
||||
assert (rcs != NULL);
|
||||
|
||||
if (rcs->flags & PARTIAL)
|
||||
RCS_reparsercsfile (rcs);
|
||||
|
||||
/* look up the revision */
|
||||
p = findnode (rcs->versions, rev);
|
||||
|
|
@ -1481,14 +1605,19 @@ List *
|
|||
RCS_symbols(rcs)
|
||||
RCSNode *rcs;
|
||||
{
|
||||
if (rcs->symbols_data) {
|
||||
rcs->symbols = getlist ();
|
||||
do_symbols (rcs->symbols, rcs->symbols_data);
|
||||
free(rcs->symbols_data);
|
||||
rcs->symbols_data = NULL;
|
||||
}
|
||||
assert(rcs != NULL);
|
||||
|
||||
return rcs->symbols;
|
||||
if (rcs->flags & PARTIAL)
|
||||
RCS_reparsercsfile (rcs);
|
||||
|
||||
if (rcs->symbols_data) {
|
||||
rcs->symbols = getlist ();
|
||||
do_symbols (rcs->symbols, rcs->symbols_data);
|
||||
free(rcs->symbols_data);
|
||||
rcs->symbols_data = NULL;
|
||||
}
|
||||
|
||||
return rcs->symbols;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1498,12 +1627,24 @@ RCS_symbols(rcs)
|
|||
*/
|
||||
char *
|
||||
RCS_check_kflag (arg)
|
||||
char *arg;
|
||||
const char *arg;
|
||||
{
|
||||
static char *kflags[] =
|
||||
{"kv", "kvl", "k", "v", "o", (char *) NULL};
|
||||
static const char *const kflags[] =
|
||||
{"kv", "kvl", "k", "v", "o", "b", (char *) NULL};
|
||||
static const char *const keyword_usage[] =
|
||||
{
|
||||
"%s %s: invalid RCS keyword expansion mode\n",
|
||||
"Valid expansion modes include:\n",
|
||||
" -kkv\tGenerate keywords using the default form.\n",
|
||||
" -kkvl\tLike -kkv, except locker's name inserted.\n",
|
||||
" -kk\tGenerate only keyword names in keyword strings.\n",
|
||||
" -kv\tGenerate only keyword values in keyword strings.\n",
|
||||
" -ko\tGenerate the old keyword string (no changes from checked in file).\n",
|
||||
" -kb\tGenerate binary file unmodified (merges not allowed) (RCS 5.7).\n",
|
||||
NULL,
|
||||
};
|
||||
char karg[10];
|
||||
char **cpp = NULL;
|
||||
char const *const *cpp = NULL;
|
||||
|
||||
#ifndef HAVE_RCS5
|
||||
error (1, 0, "%s %s: your version of RCS does not support the -k option",
|
||||
|
|
@ -1521,12 +1662,7 @@ RCS_check_kflag (arg)
|
|||
|
||||
if (arg == NULL || *cpp == NULL)
|
||||
{
|
||||
(void) fprintf (stderr, "%s %s: invalid -k option\n",
|
||||
program_name, command_name);
|
||||
(void) fprintf (stderr, "\tvalid options are:\n");
|
||||
for (cpp = kflags; *cpp != NULL; cpp++)
|
||||
(void) fprintf (stderr, "\t\t-k%s\n", *cpp);
|
||||
error (1, 0, "Please retry with a valid -k option");
|
||||
usage (keyword_usage);
|
||||
}
|
||||
|
||||
(void) sprintf (karg, "-k%s", *cpp);
|
||||
|
|
@ -1539,10 +1675,10 @@ RCS_check_kflag (arg)
|
|||
*/
|
||||
void
|
||||
RCS_check_tag (tag)
|
||||
char *tag;
|
||||
const char *tag;
|
||||
{
|
||||
char *invalid = "$,.:;@"; /* invalid RCS tag characters */
|
||||
char *cp;
|
||||
const char *cp;
|
||||
|
||||
/*
|
||||
* The first character must be an alphabetic letter. The remaining
|
||||
|
|
@ -1565,3 +1701,26 @@ RCS_check_tag (tag)
|
|||
error (1, 0, "tag `%s' must start with a letter", tag);
|
||||
}
|
||||
|
||||
#ifdef DEATH_SUPPORT
|
||||
/*
|
||||
* Return true if RCS revision with TAG is a dead revision.
|
||||
*/
|
||||
int
|
||||
RCS_isdead (rcs, tag)
|
||||
RCSNode *rcs;
|
||||
const char *tag;
|
||||
{
|
||||
Node *p;
|
||||
RCSVers *version;
|
||||
|
||||
if (rcs->flags & PARTIAL)
|
||||
RCS_reparsercsfile (rcs);
|
||||
|
||||
p = findnode (rcs->versions, tag);
|
||||
if (p == NULL)
|
||||
return (0);
|
||||
|
||||
version = (RCSVers *) p->data;
|
||||
return (version->dead);
|
||||
}
|
||||
#endif /* DEATH_SUPPORT */
|
||||
|
|
|
|||
|
|
@ -25,6 +25,13 @@
|
|||
#define RCSSYMBOLS "symbols"
|
||||
#define RCSDATE "date"
|
||||
#define RCSDESC "desc"
|
||||
#define RCSEXPAND "expand"
|
||||
|
||||
/* Used by the version of death support which results if you define
|
||||
DEATH_SUPPORT and not DEATH_STATE. Requires a hacked up RCS. Considered
|
||||
obsolete. */
|
||||
#define RCSDEAD "dead"
|
||||
|
||||
#define DATEFORM "%02d.%02d.%02d.%02d.%02d.%02d"
|
||||
#define SDATEFORM "%d.%d.%d.%d.%d.%d"
|
||||
|
||||
|
|
@ -33,6 +40,8 @@
|
|||
*/
|
||||
#define VALID 0x1 /* flags field contains valid data */
|
||||
#define INATTIC 0x2 /* RCS file is located in the Attic */
|
||||
#define PARTIAL 0x4 /* RCS file not completly parsed */
|
||||
|
||||
struct rcsnode
|
||||
{
|
||||
int refcount;
|
||||
|
|
@ -41,10 +50,12 @@ struct rcsnode
|
|||
char *head;
|
||||
char *branch;
|
||||
char *symbols_data;
|
||||
char *expand;
|
||||
List *symbols;
|
||||
List *versions;
|
||||
List *dates;
|
||||
};
|
||||
|
||||
typedef struct rcsnode RCSNode;
|
||||
|
||||
struct rcsversnode
|
||||
|
|
@ -52,6 +63,7 @@ struct rcsversnode
|
|||
char *version;
|
||||
char *date;
|
||||
char *next;
|
||||
int dead;
|
||||
List *branches;
|
||||
};
|
||||
typedef struct rcsversnode RCSVers;
|
||||
|
|
@ -69,13 +81,14 @@ typedef struct rcsversnode RCSVers;
|
|||
* exported interfaces
|
||||
*/
|
||||
List *RCS_parsefiles PROTO((List * files, char *xrepos));
|
||||
RCSNode *RCS_parse PROTO((char *file, char *repos));
|
||||
RCSNode *RCS_parse PROTO((const char *file, const char *repos));
|
||||
RCSNode *RCS_parsercsfile PROTO((char *rcsfile));
|
||||
char *RCS_check_kflag PROTO((char *arg));
|
||||
char *RCS_check_kflag PROTO((const char *arg));
|
||||
char *RCS_getdate PROTO((RCSNode * rcs, char *date, int force_tag_match));
|
||||
char *RCS_gettag PROTO((RCSNode * rcs, char *tag, int force_tag_match));
|
||||
char *RCS_gettag PROTO((RCSNode * rcs, char *symtag, int force_tag_match,
|
||||
int return_both));
|
||||
char *RCS_getversion PROTO((RCSNode * rcs, char *tag, char *date,
|
||||
int force_tag_match));
|
||||
int force_tag_match, int return_both));
|
||||
char *RCS_magicrev PROTO((RCSNode *rcs, char *rev));
|
||||
int RCS_isbranch PROTO((char *file, char *rev, List *srcfiles));
|
||||
int RCS_nodeisbranch PROTO((char *rev, RCSNode *rcs));
|
||||
|
|
@ -84,7 +97,11 @@ char *RCS_head PROTO((RCSNode * rcs));
|
|||
int RCS_datecmp PROTO((char *date1, char *date2));
|
||||
time_t RCS_getrevtime PROTO((RCSNode * rcs, char *rev, char *date, int fudge));
|
||||
List *RCS_symbols PROTO((RCSNode *rcs));
|
||||
void RCS_check_tag PROTO((char *tag));
|
||||
void RCS_check_tag PROTO((const char *tag));
|
||||
void freercsnode PROTO((RCSNode ** rnodep));
|
||||
void RCS_addnode PROTO((char *file, RCSNode *rcs, List *list));
|
||||
void RCS_addnode PROTO((const char *file, RCSNode *rcs, List *list));
|
||||
char *RCS_getbranch PROTO((RCSNode * rcs, char *tag, int force_tag_match));
|
||||
|
||||
#ifdef DEATH_SUPPORT
|
||||
int RCS_isdead PROTO((RCSNode *, const char *));
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -9,10 +9,11 @@
|
|||
*/
|
||||
|
||||
#include "cvs.h"
|
||||
#include "save-cwd.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)recurse.c 1.31 94/09/30 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)recurse.c 1.31 94/09/30 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static int do_dir_proc PROTO((Node * p, void *closure));
|
||||
|
|
@ -25,10 +26,10 @@ static void addfile PROTO((List **listp, char *dir, char *file));
|
|||
/*
|
||||
* Local static versions eliminates the need for globals
|
||||
*/
|
||||
static int (*fileproc) ();
|
||||
static int (*filesdoneproc) ();
|
||||
static Dtype (*direntproc) ();
|
||||
static int (*dirleaveproc) ();
|
||||
static FILEPROC fileproc;
|
||||
static FILESDONEPROC filesdoneproc;
|
||||
static DIRENTPROC direntproc;
|
||||
static DIRLEAVEPROC dirleaveproc;
|
||||
static int which;
|
||||
static Dtype flags;
|
||||
static int aflag;
|
||||
|
|
@ -43,10 +44,10 @@ static List *filelist = NULL; /* holds list of files on which to operate */
|
|||
static List *dirlist = NULL; /* holds list of directories on which to operate */
|
||||
|
||||
struct recursion_frame {
|
||||
int (*fileproc)();
|
||||
int (*filesdoneproc) ();
|
||||
Dtype (*direntproc) ();
|
||||
int (*dirleaveproc) ();
|
||||
FILEPROC fileproc;
|
||||
FILESDONEPROC filesdoneproc;
|
||||
DIRENTPROC direntproc;
|
||||
DIRLEAVEPROC dirleaveproc;
|
||||
Dtype flags;
|
||||
int which;
|
||||
int aflag;
|
||||
|
|
@ -61,18 +62,18 @@ struct recursion_frame {
|
|||
* we operate. In the special case of no arguments, we default to
|
||||
* ".".
|
||||
*
|
||||
* The general algorythm is as follows.
|
||||
* The general algorithm is as follows.
|
||||
*/
|
||||
int
|
||||
start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
|
||||
argc, argv, local, which, aflag, readlock,
|
||||
update_preload, dosrcs, wd_is_repos)
|
||||
int (*fileproc) ();
|
||||
int (*filesdoneproc) ();
|
||||
Dtype (*direntproc) ();
|
||||
int (*dirleaveproc) ();
|
||||
FILEPROC fileproc;
|
||||
FILESDONEPROC filesdoneproc;
|
||||
DIRENTPROC direntproc;
|
||||
DIRLEAVEPROC dirleaveproc;
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
int local;
|
||||
int which;
|
||||
int aflag;
|
||||
|
|
@ -103,7 +104,10 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
|
|||
repository = (char *) NULL;
|
||||
}
|
||||
if (entries)
|
||||
dellist (&entries);
|
||||
{
|
||||
Entries_Close (entries);
|
||||
entries = NULL;
|
||||
}
|
||||
if (srcfiles)
|
||||
dellist (&srcfiles);
|
||||
if (filelist)
|
||||
|
|
@ -122,7 +126,7 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
|
|||
* process each of the sub-directories, so we pretend like we were
|
||||
* called with the list of sub-dirs of the current dir as args
|
||||
*/
|
||||
if ((which & W_LOCAL) && !isdir (CVSADM) && !isdir (OCVSADM))
|
||||
if ((which & W_LOCAL) && !isdir (CVSADM))
|
||||
dirlist = Find_Dirs ((char *) NULL, W_LOCAL);
|
||||
else
|
||||
addlist (&dirlist, ".");
|
||||
|
|
@ -151,7 +155,7 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
|
|||
/* if this argument is a directory, then add it to the list of
|
||||
directories. */
|
||||
|
||||
if (isdir(argv[i]))
|
||||
if (!wrap_name_has (argv[i], WRAP_TOCVS) && isdir (argv[i]))
|
||||
addlist (&dirlist, argv[i]);
|
||||
else
|
||||
{
|
||||
|
|
@ -192,7 +196,7 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
|
|||
addfile (&files_by_dir, dir, comp);
|
||||
else if (isdir (dir))
|
||||
{
|
||||
if (isdir (CVSADM) || isdir (OCVSADM))
|
||||
if (isdir (CVSADM))
|
||||
{
|
||||
/* otherwise, look for it in the repository. */
|
||||
char *save_update_dir;
|
||||
|
|
@ -209,8 +213,9 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
|
|||
/* look for it in the repository. */
|
||||
repos = Name_Repository (dir, update_dir);
|
||||
(void) sprintf (tmp, "%s/%s", repos, comp);
|
||||
|
||||
if (isdir(tmp))
|
||||
free (repos);
|
||||
|
||||
if (!wrap_name_has (comp, WRAP_TOCVS) && isdir(tmp))
|
||||
addlist (&dirlist, argv[i]);
|
||||
else
|
||||
addfile (&files_by_dir, dir, comp);
|
||||
|
|
@ -262,10 +267,10 @@ start_recursion (fileproc, filesdoneproc, direntproc, dirleaveproc,
|
|||
int
|
||||
do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
|
||||
xflags, xwhich, xaflag, xreadlock, xdosrcs)
|
||||
int (*xfileproc) ();
|
||||
int (*xfilesdoneproc) ();
|
||||
Dtype (*xdirentproc) ();
|
||||
int (*xdirleaveproc) ();
|
||||
FILEPROC xfileproc;
|
||||
FILESDONEPROC xfilesdoneproc;
|
||||
DIRENTPROC xdirentproc;
|
||||
DIRLEAVEPROC xdirleaveproc;
|
||||
Dtype xflags;
|
||||
int xwhich;
|
||||
int xaflag;
|
||||
|
|
@ -291,12 +296,24 @@ do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
|
|||
readlock = noexec ? 0 : xreadlock;
|
||||
dosrcs = xdosrcs;
|
||||
|
||||
#if defined(SERVER_SUPPORT) && defined(SERVER_FLOWCONTROL)
|
||||
/*
|
||||
* Now would be a good time to check to see if we need to stop
|
||||
* generating data, to give the buffers a chance to drain to the
|
||||
* remote client. We should not have locks active at this point.
|
||||
*/
|
||||
if (server_active
|
||||
/* If there are writelocks around, we cannot pause here. */
|
||||
&& (readlock || noexec))
|
||||
server_pause_check();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Fill in repository with the current repository
|
||||
*/
|
||||
if (which & W_LOCAL)
|
||||
{
|
||||
if (isdir (CVSADM) || isdir (OCVSADM))
|
||||
if (isdir (CVSADM))
|
||||
repository = Name_Repository ((char *) NULL, update_dir);
|
||||
else
|
||||
repository = NULL;
|
||||
|
|
@ -350,7 +367,7 @@ do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
|
|||
{
|
||||
/* we will process files, so pre-parse entries */
|
||||
if (which & W_LOCAL)
|
||||
entries = ParseEntries (aflag);
|
||||
entries = Entries_Open (aflag);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -377,7 +394,8 @@ do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
|
|||
/* clean up */
|
||||
dellist (&filelist);
|
||||
dellist (&srcfiles);
|
||||
dellist (&entries);
|
||||
Entries_Close (entries);
|
||||
entries = NULL;
|
||||
}
|
||||
|
||||
/* call-back files done proc (if any) */
|
||||
|
|
@ -396,7 +414,7 @@ do_recursion (xfileproc, xfilesdoneproc, xdirentproc, xdirleaveproc,
|
|||
/* free the saved copy of the pointer if necessary */
|
||||
if (srepository)
|
||||
{
|
||||
(void) free (srepository);
|
||||
free (srepository);
|
||||
repository = (char *) NULL;
|
||||
}
|
||||
|
||||
|
|
@ -426,7 +444,6 @@ do_dir_proc (p, closure)
|
|||
void *closure;
|
||||
{
|
||||
char *dir = p->key;
|
||||
char savewd[PATH_MAX];
|
||||
char newrepos[PATH_MAX];
|
||||
List *sdirlist;
|
||||
char *srepository;
|
||||
|
|
@ -434,6 +451,7 @@ do_dir_proc (p, closure)
|
|||
Dtype dir_return = R_PROCESS;
|
||||
int stripped_dot = 0;
|
||||
int err = 0;
|
||||
struct saved_cwd cwd;
|
||||
|
||||
/* set up update_dir - skip dots if not at start */
|
||||
if (strcmp (dir, ".") != 0)
|
||||
|
|
@ -477,8 +495,8 @@ do_dir_proc (p, closure)
|
|||
if (dir_return != R_SKIP_ALL)
|
||||
{
|
||||
/* save our current directory and static vars */
|
||||
if (getwd (savewd) == NULL)
|
||||
error (1, 0, "could not get working directory: %s", savewd);
|
||||
if (save_cwd (&cwd))
|
||||
exit (1);
|
||||
sdirlist = dirlist;
|
||||
srepository = repository;
|
||||
dirlist = NULL;
|
||||
|
|
@ -511,8 +529,9 @@ do_dir_proc (p, closure)
|
|||
err = dirleaveproc (dir, err, update_dir);
|
||||
|
||||
/* get back to where we started and restore state vars */
|
||||
if (chdir (savewd) < 0)
|
||||
error (1, errno, "could not chdir to %s", savewd);
|
||||
if (restore_cwd (&cwd, NULL))
|
||||
exit (1);
|
||||
free_cwd (&cwd);
|
||||
dirlist = sdirlist;
|
||||
repository = srepository;
|
||||
}
|
||||
|
|
@ -554,7 +573,7 @@ addfile (listp, dir, file)
|
|||
Node *n;
|
||||
|
||||
/* add this dir. */
|
||||
(void) addlist (listp, dir);
|
||||
addlist (listp, dir);
|
||||
|
||||
n = findnode (*listp, dir);
|
||||
if (n == NULL)
|
||||
|
|
@ -577,8 +596,8 @@ unroll_files_proc (p, closure)
|
|||
struct recursion_frame *frame = (struct recursion_frame *) closure;
|
||||
int err = 0;
|
||||
List *save_dirlist;
|
||||
char savewd[PATH_MAX];
|
||||
char *save_update_dir = NULL;
|
||||
struct saved_cwd cwd;
|
||||
|
||||
/* if this dir was also an explicitly named argument, then skip
|
||||
it. We'll catch it later when we do dirs. */
|
||||
|
|
@ -593,9 +612,8 @@ unroll_files_proc (p, closure)
|
|||
|
||||
if (strcmp(p->key, ".") != 0)
|
||||
{
|
||||
if (getwd (savewd) == NULL)
|
||||
error (1, 0, "could not get working directory: %s", savewd);
|
||||
|
||||
if (save_cwd (&cwd))
|
||||
exit (1);
|
||||
if (chdir (p->key) < 0)
|
||||
error (1, errno, "could not chdir to %s", p->key);
|
||||
|
||||
|
|
@ -617,8 +635,9 @@ unroll_files_proc (p, closure)
|
|||
(void) strcpy (update_dir, save_update_dir);
|
||||
free (save_update_dir);
|
||||
|
||||
if (chdir (savewd) < 0)
|
||||
error (1, errno, "could not chdir to %s", savewd);
|
||||
if (restore_cwd (&cwd, NULL))
|
||||
exit (1);
|
||||
free_cwd (&cwd);
|
||||
}
|
||||
|
||||
dirlist = save_dirlist;
|
||||
|
|
|
|||
|
|
@ -12,18 +12,16 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)release.c 1.23 94/09/21 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)release.c 1.23 94/09/21 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static void release_delete PROTO((char *dir));
|
||||
|
||||
static char *release_usage[] =
|
||||
static const char *const release_usage[] =
|
||||
{
|
||||
"Usage: %s %s [-d] modules...\n",
|
||||
"\t-Q\tReally quiet.\n",
|
||||
"\t-d\tDelete the given directory.\n",
|
||||
"\t-q\tSomewhat quiet.\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -36,160 +34,201 @@ release (argc, argv)
|
|||
{
|
||||
FILE *fp;
|
||||
register int i, c;
|
||||
register char *cp;
|
||||
int margc;
|
||||
DBM *db;
|
||||
datum key, val;
|
||||
char *repository, *srepos;
|
||||
char **margv, *modargv[MAXFILEPERDIR], line[PATH_MAX];
|
||||
char line[PATH_MAX], update_cmd[PATH_MAX];
|
||||
char *thisarg;
|
||||
int arg_start_idx;
|
||||
|
||||
if (argc == -1)
|
||||
usage (release_usage);
|
||||
optind = 1;
|
||||
while ((c = getopt (argc, argv, "Qdq")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'Q':
|
||||
really_quiet = 1;
|
||||
/* FALL THROUGH */
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (!server_active)
|
||||
{
|
||||
#endif /* SERVER_SUPPORT */
|
||||
if (argc == -1)
|
||||
usage (release_usage);
|
||||
optind = 1;
|
||||
while ((c = getopt (argc, argv, "Qdq")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'Q':
|
||||
case 'q':
|
||||
#ifdef SERVER_SUPPORT
|
||||
/* The CVS 1.5 client sends these options (in addition to
|
||||
Global_option requests), so we must ignore them. */
|
||||
if (!server_active)
|
||||
#endif
|
||||
error (1, 0,
|
||||
"-q or -Q must be specified before \"%s\"",
|
||||
command_name);
|
||||
break;
|
||||
case 'd':
|
||||
case 'd':
|
||||
delete++;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
case '?':
|
||||
default:
|
||||
usage (release_usage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
#ifdef SERVER_SUPPORT
|
||||
}
|
||||
#endif /* SERVER_SUPPORT */
|
||||
|
||||
if (!(db = open_module ()))
|
||||
return (1);
|
||||
for (i = 0; i < argc; i++)
|
||||
/* We're going to run "cvs -n -q update" and check its output; if
|
||||
* the output is sufficiently unalarming, then we release with no
|
||||
* questions asked. Else we prompt, then maybe release.
|
||||
*/
|
||||
/* Construct the update command. */
|
||||
sprintf (update_cmd, "%s -n -q -d %s update",
|
||||
program_path, CVSroot);
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
/* Start the server; we'll close it after looping. */
|
||||
if (client_active)
|
||||
{
|
||||
start_server ();
|
||||
ign_setup ();
|
||||
}
|
||||
#endif /* CLIENT_SUPPORT */
|
||||
|
||||
/* If !server_active, we already skipped over argv[0] in the "argc
|
||||
-= optind;" statement above. But if server_active, we need to
|
||||
skip it now. */
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
arg_start_idx = 1;
|
||||
else
|
||||
arg_start_idx = 0;
|
||||
#endif /* SERVER_SUPPORT */
|
||||
|
||||
for (i = arg_start_idx; i < argc; i++)
|
||||
{
|
||||
|
||||
/*
|
||||
* If we are in a repository, do it. Else if we are in the parent of
|
||||
* a directory with the same name as the module, "cd" into it and
|
||||
* look for a repository there.
|
||||
*/
|
||||
if (isdir (argv[i]))
|
||||
{
|
||||
if (chdir (argv[i]) < 0)
|
||||
{
|
||||
if (!really_quiet)
|
||||
error (0, 0, "can't chdir to: %s", argv[i]);
|
||||
continue;
|
||||
}
|
||||
if (!isdir (CVSADM) && !isdir (OCVSADM))
|
||||
{
|
||||
if (!really_quiet)
|
||||
error (0, 0, "no repository module: %s", argv[i]);
|
||||
continue;
|
||||
}
|
||||
thisarg = argv[i];
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
{
|
||||
/* Just log the release -- all the interesting stuff happened
|
||||
* on the client.
|
||||
*/
|
||||
history_write ('F', thisarg, "", thisarg, ""); /* F == Free */
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* SERVER_SUPPORT */
|
||||
|
||||
/*
|
||||
* If we are in a repository, do it. Else if we are in the parent of
|
||||
* a directory with the same name as the module, "cd" into it and
|
||||
* look for a repository there.
|
||||
*/
|
||||
if (isdir (thisarg))
|
||||
{
|
||||
if (chdir (thisarg) < 0)
|
||||
{
|
||||
if (!really_quiet)
|
||||
error (0, 0, "can't chdir to: %s", thisarg);
|
||||
continue;
|
||||
}
|
||||
if (!isdir (CVSADM))
|
||||
{
|
||||
if (!really_quiet)
|
||||
error (0, 0, "no repository module: %s", thisarg);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!really_quiet)
|
||||
error (0, 0, "no such directory/module: %s", argv[i]);
|
||||
continue;
|
||||
{
|
||||
if (!really_quiet)
|
||||
error (0, 0, "no such directory: %s", thisarg);
|
||||
continue;
|
||||
}
|
||||
|
||||
repository = Name_Repository ((char *) NULL, (char *) NULL);
|
||||
srepos = Short_Repository (repository);
|
||||
|
||||
/* grab module entry from database and check against short repos */
|
||||
key.dptr = argv[i];
|
||||
key.dsize = strlen (key.dptr);
|
||||
val = dbm_fetch (db, key);
|
||||
if (!val.dptr)
|
||||
{
|
||||
error (0, 0, "no such module name: %s", argv[i]);
|
||||
continue;
|
||||
}
|
||||
val.dptr[val.dsize] = '\0';
|
||||
if ((cp = strchr (val.dptr, '#')) != NULL) /* Strip out a comment */
|
||||
{
|
||||
do
|
||||
{
|
||||
*cp-- = '\0';
|
||||
} while (isspace (*cp));
|
||||
}
|
||||
(void) sprintf (line, "%s %s", key.dptr, val.dptr);
|
||||
line2argv (&margc, modargv, line);
|
||||
margv = modargv;
|
||||
|
||||
optind = 1;
|
||||
while (getopt (margc, margv, CVSMODULE_OPTS) != -1)
|
||||
/* do nothing */ ;
|
||||
margc -= optind;
|
||||
margv += optind;
|
||||
|
||||
if (margc < 1)
|
||||
{
|
||||
error (0, 0, "modules file missing directory for key %s value %s",
|
||||
key.dptr, val.dptr);
|
||||
continue;
|
||||
}
|
||||
if (strcmp (*margv, srepos))
|
||||
{
|
||||
error (0, 0, "repository mismatch: module[%s], here[%s]",
|
||||
*margv, srepos);
|
||||
free (repository);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (!really_quiet)
|
||||
{
|
||||
/* The "release" command piggybacks on "update", which
|
||||
* does the real work of finding out if anything is not
|
||||
* up-to-date with the repository. Then "release" prompts
|
||||
* the user, telling her how many files have been
|
||||
* modified, and asking if she still wants to do the
|
||||
* release.
|
||||
*/
|
||||
fp = Popen (update_cmd, "r");
|
||||
c = 0;
|
||||
|
||||
/*
|
||||
* Now see if there is any reason not to allow a "Release" This
|
||||
* is "popen()" instead of "Popen()" since we don't want "-n" to
|
||||
* stop it.
|
||||
*/
|
||||
fp = popen ("cvs -n -q update", "r");
|
||||
c = 0;
|
||||
while (fgets (line, sizeof (line), fp))
|
||||
{
|
||||
if (strchr ("MARCZ", *line))
|
||||
c++;
|
||||
(void) printf (line);
|
||||
}
|
||||
(void) pclose (fp);
|
||||
(void) printf ("You have [%d] altered files in this repository.\n",
|
||||
c);
|
||||
(void) printf ("Are you sure you want to release %smodule `%s': ",
|
||||
delete ? "(and delete) " : "", argv[i]);
|
||||
c = !yesno ();
|
||||
if (c) /* "No" */
|
||||
{
|
||||
(void) fprintf (stderr, "** `%s' aborted by user choice.\n",
|
||||
command_name);
|
||||
free (repository);
|
||||
continue;
|
||||
}
|
||||
while (fgets (line, sizeof (line), fp))
|
||||
{
|
||||
if (strchr ("MARCZ", *line))
|
||||
c++;
|
||||
(void) printf (line);
|
||||
}
|
||||
|
||||
/* If the update exited with an error, then we just want to
|
||||
* complain and go on to the next arg. Especially, we do
|
||||
* not want to delete the local copy, since it's obviously
|
||||
* not what the user thinks it is.
|
||||
*/
|
||||
if ((pclose (fp)) != 0)
|
||||
{
|
||||
error (0, 0, "unable to release `%s'", thisarg);
|
||||
continue;
|
||||
}
|
||||
|
||||
(void) printf ("You have [%d] altered files in this repository.\n",
|
||||
c);
|
||||
(void) printf ("Are you sure you want to release %smodule `%s': ",
|
||||
delete ? "(and delete) " : "", thisarg);
|
||||
c = !yesno ();
|
||||
if (c) /* "No" */
|
||||
{
|
||||
(void) fprintf (stderr, "** `%s' aborted by user choice.\n",
|
||||
command_name);
|
||||
free (repository);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* So, we've passed all the tests, go ahead and release it. First,
|
||||
* log the release, then attempt to delete it.
|
||||
*/
|
||||
history_write ('F', argv[i], "", argv[i], ""); /* F == Free */
|
||||
free (repository);
|
||||
|
||||
if (delete)
|
||||
release_delete (argv[i]);
|
||||
}
|
||||
close_module (db);
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active)
|
||||
{
|
||||
if (fprintf (to_server, "Argument %s\n", thisarg) < 0)
|
||||
error (1, errno, "writing to server");
|
||||
if (fprintf (to_server, "release\n") < 0)
|
||||
error (1, errno, "writing to server");
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* CLIENT_SUPPORT */
|
||||
history_write ('F', thisarg, "", thisarg, ""); /* F == Free */
|
||||
#ifdef CLIENT_SUPPORT
|
||||
} /* else client not active */
|
||||
#endif /* CLIENT_SUPPORT */
|
||||
|
||||
free (repository);
|
||||
if (delete) release_delete (thisarg);
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active)
|
||||
return get_responses_and_close ();
|
||||
else
|
||||
#endif /* CLIENT_SUPPORT */
|
||||
return (0);
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
} /* else server not active */
|
||||
#endif /* SERVER_SUPPORT */
|
||||
} /* `for' loop */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* We want to "rm -r" the repository, but let us be a little paranoid. */
|
||||
|
||||
/* We want to "rm -r" the working directory, but let us be a little
|
||||
paranoid. */
|
||||
static void
|
||||
release_delete (dir)
|
||||
char *dir;
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)remove.c 1.39 94/10/07 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)remove.c 1.39 94/10/07 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static int remove_fileproc PROTO((char *file, char *update_dir,
|
||||
|
|
@ -32,7 +32,7 @@ static int local;
|
|||
static int removed_files;
|
||||
static int existing_files;
|
||||
|
||||
static char *remove_usage[] =
|
||||
static const char *const remove_usage[] =
|
||||
{
|
||||
"Usage: %s %s [-flR] [files...]\n",
|
||||
"\t-f\tDelete the file before removing it.\n",
|
||||
|
|
@ -44,7 +44,7 @@ static char *remove_usage[] =
|
|||
int
|
||||
cvsremove (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
int c, err;
|
||||
|
||||
|
|
@ -74,6 +74,21 @@ cvsremove (argc, argv)
|
|||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
wrap_setup ();
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active) {
|
||||
start_server ();
|
||||
ign_setup ();
|
||||
if (local)
|
||||
send_arg("-l");
|
||||
send_files (argc, argv, local, 0);
|
||||
if (fprintf (to_server, "remove\n") < 0)
|
||||
error (1, errno, "writing to server");
|
||||
return get_responses_and_close ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* start the recursion processor */
|
||||
err = start_recursion (remove_fileproc, (int (*) ()) NULL, remove_dirproc,
|
||||
(int (*) ()) NULL, argc, argv, local,
|
||||
|
|
@ -108,12 +123,22 @@ remove_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
char fname[PATH_MAX];
|
||||
Vers_TS *vers;
|
||||
|
||||
/*
|
||||
* If unlinking the file works, good. If not, the "unremoved"
|
||||
* error will indicate problems.
|
||||
*/
|
||||
if (force)
|
||||
(void) unlink (file);
|
||||
{
|
||||
if (!noexec)
|
||||
{
|
||||
if (unlink (file) < 0 && ! existence_error (errno))
|
||||
{
|
||||
if (update_dir[0] == '\0')
|
||||
error (0, errno, "unable to remove %s", file);
|
||||
else
|
||||
error (0, errno, "unable to remove %s/%s", update_dir,
|
||||
file);
|
||||
}
|
||||
}
|
||||
/* else FIXME should probably act as if the file doesn't exist
|
||||
in doing the following checks. */
|
||||
}
|
||||
|
||||
vers = Version_TS (repository, (char *) NULL, (char *) NULL, (char *) NULL,
|
||||
file, 0, 0, entries, srcfiles);
|
||||
|
|
@ -133,16 +158,18 @@ remove_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
{
|
||||
/*
|
||||
* It's a file that has been added, but not commited yet. So,
|
||||
* remove the ,p and ,t file for it and scratch it from the
|
||||
* entries file.
|
||||
*/
|
||||
* remove the ,t file for it and scratch it from the
|
||||
* entries file. */
|
||||
Scratch_Entry (entries, file);
|
||||
(void) sprintf (fname, "%s/%s%s", CVSADM, file, CVSEXT_OPT);
|
||||
(void) unlink_file (fname);
|
||||
(void) sprintf (fname, "%s/%s%s", CVSADM, file, CVSEXT_LOG);
|
||||
(void) unlink_file (fname);
|
||||
if (!quiet)
|
||||
error (0, 0, "removed `%s'", file);
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
server_checked_in (file, update_dir, repository);
|
||||
#endif
|
||||
}
|
||||
else if (vers->vn_user[0] == '-')
|
||||
{
|
||||
|
|
@ -159,6 +186,11 @@ remove_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
if (!quiet)
|
||||
error (0, 0, "scheduling `%s' for removal", file);
|
||||
removed_files++;
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
server_checked_in (file, update_dir, repository);
|
||||
#endif
|
||||
}
|
||||
|
||||
freevers_ts (&vers);
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)repos.c 1.32 94/09/23 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)repos.c 1.32 94/09/23 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
char *
|
||||
|
|
@ -28,9 +28,7 @@ Name_Repository (dir, update_dir)
|
|||
char path[PATH_MAX];
|
||||
char tmp[PATH_MAX];
|
||||
char cvsadm[PATH_MAX];
|
||||
char ocvsadm[PATH_MAX];
|
||||
char *cp;
|
||||
int has_cvsadm = 0, has_ocvsadm = 0;
|
||||
|
||||
if (update_dir && *update_dir)
|
||||
xupdate_dir = update_dir;
|
||||
|
|
@ -38,47 +36,18 @@ Name_Repository (dir, update_dir)
|
|||
xupdate_dir = ".";
|
||||
|
||||
if (dir != NULL)
|
||||
{
|
||||
(void) sprintf (cvsadm, "%s/%s", dir, CVSADM);
|
||||
(void) sprintf (ocvsadm, "%s/%s", dir, OCVSADM);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void) strcpy (cvsadm, CVSADM);
|
||||
(void) strcpy (ocvsadm, OCVSADM);
|
||||
}
|
||||
|
||||
/* sanity checks */
|
||||
if (!(has_cvsadm = isdir (cvsadm)) && !(has_ocvsadm = isdir (ocvsadm)))
|
||||
if (!isdir (cvsadm))
|
||||
{
|
||||
error (0, 0, "in directory %s:", xupdate_dir);
|
||||
error (1, 0, "there is no version here; do '%s checkout' first",
|
||||
program_name);
|
||||
}
|
||||
|
||||
if (has_ocvsadm)
|
||||
{
|
||||
if (has_cvsadm)
|
||||
{
|
||||
error (0, 0, "in directory %s:", xupdate_dir);
|
||||
error (1, 0, "error: both `%s' and `%s' exist; I give up",
|
||||
CVSADM, OCVSADM);
|
||||
}
|
||||
if (rename (ocvsadm, cvsadm) < 0)
|
||||
{
|
||||
error (0, 0, "in directory %s:", xupdate_dir);
|
||||
error (1, errno, "cannot rename `%s' to `%s'; I give up",
|
||||
OCVSADM, CVSADM);
|
||||
}
|
||||
|
||||
/*
|
||||
* We have converted the old CVS.adm directory to the new CVS
|
||||
* directory. Now, convert the Entries file to the new format, if
|
||||
* necessary.
|
||||
*/
|
||||
check_entries (dir);
|
||||
}
|
||||
|
||||
if (dir != NULL)
|
||||
(void) sprintf (tmp, "%s/%s", dir, CVSADM_ENT);
|
||||
else
|
||||
|
|
@ -127,7 +96,7 @@ Name_Repository (dir, update_dir)
|
|||
error (0, 0, "`..'-relative repositories are not supported.");
|
||||
error (1, 0, "illegal source repository");
|
||||
}
|
||||
if (repos[0] != '/')
|
||||
if (! isabsolute(repos))
|
||||
{
|
||||
if (CVSroot == NULL)
|
||||
{
|
||||
|
|
@ -139,7 +108,11 @@ Name_Repository (dir, update_dir)
|
|||
(void) strcpy (path, repos);
|
||||
(void) sprintf (repos, "%s/%s", CVSroot, path);
|
||||
}
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (!client_active && !isdir (repos))
|
||||
#else
|
||||
if (!isdir (repos))
|
||||
#endif
|
||||
{
|
||||
error (0, 0, "in directory %s:", xupdate_dir);
|
||||
error (1, 0, "there is no repository %s", repos);
|
||||
|
|
@ -162,9 +135,13 @@ Short_Repository (repository)
|
|||
if (repository == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* if repository matches CVSroot at the beginning, strip off CVSroot */
|
||||
/* If repository matches CVSroot at the beginning, strip off CVSroot */
|
||||
/* And skip leading '/' in rep, in case CVSroot ended with '/'. */
|
||||
if (strncmp (CVSroot, repository, strlen (CVSroot)) == 0)
|
||||
return (repository + strlen (CVSroot) + 1);
|
||||
{
|
||||
char *rep = repository + strlen (CVSroot);
|
||||
return (*rep == '/') ? rep+1 : rep;
|
||||
}
|
||||
else
|
||||
return (repository);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "@(#)root.c,v 1.2 1994/09/15 05:32:17 zoo Exp";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)root.c,v 1.2 1994/09/15 05:32:17 zoo Exp";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
char *
|
||||
|
|
@ -38,22 +38,19 @@ Name_Root(dir, update_dir)
|
|||
if (dir != NULL)
|
||||
{
|
||||
(void) sprintf (cvsadm, "%s/%s", dir, CVSADM);
|
||||
(void) sprintf (tmp, "%s/%s", dir, CVSADM_ROOT);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void) strcpy (cvsadm, CVSADM);
|
||||
}
|
||||
|
||||
if (dir != NULL)
|
||||
(void) sprintf (tmp, "%s/%s", dir, CVSADM_ROOT);
|
||||
else
|
||||
(void) strcpy (tmp, CVSADM_ROOT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Do not bother looking for a readable file if there is no cvsadm
|
||||
* directory present.
|
||||
*
|
||||
* It is possiible that not all repositories will have a CVS/Root
|
||||
* It is possible that not all repositories will have a CVS/Root
|
||||
* file. This is ok, but the user will need to specify -d
|
||||
* /path/name or have the environment variable CVSROOT set in
|
||||
* order to continue.
|
||||
|
|
@ -90,7 +87,14 @@ Name_Root(dir, update_dir)
|
|||
* root now contains a candidate for CVSroot. It must be an
|
||||
* absolute pathname
|
||||
*/
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
/* It must specify a server via remote CVS or be an absolute pathname. */
|
||||
if ((strchr (root, ':') == NULL)
|
||||
&& ! isabsolute (root))
|
||||
#else
|
||||
if (root[0] != '/')
|
||||
#endif
|
||||
{
|
||||
error (0, 0, "in directory %s:", xupdate_dir);
|
||||
error (0, 0,
|
||||
|
|
@ -99,7 +103,11 @@ Name_Root(dir, update_dir)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if ((strchr (root, ':') == NULL) && !isdir (root))
|
||||
#else
|
||||
if (!isdir (root))
|
||||
#endif
|
||||
{
|
||||
error (0, 0, "in directory %s:", xupdate_dir);
|
||||
error (0, 0,
|
||||
|
|
@ -154,6 +162,9 @@ Create_Root (dir, rootdir)
|
|||
FILE *fout;
|
||||
char tmp[PATH_MAX];
|
||||
|
||||
if (noexec)
|
||||
return;
|
||||
|
||||
/* record the current cvs root */
|
||||
|
||||
if (rootdir != NULL)
|
||||
|
|
@ -163,7 +174,7 @@ Create_Root (dir, rootdir)
|
|||
else
|
||||
(void) strcpy (tmp, CVSADM_ROOT);
|
||||
fout = open_file (tmp, "w+");
|
||||
if (fprintf (fout, "%s\n", rootdir) == EOF)
|
||||
if (fprintf (fout, "%s\n", rootdir) < 0)
|
||||
error (1, errno, "write to %s failed", tmp);
|
||||
if (fclose (fout) == EOF)
|
||||
error (1, errno, "cannot close %s", tmp);
|
||||
|
|
|
|||
|
|
@ -14,19 +14,45 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)rtag.c 1.61 94/09/30 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)rtag.c 1.61 94/09/30 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static int check_fileproc PROTO((char *file, char *update_dir,
|
||||
char *repository, List * entries,
|
||||
List * srcfiles));
|
||||
static int check_filesdoneproc PROTO((int err, char *repos, char *update_dir));
|
||||
static int pretag_proc PROTO((char *repository, char *filter));
|
||||
static void masterlist_delproc PROTO((Node *p));
|
||||
static void tag_delproc PROTO((Node *p));
|
||||
static int pretag_list_proc PROTO((Node *p, void *closure));
|
||||
|
||||
static Dtype rtag_dirproc PROTO((char *dir, char *repos, char *update_dir));
|
||||
static int rtag_fileproc PROTO((char *file, char *update_dir,
|
||||
char *repository, List * entries,
|
||||
List * srcfiles));
|
||||
static int rtag_proc PROTO((int *pargc, char *argv[], char *xwhere,
|
||||
static int rtag_proc PROTO((int *pargc, char **argv, char *xwhere,
|
||||
char *mwhere, char *mfile, int shorten,
|
||||
int local_specified, char *mname, char *msg));
|
||||
static int rtag_delete PROTO((RCSNode *rcsfile));
|
||||
|
||||
|
||||
struct tag_info
|
||||
{
|
||||
Ctype status;
|
||||
char *rev;
|
||||
char *tag;
|
||||
char *options;
|
||||
};
|
||||
|
||||
struct master_lists
|
||||
{
|
||||
List *tlist;
|
||||
};
|
||||
|
||||
static List *mtlist;
|
||||
static List *tlist;
|
||||
|
||||
static char *symtag;
|
||||
static char *numtag;
|
||||
static int delete; /* adding a tag by default */
|
||||
|
|
@ -37,16 +63,14 @@ static int local; /* recursive by default */
|
|||
static int force_tag_match = 1; /* force by default */
|
||||
static int force_tag_move; /* don't move existing tags by default */
|
||||
|
||||
static char *rtag_usage[] =
|
||||
static const char *const rtag_usage[] =
|
||||
{
|
||||
"Usage: %s %s [-QaflRnqF] [-b] [-d] [-r tag|-D date] tag modules...\n",
|
||||
"\t-Q\tReally quiet.\n",
|
||||
"Usage: %s %s [-aflRnF] [-b] [-d] [-r tag|-D date] tag modules...\n",
|
||||
"\t-a\tClear tag from removed files that would not otherwise be tagged.\n",
|
||||
"\t-f\tForce a head revision match if tag/date not found.\n",
|
||||
"\t-l\tLocal directory only, not recursive\n",
|
||||
"\t-R\tProcess directories recursively.\n",
|
||||
"\t-n\tNo execution of 'tag program'\n",
|
||||
"\t-q\tSomewhat quiet.\n",
|
||||
"\t-d\tDelete the given Tag.\n",
|
||||
"\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n",
|
||||
"\t-[rD]\tExisting tag or Date.\n",
|
||||
|
|
@ -57,7 +81,7 @@ static char *rtag_usage[] =
|
|||
int
|
||||
rtag (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
register int i;
|
||||
int c;
|
||||
|
|
@ -80,10 +104,15 @@ rtag (argc, argv)
|
|||
run_module_prog = 0;
|
||||
break;
|
||||
case 'Q':
|
||||
really_quiet = 1;
|
||||
/* FALL THROUGH */
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
#ifdef SERVER_SUPPORT
|
||||
/* The CVS 1.5 client sends these options (in addition to
|
||||
Global_option requests), so we must ignore them. */
|
||||
if (!server_active)
|
||||
#endif
|
||||
error (1, 0,
|
||||
"-q or -Q must be specified before \"%s\"",
|
||||
command_name);
|
||||
break;
|
||||
case 'l':
|
||||
local = 1;
|
||||
|
|
@ -131,6 +160,46 @@ rtag (argc, argv)
|
|||
error (0, 0, "warning: -b ignored with -d options");
|
||||
RCS_check_tag (symtag);
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active)
|
||||
{
|
||||
/* We're the client side. Fire up the remote server. */
|
||||
start_server ();
|
||||
|
||||
ign_setup ();
|
||||
|
||||
if (local)
|
||||
send_arg("-l");
|
||||
if (delete)
|
||||
send_arg("-d");
|
||||
if (branch_mode)
|
||||
send_arg("-b");
|
||||
if (force_tag_move)
|
||||
send_arg("-F");
|
||||
if (run_module_prog)
|
||||
send_arg("-n");
|
||||
if (attic_too)
|
||||
send_arg("-a");
|
||||
|
||||
if (numtag)
|
||||
option_with_arg ("-r", numtag);
|
||||
if (date)
|
||||
client_senddate (date);
|
||||
|
||||
send_arg (symtag);
|
||||
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < argc; ++i)
|
||||
send_arg (argv[i]);
|
||||
}
|
||||
|
||||
if (fprintf (to_server, "rtag\n") < 0)
|
||||
error (1, errno, "writing to server");
|
||||
return get_responses_and_close ();
|
||||
}
|
||||
#endif
|
||||
|
||||
db = open_module ();
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
|
|
@ -153,7 +222,7 @@ static int
|
|||
rtag_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified,
|
||||
mname, msg)
|
||||
int *pargc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
char *xwhere;
|
||||
char *mwhere;
|
||||
char *mfile;
|
||||
|
|
@ -220,14 +289,214 @@ rtag_proc (pargc, argv, xwhere, mwhere, mfile, shorten, local_specified,
|
|||
else
|
||||
which = W_REPOS;
|
||||
|
||||
/* check to make sure they are authorized to tag all the
|
||||
specified files in the repository */
|
||||
|
||||
mtlist = getlist();
|
||||
err = start_recursion (check_fileproc, check_filesdoneproc,
|
||||
(DIRENTPROC) NULL, (DIRLEAVEPROC) NULL,
|
||||
*pargc - 1, argv + 1, local, which, 0, 1,
|
||||
where, 1, 1);
|
||||
|
||||
if (err)
|
||||
{
|
||||
error (1, 0, "correct the above errors first!");
|
||||
}
|
||||
|
||||
/* start the recursion processor */
|
||||
err = start_recursion (rtag_fileproc, (int (*) ()) NULL, rtag_dirproc,
|
||||
(int (*) ()) NULL, *pargc - 1, argv + 1, local,
|
||||
err = start_recursion (rtag_fileproc, (FILESDONEPROC) NULL, rtag_dirproc,
|
||||
(DIRLEAVEPROC) NULL, *pargc - 1, argv + 1, local,
|
||||
which, 0, 1, where, 1, 1);
|
||||
|
||||
dellist(&mtlist);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
/* check file that is to be tagged */
|
||||
/* All we do here is add it to our list */
|
||||
|
||||
static int
|
||||
check_fileproc(file, update_dir, repository, entries, srcfiles)
|
||||
char *file;
|
||||
char *update_dir;
|
||||
char *repository;
|
||||
List * entries;
|
||||
List * srcfiles;
|
||||
{
|
||||
char *xdir;
|
||||
Node *p;
|
||||
Vers_TS *vers;
|
||||
|
||||
if (update_dir[0] == '\0')
|
||||
xdir = ".";
|
||||
else
|
||||
xdir = update_dir;
|
||||
if ((p = findnode (mtlist, xdir)) != NULL)
|
||||
{
|
||||
tlist = ((struct master_lists *) p->data)->tlist;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct master_lists *ml;
|
||||
|
||||
tlist = getlist ();
|
||||
p = getnode ();
|
||||
p->key = xstrdup (xdir);
|
||||
p->type = UPDATE;
|
||||
ml = (struct master_lists *)
|
||||
xmalloc (sizeof (struct master_lists));
|
||||
ml->tlist = tlist;
|
||||
p->data = (char *) ml;
|
||||
p->delproc = masterlist_delproc;
|
||||
(void) addnode (mtlist, p);
|
||||
}
|
||||
/* do tlist */
|
||||
p = getnode ();
|
||||
p->key = xstrdup (file);
|
||||
p->type = UPDATE;
|
||||
p->delproc = tag_delproc;
|
||||
vers = Version_TS (repository, (char *) NULL, (char *) NULL,
|
||||
(char *) NULL, file, 0, 0, entries, srcfiles);
|
||||
p->data = RCS_getversion(vers->srcfile, numtag, date, force_tag_match, 0);
|
||||
if (p->data != NULL)
|
||||
{
|
||||
int addit = 1;
|
||||
char *oversion;
|
||||
|
||||
oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1, 0);
|
||||
if (oversion == NULL)
|
||||
{
|
||||
if (delete)
|
||||
{
|
||||
addit = 0;
|
||||
}
|
||||
}
|
||||
else if (strcmp(oversion, p->data) == 0)
|
||||
{
|
||||
addit = 0;
|
||||
}
|
||||
else if (!force_tag_move)
|
||||
{
|
||||
addit = 0;
|
||||
}
|
||||
if (oversion != NULL)
|
||||
{
|
||||
free(oversion);
|
||||
}
|
||||
if (!addit)
|
||||
{
|
||||
free(p->data);
|
||||
p->data = NULL;
|
||||
}
|
||||
}
|
||||
freevers_ts (&vers);
|
||||
(void) addnode (tlist, p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
check_filesdoneproc(err, repos, update_dir)
|
||||
int err;
|
||||
char *repos;
|
||||
char *update_dir;
|
||||
{
|
||||
int n;
|
||||
Node *p;
|
||||
|
||||
p = findnode(mtlist, update_dir);
|
||||
if (p != NULL)
|
||||
{
|
||||
tlist = ((struct master_lists *) p->data)->tlist;
|
||||
}
|
||||
else
|
||||
{
|
||||
tlist = (List *) NULL;
|
||||
}
|
||||
if ((tlist == NULL) || (tlist->list->next == tlist->list))
|
||||
{
|
||||
return (err);
|
||||
}
|
||||
if ((n = Parse_Info(CVSROOTADM_TAGINFO, repos, pretag_proc, 1)) > 0)
|
||||
{
|
||||
error (0, 0, "Pre-tag check failed");
|
||||
err += n;
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
pretag_proc(repository, filter)
|
||||
char *repository;
|
||||
char *filter;
|
||||
{
|
||||
if (filter[0] == '/')
|
||||
{
|
||||
char *s, *cp;
|
||||
|
||||
s = xstrdup(filter);
|
||||
for (cp=s; *cp; cp++)
|
||||
{
|
||||
if (isspace(*cp))
|
||||
{
|
||||
*cp = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isfile(s))
|
||||
{
|
||||
error (0, errno, "cannot find pre-tag filter '%s'", s);
|
||||
free(s);
|
||||
return (1);
|
||||
}
|
||||
free(s);
|
||||
}
|
||||
run_setup("%s %s %s %s",
|
||||
filter,
|
||||
symtag,
|
||||
delete ? "del" : force_tag_move ? "mov" : "add",
|
||||
repository);
|
||||
walklist(tlist, pretag_list_proc, NULL);
|
||||
return (run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY));
|
||||
}
|
||||
|
||||
static void
|
||||
masterlist_delproc(p)
|
||||
Node *p;
|
||||
{
|
||||
struct master_lists *ml;
|
||||
|
||||
ml = (struct master_lists *)p->data;
|
||||
dellist(&ml->tlist);
|
||||
free(ml);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
tag_delproc(p)
|
||||
Node *p;
|
||||
{
|
||||
if (p->data != NULL)
|
||||
{
|
||||
free(p->data);
|
||||
p->data = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
pretag_list_proc(p, closure)
|
||||
Node *p;
|
||||
void *closure;
|
||||
{
|
||||
if (p->data != NULL)
|
||||
{
|
||||
run_arg(p->key);
|
||||
run_arg(p->data);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to tag a particular file, as appropriate with the options that were
|
||||
* set above.
|
||||
|
|
@ -272,7 +541,7 @@ rtag_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
return (rtag_delete (rcsfile));
|
||||
}
|
||||
|
||||
version = RCS_getversion (rcsfile, numtag, date, force_tag_match);
|
||||
version = RCS_getversion (rcsfile, numtag, date, force_tag_match, 0);
|
||||
if (version == NULL)
|
||||
{
|
||||
/* If -a specified, clean up any old tags */
|
||||
|
|
@ -299,7 +568,7 @@ rtag_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
* the branch. Use a symbolic tag for that.
|
||||
*/
|
||||
rev = branch_mode ? RCS_magicrev (rcsfile, version) : numtag;
|
||||
run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, symtag, numtag);
|
||||
retcode = RCS_settag(rcsfile->path, symtag, numtag);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -315,7 +584,7 @@ rtag_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
* typical tagging operation.
|
||||
*/
|
||||
rev = branch_mode ? RCS_magicrev (rcsfile, version) : version;
|
||||
oversion = RCS_getversion (rcsfile, symtag, (char *) 0, 1);
|
||||
oversion = RCS_getversion (rcsfile, symtag, (char *) NULL, 1, 0);
|
||||
if (oversion != NULL)
|
||||
{
|
||||
int isbranch = RCS_isbranch (file, symtag, srcfiles);
|
||||
|
|
@ -347,10 +616,10 @@ rtag_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
}
|
||||
free (oversion);
|
||||
}
|
||||
run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, symtag, rev);
|
||||
retcode = RCS_settag(rcsfile->path, symtag, rev);
|
||||
}
|
||||
run_arg (rcsfile->path);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
|
||||
|
||||
if (retcode != 0)
|
||||
{
|
||||
error (1, retcode == -1 ? errno : 0,
|
||||
"failed to set tag `%s' to revision `%s' in `%s'",
|
||||
|
|
@ -382,20 +651,18 @@ rtag_delete (rcsfile)
|
|||
|
||||
if (numtag)
|
||||
{
|
||||
version = RCS_getversion (rcsfile, numtag, (char *) 0, 1);
|
||||
version = RCS_getversion (rcsfile, numtag, (char *) NULL, 1, 0);
|
||||
if (version == NULL)
|
||||
return (0);
|
||||
free (version);
|
||||
}
|
||||
|
||||
version = RCS_getversion (rcsfile, symtag, (char *) 0, 1);
|
||||
version = RCS_getversion (rcsfile, symtag, (char *) NULL, 1, 0);
|
||||
if (version == NULL)
|
||||
return (0);
|
||||
free (version);
|
||||
|
||||
run_setup ("%s%s -q -N%s", Rcsbin, RCS, symtag);
|
||||
run_arg (rcsfile->path);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL)) != 0)
|
||||
if ((retcode = RCS_deltag(rcsfile->path, symtag, 1)) != 0)
|
||||
{
|
||||
if (!quiet)
|
||||
error (0, retcode == -1 ? errno : 0,
|
||||
|
|
@ -420,3 +687,6 @@ rtag_dirproc (dir, repos, update_dir)
|
|||
error (0, 0, "%s %s", delete ? "Untagging" : "Tagging", update_dir);
|
||||
return (R_PROCESS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)status.c 1.56 94/10/07 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)status.c 1.56 94/10/07 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static Dtype status_dirproc PROTO((char *dir, char *repos, char *update_dir));
|
||||
|
|
@ -26,7 +26,7 @@ static int long_format = 0;
|
|||
static char *xfile;
|
||||
static List *xsrcfiles;
|
||||
|
||||
static char *status_usage[] =
|
||||
static const char *const status_usage[] =
|
||||
{
|
||||
"Usage: %s %s [-vlR] [files...]\n",
|
||||
"\t-v\tVerbose format; includes tag information for the file\n",
|
||||
|
|
@ -38,7 +38,7 @@ static char *status_usage[] =
|
|||
int
|
||||
status (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
int c;
|
||||
int err = 0;
|
||||
|
|
@ -69,9 +69,34 @@ status (argc, argv)
|
|||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
wrap_setup ();
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active) {
|
||||
start_server ();
|
||||
|
||||
ign_setup ();
|
||||
|
||||
if (long_format)
|
||||
send_arg("-v");
|
||||
if (local)
|
||||
send_arg("-l");
|
||||
|
||||
/* XXX This should only need to send file info; the file
|
||||
contents themselves will not be examined. */
|
||||
send_files (argc, argv, local, 0);
|
||||
|
||||
if (fprintf (to_server, "status\n") < 0)
|
||||
error (1, errno, "writing to server");
|
||||
err = get_responses_and_close ();
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* start the recursion processor */
|
||||
err = start_recursion (status_fileproc, (int (*) ()) NULL, status_dirproc,
|
||||
(int (*) ()) NULL, argc, argv, local,
|
||||
err = start_recursion (status_fileproc, (FILESDONEPROC) NULL, status_dirproc,
|
||||
(DIRLEAVEPROC) NULL, argc, argv, local,
|
||||
W_LOCAL, 0, 1, (char *) NULL, 1, 0);
|
||||
|
||||
return (err);
|
||||
|
|
@ -104,6 +129,11 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
case T_CHECKOUT:
|
||||
sstat = "Needs Checkout";
|
||||
break;
|
||||
#ifdef SERVER_SUPPORT
|
||||
case T_PATCH:
|
||||
sstat = "Needs Patch";
|
||||
break;
|
||||
#endif
|
||||
case T_CONFLICT:
|
||||
sstat = "Unresolved Conflict";
|
||||
break;
|
||||
|
|
@ -143,6 +173,10 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
(void) printf (" Working revision:\tNo entry for %s\n", file);
|
||||
else if (vers->vn_user[0] == '0' && vers->vn_user[1] == '\0')
|
||||
(void) printf (" Working revision:\tNew file!\n");
|
||||
#ifdef SERVER_SUPPORT
|
||||
else if (server_active)
|
||||
(void) printf (" Working revision:\t%s\n", vers->vn_user);
|
||||
#endif
|
||||
else
|
||||
(void) printf (" Working revision:\t%s\t%s\n", vers->vn_user,
|
||||
vers->ts_rcs);
|
||||
|
|
@ -181,17 +215,17 @@ status_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (!really_quiet)
|
||||
(void) printf (" Sticky Tag:\t\t(none)\n");
|
||||
|
||||
if (edata->date)
|
||||
(void) printf (" Sticky Date:\t\t%s\n", edata->date);
|
||||
else
|
||||
else if (!really_quiet)
|
||||
(void) printf (" Sticky Date:\t\t(none)\n");
|
||||
|
||||
if (edata->options && edata->options[0])
|
||||
(void) printf (" Sticky Options:\t%s\n", edata->options);
|
||||
else
|
||||
else if (!really_quiet)
|
||||
(void) printf (" Sticky Options:\t(none)\n");
|
||||
|
||||
if (long_format && vers->srcfile)
|
||||
|
|
|
|||
|
|
@ -14,29 +14,57 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)tag.c 1.60 94/09/30 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)tag.c 1.60 94/09/30 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static int check_fileproc PROTO((char *file, char *update_dir,
|
||||
char *repository, List * entries,
|
||||
List * srcfiles));
|
||||
static int check_filesdoneproc PROTO((int err, char *repos, char *update_dir));
|
||||
static int pretag_proc PROTO((char *repository, char *filter));
|
||||
static void masterlist_delproc PROTO((Node *p));
|
||||
static void tag_delproc PROTO((Node *p));
|
||||
static int pretag_list_proc PROTO((Node *p, void *closure));
|
||||
|
||||
static Dtype tag_dirproc PROTO((char *dir, char *repos, char *update_dir));
|
||||
static int tag_fileproc PROTO((char *file, char *update_dir,
|
||||
char *repository, List * entries,
|
||||
List * srcfiles));
|
||||
|
||||
static char *numtag;
|
||||
static char *date = NULL;
|
||||
static char *symtag;
|
||||
static int delete; /* adding a tag by default */
|
||||
static int branch_mode; /* make an automagic "branch" tag */
|
||||
static int local; /* recursive by default */
|
||||
static int force_tag_match = 1; /* force tag to match by default */
|
||||
static int force_tag_move; /* don't force tag to move by default */
|
||||
|
||||
static char *tag_usage[] =
|
||||
struct tag_info
|
||||
{
|
||||
"Usage: %s %s [-QlRqF] [-b] [-d] tag [files...]\n",
|
||||
"\t-Q\tReally quiet.\n",
|
||||
Ctype status;
|
||||
char *rev;
|
||||
char *tag;
|
||||
char *options;
|
||||
};
|
||||
|
||||
struct master_lists
|
||||
{
|
||||
List *tlist;
|
||||
};
|
||||
|
||||
static List *mtlist;
|
||||
static List *tlist;
|
||||
|
||||
static const char *const tag_usage[] =
|
||||
{
|
||||
"Usage: %s %s [-lRF] [-b] [-d] tag [files...]\n",
|
||||
"\t-l\tLocal directory only, not recursive.\n",
|
||||
"\t-R\tProcess directories recursively.\n",
|
||||
"\t-q\tSomewhat quiet.\n",
|
||||
"\t-d\tDelete the given Tag.\n",
|
||||
"\t-[rD]\tExisting tag or date.\n",
|
||||
"\t-f\tForce a head revision if tag etc not found.\n",
|
||||
"\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n",
|
||||
"\t-F\tMove tag if it already exists\n",
|
||||
NULL
|
||||
|
|
@ -45,7 +73,7 @@ static char *tag_usage[] =
|
|||
int
|
||||
tag (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
int c;
|
||||
int err = 0;
|
||||
|
|
@ -54,15 +82,20 @@ tag (argc, argv)
|
|||
usage (tag_usage);
|
||||
|
||||
optind = 1;
|
||||
while ((c = getopt (argc, argv, "FQqlRdb")) != -1)
|
||||
while ((c = getopt (argc, argv, "FQqlRdr:D:bf")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'Q':
|
||||
really_quiet = 1;
|
||||
/* FALL THROUGH */
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
#ifdef SERVER_SUPPORT
|
||||
/* The CVS 1.5 client sends these options (in addition to
|
||||
Global_option requests), so we must ignore them. */
|
||||
if (!server_active)
|
||||
#endif
|
||||
error (1, 0,
|
||||
"-q or -Q must be specified before \"%s\"",
|
||||
command_name);
|
||||
break;
|
||||
case 'l':
|
||||
local = 1;
|
||||
|
|
@ -73,6 +106,17 @@ tag (argc, argv)
|
|||
case 'd':
|
||||
delete = 1;
|
||||
break;
|
||||
case 'r':
|
||||
numtag = optarg;
|
||||
break;
|
||||
case 'D':
|
||||
if (date)
|
||||
free (date);
|
||||
date = Make_Date (optarg);
|
||||
break;
|
||||
case 'f':
|
||||
force_tag_match = 0;
|
||||
break;
|
||||
case 'b':
|
||||
branch_mode = 1;
|
||||
break;
|
||||
|
|
@ -98,13 +142,246 @@ tag (argc, argv)
|
|||
error (0, 0, "warning: -b ignored with -d options");
|
||||
RCS_check_tag (symtag);
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
if (client_active)
|
||||
{
|
||||
/* We're the client side. Fire up the remote server. */
|
||||
start_server ();
|
||||
|
||||
ign_setup ();
|
||||
|
||||
if (local)
|
||||
send_arg("-l");
|
||||
if (delete)
|
||||
send_arg("-d");
|
||||
if (branch_mode)
|
||||
send_arg("-b");
|
||||
if (force_tag_move)
|
||||
send_arg("-F");
|
||||
|
||||
send_arg (symtag);
|
||||
|
||||
#if 0
|
||||
/* FIXME: We shouldn't have to send current files, but I'm not sure
|
||||
whether it works. So send the files --
|
||||
it's slower but it works. */
|
||||
send_file_names (argc, argv);
|
||||
#else
|
||||
send_files (argc, argv, local, 0);
|
||||
#endif
|
||||
if (fprintf (to_server, "tag\n") < 0)
|
||||
error (1, errno, "writing to server");
|
||||
return get_responses_and_close ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check to make sure they are authorized to tag all the
|
||||
specified files in the repository */
|
||||
|
||||
mtlist = getlist();
|
||||
err = start_recursion (check_fileproc, check_filesdoneproc,
|
||||
(DIRENTPROC) NULL, (DIRLEAVEPROC) NULL,
|
||||
argc, argv, local, W_LOCAL, 0, 1,
|
||||
(char *) NULL, 1, 0);
|
||||
|
||||
if (err)
|
||||
{
|
||||
error (1, 0, "correct the above errors first!");
|
||||
}
|
||||
|
||||
/* start the recursion processor */
|
||||
err = start_recursion (tag_fileproc, (int (*) ()) NULL, tag_dirproc,
|
||||
(int (*) ()) NULL, argc, argv, local,
|
||||
err = start_recursion (tag_fileproc, (FILESDONEPROC) NULL, tag_dirproc,
|
||||
(DIRLEAVEPROC) NULL, argc, argv, local,
|
||||
W_LOCAL, 0, 1, (char *) NULL, 1, 0);
|
||||
dellist(&mtlist);
|
||||
return (err);
|
||||
}
|
||||
|
||||
/* check file that is to be tagged */
|
||||
/* All we do here is add it to our list */
|
||||
|
||||
static int
|
||||
check_fileproc(file, update_dir, repository, entries, srcfiles)
|
||||
char *file;
|
||||
char *update_dir;
|
||||
char *repository;
|
||||
List * entries;
|
||||
List * srcfiles;
|
||||
{
|
||||
char *xdir;
|
||||
Node *p;
|
||||
Vers_TS *vers;
|
||||
|
||||
if (update_dir[0] == '\0')
|
||||
xdir = ".";
|
||||
else
|
||||
xdir = update_dir;
|
||||
if ((p = findnode (mtlist, xdir)) != NULL)
|
||||
{
|
||||
tlist = ((struct master_lists *) p->data)->tlist;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct master_lists *ml;
|
||||
|
||||
tlist = getlist ();
|
||||
p = getnode ();
|
||||
p->key = xstrdup (xdir);
|
||||
p->type = UPDATE;
|
||||
ml = (struct master_lists *)
|
||||
xmalloc (sizeof (struct master_lists));
|
||||
ml->tlist = tlist;
|
||||
p->data = (char *) ml;
|
||||
p->delproc = masterlist_delproc;
|
||||
(void) addnode (mtlist, p);
|
||||
}
|
||||
/* do tlist */
|
||||
p = getnode ();
|
||||
p->key = xstrdup (file);
|
||||
p->type = UPDATE;
|
||||
p->delproc = tag_delproc;
|
||||
vers = Version_TS (repository, (char *) NULL, (char *) NULL, (char *) NULL,
|
||||
file, 0, 0, entries, srcfiles);
|
||||
p->data = RCS_getversion(vers->srcfile, numtag, date, force_tag_match, 0);
|
||||
if (p->data != NULL)
|
||||
{
|
||||
int addit = 1;
|
||||
char *oversion;
|
||||
|
||||
oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1, 0);
|
||||
if (oversion == NULL)
|
||||
{
|
||||
if (delete)
|
||||
{
|
||||
addit = 0;
|
||||
}
|
||||
}
|
||||
else if (strcmp(oversion, p->data) == 0)
|
||||
{
|
||||
addit = 0;
|
||||
}
|
||||
else if (!force_tag_move)
|
||||
{
|
||||
addit = 0;
|
||||
}
|
||||
if (oversion != NULL)
|
||||
{
|
||||
free(oversion);
|
||||
}
|
||||
if (!addit)
|
||||
{
|
||||
free(p->data);
|
||||
p->data = NULL;
|
||||
}
|
||||
}
|
||||
freevers_ts(&vers);
|
||||
(void) addnode (tlist, p);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
check_filesdoneproc(err, repos, update_dir)
|
||||
int err;
|
||||
char *repos;
|
||||
char *update_dir;
|
||||
{
|
||||
int n;
|
||||
Node *p;
|
||||
|
||||
p = findnode(mtlist, update_dir);
|
||||
if (p != NULL)
|
||||
{
|
||||
tlist = ((struct master_lists *) p->data)->tlist;
|
||||
}
|
||||
else
|
||||
{
|
||||
tlist = (List *) NULL;
|
||||
}
|
||||
if ((tlist == NULL) || (tlist->list->next == tlist->list))
|
||||
{
|
||||
return (err);
|
||||
}
|
||||
if ((n = Parse_Info(CVSROOTADM_TAGINFO, repos, pretag_proc, 1)) > 0)
|
||||
{
|
||||
error (0, 0, "Pre-tag check failed");
|
||||
err += n;
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
pretag_proc(repository, filter)
|
||||
char *repository;
|
||||
char *filter;
|
||||
{
|
||||
if (filter[0] == '/')
|
||||
{
|
||||
char *s, *cp;
|
||||
|
||||
s = xstrdup(filter);
|
||||
for (cp=s; *cp; cp++)
|
||||
{
|
||||
if (isspace(*cp))
|
||||
{
|
||||
*cp = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isfile(s))
|
||||
{
|
||||
error (0, errno, "cannot find pre-tag filter '%s'", s);
|
||||
free(s);
|
||||
return (1);
|
||||
}
|
||||
free(s);
|
||||
}
|
||||
run_setup("%s %s %s %s",
|
||||
filter,
|
||||
symtag,
|
||||
delete ? "del" : force_tag_move ? "mov" : "add",
|
||||
repository);
|
||||
walklist(tlist, pretag_list_proc, NULL);
|
||||
return (run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY));
|
||||
}
|
||||
|
||||
static void
|
||||
masterlist_delproc(p)
|
||||
Node *p;
|
||||
{
|
||||
struct master_lists *ml;
|
||||
|
||||
ml = (struct master_lists *)p->data;
|
||||
dellist(&ml->tlist);
|
||||
free(ml);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
tag_delproc(p)
|
||||
Node *p;
|
||||
{
|
||||
if (p->data != NULL)
|
||||
{
|
||||
free(p->data);
|
||||
p->data = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
pretag_list_proc(p, closure)
|
||||
Node *p;
|
||||
void *closure;
|
||||
{
|
||||
if (p->data != NULL)
|
||||
{
|
||||
run_arg(p->key);
|
||||
run_arg(p->data);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Called to tag a particular file (the currently checked out version is
|
||||
* tagged with the specified tag - or the specified tag is deleted).
|
||||
|
|
@ -119,6 +396,7 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
List *srcfiles;
|
||||
{
|
||||
char *version, *oversion;
|
||||
char *nversion = NULL;
|
||||
char *rev;
|
||||
Vers_TS *vers;
|
||||
int retcode = 0;
|
||||
|
|
@ -126,6 +404,18 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
vers = Version_TS (repository, (char *) NULL, (char *) NULL, (char *) NULL,
|
||||
file, 0, 0, entries, srcfiles);
|
||||
|
||||
if ((numtag != NULL) || (date != NULL))
|
||||
{
|
||||
nversion = RCS_getversion(vers->srcfile,
|
||||
numtag,
|
||||
date,
|
||||
force_tag_match, 0);
|
||||
if (nversion == NULL)
|
||||
{
|
||||
freevers_ts (&vers);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
if (delete)
|
||||
{
|
||||
|
||||
|
|
@ -138,7 +428,7 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
* "rcs" to remove the tag... trust me.
|
||||
*/
|
||||
|
||||
version = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1);
|
||||
version = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1, 0);
|
||||
if (version == NULL || vers->srcfile == NULL)
|
||||
{
|
||||
freevers_ts (&vers);
|
||||
|
|
@ -146,9 +436,7 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
}
|
||||
free (version);
|
||||
|
||||
run_setup ("%s%s -q -N%s", Rcsbin, RCS, symtag);
|
||||
run_arg (vers->srcfile->path);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, DEVNULL, RUN_NORMAL)) != 0)
|
||||
if ((retcode = RCS_deltag(vers->srcfile->path, symtag, 1)) != 0)
|
||||
{
|
||||
if (!quiet)
|
||||
error (0, retcode == -1 ? errno : 0,
|
||||
|
|
@ -175,7 +463,14 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
* If we are adding a tag, we need to know which version we have checked
|
||||
* out and we'll tag that version.
|
||||
*/
|
||||
version = vers->vn_user;
|
||||
if (nversion == NULL)
|
||||
{
|
||||
version = vers->vn_user;
|
||||
}
|
||||
else
|
||||
{
|
||||
version = nversion;
|
||||
}
|
||||
if (version == NULL)
|
||||
{
|
||||
freevers_ts (&vers);
|
||||
|
|
@ -212,7 +507,7 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
* module -- which I have found to be a typical tagging operation.
|
||||
*/
|
||||
rev = branch_mode ? RCS_magicrev (vers->srcfile, version) : version;
|
||||
oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1);
|
||||
oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1, 0);
|
||||
if (oversion != NULL)
|
||||
{
|
||||
int isbranch = RCS_isbranch (file, symtag, srcfiles);
|
||||
|
|
@ -245,9 +540,7 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
free (oversion);
|
||||
}
|
||||
|
||||
run_setup ("%s%s -q -N%s:%s", Rcsbin, RCS, symtag, rev);
|
||||
run_arg (vers->srcfile->path);
|
||||
if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL)) != 0)
|
||||
if ((retcode = RCS_settag(vers->srcfile->path, symtag, rev)) != 0)
|
||||
{
|
||||
error (1, retcode == -1 ? errno : 0,
|
||||
"failed to set tag %s to revision %s in %s",
|
||||
|
|
@ -266,6 +559,10 @@ tag_fileproc (file, update_dir, repository, entries, srcfiles)
|
|||
}
|
||||
|
||||
freevers_ts (&vers);
|
||||
if (nversion != NULL)
|
||||
{
|
||||
free(nversion);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -9,11 +9,13 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)vers_ts.c 1.45 94/10/07 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)vers_ts.c 1.45 94/10/07 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
#define ctime(X) do not use ctime, please
|
||||
#ifdef SERVER_SUPPORT
|
||||
static void time_stamp_server PROTO((char *, Vers_TS *));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Fill in and return a Vers_TS structure "user" is the name of the local
|
||||
|
|
@ -136,16 +138,39 @@ Version_TS (repository, options, tag, date, user, force_tag_match,
|
|||
/* squirrel away the rcsdata pointer for others */
|
||||
vers_ts->srcfile = rcsdata;
|
||||
|
||||
#ifndef DEATH_SUPPORT
|
||||
/* (is this indeed death support? I haven't looked carefully). */
|
||||
/* get RCS version number into vn_rcs (if appropriate) */
|
||||
if (((vers_ts->tag || vers_ts->date) && force_tag_match) ||
|
||||
((rcsdata->flags & VALID) && (rcsdata->flags & INATTIC) == 0))
|
||||
{
|
||||
#endif
|
||||
if (vers_ts->tag && strcmp (vers_ts->tag, TAG_BASE) == 0)
|
||||
{
|
||||
vers_ts->vn_rcs = xstrdup (vers_ts->vn_user);
|
||||
vers_ts->vn_tag = xstrdup (vers_ts->vn_user);
|
||||
}
|
||||
else
|
||||
{
|
||||
vers_ts->vn_rcs = RCS_getversion (rcsdata, vers_ts->tag,
|
||||
vers_ts->date, force_tag_match);
|
||||
vers_ts->date, force_tag_match, 1);
|
||||
if (vers_ts->vn_rcs == NULL)
|
||||
vers_ts->vn_tag = NULL;
|
||||
else
|
||||
{
|
||||
char *colon = strchr (vers_ts->vn_rcs, ':');
|
||||
if (colon)
|
||||
{
|
||||
vers_ts->vn_tag = xstrdup (colon+1);
|
||||
*colon = '\0';
|
||||
}
|
||||
else
|
||||
vers_ts->vn_tag = xstrdup (vers_ts->vn_rcs);
|
||||
}
|
||||
}
|
||||
#ifndef DEATH_SUPPORT
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If the source control file exists and has the requested revision,
|
||||
|
|
@ -167,12 +192,81 @@ Version_TS (repository, options, tag, date, user, force_tag_match,
|
|||
/* get user file time-stamp in ts_user */
|
||||
if (entries != (List *) NULL)
|
||||
{
|
||||
vers_ts->ts_user = time_stamp (user);
|
||||
#ifdef SERVER_SUPPORT
|
||||
if (server_active)
|
||||
time_stamp_server (user, vers_ts);
|
||||
else
|
||||
#endif
|
||||
vers_ts->ts_user = time_stamp (user);
|
||||
}
|
||||
|
||||
return (vers_ts);
|
||||
}
|
||||
|
||||
#ifdef SERVER_SUPPORT
|
||||
|
||||
/* Set VERS_TS->TS_USER to time stamp for FILE. */
|
||||
|
||||
/* Separate these out to keep the logic below clearer. */
|
||||
#define mark_lost(V) ((V)->ts_user = 0)
|
||||
#define mark_unchanged(V) ((V)->ts_user = xstrdup ((V)->ts_rcs))
|
||||
|
||||
static void
|
||||
time_stamp_server (file, vers_ts)
|
||||
char *file;
|
||||
Vers_TS *vers_ts;
|
||||
{
|
||||
struct stat sb;
|
||||
char *cp;
|
||||
|
||||
if (stat (file, &sb) < 0)
|
||||
{
|
||||
if (! existence_error (errno))
|
||||
error (1, errno, "cannot stat temp file");
|
||||
if (use_unchanged)
|
||||
{
|
||||
/* Missing file means lost or unmodified; check entries
|
||||
file to see which.
|
||||
|
||||
XXX FIXME - If there's no entries file line, we
|
||||
wouldn't be getting the file at all, so consider it
|
||||
lost. I don't know that that's right, but it's not
|
||||
clear to me that either choice is. Besides, would we
|
||||
have an RCS string in that case anyways? */
|
||||
if (vers_ts->entdata == NULL)
|
||||
mark_lost (vers_ts);
|
||||
else if (vers_ts->entdata->timestamp
|
||||
&& vers_ts->entdata->timestamp[0] == '=')
|
||||
mark_unchanged (vers_ts);
|
||||
else
|
||||
mark_lost (vers_ts);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Missing file in the temp directory means that the file
|
||||
was not modified. */
|
||||
mark_unchanged (vers_ts);
|
||||
}
|
||||
}
|
||||
else if (sb.st_mtime == 0)
|
||||
{
|
||||
if (use_unchanged)
|
||||
/* We shouldn't reach this case any more! */
|
||||
abort ();
|
||||
|
||||
/* Special code used by server.c to indicate the file was lost. */
|
||||
mark_lost (vers_ts);
|
||||
}
|
||||
else
|
||||
{
|
||||
vers_ts->ts_user = xmalloc (25);
|
||||
cp = asctime (gmtime (&sb.st_mtime)); /* copy in the modify time */
|
||||
cp[24] = 0;
|
||||
(void) strcpy (vers_ts->ts_user, cp);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SERVER_SUPPORT */
|
||||
/*
|
||||
* Gets the time-stamp for the file "file" and returns it in space it
|
||||
* allocates
|
||||
|
|
@ -213,6 +307,8 @@ freevers_ts (versp)
|
|||
free ((*versp)->vn_user);
|
||||
if ((*versp)->vn_rcs)
|
||||
free ((*versp)->vn_rcs);
|
||||
if ((*versp)->vn_tag)
|
||||
free ((*versp)->vn_tag);
|
||||
if ((*versp)->ts_user)
|
||||
free ((*versp)->ts_user);
|
||||
if ((*versp)->ts_rcs)
|
||||
|
|
|
|||
25
gnu/usr.bin/cvs/cvsbug/Makefile
Normal file
25
gnu/usr.bin/cvs/cvsbug/Makefile
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# $Id: Makefile,v 1.2 1995/07/25 00:31:51 bde Exp $
|
||||
|
||||
MAN8= cvsbug.8
|
||||
|
||||
CLEANFILES+= cvsbug
|
||||
|
||||
.SUFFIXES: .sh
|
||||
|
||||
all: cvsbug
|
||||
|
||||
.sh:
|
||||
echo > ver cvs-`sed < ${.CURDIR}/../lib/version.c \
|
||||
-e '/version_string/!d' \
|
||||
-e 's/[^0-9.]*\([0-9.]*\).*/\1/' \
|
||||
-e q`
|
||||
sed -e "s,xVERSIONx,`cat ver`,g" ${.CURDIR}/$@.sh > $@
|
||||
|
||||
|
||||
afterinstall:
|
||||
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
|
||||
cvsbug ${DESTDIR}${BINDIR}/cvsbug
|
||||
|
||||
.include "../../Makefile.inc"
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
|
|
@ -1,8 +1,27 @@
|
|||
# $Id: Makefile,v 1.1 1994/10/22 04:51:39 nate Exp $
|
||||
# $Id: Makefile,v 1.2 1995/07/25 00:31:51 bde Exp $
|
||||
|
||||
MAN8= cvsinit.8
|
||||
|
||||
EXAMPDIR= /usr/share/examples/cvs
|
||||
CLEANFILES+= cvsinit
|
||||
|
||||
.SUFFIXES: .sh
|
||||
|
||||
all: cvsinit
|
||||
|
||||
.sh:
|
||||
echo > ver \
|
||||
cvs-`sed < ${.CURDIR}/../lib/version.c \
|
||||
-e '/version_string/!d' \
|
||||
-e 's/[^0-9.]*\([0-9.]*\).*/\1/' \
|
||||
-e q`
|
||||
sed -e 's,xLIBDIRx,$(EXAMPDIR),g' \
|
||||
-e "s,xVERSIONx,`cat ver`,g" ${.CURDIR}/$@.sh > $@
|
||||
|
||||
afterinstall:
|
||||
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
|
||||
${.CURDIR}/cvsinit.sh ${DESTDIR}${BINDIR}/cvsinit
|
||||
cvsinit ${DESTDIR}${BINDIR}/cvsinit
|
||||
|
||||
.include "../../Makefile.inc"
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,28 @@
|
|||
#! /bin/sh
|
||||
:
|
||||
#
|
||||
#ident "@(#)cvs:$Name: $:$Id: cvsinit.sh,v 1.7 1995/11/14 23:44:18 woods Exp $"
|
||||
# Copyright (c) 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.
|
||||
#
|
||||
# $CVSid: @(#)cvsinit.sh 1.1 94/10/22 $
|
||||
#
|
||||
# This script should be run once to help you setup your site for CVS.
|
||||
|
||||
# This script should be run for each repository you create to help you
|
||||
# setup your site for CVS. You may also run it to update existing
|
||||
# repositories if you install a new version of CVS.
|
||||
|
||||
# this line is edited by Makefile when creating cvsinit.inst
|
||||
CVSLIB="/usr/src/gnu/usr.bin/cvs"
|
||||
CVSLIB="xLIBDIRx"
|
||||
|
||||
CVS_VERSION="xVERSIONx"
|
||||
|
||||
# All purpose usage message, also suffices for --help and --version.
|
||||
if test $# -gt 0; then
|
||||
echo "cvsinit version $CVS_VERSION"
|
||||
echo "usage: $0"
|
||||
echo "(set CVSROOT to the repository that you want to initialize)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Make sure that the CVSROOT variable is set
|
||||
if [ "x$CVSROOT" = x ]; then
|
||||
|
|
@ -23,17 +34,16 @@ if [ "x$CVSROOT" = x ]; then
|
|||
echo "plenty of free space."
|
||||
echo ""
|
||||
echo "Please enter the full path for your CVSROOT source repository:"
|
||||
read CVSROOT
|
||||
read CVSROOT junk
|
||||
unset junk
|
||||
remind_cvsroot=yes
|
||||
else
|
||||
echo "Using $CVSROOT as the source repository."
|
||||
remind_cvsroot=no
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Now, create the $CVSROOT if it is not already there
|
||||
if [ ! -d $CVSROOT ]; then
|
||||
echo "Hmmm... $CVSROOT does not exist; trying to make it..."
|
||||
echo "Creating $CVSROOT..."
|
||||
path=
|
||||
for comp in `echo $CVSROOT | sed -e 's,/, ,g'`; do
|
||||
path=$path/$comp
|
||||
|
|
@ -42,7 +52,7 @@ if [ ! -d $CVSROOT ]; then
|
|||
fi
|
||||
done
|
||||
else
|
||||
echo "Good... $CVSROOT already exists."
|
||||
true
|
||||
fi
|
||||
|
||||
# Next, check for $CVSROOT/CVSROOT
|
||||
|
|
@ -52,81 +62,63 @@ if [ ! -d $CVSROOT/CVSROOT ]; then
|
|||
echo "I will rename it to $CVSROOT/CVSROOT for you..."
|
||||
mv $CVSROOT/CVSROOT.adm $CVSROOT/CVSROOT
|
||||
else
|
||||
echo "Making the $CVSROOT/CVSROOT directory..."
|
||||
echo "Creating the $CVSROOT/CVSROOT directory..."
|
||||
mkdir $CVSROOT/CVSROOT
|
||||
fi
|
||||
else
|
||||
echo "Wow!... so does $CVSROOT/CVSROOT."
|
||||
true
|
||||
fi
|
||||
echo ""
|
||||
if [ ! -d $CVSROOT/CVSROOT ]; then
|
||||
echo "You still don't have a $CVSROOT/CVSROOT directory."
|
||||
echo "Unable to create $CVSROOT/CVSROOT."
|
||||
echo "I give up."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create the special *info files within $CVSROOT/CVSROOT
|
||||
# Create the special control files and templates within $CVSROOT/CVSROOT
|
||||
|
||||
# Trump up a simple modules file, if one doesn't exist
|
||||
if [ -f $CVSROOT/CVSROOT/modules,v ]; then
|
||||
if [ ! -f $CVSROOT/CVSROOT/modules ]; then
|
||||
echo "You have a $CVSROOT/CVSROOT/modules,v file,"
|
||||
echo "But no $CVSROOT/CVSROOT/modules file. This is OK."
|
||||
echo "I'll checkout a fresh copy..."
|
||||
(cd $CVSROOT/CVSROOT; co -q modules)
|
||||
echo ""
|
||||
fi
|
||||
else
|
||||
if [ -f $CVSROOT/CVSROOT/modules ]; then
|
||||
echo "You have a $CVSROOT/CVSROOT/modules file,"
|
||||
echo "But no $CVSROOT/CVSROOT/modules,v file."
|
||||
echo "I'll create one for you, but otherwise leave it alone..."
|
||||
EXAMPLES="checkoutlist commitinfo cvswrappers editinfo loginfo modules
|
||||
rcsinfo rcstemplate taginfo wrap unwrap"
|
||||
|
||||
NEWSAMPLE=false
|
||||
for info in $EXAMPLES; do
|
||||
if [ -f $CVSROOT/CVSROOT/${info},v ]; then
|
||||
if [ ! -f $CVSROOT/CVSROOT/$info ]; then
|
||||
echo "Checking out $CVSROOT/CVSROOT/$info"
|
||||
echo " from $CVSROOT/CVSROOT/${info},v..."
|
||||
(cd $CVSROOT/CVSROOT; co -q $info)
|
||||
fi
|
||||
else
|
||||
echo "The $CVSROOT/CVSROOT/modules file does not exist."
|
||||
echo "Making a simple one for you..."
|
||||
cat > $CVSROOT/CVSROOT/modules <<"HERE"
|
||||
#
|
||||
# The CVS modules file
|
||||
#
|
||||
# Three different line formats are valid:
|
||||
# key -a aliases...
|
||||
# key [options] directory
|
||||
# key [options] directory files...
|
||||
#
|
||||
# Where "options" are composed of:
|
||||
# -i prog Run "prog" on "cvs commit" from top-level of module.
|
||||
# -o prog Run "prog" on "cvs checkout" of module.
|
||||
# -t prog Run "prog" on "cvs rtag" of module.
|
||||
# -u prog Run "prog" on "cvs update" of module.
|
||||
# -d dir Place module in directory "dir" instead of module name.
|
||||
# -l Top-level directory only -- do not recurse.
|
||||
#
|
||||
# And "directory" is a path to a directory relative to $CVSROOT.
|
||||
#
|
||||
# The "-a" option specifies an alias. An alias is interpreted as if
|
||||
# everything on the right of the "-a" had been typed on the command line.
|
||||
#
|
||||
# You can encode a module within a module by using the special '&'
|
||||
# character to interpose another module into the current module. This
|
||||
# can be useful for creating a module that consists of many directories
|
||||
# spread out over the entire source repository.
|
||||
#
|
||||
|
||||
# Convenient aliases
|
||||
world -a .
|
||||
|
||||
# CVSROOT support; run mkmodules whenever anything changes.
|
||||
CVSROOT -i mkmodules CVSROOT
|
||||
modules -i mkmodules CVSROOT modules
|
||||
loginfo -i mkmodules CVSROOT loginfo
|
||||
commitinfo -i mkmodules CVSROOT commitinfo
|
||||
rcsinfo -i mkmodules CVSROOT rcsinfo
|
||||
editinfo -i mkmodules CVSROOT editinfo
|
||||
|
||||
# Add other modules here...
|
||||
HERE
|
||||
NEWSAMPLE=true
|
||||
if [ -f $CVSROOT/CVSROOT/$info ]; then
|
||||
echo "Checking in $CVSROOT/CVSROOT/${info},v"
|
||||
echo " from $CVSROOT/CVSROOT/$info..."
|
||||
else
|
||||
echo "Creating a sample $CVSROOT/CVSROOT/$info file..."
|
||||
case $info in
|
||||
modules)
|
||||
sed -n -e '/END_REQUIRED_CONTENT/q' \
|
||||
-e p $CVSLIB/examples/modules > $CVSROOT/CVSROOT/modules
|
||||
;;
|
||||
rcstemplate)
|
||||
cp $CVSLIB/examples/$info $CVSROOT/CVSROOT/$info
|
||||
;;
|
||||
wrap|unwrap)
|
||||
cp $CVSLIB/examples/$info $CVSROOT/CVSROOT/$info
|
||||
chmod +x $CVSROOT/CVSROOT/$info
|
||||
;;
|
||||
*)
|
||||
# comment out everything in all the other examples....
|
||||
sed -e 's/^\([^#]\)/#\1/' $CVSLIB/examples/$info > $CVSROOT/CVSROOT/$info
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
(cd $CVSROOT/CVSROOT; ci -q -u -t/dev/null -m"initial checkin of $info" $info)
|
||||
fi
|
||||
(cd $CVSROOT/CVSROOT; ci -q -u -t/dev/null -m'initial checkin of modules' modules)
|
||||
done
|
||||
|
||||
if $NEWSAMPLE ; then
|
||||
echo "NOTE: You may wish to check out the CVSROOT module and edit any new"
|
||||
echo "configuration files to match your local requirements."
|
||||
echo ""
|
||||
fi
|
||||
|
||||
|
|
@ -138,86 +130,18 @@ if grep CVSROOT.adm $CVSROOT/CVSROOT/modules >/dev/null 2>&1; then
|
|||
echo ""
|
||||
fi
|
||||
|
||||
# loginfo, like modules, is special-cased
|
||||
if [ -f $CVSROOT/CVSROOT/loginfo,v ]; then
|
||||
if [ ! -f $CVSROOT/CVSROOT/loginfo ]; then
|
||||
echo "You have a $CVSROOT/CVSROOT/loginfo,v file,"
|
||||
echo "But no $CVSROOT/CVSROOT/loginfo file. This is OK."
|
||||
echo "I'll checkout a fresh copy..."
|
||||
(cd $CVSROOT/CVSROOT; co -q loginfo)
|
||||
echo ""
|
||||
fi
|
||||
else
|
||||
if [ -f $CVSROOT/CVSROOT/loginfo ]; then
|
||||
echo "You have a $CVSROOT/CVSROOT/loginfo file,"
|
||||
echo "But no $CVSROOT/CVSROOT/loginfo,v file."
|
||||
echo "I'll create one for you, but otherwise leave it alone..."
|
||||
else
|
||||
echo "The $CVSROOT/CVSROOT/loginfo file does not exist."
|
||||
echo "Making a simple one for you..."
|
||||
# try to find perl; use fancy log script if we can
|
||||
for perlpath in `echo $PATH | sed -e 's/:/ /g'` x; do
|
||||
if [ -f $perlpath/perl -a -r $CVSLIB/contrib/log.pl ]; then
|
||||
echo "#!$perlpath/perl" > $CVSROOT/CVSROOT/log.pl
|
||||
cat $CVSLIB/contrib/log.pl >> $CVSROOT/CVSROOT/log.pl
|
||||
chmod 755 $CVSROOT/CVSROOT/log.pl
|
||||
cp $CVSLIB/examples/loginfo $CVSROOT/CVSROOT/loginfo
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ $perlpath = x -o ! -r $CVSLIB/contrib/log.pl ]; then
|
||||
# we did not find perl anywhere, so make a simple loginfo file
|
||||
cat > $CVSROOT/CVSROOT/loginfo <<"HERE"
|
||||
# These files are generated from the contrib files.
|
||||
# FIXME: Is it really wise to overwrite possible local changes like this?
|
||||
# Normal folks will keep these up to date by modifying the source in
|
||||
# their CVS module and re-installing CVS, but is everyone OK with that?
|
||||
#
|
||||
# The "loginfo" file is used to control where "cvs commit" log information
|
||||
# is sent. The first entry on a line is a regular expression which is tested
|
||||
# against the directory that the change is being made to, relative to the
|
||||
# $CVSROOT. If a match is found, then the remainder of the line is a filter
|
||||
# program that should expect log information on its standard input.
|
||||
#
|
||||
# The filter program may use one and only one % modifier (ala printf). If
|
||||
# %s is specified in the filter program, a brief title is included (enclosed
|
||||
# in single quotes) showing the modified file names.
|
||||
CONTRIBS="log commit_prep log_accum cln_hist"
|
||||
#
|
||||
# If the repository name does not match any of the regular expressions in this
|
||||
# file, the "DEFAULT" line is used, if it is specified.
|
||||
#
|
||||
# If the name ALL appears as a regular expression it is always used
|
||||
# in addition to the first matching regex or DEFAULT.
|
||||
#
|
||||
DEFAULT (echo ""; echo $USER; date; cat) >> $CVSROOT/CVSROOT/commitlog
|
||||
HERE
|
||||
fi
|
||||
fi
|
||||
(cd $CVSROOT/CVSROOT; ci -q -u -t/dev/null -m'initial checkin of loginfo' loginfo)
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# The remaining files are generated from the examples files.
|
||||
for info in commitinfo rcsinfo editinfo; do
|
||||
if [ -f $CVSROOT/CVSROOT/${info},v ]; then
|
||||
if [ ! -f $CVSROOT/CVSROOT/$info ]; then
|
||||
echo "You have a $CVSROOT/CVSROOT/${info},v file,"
|
||||
echo "But no $CVSROOT/CVSROOT/$info file. This is OK."
|
||||
echo "I'll checkout a fresh copy..."
|
||||
(cd $CVSROOT/CVSROOT; co -q $info)
|
||||
echo ""
|
||||
fi
|
||||
else
|
||||
if [ -f $CVSROOT/CVSROOT/$info ]; then
|
||||
echo "You have a $CVSROOT/CVSROOT/$info file,"
|
||||
echo "But no $CVSROOT/CVSROOT/${info},v file."
|
||||
echo "I'll create one for you, but otherwise leave it alone..."
|
||||
(cd $CVSROOT/CVSROOT; ci -q -u -t/dev/null -m"initial checkin of $info" $info)
|
||||
else
|
||||
echo "The $CVSROOT/CVSROOT/$info file does not exist."
|
||||
if [ -r $CVSLIB/examples/$info ]; then
|
||||
echo "Making a simple one for you..."
|
||||
sed -e 's/^\([^#]\)/#\1/' $CVSLIB/examples/$info > $CVSROOT/CVSROOT/$info
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
for contrib in $CONTRIBS; do
|
||||
echo "Copying the new version of '${contrib}'"
|
||||
echo " to $CVSROOT/CVSROOT for you..."
|
||||
cp $CVSLIB/contrib/$contrib $CVSROOT/CVSROOT/$contrib
|
||||
done
|
||||
|
||||
# XXX - also add a stub for the cvsignore file
|
||||
|
|
@ -226,16 +150,12 @@ done
|
|||
if [ ! -f $CVSROOT/CVSROOT/history ]; then
|
||||
echo "Enabling CVS history logging..."
|
||||
touch $CVSROOT/CVSROOT/history
|
||||
echo ""
|
||||
chmod g+w $CVSROOT/CVSROOT/history
|
||||
echo "(Remove $CVSROOT/CVSROOT/history to disable.)"
|
||||
fi
|
||||
|
||||
# finish up by running mkmodules
|
||||
echo "All done! Running 'mkmodules' as my final step..."
|
||||
mkmodules $CVSROOT/CVSROOT
|
||||
|
||||
# and, if necessary, remind them about setting CVSROOT
|
||||
if [ $remind_cvsroot = yes ]; then
|
||||
echo "Remember to set the CVSROOT environment variable in your login script"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
INFO = cvs
|
||||
# $Id$
|
||||
|
||||
INFO = cvs cvsclient
|
||||
|
||||
.include <bsd.info.mk>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
# $Id: Makefile,v 1.1 1995/04/08 17:50:48 nate Exp $
|
||||
# $Id: Makefile,v 1.2 1995/07/25 00:31:56 bde Exp $
|
||||
|
||||
CVSFILES= commitinfo loginfo rcsinfo editinfo modules
|
||||
CVSFILES= checkoutlist commitinfo cvswrappers editinfo loginfo modules \
|
||||
rcsinfo rcstemplate taginfo unwrap wrap
|
||||
|
||||
EXAMPDIR = /usr/share/examples/cvs
|
||||
|
||||
NOMAN = noman
|
||||
NOOBJ = noobj
|
||||
|
||||
all clean:
|
||||
@echo -n
|
||||
|
||||
install:
|
||||
cd ${.CURDIR}; \
|
||||
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 ${CVSFILES} \
|
||||
${DESTDIR}${EXAMPDIR}
|
||||
${DESTDIR}${EXAMPDIR}/examples
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
# $Id: Makefile,v 1.25 1995/03/22 19:39:45 nate Exp $
|
||||
# $Id: Makefile,v 1.8 1995/03/31 07:55:28 nate Exp $
|
||||
|
||||
LIB = cvs
|
||||
NOPROFILE= yes
|
||||
CFLAGS += -I${.CURDIR} -I${.CURDIR}/../cvs -DHAVE_CONFIG_H -DHAVE_TIMEZONE
|
||||
SRCS = argmatch.c error.c getdate.y getopt.c getopt1.c fnmatch.c myndbm.c \
|
||||
hash.c sighandle.c strippath.c stripslash.c subr.c version.c yesno.c
|
||||
CFLAGS += -I${.CURDIR} -I${.CURDIR}/../cvs -DHAVE_CONFIG_H
|
||||
SRCS = argmatch.c error.c filesubr.c getdate.y getline.c \
|
||||
getopt.c getopt1.c hash.c md5.c myndbm.c run.c save-cwd.c \
|
||||
sighandle.c strippath.c stripslash.c subr.c version.c \
|
||||
xgetwd.c yesno.c
|
||||
|
||||
CLEANFILES+= getdate.c y.tab.h
|
||||
|
||||
|
|
@ -12,3 +14,4 @@ install:
|
|||
@echo -n
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
#include <string.h>
|
||||
|
|
@ -39,7 +41,7 @@ argmatch (arg, optlist)
|
|||
char **optlist;
|
||||
{
|
||||
int i; /* Temporary index in OPTLIST. */
|
||||
int arglen; /* Length of ARG. */
|
||||
size_t arglen; /* Length of ARG. */
|
||||
int matchind = -1; /* Index of first nonexact match. */
|
||||
int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
|
|
@ -494,7 +498,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
|||
for (p = longopts, option_index = 0; p->name; p++, option_index++)
|
||||
if (!strncmp (p->name, nextchar, nameend - nextchar))
|
||||
{
|
||||
if (nameend - nextchar == strlen (p->name))
|
||||
if (nameend - nextchar == (int) strlen (p->name))
|
||||
{
|
||||
/* Exact match found. */
|
||||
pfound = p;
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)hash.c 1.19 94/09/23 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)hash.c 1.19 94/09/23 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
/* global caches */
|
||||
|
|
@ -23,7 +23,7 @@ static void freenode_mem PROTO((Node * p));
|
|||
/* hash function */
|
||||
static int
|
||||
hashp (key)
|
||||
char *key;
|
||||
const char *key;
|
||||
{
|
||||
unsigned int h = 0;
|
||||
unsigned int g;
|
||||
|
|
@ -254,7 +254,7 @@ addnode (list, p)
|
|||
Node *
|
||||
findnode (list, key)
|
||||
List *list;
|
||||
char *key;
|
||||
const char *key;
|
||||
{
|
||||
Node *head, *p;
|
||||
|
||||
|
|
@ -277,7 +277,7 @@ findnode (list, key)
|
|||
int
|
||||
walklist (list, proc, closure)
|
||||
List *list;
|
||||
int (*proc) ();
|
||||
int (*proc) PROTO ((Node *, void *));
|
||||
void *closure;
|
||||
{
|
||||
Node *head, *p;
|
||||
|
|
@ -298,7 +298,7 @@ walklist (list, proc, closure)
|
|||
void
|
||||
sortlist (list, comp)
|
||||
List *list;
|
||||
int (*comp) ();
|
||||
int (*comp) PROTO ((const Node *, const Node *));
|
||||
{
|
||||
Node *head, *remain, *p, *q;
|
||||
|
||||
|
|
@ -363,7 +363,8 @@ nodetypestring (type)
|
|||
return("<trash>");
|
||||
}
|
||||
|
||||
int
|
||||
static int printnode PROTO ((Node *, void *));
|
||||
static int
|
||||
printnode (node, closure)
|
||||
Node *node;
|
||||
void *closure;
|
||||
|
|
|
|||
|
|
@ -44,23 +44,12 @@ struct list
|
|||
};
|
||||
typedef struct list List;
|
||||
|
||||
struct entnode
|
||||
{
|
||||
char *version;
|
||||
char *timestamp;
|
||||
char *options;
|
||||
char *tag;
|
||||
char *date;
|
||||
char *conflict;
|
||||
};
|
||||
typedef struct entnode Entnode;
|
||||
|
||||
List *getlist PROTO((void));
|
||||
Node *findnode PROTO((List * list, char *key));
|
||||
Node *findnode PROTO((List * list, const char *key));
|
||||
Node *getnode PROTO((void));
|
||||
int addnode PROTO((List * list, Node * p));
|
||||
int walklist PROTO((List * list, int PROTO((*proc)) PROTO((Node *n, void *closure)), void *closure));
|
||||
int walklist PROTO((List * list, int (*)(Node *n, void *closure), void *closure));
|
||||
void dellist PROTO((List ** listp));
|
||||
void delnode PROTO((Node * p));
|
||||
void freenode PROTO((Node * p));
|
||||
void sortlist PROTO((List * list, int PROTO((*comp))()));
|
||||
void sortlist PROTO((List * list, int (*)(const Node *, const Node *)));
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
#ifdef MY_NDBM
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)myndbm.c 1.7 94/09/23 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)myndbm.c 1.7 94/09/23 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
static void mydbm_load_file ();
|
||||
|
|
|
|||
|
|
@ -11,248 +11,11 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)subr.c 1.64 94/10/07 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)subr.c 1.64 94/10/07 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
#ifdef _MINIX
|
||||
#undef POSIX /* Minix 1.6 doesn't support POSIX.1 sigaction yet */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_VPRINTF
|
||||
#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
|
||||
#include <stdarg.h>
|
||||
#define VA_START(args, lastarg) va_start(args, lastarg)
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#define VA_START(args, lastarg) va_start(args)
|
||||
#endif
|
||||
#else
|
||||
#define va_alist a1, a2, a3, a4, a5, a6, a7, a8
|
||||
#define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* I don't know of a convenient way to test this at configure time, or else
|
||||
* I'd certainly do it there.
|
||||
*/
|
||||
#if defined(NeXT)
|
||||
#define LOSING_TMPNAM_FUNCTION
|
||||
#ifndef _POSIX_SOURCE
|
||||
/*
|
||||
* NeXT doesn't define these without _POSIX_SOURCE,
|
||||
* but that changes a lot of things.
|
||||
*/
|
||||
#define WEXITSTATUS(x) ((x).w_retcode)
|
||||
#define WTERMSIG(x) ((x).w_termsig)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void run_add_arg PROTO((char *s));
|
||||
static void run_init_prog PROTO((void));
|
||||
|
||||
extern char *getlogin ();
|
||||
extern char *strtok ();
|
||||
|
||||
/*
|
||||
* Copies "from" to "to". mallocs a buffer large enough to hold the entire
|
||||
* file and does one read/one write to do the copy. This is reasonable,
|
||||
* since source files are typically not too large.
|
||||
*/
|
||||
void
|
||||
copy_file (from, to)
|
||||
char *from;
|
||||
char *to;
|
||||
{
|
||||
struct stat sb;
|
||||
struct utimbuf t;
|
||||
int fdin, fdout;
|
||||
char *buf;
|
||||
|
||||
if (trace)
|
||||
(void) fprintf (stderr, "-> copy(%s,%s)\n", from, to);
|
||||
if (noexec)
|
||||
return;
|
||||
|
||||
if ((fdin = open (from, O_RDONLY)) < 0)
|
||||
error (1, errno, "cannot open %s for copying", from);
|
||||
if (fstat (fdin, &sb) < 0)
|
||||
error (1, errno, "cannot fstat %s", from);
|
||||
if ((fdout = creat (to, (int) sb.st_mode & 07777)) < 0)
|
||||
error (1, errno, "cannot create %s for copying", to);
|
||||
if (sb.st_size > 0)
|
||||
{
|
||||
buf = xmalloc ((int) sb.st_size);
|
||||
if (read (fdin, buf, (int) sb.st_size) != (int) sb.st_size)
|
||||
error (1, errno, "cannot read file %s for copying", from);
|
||||
if (write (fdout, buf, (int) sb.st_size) != (int) sb.st_size
|
||||
#ifdef HAVE_FSYNC
|
||||
|| fsync (fdout) == -1
|
||||
#endif
|
||||
)
|
||||
{
|
||||
error (1, errno, "cannot write file %s for copying", to);
|
||||
}
|
||||
free (buf);
|
||||
}
|
||||
(void) close (fdin);
|
||||
if (close (fdout) < 0)
|
||||
error (1, errno, "cannot close %s", to);
|
||||
|
||||
/* now, set the times for the copied file to match those of the original */
|
||||
memset ((char *) &t, 0, sizeof (t));
|
||||
t.actime = sb.st_atime;
|
||||
t.modtime = sb.st_mtime;
|
||||
(void) utime (to, &t);
|
||||
}
|
||||
|
||||
/* FIXME-krp: these functions would benefit from caching the char * &
|
||||
stat buf. */
|
||||
|
||||
/*
|
||||
* Returns non-zero if the argument file is a directory, or is a symbolic
|
||||
* link which points to a directory.
|
||||
*/
|
||||
int
|
||||
isdir (file)
|
||||
char *file;
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if (stat (file, &sb) < 0)
|
||||
return (0);
|
||||
return (S_ISDIR (sb.st_mode));
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns non-zero if the argument file is a symbolic link.
|
||||
*/
|
||||
int
|
||||
islink (file)
|
||||
char *file;
|
||||
{
|
||||
#ifdef S_ISLNK
|
||||
struct stat sb;
|
||||
|
||||
if (lstat (file, &sb) < 0)
|
||||
return (0);
|
||||
return (S_ISLNK (sb.st_mode));
|
||||
#else
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns non-zero if the argument file exists.
|
||||
*/
|
||||
int
|
||||
isfile (file)
|
||||
char *file;
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if (stat (file, &sb) < 0)
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns non-zero if the argument file is readable.
|
||||
* XXX - must be careful if "cvs" is ever made setuid!
|
||||
*/
|
||||
int
|
||||
isreadable (file)
|
||||
char *file;
|
||||
{
|
||||
return (access (file, R_OK) != -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns non-zero if the argument file is writable
|
||||
* XXX - muct be careful if "cvs" is ever made setuid!
|
||||
*/
|
||||
int
|
||||
iswritable (file)
|
||||
char *file;
|
||||
{
|
||||
return (access (file, W_OK) != -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a file and die if it fails
|
||||
*/
|
||||
FILE *
|
||||
open_file (name, mode)
|
||||
char *name;
|
||||
char *mode;
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen (name, mode)) == NULL)
|
||||
error (1, errno, "cannot open %s", name);
|
||||
return (fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a file if allowed and return.
|
||||
*/
|
||||
FILE *
|
||||
Fopen (name, mode)
|
||||
char *name;
|
||||
char *mode;
|
||||
{
|
||||
if (trace)
|
||||
(void) fprintf (stderr, "-> fopen(%s,%s)\n", name, mode);
|
||||
if (noexec)
|
||||
return (NULL);
|
||||
|
||||
return (fopen (name, mode));
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a directory and die if it fails
|
||||
*/
|
||||
void
|
||||
make_directory (name)
|
||||
char *name;
|
||||
{
|
||||
struct stat buf;
|
||||
|
||||
if (stat (name, &buf) == 0 && (!S_ISDIR (buf.st_mode)))
|
||||
error (0, 0, "%s already exists but is not a directory", name);
|
||||
if (!noexec && mkdir (name, 0777) < 0)
|
||||
error (1, errno, "cannot make directory %s", name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a path to the argument directory, printing a message if something
|
||||
* goes wrong.
|
||||
*/
|
||||
void
|
||||
make_directories (name)
|
||||
char *name;
|
||||
{
|
||||
char *cp;
|
||||
|
||||
if (noexec)
|
||||
return;
|
||||
|
||||
if (mkdir (name, 0777) == 0 || errno == EEXIST)
|
||||
return;
|
||||
if (errno != ENOENT)
|
||||
{
|
||||
error (0, errno, "cannot make path to %s", name);
|
||||
return;
|
||||
}
|
||||
if ((cp = strrchr (name, '/')) == NULL)
|
||||
return;
|
||||
*cp = '\0';
|
||||
make_directories (name);
|
||||
*cp++ = '/';
|
||||
if (*cp == '\0')
|
||||
return;
|
||||
(void) mkdir (name, 0777);
|
||||
}
|
||||
|
||||
/*
|
||||
* malloc some data and die if it fails
|
||||
|
|
@ -263,7 +26,14 @@ xmalloc (bytes)
|
|||
{
|
||||
char *cp;
|
||||
|
||||
if ((cp = malloc (bytes)) == NULL)
|
||||
/* Parts of CVS try to xmalloc zero bytes and then free it. Some
|
||||
systems have a malloc which returns NULL for zero byte
|
||||
allocations but a free which can't handle NULL, so compensate. */
|
||||
if (bytes == 0)
|
||||
bytes = 1;
|
||||
|
||||
cp = malloc (bytes);
|
||||
if (cp == NULL)
|
||||
error (1, 0, "can not allocate %lu bytes", (unsigned long) bytes);
|
||||
return (cp);
|
||||
}
|
||||
|
|
@ -295,7 +65,7 @@ xrealloc (ptr, bytes)
|
|||
*/
|
||||
char *
|
||||
xstrdup (str)
|
||||
char *str;
|
||||
const char *str;
|
||||
{
|
||||
char *s;
|
||||
|
||||
|
|
@ -306,143 +76,16 @@ xstrdup (str)
|
|||
return (s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Change the mode of a file, either adding write permissions, or removing
|
||||
* all write permissions. Adding write permissions honors the current umask
|
||||
* setting.
|
||||
*/
|
||||
/* Remove trailing newlines from STRING, destructively. */
|
||||
void
|
||||
xchmod (fname, writable)
|
||||
char *fname;
|
||||
int writable;
|
||||
strip_trailing_newlines (str)
|
||||
char *str;
|
||||
{
|
||||
struct stat sb;
|
||||
mode_t mode, oumask;
|
||||
int len;
|
||||
len = strlen (str) - 1;
|
||||
|
||||
if (stat (fname, &sb) < 0)
|
||||
{
|
||||
if (!noexec)
|
||||
error (0, errno, "cannot stat %s", fname);
|
||||
return;
|
||||
}
|
||||
if (writable)
|
||||
{
|
||||
oumask = umask (0);
|
||||
(void) umask (oumask);
|
||||
mode = sb.st_mode | ((S_IWRITE | S_IWGRP | S_IWOTH) & ~oumask);
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = sb.st_mode & ~(S_IWRITE | S_IWGRP | S_IWOTH);
|
||||
}
|
||||
|
||||
if (trace)
|
||||
(void) fprintf (stderr, "-> chmod(%s,%o)\n", fname, mode);
|
||||
if (noexec)
|
||||
return;
|
||||
|
||||
if (chmod (fname, mode) < 0)
|
||||
error (0, errno, "cannot change mode of file %s", fname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Rename a file and die if it fails
|
||||
*/
|
||||
void
|
||||
rename_file (from, to)
|
||||
char *from;
|
||||
char *to;
|
||||
{
|
||||
if (trace)
|
||||
(void) fprintf (stderr, "-> rename(%s,%s)\n", from, to);
|
||||
if (noexec)
|
||||
return;
|
||||
|
||||
if (rename (from, to) < 0)
|
||||
error (1, errno, "cannot rename file %s to %s", from, to);
|
||||
}
|
||||
|
||||
/*
|
||||
* link a file, if possible.
|
||||
*/
|
||||
int
|
||||
link_file (from, to)
|
||||
char *from, *to;
|
||||
{
|
||||
if (trace)
|
||||
(void) fprintf (stderr, "-> link(%s,%s)\n", from, to);
|
||||
if (noexec)
|
||||
return (0);
|
||||
|
||||
return (link (from, to));
|
||||
}
|
||||
|
||||
/*
|
||||
* unlink a file, if possible.
|
||||
*/
|
||||
int
|
||||
unlink_file (f)
|
||||
char *f;
|
||||
{
|
||||
if (trace)
|
||||
(void) fprintf (stderr, "-> unlink(%s)\n", f);
|
||||
if (noexec)
|
||||
return (0);
|
||||
|
||||
return (unlink (f));
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare "file1" to "file2". Return non-zero if they don't compare exactly.
|
||||
*
|
||||
* mallocs a buffer large enough to hold the entire file and does two reads to
|
||||
* load the buffer and calls memcmp to do the cmp. This is reasonable, since
|
||||
* source files are typically not too large.
|
||||
*/
|
||||
|
||||
/* richfix: this *could* exploit mmap. */
|
||||
|
||||
int
|
||||
xcmp (file1, file2)
|
||||
char *file1;
|
||||
char *file2;
|
||||
{
|
||||
register char *buf1, *buf2;
|
||||
struct stat sb;
|
||||
off_t size;
|
||||
int ret, fd1, fd2;
|
||||
|
||||
if ((fd1 = open (file1, O_RDONLY)) < 0)
|
||||
error (1, errno, "cannot open file %s for comparing", file1);
|
||||
if ((fd2 = open (file2, O_RDONLY)) < 0)
|
||||
error (1, errno, "cannot open file %s for comparing", file2);
|
||||
if (fstat (fd1, &sb) < 0)
|
||||
error (1, errno, "cannot fstat %s", file1);
|
||||
size = sb.st_size;
|
||||
if (fstat (fd2, &sb) < 0)
|
||||
error (1, errno, "cannot fstat %s", file2);
|
||||
if (size == sb.st_size)
|
||||
{
|
||||
if (size == 0)
|
||||
ret = 0;
|
||||
else
|
||||
{
|
||||
buf1 = xmalloc ((int) size);
|
||||
buf2 = xmalloc ((int) size);
|
||||
if (read (fd1, buf1, (int) size) != (int) size)
|
||||
error (1, errno, "cannot read file %s for comparing", file1);
|
||||
if (read (fd2, buf2, (int) size) != (int) size)
|
||||
error (1, errno, "cannot read file %s for comparing", file2);
|
||||
ret = memcmp(buf1, buf2, (int) size);
|
||||
free (buf1);
|
||||
free (buf2);
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = 1;
|
||||
(void) close (fd1);
|
||||
(void) close (fd2);
|
||||
return (ret);
|
||||
while (str[len] == '\n')
|
||||
str[len--] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -451,7 +94,7 @@ xcmp (file1, file2)
|
|||
void
|
||||
free_names (pargc, argv)
|
||||
int *pargc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
register int i;
|
||||
|
||||
|
|
@ -470,7 +113,7 @@ free_names (pargc, argv)
|
|||
void
|
||||
line2argv (pargc, argv, line)
|
||||
int *pargc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
char *line;
|
||||
{
|
||||
char *cp;
|
||||
|
|
@ -488,14 +131,13 @@ line2argv (pargc, argv, line)
|
|||
*/
|
||||
int
|
||||
numdots (s)
|
||||
char *s;
|
||||
const char *s;
|
||||
{
|
||||
char *cp;
|
||||
int dots = 0;
|
||||
|
||||
for (cp = s; *cp; cp++)
|
||||
for (; *s; s++)
|
||||
{
|
||||
if (*cp == '.')
|
||||
if (*s == '.')
|
||||
dots++;
|
||||
}
|
||||
return (dots);
|
||||
|
|
@ -518,394 +160,18 @@ getcaller ()
|
|||
if (uid == (uid_t) 0)
|
||||
{
|
||||
/* super-user; try getlogin() to distinguish */
|
||||
if (((name = getenv("LOGNAME")) || (name = getenv("USER")) ||
|
||||
(name = getlogin ())) && *name)
|
||||
if (((name = getlogin ()) || (name = getenv("LOGNAME")) ||
|
||||
(name = getenv("USER"))) && *name)
|
||||
return (name);
|
||||
}
|
||||
if ((pw = (struct passwd *) getpwuid (uid)) == NULL)
|
||||
{
|
||||
(void) sprintf (uidname, "uid%d", (unsigned long) uid);
|
||||
(void) sprintf (uidname, "uid%lu", (unsigned long) uid);
|
||||
return (uidname);
|
||||
}
|
||||
return (pw->pw_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* To exec a program under CVS, first call run_setup() to setup any initial
|
||||
* arguments. The options to run_setup are essentially like printf(). The
|
||||
* arguments will be parsed into whitespace separated words and added to the
|
||||
* global run_argv list.
|
||||
*
|
||||
* Then, optionally call run_arg() for each additional argument that you'd like
|
||||
* to pass to the executed program.
|
||||
*
|
||||
* Finally, call run_exec() to execute the program with the specified arguments.
|
||||
* The execvp() syscall will be used, so that the PATH is searched correctly.
|
||||
* File redirections can be performed in the call to run_exec().
|
||||
*/
|
||||
static char *run_prog;
|
||||
static char **run_argv;
|
||||
static int run_argc;
|
||||
static int run_argc_allocated;
|
||||
|
||||
/* VARARGS */
|
||||
#if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__))
|
||||
void
|
||||
run_setup (char *fmt,...)
|
||||
#else
|
||||
void
|
||||
run_setup (fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
|
||||
#endif
|
||||
{
|
||||
#ifdef HAVE_VPRINTF
|
||||
va_list args;
|
||||
|
||||
#endif
|
||||
char *cp;
|
||||
int i;
|
||||
|
||||
run_init_prog ();
|
||||
|
||||
/* clean out any malloc'ed values from run_argv */
|
||||
for (i = 0; i < run_argc; i++)
|
||||
{
|
||||
if (run_argv[i])
|
||||
{
|
||||
free (run_argv[i]);
|
||||
run_argv[i] = (char *) 0;
|
||||
}
|
||||
}
|
||||
run_argc = 0;
|
||||
|
||||
/* process the varargs into run_prog */
|
||||
#ifdef HAVE_VPRINTF
|
||||
VA_START (args, fmt);
|
||||
(void) vsprintf (run_prog, fmt, args);
|
||||
va_end (args);
|
||||
#else
|
||||
(void) sprintf (run_prog, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
#endif
|
||||
|
||||
/* put each word into run_argv, allocating it as we go */
|
||||
for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t"))
|
||||
run_add_arg (cp);
|
||||
}
|
||||
|
||||
void
|
||||
run_arg (s)
|
||||
char *s;
|
||||
{
|
||||
run_add_arg (s);
|
||||
}
|
||||
|
||||
/* VARARGS */
|
||||
#if defined (HAVE_VPRINTF) && (defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__))
|
||||
void
|
||||
run_args (char *fmt,...)
|
||||
#else
|
||||
void
|
||||
run_args (fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
|
||||
#endif
|
||||
{
|
||||
#ifdef HAVE_VPRINTF
|
||||
va_list args;
|
||||
|
||||
#endif
|
||||
|
||||
run_init_prog ();
|
||||
|
||||
/* process the varargs into run_prog */
|
||||
#ifdef HAVE_VPRINTF
|
||||
VA_START (args, fmt);
|
||||
(void) vsprintf (run_prog, fmt, args);
|
||||
va_end (args);
|
||||
#else
|
||||
(void) sprintf (run_prog, fmt, a1, a2, a3, a4, a5, a6, a7, a8);
|
||||
#endif
|
||||
|
||||
/* and add the (single) argument to the run_argv list */
|
||||
run_add_arg (run_prog);
|
||||
}
|
||||
|
||||
static void
|
||||
run_add_arg (s)
|
||||
char *s;
|
||||
{
|
||||
/* allocate more argv entries if we've run out */
|
||||
if (run_argc >= run_argc_allocated)
|
||||
{
|
||||
run_argc_allocated += 50;
|
||||
run_argv = (char **) xrealloc ((char *) run_argv,
|
||||
run_argc_allocated * sizeof (char **));
|
||||
}
|
||||
|
||||
if (s)
|
||||
run_argv[run_argc++] = xstrdup (s);
|
||||
else
|
||||
run_argv[run_argc] = (char *) 0;/* not post-incremented on purpose! */
|
||||
}
|
||||
|
||||
static void
|
||||
run_init_prog ()
|
||||
{
|
||||
/* make sure that run_prog is allocated once */
|
||||
if (run_prog == (char *) 0)
|
||||
run_prog = xmalloc (10 * 1024); /* 10K of args for _setup and _arg */
|
||||
}
|
||||
|
||||
int
|
||||
run_exec (stin, stout, sterr, flags)
|
||||
char *stin;
|
||||
char *stout;
|
||||
char *sterr;
|
||||
int flags;
|
||||
{
|
||||
int shin, shout, sherr;
|
||||
int mode_out, mode_err;
|
||||
#if defined(NeXT) && !defined(_POSIX_SOURCE)
|
||||
union wait status;
|
||||
#else
|
||||
int status;
|
||||
#endif
|
||||
int rc = -1;
|
||||
int rerrno = 0;
|
||||
int pid, w;
|
||||
|
||||
#ifdef POSIX
|
||||
sigset_t sigset_mask, sigset_omask;
|
||||
struct sigaction act, iact, qact;
|
||||
|
||||
#else
|
||||
#ifdef BSD_SIGNALS
|
||||
int mask;
|
||||
struct sigvec vec, ivec, qvec;
|
||||
|
||||
#else
|
||||
RETSIGTYPE (*istat) (), (*qstat) ();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (trace)
|
||||
{
|
||||
(void) fprintf (stderr, "-> system(");
|
||||
run_print (stderr);
|
||||
(void) fprintf (stderr, ")\n");
|
||||
}
|
||||
if (noexec && (flags & RUN_REALLY) == 0)
|
||||
return (0);
|
||||
|
||||
/* make sure that we are null terminated, since we didn't calloc */
|
||||
run_add_arg ((char *) 0);
|
||||
|
||||
/* setup default file descriptor numbers */
|
||||
shin = 0;
|
||||
shout = 1;
|
||||
sherr = 2;
|
||||
|
||||
/* set the file modes for stdout and stderr */
|
||||
mode_out = mode_err = O_WRONLY | O_CREAT;
|
||||
mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC);
|
||||
mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC);
|
||||
|
||||
if (stin && (shin = open (stin, O_RDONLY)) == -1)
|
||||
{
|
||||
rerrno = errno;
|
||||
error (0, errno, "cannot open %s for reading (prog %s)",
|
||||
stin, run_argv[0]);
|
||||
goto out0;
|
||||
}
|
||||
if (stout && (shout = open (stout, mode_out, 0666)) == -1)
|
||||
{
|
||||
rerrno = errno;
|
||||
error (0, errno, "cannot open %s for writing (prog %s)",
|
||||
stout, run_argv[0]);
|
||||
goto out1;
|
||||
}
|
||||
if (sterr && (flags & RUN_COMBINED) == 0)
|
||||
{
|
||||
if ((sherr = open (sterr, mode_err, 0666)) == -1)
|
||||
{
|
||||
rerrno = errno;
|
||||
error (0, errno, "cannot open %s for writing (prog %s)",
|
||||
sterr, run_argv[0]);
|
||||
goto out2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure we don't flush this twice, once in the subprocess. */
|
||||
fflush (stdout);
|
||||
fflush (stderr);
|
||||
|
||||
/* The output files, if any, are now created. Do the fork and dups */
|
||||
#ifdef HAVE_VFORK
|
||||
pid = vfork ();
|
||||
#else
|
||||
pid = fork ();
|
||||
#endif
|
||||
if (pid == 0)
|
||||
{
|
||||
if (shin != 0)
|
||||
{
|
||||
(void) dup2 (shin, 0);
|
||||
(void) close (shin);
|
||||
}
|
||||
if (shout != 1)
|
||||
{
|
||||
(void) dup2 (shout, 1);
|
||||
(void) close (shout);
|
||||
}
|
||||
if (flags & RUN_COMBINED)
|
||||
(void) dup2 (1, 2);
|
||||
else if (sherr != 2)
|
||||
{
|
||||
(void) dup2 (sherr, 2);
|
||||
(void) close (sherr);
|
||||
}
|
||||
|
||||
/* dup'ing is done. try to run it now */
|
||||
(void) execvp (run_argv[0], run_argv);
|
||||
error (0, errno, "cannot exec %s", run_argv[0]);
|
||||
_exit (127);
|
||||
}
|
||||
else if (pid == -1)
|
||||
{
|
||||
rerrno = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* the parent. Ignore some signals for now */
|
||||
#ifdef POSIX
|
||||
if (flags & RUN_SIGIGNORE)
|
||||
{
|
||||
act.sa_handler = SIG_IGN;
|
||||
(void) sigemptyset (&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
(void) sigaction (SIGINT, &act, &iact);
|
||||
(void) sigaction (SIGQUIT, &act, &qact);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void) sigemptyset (&sigset_mask);
|
||||
(void) sigaddset (&sigset_mask, SIGINT);
|
||||
(void) sigaddset (&sigset_mask, SIGQUIT);
|
||||
(void) sigprocmask (SIG_SETMASK, &sigset_mask, &sigset_omask);
|
||||
}
|
||||
#else
|
||||
#ifdef BSD_SIGNALS
|
||||
if (flags & RUN_SIGIGNORE)
|
||||
{
|
||||
memset ((char *) &vec, 0, sizeof (vec));
|
||||
vec.sv_handler = SIG_IGN;
|
||||
(void) sigvec (SIGINT, &vec, &ivec);
|
||||
(void) sigvec (SIGQUIT, &vec, &qvec);
|
||||
}
|
||||
else
|
||||
mask = sigblock (sigmask (SIGINT) | sigmask (SIGQUIT));
|
||||
#else
|
||||
istat = signal (SIGINT, SIG_IGN);
|
||||
qstat = signal (SIGQUIT, SIG_IGN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* wait for our process to die and munge return status */
|
||||
#ifdef POSIX
|
||||
while ((w = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
|
||||
;
|
||||
#else
|
||||
while ((w = wait (&status)) != pid)
|
||||
{
|
||||
if (w == -1 && errno != EINTR)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (w == -1)
|
||||
{
|
||||
rc = -1;
|
||||
rerrno = errno;
|
||||
}
|
||||
else if (WIFEXITED (status))
|
||||
rc = WEXITSTATUS (status);
|
||||
else if (WIFSIGNALED (status))
|
||||
{
|
||||
if (WTERMSIG (status) == SIGPIPE)
|
||||
error (1, 0, "broken pipe");
|
||||
rc = 2;
|
||||
}
|
||||
else
|
||||
rc = 1;
|
||||
|
||||
/* restore the signals */
|
||||
#ifdef POSIX
|
||||
if (flags & RUN_SIGIGNORE)
|
||||
{
|
||||
(void) sigaction (SIGINT, &iact, (struct sigaction *) NULL);
|
||||
(void) sigaction (SIGQUIT, &qact, (struct sigaction *) NULL);
|
||||
}
|
||||
else
|
||||
(void) sigprocmask (SIG_SETMASK, &sigset_omask, (sigset_t *) NULL);
|
||||
#else
|
||||
#ifdef BSD_SIGNALS
|
||||
if (flags & RUN_SIGIGNORE)
|
||||
{
|
||||
(void) sigvec (SIGINT, &ivec, (struct sigvec *) NULL);
|
||||
(void) sigvec (SIGQUIT, &qvec, (struct sigvec *) NULL);
|
||||
}
|
||||
else
|
||||
(void) sigsetmask (mask);
|
||||
#else
|
||||
(void) signal (SIGINT, istat);
|
||||
(void) signal (SIGQUIT, qstat);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* cleanup the open file descriptors */
|
||||
out:
|
||||
if (sterr)
|
||||
(void) close (sherr);
|
||||
out2:
|
||||
if (stout)
|
||||
(void) close (shout);
|
||||
out1:
|
||||
if (stin)
|
||||
(void) close (shin);
|
||||
|
||||
out0:
|
||||
if (rerrno)
|
||||
errno = rerrno;
|
||||
return (rc);
|
||||
}
|
||||
|
||||
void
|
||||
run_print (fp)
|
||||
FILE *fp;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < run_argc; i++)
|
||||
{
|
||||
(void) fprintf (fp, "%s", run_argv[i]);
|
||||
if (i != run_argc - 1)
|
||||
(void) fprintf (fp, " ");
|
||||
}
|
||||
}
|
||||
|
||||
FILE *
|
||||
Popen (cmd, mode)
|
||||
char *cmd, *mode;
|
||||
{
|
||||
if (trace)
|
||||
(void) fprintf (stderr, "-> Popen(%s,%s)\n", cmd, mode);
|
||||
if (noexec)
|
||||
return (NULL);
|
||||
return (popen (cmd, mode));
|
||||
}
|
||||
|
||||
#ifdef lint
|
||||
#ifndef __GNUC__
|
||||
/* ARGSUSED */
|
||||
|
|
@ -1031,19 +297,26 @@ gca (rev1, rev2)
|
|||
return (xstrdup (gca));
|
||||
}
|
||||
|
||||
#ifdef LOSING_TMPNAM_FUNCTION
|
||||
char *tmpnam(char *s)
|
||||
/*
|
||||
* Sanity checks and any required fix-up on message passed to RCS via '-m'.
|
||||
* RCS 5.7 requires that a non-total-whitespace, non-null message be provided
|
||||
* with '-m'.
|
||||
*/
|
||||
char *
|
||||
make_message_rcslegal (message)
|
||||
char *message;
|
||||
{
|
||||
static char value[L_tmpnam+1];
|
||||
if ((message == NULL) || (*message == '\0') || isspace (*message))
|
||||
{
|
||||
char *t;
|
||||
|
||||
if (s){
|
||||
strcpy(s,"/tmp/cvsXXXXXX");
|
||||
mktemp(s);
|
||||
return s;
|
||||
}else{
|
||||
strcpy(value,"/tmp/cvsXXXXXX");
|
||||
mktemp(s);
|
||||
return value;
|
||||
if (message)
|
||||
for (t = message; *t; t++)
|
||||
if (!isspace (*t))
|
||||
return message;
|
||||
|
||||
return "*** empty log message ***\n";
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -17,45 +17,162 @@
|
|||
|
||||
/* $CVSid: @(#)system.h 1.18 94/09/25 $ */
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifndef alloca
|
||||
#define alloca __builtin_alloca
|
||||
#endif
|
||||
#else
|
||||
#ifdef HAVE_ALLOCA_H
|
||||
#include <alloca.h>
|
||||
#else
|
||||
#ifdef _AIX
|
||||
/* AIX alloca decl has to be the first thing in the file, bletch! */
|
||||
#pragma alloca
|
||||
#else /* not _AIX */
|
||||
#ifdef ALLOCA_IN_STDLIB
|
||||
/* then we need do nothing */
|
||||
#else
|
||||
char *alloca ();
|
||||
#endif /* not ALLOCA_IN_STDLIB */
|
||||
#endif /* not _AIX */
|
||||
#endif /* not HAVE_ALLOCA_H */
|
||||
#endif /* not __GNUS__ */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifndef S_ISREG /* Doesn't have POSIX.1 stat stuff. */
|
||||
#ifndef mode_t
|
||||
#define mode_t unsigned short
|
||||
#endif
|
||||
|
||||
#ifdef STAT_MACROS_BROKEN
|
||||
#undef S_ISBLK
|
||||
#undef S_ISCHR
|
||||
#undef S_ISDIR
|
||||
#undef S_ISREG
|
||||
#undef S_ISFIFO
|
||||
#undef S_ISLNK
|
||||
#undef S_ISSOCK
|
||||
#undef S_ISMPB
|
||||
#undef S_ISMPC
|
||||
#undef S_ISNWK
|
||||
#endif
|
||||
|
||||
/* Not all systems have S_IFMT, but we probably want to use it if we
|
||||
do. See ChangeLog for a more detailed discussion. */
|
||||
|
||||
#if !defined(S_ISBLK) && defined(S_IFBLK)
|
||||
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
|
||||
# if defined(S_IFMT)
|
||||
# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
|
||||
# else
|
||||
# define S_ISBLK(m) ((m) & S_IFBLK)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISCHR) && defined(S_IFCHR)
|
||||
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
|
||||
# if defined(S_IFMT)
|
||||
# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
|
||||
# else
|
||||
# define S_ISCHR(m) ((m) & S_IFCHR)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISDIR) && defined(S_IFDIR)
|
||||
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
# if defined(S_IFMT)
|
||||
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
# else
|
||||
# define S_ISDIR(m) ((m) & S_IFDIR)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISREG) && defined(S_IFREG)
|
||||
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
# if defined(S_IFMT)
|
||||
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
# else
|
||||
# define S_ISREG(m) ((m) & S_IFREG)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISFIFO) && defined(S_IFIFO)
|
||||
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
|
||||
# if defined(S_IFMT)
|
||||
# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
|
||||
# else
|
||||
# define S_ISFIFO(m) ((m) & S_IFIFO)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISLNK) && defined(S_IFLNK)
|
||||
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
||||
# if defined(S_IFMT)
|
||||
# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
||||
# else
|
||||
# define S_ISLNK(m) ((m) & S_IFLNK)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISSOCK) && defined(S_IFSOCK)
|
||||
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
|
||||
# if defined(S_IFMT)
|
||||
# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
|
||||
# else
|
||||
# define S_ISSOCK(m) ((m) & S_IFSOCK)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
|
||||
#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
|
||||
#define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
|
||||
# if defined(S_IFMT)
|
||||
# define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
|
||||
# define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
|
||||
# else
|
||||
# define S_ISMPB(m) ((m) & S_IFMPB)
|
||||
# define S_ISMPC(m) ((m) & S_IFMPC)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
|
||||
#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
|
||||
# if defined(S_IFMT)
|
||||
# define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
|
||||
# else
|
||||
# define S_ISNWK(m) ((m) & S_IFNWK)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_MKFIFO)
|
||||
#define mkfifo(path, mode) (mknod ((path), (mode) | S_IFIFO, 0))
|
||||
#endif
|
||||
|
||||
#ifdef NEED_DECOY_PERMISSIONS /* OS/2, really */
|
||||
|
||||
#define S_IRUSR S_IREAD
|
||||
#define S_IWUSR S_IWRITE
|
||||
#define S_IXUSR S_IEXEC
|
||||
#define S_IRWXU (S_IRUSR | S_IWUSR | S_IXUSR)
|
||||
#define S_IRGRP S_IREAD
|
||||
#define S_IWGRP S_IWRITE
|
||||
#define S_IXGRP S_IEXEC
|
||||
#define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
|
||||
#define S_IROTH S_IREAD
|
||||
#define S_IWOTH S_IWRITE
|
||||
#define S_IXOTH S_IEXEC
|
||||
#define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
|
||||
|
||||
#else /* ! NEED_DECOY_PERMISSIONS */
|
||||
|
||||
#ifndef S_IRUSR
|
||||
#define S_IRUSR 0400
|
||||
#define S_IWUSR 0200
|
||||
#define S_IXUSR 0100
|
||||
/* Read, write, and execute by owner. */
|
||||
#define S_IRWXU (S_IRUSR|S_IWUSR|S_IXUSR)
|
||||
|
||||
#define S_IRGRP (S_IRUSR >> 3) /* Read by group. */
|
||||
#define S_IWGRP (S_IWUSR >> 3) /* Write by group. */
|
||||
#define S_IXGRP (S_IXUSR >> 3) /* Execute by group. */
|
||||
/* Read, write, and execute by group. */
|
||||
#define S_IRWXG (S_IRWXU >> 3)
|
||||
|
||||
#define S_IROTH (S_IRGRP >> 3) /* Read by others. */
|
||||
#define S_IWOTH (S_IWGRP >> 3) /* Write by others. */
|
||||
#define S_IXOTH (S_IXGRP >> 3) /* Execute by others. */
|
||||
/* Read, write, and execute by others. */
|
||||
#define S_IRWXO (S_IRWXG >> 3)
|
||||
#endif /* !def S_IRUSR */
|
||||
#endif /* NEED_DECOY_PERMISSIONS */
|
||||
|
||||
#if defined(POSIX) || defined(HAVE_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
|
@ -63,25 +180,38 @@
|
|||
off_t lseek ();
|
||||
#endif
|
||||
|
||||
#ifdef TM_IN_SYS_TIME
|
||||
#include <sys/time.h>
|
||||
#if TIME_WITH_SYS_TIME
|
||||
# include <sys/time.h>
|
||||
# include <time.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
# if HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
# else
|
||||
# include <time.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SYS_TIMEB_H
|
||||
#ifdef HAVE_IO_H
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DIRECT_H
|
||||
#include <direct.h>
|
||||
#endif
|
||||
|
||||
#ifdef timezone
|
||||
#undef timezone /* needed for sgi */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_TIMEB_H
|
||||
#include <sys/timeb.h>
|
||||
#else
|
||||
struct timeb {
|
||||
time_t time; /* Seconds since the epoch */
|
||||
unsigned short millitm; /* Field not used */
|
||||
#ifdef timezone
|
||||
short tzone;
|
||||
#else
|
||||
short timezone;
|
||||
#endif
|
||||
short dstflag; /* Field not used */
|
||||
};
|
||||
#else
|
||||
#include <sys/timeb.h>
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_FTIME) && !defined(HAVE_TIMEZONE)
|
||||
|
|
@ -106,10 +236,17 @@ extern long timezone;
|
|||
** PATH_MAX in terms of MAXPATHLEN.
|
||||
** 3. If neither is defined, include limits.h and check for
|
||||
** PATH_MAX again.
|
||||
** 3.1 If we now have PATHSIZE, define PATH_MAX in terms of that.
|
||||
** and ignore the rest. Since _POSIX_PATH_MAX (checked for
|
||||
** next) is the *most* restrictive (smallest) value, if we
|
||||
** trust _POSIX_PATH_MAX, several of our buffers are too small.
|
||||
** 4. If PATH_MAX is still not defined but _POSIX_PATH_MAX is,
|
||||
** then define PATH_MAX in terms of _POSIX_PATH_MAX.
|
||||
** 5. And if even _POSIX_PATH_MAX doesn't exist just put in
|
||||
** a reasonable value.
|
||||
** *. All in all, this is an excellent argument for using pathconf()
|
||||
** when at all possible. Or better yet, dynamically allocate
|
||||
** our buffers and use getcwd() not getwd().
|
||||
**
|
||||
** This works on:
|
||||
** Sun Sparc 10 SunOS 4.1.3 & Solaris 1.2
|
||||
|
|
@ -118,12 +255,16 @@ extern long timezone;
|
|||
** IBM RS6000 AIX 3.2
|
||||
** Dec Alpha OSF 1 ????
|
||||
** Intel 386 BSDI BSD/386
|
||||
** Intel 386 SCO OpenServer Release 5
|
||||
** Apollo Domain 10.4
|
||||
** NEC SVR4
|
||||
*/
|
||||
|
||||
/* On MOST systems this will get you MAXPATHLEN */
|
||||
/* On MOST systems this will get you MAXPATHLEN.
|
||||
Windows NT doesn't have this file, tho. */
|
||||
#ifdef HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
# ifdef MAXPATHLEN
|
||||
|
|
@ -131,20 +272,28 @@ extern long timezone;
|
|||
# else
|
||||
# include <limits.h>
|
||||
# ifndef PATH_MAX
|
||||
# ifdef _POSIX_PATH_MAX
|
||||
# define PATH_MAX _POSIX_PATH_MAX
|
||||
# else
|
||||
# define PATH_MAX 1024
|
||||
# endif /* _POSIX_PATH_MAX */
|
||||
# endif /* PATH_MAX */
|
||||
# ifdef PATHSIZE
|
||||
# define PATH_MAX PATHSIZE
|
||||
# else /* no PATHSIZE */
|
||||
# ifdef _POSIX_PATH_MAX
|
||||
# define PATH_MAX _POSIX_PATH_MAX
|
||||
# else
|
||||
# define PATH_MAX 1024
|
||||
# endif /* no _POSIX_PATH_MAX */
|
||||
# endif /* no PATHSIZE */
|
||||
# endif /* no PATH_MAX */
|
||||
# endif /* MAXPATHLEN */
|
||||
#endif /* PATH_MAX */
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_UTIME_H
|
||||
/* The NeXT (without _POSIX_SOURCE, which we don't want) has a utime.h
|
||||
which doesn't define anything. It would be cleaner to have configure
|
||||
check for struct utimbuf, but for now I'm checking NeXT here (so I don't
|
||||
have to debug the configure check across all the machines). */
|
||||
#if defined (HAVE_UTIME_H) && !defined (NeXT)
|
||||
#include <utime.h>
|
||||
#elif defined (HAVE_SYS_UTIME_H)
|
||||
# include <sys/utime.h>
|
||||
#else
|
||||
#ifndef ALTOS
|
||||
struct utimbuf
|
||||
|
|
@ -179,12 +328,31 @@ int utime ();
|
|||
#define bzero(s, n) memset ((s), 0, (n))
|
||||
#endif /* bzero */
|
||||
|
||||
#else /* not STDC_HJEADERS and not HAVE_STRING_H */
|
||||
#else /* not STDC_HEADERS and not HAVE_STRING_H */
|
||||
#include <strings.h>
|
||||
/* memory.h and strings.h conflict on some systems. */
|
||||
#endif /* not STDC_HEADERS and not HAVE_STRING_H */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
/* Not all systems set the same error code on a non-existent-file
|
||||
error. This tries to ask the question somewhat portably.
|
||||
On systems that don't have ENOTEXIST, this should behave just like
|
||||
x == ENOENT. "x" is probably errno, of course. */
|
||||
|
||||
#ifdef ENOTEXIST
|
||||
# ifdef EOS2ERR
|
||||
# define existence_error(x) \
|
||||
(((x) == ENOTEXIST) || ((x) == ENOENT) || ((x) == EOS2ERR))
|
||||
# else
|
||||
# define existence_error(x) \
|
||||
(((x) == ENOTEXIST) || ((x) == ENOENT))
|
||||
# endif
|
||||
#else
|
||||
# define existence_error(x) ((x) == ENOENT)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
|
|
@ -201,6 +369,29 @@ char *getcwd ();
|
|||
char *getwd ();
|
||||
#endif
|
||||
|
||||
/* check for POSIX signals */
|
||||
#if defined(HAVE_SIGACTION) && defined(HAVE_SIGPROCMASK)
|
||||
# define POSIX_SIGNALS
|
||||
#endif
|
||||
|
||||
/* MINIX 1.6 doesn't properly support sigaction */
|
||||
#if defined(_MINIX)
|
||||
# undef POSIX_SIGNALS
|
||||
#endif
|
||||
|
||||
/* If !POSIX, try for BSD.. Reason: 4.4BSD implements these as wrappers */
|
||||
#if !defined(POSIX_SIGNALS)
|
||||
# if defined(HAVE_SIGVEC) && defined(HAVE_SIGSETMASK) && defined(HAVE_SIGBLOCK)
|
||||
# define BSD_SIGNALS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Under OS/2, this must be included _after_ stdio.h; that's why we do
|
||||
it here. */
|
||||
#ifdef USE_OWN_TCPIP_H
|
||||
#include "tcpip.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
|
|
@ -220,23 +411,22 @@ char *getwd ();
|
|||
#define R_OK 4
|
||||
#endif
|
||||
|
||||
/* unistd.h defines _POSIX_VERSION on POSIX.1 systems. */
|
||||
#if defined(DIRENT) || defined(_POSIX_VERSION)
|
||||
#include <dirent.h>
|
||||
#define NLENGTH(dirent) (strlen((dirent)->d_name))
|
||||
#else /* not (DIRENT or _POSIX_VERSION) */
|
||||
#define dirent direct
|
||||
#define NLENGTH(dirent) ((dirent)->d_namlen)
|
||||
#ifdef HAVE_SYS_NDIR_H
|
||||
#include <sys/ndir.h>
|
||||
#if HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
# define NAMLEN(dirent) strlen((dirent)->d_name)
|
||||
#else
|
||||
# define dirent direct
|
||||
# define NAMLEN(dirent) (dirent)->d_namlen
|
||||
# if HAVE_SYS_NDIR_H
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if HAVE_SYS_DIR_H
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if HAVE_NDIR_H
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
#ifdef HAVE_SYS_DIR_H
|
||||
#include <sys/dir.h>
|
||||
#endif
|
||||
#ifdef HAVE_NDIR_H
|
||||
#include <ndir.h>
|
||||
#endif
|
||||
#endif /* not (DIRENT or _POSIX_VERSION) */
|
||||
|
||||
/* Convert B 512-byte blocks to kilobytes if K is nonzero,
|
||||
otherwise return it unchanged. */
|
||||
|
|
@ -260,3 +450,47 @@ char *getwd ();
|
|||
#define S_IWOTH 0000002 /* write permission, other */
|
||||
#endif
|
||||
|
||||
/* Under MS-DOS and its derivatives (like Windows NT), mkdir takes only one
|
||||
argument; permission is handled very differently on those systems than in
|
||||
in Unix. So we leave such systems a hook on which they can hang their
|
||||
own definitions. */
|
||||
#ifndef CVS_MKDIR
|
||||
#define CVS_MKDIR mkdir
|
||||
#endif
|
||||
|
||||
/* Some file systems are case-insensitive. If FOLD_FN_CHAR is
|
||||
#defined, it maps the character C onto its "canonical" form. In a
|
||||
case-insensitive system, it would map all alphanumeric characters
|
||||
to lower case. Under Windows NT, / and \ are both path component
|
||||
separators, so FOLD_FN_CHAR would map them both to /. */
|
||||
#ifndef FOLD_FN_CHAR
|
||||
#define FOLD_FN_CHAR(c) (c)
|
||||
#define fnfold(filename) (filename)
|
||||
#define fncmp strcmp
|
||||
#endif
|
||||
|
||||
/* Different file systems have different path component separators.
|
||||
For the VMS port we might need to abstract further back than this. */
|
||||
#ifndef ISDIRSEP
|
||||
#define ISDIRSEP(c) ((c) == '/')
|
||||
#endif
|
||||
|
||||
|
||||
/* On some systems, lines in text files should be terminated with CRLF,
|
||||
not just LF, and the read and write routines do this translation
|
||||
for you. LINES_CRLF_TERMINATED is #defined on such systems.
|
||||
- OPEN_BINARY is the flag to pass to the open function for
|
||||
untranslated I/O.
|
||||
- FOPEN_BINARY_READ is the string to pass to fopen to get
|
||||
untranslated reading.
|
||||
- FOPEN_BINARY_WRITE is the string to pass to fopen to get
|
||||
untranslated writing. */
|
||||
#if LINES_CRLF_TERMINATED
|
||||
#define OPEN_BINARY (O_BINARY)
|
||||
#define FOPEN_BINARY_READ ("rb")
|
||||
#define FOPEN_BINARY_WRITE ("wb")
|
||||
#else
|
||||
#define OPEN_BINARY (0)
|
||||
#define FOPEN_BINARY_READ ("r")
|
||||
#define FOPEN_BINARY_WRITE ("w")
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -13,8 +13,22 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)version.c 1.15 94/10/03 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)version.c 1.15 94/10/03 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
char *version_string = "\nConcurrent Versions System (CVS) 1.4 Alpha-2\n";
|
||||
char *version_string = "\nConcurrent Versions System (CVS) 1.6.3";
|
||||
|
||||
#ifdef CLIENT_SUPPORT
|
||||
#ifdef SERVER_SUPPORT
|
||||
char *config_string = " (client/server)\n";
|
||||
#else
|
||||
char *config_string = " (client)\n";
|
||||
#endif
|
||||
#else
|
||||
#ifdef SERVER_SUPPORT
|
||||
char *config_string = " (server)\n";
|
||||
#else
|
||||
char *config_string = "\n";
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# $Id: Makefile,v 1.25 1995/03/22 19:39:45 nate Exp $
|
||||
# $Id: Makefile,v 1.5 1995/03/31 07:55:30 nate Exp $
|
||||
|
||||
PROG = mkmodules
|
||||
SRCS = mkmodules.c
|
||||
CFLAGS+= -I${.CURDIR}/../cvs -I${.CURDIR}/../lib -DHAVE_CONFIG_H -DHAVE_TIMEZONE
|
||||
CFLAGS+= -I${.CURDIR}/../cvs -I${.CURDIR}/../lib -DHAVE_CONFIG_H
|
||||
DPADD+= ${LIBCVS}
|
||||
LDADD+= -lcvs
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
#include "cvs.h"
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$CVSid: @(#)mkmodules.c 1.45 94/09/30 $";
|
||||
USE(rcsid)
|
||||
static const char rcsid[] = "$CVSid: @(#)mkmodules.c 1.45 94/09/30 $";
|
||||
USE(rcsid);
|
||||
#endif
|
||||
|
||||
#ifndef DBLKSIZ
|
||||
|
|
@ -25,6 +25,7 @@ USE(rcsid)
|
|||
char *program_name, *command_name;
|
||||
|
||||
char *Rcsbin = RCSBIN_DFLT;
|
||||
char *CVSroot = CVSROOT_DFLT;
|
||||
int noexec = 0; /* Here only to satisfy use in subr.c */
|
||||
int trace = 0; /* Here only to satisfy use in subr.c */
|
||||
|
||||
|
|
@ -42,9 +43,8 @@ static void write_dbmfile PROTO((char *temp));
|
|||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
char **argv;
|
||||
{
|
||||
extern char *getenv ();
|
||||
char temp[PATH_MAX];
|
||||
char *cp, *last, *fname;
|
||||
#ifdef MY_NDBM
|
||||
|
|
@ -64,19 +64,20 @@ main (argc, argv)
|
|||
"a %s file can be used to validate log messages"},
|
||||
{CVSROOTADM_COMMITINFO,
|
||||
"a %s file can be used to configure 'cvs commit' checking"},
|
||||
{CVSROOTADM_TAGINFO,
|
||||
"a %s file can be used to configure 'cvs tag' checking"},
|
||||
{CVSROOTADM_IGNORE,
|
||||
"a %s file can be used to specify files to ignore"},
|
||||
{CVSROOTADM_CHECKOUTLIST,
|
||||
"a %s file can specify extra CVSROOT files to auto-checkout"},
|
||||
{CVSROOTADM_WRAPPER,
|
||||
"a %s file can be used to specify files to treat as wrappers"},
|
||||
{NULL, NULL}};
|
||||
|
||||
/*
|
||||
* Just save the last component of the path for error messages
|
||||
*/
|
||||
if ((program_name = strrchr (argv[0], '/')) == NULL)
|
||||
program_name = argv[0];
|
||||
else
|
||||
program_name++;
|
||||
program_name = last_component (argv[0]);
|
||||
|
||||
if (argc != 2)
|
||||
mkmodules_usage ();
|
||||
|
|
@ -164,9 +165,15 @@ main (argc, argv)
|
|||
/*
|
||||
* File format:
|
||||
* [<whitespace>]<filename><whitespace><error message><end-of-line>
|
||||
*
|
||||
* comment lines begin with '#'
|
||||
*/
|
||||
for (; fgets (line, sizeof (line), fp) != NULL;)
|
||||
while (fgets (line, sizeof (line), fp) != NULL)
|
||||
{
|
||||
/* skip lines starting with # */
|
||||
if (line[0] == '#')
|
||||
continue;
|
||||
|
||||
if ((last = strrchr (line, '\n')) != NULL)
|
||||
*last = '\0'; /* strip the newline */
|
||||
|
||||
|
|
@ -329,12 +336,14 @@ write_dbmfile (temp)
|
|||
(void) fclose (fp);
|
||||
if (err)
|
||||
{
|
||||
char dotdir[50], dotpag[50];
|
||||
char dotdir[50], dotpag[50], dotdb[50];
|
||||
|
||||
(void) sprintf (dotdir, "%s.dir", temp);
|
||||
(void) sprintf (dotpag, "%s.pag", temp);
|
||||
(void) sprintf (dotdb, "%s.db", temp);
|
||||
(void) unlink_file (dotdir);
|
||||
(void) unlink_file (dotpag);
|
||||
(void) unlink_file (dotdb);
|
||||
error (1, 0, "DBM creation failed; correct above errors");
|
||||
}
|
||||
}
|
||||
|
|
@ -343,29 +352,36 @@ static void
|
|||
rename_dbmfile (temp)
|
||||
char *temp;
|
||||
{
|
||||
char newdir[50], newpag[50];
|
||||
char dotdir[50], dotpag[50];
|
||||
char bakdir[50], bakpag[50];
|
||||
char newdir[50], newpag[50], newdb[50];
|
||||
char dotdir[50], dotpag[50], dotdb[50];
|
||||
char bakdir[50], bakpag[50], bakdb[50];
|
||||
|
||||
(void) sprintf (dotdir, "%s.dir", CVSROOTADM_MODULES);
|
||||
(void) sprintf (dotpag, "%s.pag", CVSROOTADM_MODULES);
|
||||
(void) sprintf (dotdb, "%s.db", CVSROOTADM_MODULES);
|
||||
(void) sprintf (bakdir, "%s%s.dir", BAKPREFIX, CVSROOTADM_MODULES);
|
||||
(void) sprintf (bakpag, "%s%s.pag", BAKPREFIX, CVSROOTADM_MODULES);
|
||||
(void) sprintf (bakdb, "%s%s.db", BAKPREFIX, CVSROOTADM_MODULES);
|
||||
(void) sprintf (newdir, "%s.dir", temp);
|
||||
(void) sprintf (newpag, "%s.pag", temp);
|
||||
(void) sprintf (newdb, "%s.db", temp);
|
||||
|
||||
(void) chmod (newdir, 0666);
|
||||
(void) chmod (newpag, 0666);
|
||||
(void) chmod (newdb, 0666);
|
||||
|
||||
/* don't mess with me */
|
||||
SIG_beginCrSect ();
|
||||
|
||||
(void) unlink_file (bakdir); /* rm .#modules.dir .#modules.pag */
|
||||
(void) unlink_file (bakpag);
|
||||
(void) unlink_file (bakdb);
|
||||
(void) rename (dotdir, bakdir); /* mv modules.dir .#modules.dir */
|
||||
(void) rename (dotpag, bakpag); /* mv modules.pag .#modules.pag */
|
||||
(void) rename (dotdb, bakdb); /* mv modules.db .#modules.db */
|
||||
(void) rename (newdir, dotdir); /* mv "temp".dir modules.dir */
|
||||
(void) rename (newpag, dotpag); /* mv "temp".pag modules.pag */
|
||||
(void) rename (newdb, dotdb); /* mv "temp".db modules.db */
|
||||
|
||||
/* OK -- make my day */
|
||||
SIG_endCrSect ();
|
||||
|
|
@ -403,6 +419,14 @@ Lock_Cleanup ()
|
|||
{
|
||||
}
|
||||
|
||||
int server_active = 0;
|
||||
|
||||
void
|
||||
server_cleanup (sig)
|
||||
int sig;
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
mkmodules_usage ()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue