ftp.nice.ch/pub/next/unix/developer/cvs.950905.s.tar.gz#/cvs-1.5.1/src/vers_ts.c

This is vers_ts.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: @(#)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
 * file; entries is the entries file - preparsed for our pleasure. xfiles is
 * all source code control files, preparsed for our pleasure
 */
Vers_TS *
Version_TS (repository, options, tag, date, user, force_tag_match,
	    set_time, entries, xfiles)
    char *repository;
    char *options;
    char *tag;
    char *date;
    char *user;
    int force_tag_match;
    int set_time;
    List *entries;
    List *xfiles;
{
    Node *p;
    RCSNode *rcsdata;
    Vers_TS *vers_ts;
    struct stickydirtag *sdtp;

    /* get a new Vers_TS struct */
    vers_ts = (Vers_TS *) xmalloc (sizeof (Vers_TS));
    memset ((char *) vers_ts, 0, sizeof (*vers_ts));

    /*
     * look up the entries file entry and fill in the version and timestamp
     * if entries is NULL, there is no entries file so don't bother trying to
     * look it up (used by checkout -P)
     */
    if (entries == NULL)
    {
	sdtp = NULL;
	p = NULL;
    }
    else
    {
	p = findnode (entries, user);
	sdtp = (struct stickydirtag *) entries->list->data; /* list-private */
    }

    if (p != NULL)
    {
	Entnode *entdata = (Entnode *) p->data;

	vers_ts->vn_user = xstrdup (entdata->version);
	vers_ts->ts_rcs = xstrdup (entdata->timestamp);
	vers_ts->ts_conflict = xstrdup (entdata->conflict);
	if (!tag)
	{
	    if (!(sdtp && sdtp->aflag))
		vers_ts->tag = xstrdup (entdata->tag);
	}
	if (!date)
	{
	    if (!(sdtp && sdtp->aflag))
		vers_ts->date = xstrdup (entdata->date);
	}
	if (!options || (options && *options == '\0'))
	{
	    if (!(sdtp && sdtp->aflag))
		vers_ts->options = xstrdup (entdata->options);
	}
	vers_ts->entdata = entdata;
    }

    /*
     * -k options specified on the command line override (and overwrite)
     * options stored in the entries file
     */
    if (options)
	vers_ts->options = xstrdup (options);
    else if (sdtp && sdtp->aflag == 0)
    {
	if (!vers_ts->options)
	    vers_ts->options = xstrdup (sdtp->options);
    }
    if (!vers_ts->options)
	vers_ts->options = xstrdup ("");

    /*
     * if tags were specified on the command line, they override what is in
     * the Entries file
     */
    if (tag || date)
    {
	vers_ts->tag = xstrdup (tag);
	vers_ts->date = xstrdup (date);
    }
    else if (!vers_ts->entdata && (sdtp && sdtp->aflag == 0))
    {
	if (!vers_ts->tag)
	    vers_ts->tag = xstrdup (sdtp->tag);
	if (!vers_ts->date)
	    vers_ts->date = xstrdup (sdtp->date);
    }

    /* Now look up the info on the source controlled file */
    if (xfiles != (List *) NULL)
    {
	p = findnode (xfiles, user);
	if (p != NULL)
	{
	    rcsdata = (RCSNode *) p->data;
	    rcsdata->refcount++;
	}
	else
	    rcsdata = NULL;
    }
    else if (repository != NULL)
	rcsdata = RCS_parse (user, repository);
    else
	rcsdata = NULL;

    if (rcsdata != NULL)
    {
	/* 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);
	    else
		vers_ts->vn_rcs = RCS_getversion (rcsdata, vers_ts->tag,
					    vers_ts->date, force_tag_match);
#ifndef DEATH_SUPPORT
	} 
#endif

	/*
	 * If the source control file exists and has the requested revision,
	 * get the Date the revision was checked in.  If "user" exists, set
	 * its mtime.
	 */
	if (set_time)
	{
	    struct utimbuf t;

	    memset ((char *) &t, 0, sizeof (t));
	    if (vers_ts->vn_rcs &&
		(t.actime = t.modtime = RCS_getrevtime (rcsdata,
		 vers_ts->vn_rcs, (char *) 0, 0)) != -1)
		(void) utime (user, &t);
	}
    }

    /* get user file time-stamp in ts_user */
    if (entries != (List *) NULL)
    {
#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 (errno != ENOENT)
	    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
 */
char *
time_stamp (file)
    char *file;
{
    struct stat sb;
    char *cp;
    char *ts;

    if (stat (file, &sb) < 0)
    {
	ts = NULL;
    }
    else
    {
	ts = xmalloc (25);
	cp = asctime (gmtime (&sb.st_mtime));	/* copy in the modify time */
	cp[24] = 0;
	(void) strcpy (ts, cp);
    }

    return (ts);
}

/*
 * free up a Vers_TS struct
 */
void
freevers_ts (versp)
    Vers_TS **versp;
{
    if ((*versp)->srcfile)
	freercsnode (&((*versp)->srcfile));
    if ((*versp)->vn_user)
	free ((*versp)->vn_user);
    if ((*versp)->vn_rcs)
	free ((*versp)->vn_rcs);
    if ((*versp)->ts_user)
	free ((*versp)->ts_user);
    if ((*versp)->ts_rcs)
	free ((*versp)->ts_rcs);
    if ((*versp)->options)
	free ((*versp)->options);
    if ((*versp)->tag)
	free ((*versp)->tag);
    if ((*versp)->date)
	free ((*versp)->date);
    if ((*versp)->ts_conflict)
	free ((*versp)->ts_conflict);
    free ((char *) *versp);
    *versp = (Vers_TS *) NULL;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.