This is classify.c in view mode; [Download] [Up]
/*
* 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.
*
*/
#include "cvs.h"
#ifndef lint
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
*/
Ctype
Classify_File (file, tag, date, options, force_tag_match, aflag, repository,
entries, srcfiles, versp, update_dir, pipeout)
char *file;
char *tag;
char *date;
char *options;
int force_tag_match;
int aflag;
char *repository;
List *entries;
List *srcfiles;
Vers_TS **versp;
char *update_dir;
int pipeout;
{
Vers_TS *vers;
Ctype ret;
char *fullname;
fullname = xmalloc (strlen (update_dir) + strlen (file) + 10);
if (update_dir[0] == '\0')
strcpy (fullname, file);
else
sprintf (fullname, "%s/%s", update_dir, file);
/* get all kinds of good data about the file */
vers = Version_TS (repository, options, tag, date, file,
force_tag_match, 0, entries, srcfiles);
if (vers->vn_user == NULL)
{
/* No entry available, ts_rcs is invalid */
if (vers->vn_rcs == NULL)
{
/* there is no RCS file either */
if (vers->ts_user == NULL)
{
/* there is no user file */
if (!force_tag_match || !(vers->tag || vers->date))
if (!really_quiet)
error (0, 0, "nothing known about %s", fullname);
ret = T_UNKNOWN;
}
else
{
/* there is a user file */
if (!force_tag_match || !(vers->tag || vers->date))
if (!really_quiet)
error (0, 0, "use `cvs add' to create an entry for %s",
fullname);
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 */
if (vers->ts_user == NULL)
{
/* There is no user file; needs checkout */
ret = T_CHECKOUT;
}
else
{
if (pipeout)
{
/*
* The user file doesn't necessarily have anything
* to do with this.
*/
ret = T_CHECKOUT;
}
/*
* There is a user file; print a warning and add it to the
* conflict list, only if it is indeed different from what we
* plan to extract
*/
else if (No_Difference (file, vers, entries,
repository, update_dir))
{
/* the files were different so it is a conflict */
if (!really_quiet)
error (0, 0, "move away %s; it is in the way",
fullname);
ret = T_CONFLICT;
}
else
/* since there was no difference, still needs checkout */
ret = T_CHECKOUT;
}
}
}
else if (strcmp (vers->vn_user, "0") == 0)
{
/* An entry for a new-born file; ts_rcs is dummy */
if (vers->ts_user == NULL)
{
/*
* There is no user file, but there should be one; remove the
* entry
*/
if (!really_quiet)
error (0, 0, "warning: new-born %s has disappeared", fullname);
ret = T_REMOVE_ENTRY;
}
else
{
/* There is a user file */
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
*/
if (!really_quiet)
error (0, 0,
"conflict: %s created independently by second party",
fullname);
#ifdef DEATH_SUPPORT
}
#endif
ret = T_CONFLICT;
}
}
}
else if (vers->vn_user[0] == '-')
{
/* An entry for a removed file, ts_rcs is invalid */
if (vers->ts_user == NULL)
{
char tmp[PATH_MAX];
/* There is no user file (as it should be) */
(void) sprintf (tmp, "-%s", vers->vn_rcs ? vers->vn_rcs : "");
if (vers->vn_rcs == NULL)
{
/*
* There is no RCS file; this is all-right, but it has been
* removed independently by a second party; remove the entry
*/
ret = T_REMOVE_ENTRY;
}
else if (strcmp (tmp, vers->vn_user) == 0)
/*
* The RCS file is the same version as the user file was, and
* that's OK; remove it
*/
ret = T_REMOVED;
else
{
/*
* The RCS file is a newer version than the removed user file
* and this is definitely not OK; make it a conflict.
*/
if (!really_quiet)
error (0, 0,
"conflict: removed %s was modified by second party",
fullname);
ret = T_CONFLICT;
}
}
else
{
/* The user file shouldn't be there */
if (!really_quiet)
error (0, 0, "%s should be removed and is still there",
fullname);
ret = T_REMOVED;
}
}
else
{
/* A normal entry, TS_Rcs is valid */
if (vers->vn_rcs == NULL)
{
/* There is no RCS file */
if (vers->ts_user == NULL)
{
/* There is no user file, so just remove the entry */
if (!really_quiet)
error (0, 0, "warning: %s is not (any longer) pertinent",
fullname);
ret = T_REMOVE_ENTRY;
}
else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
{
/*
* The user file is still unmodified, so just remove it from
* the entry list
*/
if (!really_quiet)
error (0, 0, "%s is no longer in the repository",
fullname);
ret = T_REMOVE_ENTRY;
}
else
{
/*
* The user file has been modified and since it is no longer
* in the repository, a conflict is raised
*/
if (No_Difference (file, vers, entries,
repository, update_dir))
{
/* they are different -> conflict */
if (!really_quiet)
error (0, 0,
"conflict: %s is modified but no longer in the repository",
fullname);
ret = T_CONFLICT;
}
else
{
/* they weren't really different */
if (!really_quiet)
error (0, 0,
"warning: %s is not (any longer) pertinent",
fullname);
ret = T_REMOVE_ENTRY;
}
}
}
else if (strcmp (vers->vn_rcs, vers->vn_user) == 0)
{
/* The RCS file is the same version as the user file */
if (vers->ts_user == NULL)
{
/*
* There is no user file, so note that it was lost and
* extract a new version
*/
if (strcmp (command_name, "update") == 0)
if (!really_quiet)
error (0, 0, "warning: %s was lost", fullname);
ret = T_CHECKOUT;
}
else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
{
/*
* The user file is still unmodified, so nothing special at
* all to do -- no lists updated, unless the sticky -k option
* has changed. If the sticky tag has changed, we just need
* to re-register the entry
*/
if (vers->entdata->options &&
strcmp (vers->entdata->options, vers->options) != 0)
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;
}
}
else
{
/*
* The user file appears to have been modified, but we call
* No_Difference to verify that it really has been modified
*/
if (No_Difference (file, vers, entries,
repository, update_dir))
{
/*
* they really are different; modified if we aren't
* changing any sticky -k options, else needs merge
*/
#ifdef XXX_FIXME_WHEN_RCSMERGE_IS_FIXED
if (strcmp (vers->entdata->options ?
vers->entdata->options : "", vers->options) == 0)
ret = T_MODIFIED;
else
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
{
/* file has not changed; check out if -k changed */
if (strcmp (vers->entdata->options ?
vers->entdata->options : "", vers->options) != 0)
{
ret = T_CHECKOUT;
}
else
{
/*
* else -> note that No_Difference will Register the
* file already for us, using the new tag/date. This
* is the desired behaviour
*/
ret = T_UPTODATE;
}
}
}
}
else
{
/* The RCS file is a newer version than the user file */
if (vers->ts_user == NULL)
{
/* There is no user file, so just get it */
if (strcmp (command_name, "update") == 0)
if (!really_quiet)
error (0, 0, "warning: %s was lost", fullname);
ret = T_CHECKOUT;
}
else if (strcmp (vers->ts_user, vers->ts_rcs) == 0)
{
/*
* 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
{
if (No_Difference (file, vers, entries,
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
}
}
}
/* free up the vers struct, or just return it */
if (versp != (Vers_TS **) NULL)
*versp = vers;
else
freevers_ts (&vers);
free (fullname);
/* return the status of the file */
return (ret);
}
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)
{
char *enttag = vers->entdata->tag;
char *entdate = vers->entdata->date;
if ((enttag && vers->tag && strcmp (enttag, vers->tag)) ||
((enttag && !vers->tag) || (!enttag && vers->tag)) ||
(entdate && vers->date && strcmp (entdate, vers->date)) ||
((entdate && !vers->date) || (!entdate && vers->date)))
{
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
}
}
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.