this is not used anymore.

This commit is contained in:
christos 2002-11-28 22:03:41 +00:00
parent 71a5c52102
commit a65d983bd0
1 changed files with 0 additions and 764 deletions

View File

@ -1,764 +0,0 @@
/*
* 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 source distribution.
*
* Rtag
*
* Add or delete a symbolic name to an RCS file, or a collection of RCS files.
* Uses the modules database, if necessary.
*/
#include "cvs.h"
static int check_fileproc PROTO ((void *callerdat, struct file_info *finfo));
static int check_filesdoneproc PROTO ((void *callerdat, int err,
char *repos, char *update_dir,
List *entries));
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 ((void *callerdat, char *dir,
char *repos, char *update_dir,
List *entries));
static int rtag_fileproc PROTO ((void *callerdat, struct file_info *finfo));
static int rtag_filesdoneproc PROTO ((void *callerdat, int err,
char *repos, char *update_dir,
List *entries));
static int rtag_proc PROTO((int argc, 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 numtag_validated = 0;
static int delete_flag; /* adding a tag by default */
static int attic_too; /* remove tag from Attic files */
static int branch_mode; /* make an automagic "branch" tag */
static char *date;
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 const char *const rtag_usage[] =
{
"Usage: %s %s [-aflRnF] [-b] [-d] [-r rev|-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-d\tDelete the given Tag.\n",
"\t-b\tMake the tag a \"branch\" tag, allowing concurrent development.\n",
"\t-r rev\tExisting revision/tag.\n",
"\t-D\tExisting date.\n",
"\t-F\tMove tag if it already exists\n",
"(Specify the --help global option for a list of other help options)\n",
NULL
};
int
rtag (argc, argv)
int argc;
char **argv;
{
register int i;
int c;
DBM *db;
int run_module_prog = 1;
int err = 0;
if (argc == -1)
usage (rtag_usage);
optind = 0;
while ((c = getopt (argc, argv, "+FanfQqlRdbr:D:")) != -1)
{
switch (c)
{
case 'a':
attic_too = 1;
break;
case 'n':
run_module_prog = 0;
break;
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 'l':
local = 1;
break;
case 'R':
local = 0;
break;
case 'd':
delete_flag = 1;
break;
case 'f':
force_tag_match = 0;
break;
case 'b':
branch_mode = 1;
break;
case 'r':
numtag = optarg;
break;
case 'D':
if (date)
free (date);
date = Make_Date (optarg);
break;
case 'F':
force_tag_move = 1;
break;
case '?':
default:
usage (rtag_usage);
break;
}
}
argc -= optind;
argv += optind;
if (argc < 2)
usage (rtag_usage);
symtag = argv[0];
argc--;
argv++;
if (date && numtag)
error (1, 0, "-r and -D options are mutually exclusive");
if (delete_flag && branch_mode)
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 (!force_tag_match)
send_arg ("-f");
if (local)
send_arg("-l");
if (delete_flag)
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]);
}
send_to_server ("rtag\012", 0);
return get_responses_and_close ();
}
#endif
db = open_module ();
for (i = 0; i < argc; i++)
{
/* XXX last arg should be repository, but doesn't make sense here */
history_write ('T', (delete_flag ? "D" : (numtag ? numtag :
(date ? date : "A"))), symtag, argv[i], "");
err += do_module (db, argv[i], TAG,
delete_flag ? "Untagging" : "Tagging",
rtag_proc, (char *) NULL, 0, 0, run_module_prog,
symtag);
}
close_module (db);
return (err);
}
/*
* callback proc for doing the real work of tagging
*/
/* ARGSUSED */
static int
rtag_proc (argc, argv, xwhere, mwhere, mfile, shorten, local_specified,
mname, msg)
int argc;
char **argv;
char *xwhere;
char *mwhere;
char *mfile;
int shorten;
int local_specified;
char *mname;
char *msg;
{
/* Begin section which is identical to patch_proc--should this
be abstracted out somehow? */
char *myargv[2];
int err = 0;
int which;
char *repository;
char *where;
repository = xmalloc (strlen (CVSroot_directory) + strlen (argv[0])
+ (mfile == NULL ? 0 : strlen (mfile)) + 30);
(void) sprintf (repository, "%s/%s", CVSroot_directory, argv[0]);
where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 : strlen (mfile))
+ 10);
(void) strcpy (where, argv[0]);
/* if mfile isn't null, we need to set up to do only part of the module */
if (mfile != NULL)
{
char *cp;
char *path;
/* if the portion of the module is a path, put the dir part on repos */
if ((cp = strrchr (mfile, '/')) != NULL)
{
*cp = '\0';
(void) strcat (repository, "/");
(void) strcat (repository, mfile);
(void) strcat (where, "/");
(void) strcat (where, mfile);
mfile = cp + 1;
}
/* take care of the rest */
path = xmalloc (strlen (repository) + strlen (mfile) + 5);
(void) sprintf (path, "%s/%s", repository, mfile);
if (isdir (path))
{
/* directory means repository gets the dir tacked on */
(void) strcpy (repository, path);
(void) strcat (where, "/");
(void) strcat (where, mfile);
}
else
{
myargv[0] = argv[0];
myargv[1] = mfile;
argc = 2;
argv = myargv;
}
free (path);
}
/* cd to the starting repository */
if ( CVS_CHDIR (repository) < 0)
{
error (0, errno, "cannot chdir to %s", repository);
free (repository);
return (1);
}
free (repository);
/* End section which is identical to patch_proc. */
if (delete_flag || attic_too || (force_tag_match && numtag))
which = W_REPOS | W_ATTIC;
else
which = W_REPOS;
if (numtag != NULL && !numtag_validated)
{
tag_check_valid (numtag, argc - 1, argv + 1, local, 0, NULL);
numtag_validated = 1;
}
/* 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, NULL,
argc - 1, argv + 1, local, which, 0, 1,
where, 1);
if (err)
{
error (1, 0, "correct the above errors first!");
}
/* start the recursion processor */
err = start_recursion (rtag_fileproc, rtag_filesdoneproc, rtag_dirproc,
(DIRLEAVEPROC) NULL, NULL,
argc - 1, argv + 1, local,
which, 0, 0, where, 1);
free (where);
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 (callerdat, finfo)
void *callerdat;
struct file_info *finfo;
{
char *xdir;
Node *p;
Vers_TS *vers;
if (finfo->update_dir[0] == '\0')
xdir = ".";
else
xdir = finfo->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 (finfo->file);
p->type = UPDATE;
p->delproc = tag_delproc;
vers = Version_TS (finfo, NULL, NULL, NULL, 0, 0);
p->data = RCS_getversion(vers->srcfile, numtag, date, force_tag_match,
(int *) NULL);
if (p->data != NULL)
{
int addit = 1;
char *oversion;
oversion = RCS_getversion (vers->srcfile, symtag, (char *) NULL, 1,
(int *) NULL);
if (oversion == NULL)
{
if (delete_flag)
{
/* Deleting a tag which did not exist is a noop and
should not be logged. */
addit = 0;
}
}
else if (delete_flag)
{
free (p->data);
p->data = xstrdup (oversion);
}
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 (callerdat, err, repos, update_dir, entries)
void *callerdat;
int err;
char *repos;
char *update_dir;
List *entries;
{
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 ((unsigned char) *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 (filter);
run_arg (symtag);
run_arg (delete_flag ? "del" : force_tag_move ? "mov" : "add");
run_arg (repository);
walklist(tlist, pretag_list_proc, NULL);
return (run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL));
}
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.
*/
/* ARGSUSED */
static int
rtag_fileproc (callerdat, finfo)
void *callerdat;
struct file_info *finfo;
{
RCSNode *rcsfile;
char *version, *rev;
int retcode = 0;
/* Lock the directory if it is not already locked. We might be
able to rely on rtag_dirproc for this. */
/* It would be nice to provide consistency with respect to
commits; however CVS lacks the infrastructure to do that (see
Concurrency in cvs.texinfo and comment in do_recursion). We
can and will prevent simultaneous tag operations from
interfering with each other, by write locking each directory as
we enter it, and unlocking it as we leave it. */
lock_dir_for_write (finfo->repository);
/* find the parsed RCS data */
if ((rcsfile = finfo->rcs) == NULL)
return (1);
/*
* For tagging an RCS file which is a symbolic link, you'd best be
* running with RCS 5.6, since it knows how to handle symbolic links
* correctly without breaking your link!
*/
if (delete_flag)
return (rtag_delete (rcsfile));
/*
* If we get here, we are adding a tag. But, if -a was specified, we
* need to check to see if a -r or -D option was specified. If neither
* was specified and the file is in the Attic, remove the tag.
*/
if (attic_too && (!numtag && !date))
{
if ((rcsfile->flags & VALID) && (rcsfile->flags & INATTIC))
return (rtag_delete (rcsfile));
}
version = RCS_getversion (rcsfile, numtag, date, force_tag_match,
(int *) NULL);
if (version == NULL)
{
/* If -a specified, clean up any old tags */
if (attic_too)
(void) rtag_delete (rcsfile);
if (!quiet && !force_tag_match)
{
error (0, 0, "cannot find tag `%s' in `%s'",
numtag ? numtag : "head", rcsfile->path);
return (1);
}
return (0);
}
if (numtag
&& isdigit ((unsigned char) *numtag)
&& strcmp (numtag, version) != 0)
{
/*
* We didn't find a match for the numeric tag that was specified, but
* that's OK. just pass the numeric tag on to rcs, to be tagged as
* specified. Could get here if one tried to tag "1.1.1" and there
* was a 1.1.1 branch with some head revision. In this case, we want
* the tag to reference "1.1.1" and not the revision at the head of
* the branch. Use a symbolic tag for that.
*/
rev = branch_mode ? RCS_magicrev (rcsfile, version) : numtag;
retcode = RCS_settag(rcsfile, symtag, numtag);
if (retcode == 0)
RCS_rewrite (rcsfile, NULL, NULL);
}
else
{
char *oversion;
/*
* As an enhancement for the case where a tag is being re-applied to
* a large body of a module, make one extra call to RCS_getversion to
* see if the tag is already set in the RCS file. If so, check to
* see if it needs to be moved. If not, do nothing. This will
* likely save a lot of time when simply moving the tag to the
* "current" head revisions of a module -- which I have found to be a
* typical tagging operation.
*/
rev = branch_mode ? RCS_magicrev (rcsfile, version) : version;
oversion = RCS_getversion (rcsfile, symtag, (char *) NULL, 1,
(int *) NULL);
if (oversion != NULL)
{
int isbranch = RCS_nodeisbranch (finfo->rcs, symtag);
/*
* if versions the same and neither old or new are branches don't
* have to do anything
*/
if (strcmp (version, oversion) == 0 && !branch_mode && !isbranch)
{
free (oversion);
free (version);
return (0);
}
if (!force_tag_move)
{
/* we're NOT going to move the tag */
(void) printf ("W %s", finfo->fullname);
(void) printf (" : %s already exists on %s %s",
symtag, isbranch ? "branch" : "version",
oversion);
(void) printf (" : NOT MOVING tag to %s %s\n",
branch_mode ? "branch" : "version", rev);
free (oversion);
free (version);
return (0);
}
free (oversion);
}
retcode = RCS_settag(rcsfile, symtag, rev);
if (retcode == 0)
RCS_rewrite (rcsfile, NULL, NULL);
}
if (retcode != 0)
{
error (1, retcode == -1 ? errno : 0,
"failed to set tag `%s' to revision `%s' in `%s'",
symtag, rev, rcsfile->path);
if (branch_mode)
free (rev);
free (version);
return (1);
}
if (branch_mode)
free (rev);
free (version);
return (0);
}
/*
* If -d is specified, "force_tag_match" is set, so that this call to
* RCS_getversion() will return a NULL version string if the symbolic
* tag does not exist in the RCS file.
*
* If the -r flag was used, numtag is set, and we only delete the
* symtag from files that have numtag.
*
* This is done here because it's MUCH faster than just blindly calling
* "rcs" to remove the tag... trust me.
*/
static int
rtag_delete (rcsfile)
RCSNode *rcsfile;
{
char *version;
int retcode;
if (numtag)
{
version = RCS_getversion (rcsfile, numtag, (char *) NULL, 1,
(int *) NULL);
if (version == NULL)
return (0);
free (version);
}
version = RCS_getversion (rcsfile, symtag, (char *) NULL, 1,
(int *) NULL);
if (version == NULL)
return (0);
free (version);
if ((retcode = RCS_deltag(rcsfile, symtag)) != 0)
{
if (!quiet)
error (0, retcode == -1 ? errno : 0,
"failed to remove tag `%s' from `%s'", symtag,
rcsfile->path);
return (1);
}
RCS_rewrite (rcsfile, NULL, NULL);
return (0);
}
/* Clear any lock we may hold on the current directory. */
static int
rtag_filesdoneproc (callerdat, err, repos, update_dir, entries)
void *callerdat;
int err;
char *repos;
char *update_dir;
List *entries;
{
Lock_Cleanup ();
return (err);
}
/*
* Print a warm fuzzy message
*/
/* ARGSUSED */
static Dtype
rtag_dirproc (callerdat, dir, repos, update_dir, entries)
void *callerdat;
char *dir;
char *repos;
char *update_dir;
List *entries;
{
if (ignore_directory (update_dir))
{
/* print the warm fuzzy message */
if (!quiet)
error (0, 0, "Ignoring %s", update_dir);
return R_SKIP_ALL;
}
if (!quiet)
error (0, 0, "%s %s", delete_flag ? "Untagging" : "Tagging",
update_dir);
return (R_PROCESS);
}