#include "cvs.h"
#ifdef SERVER_SUPPORT
static void time_stamp_server PROTO((const char *, Vers_TS *, Entnode *));
#endif
Vers_TS *
Version_TS (finfo, options, tag, date, force_tag_match, set_time)
struct file_info *finfo;
char *options;
char *tag;
char *date;
int force_tag_match;
int set_time;
{
Node *p;
RCSNode *rcsdata;
Vers_TS *vers_ts;
struct stickydirtag *sdtp;
Entnode *entdata;
#ifdef UTIME_EXPECTS_WRITABLE
int change_it_back = 0;
#endif
vers_ts = (Vers_TS *) xmalloc (sizeof (Vers_TS));
memset ((char *) vers_ts, 0, sizeof (*vers_ts));
if (finfo->entries == NULL)
{
sdtp = NULL;
p = NULL;
}
else
{
p = findnode_fn (finfo->entries, finfo->file);
sdtp = finfo->entries->list->data;
}
entdata = NULL;
if (p != NULL)
{
entdata = p->data;
if (entdata->type == ENT_SUBDIR)
{
vers_ts->entdata = entdata;
}
else
#ifdef SERVER_SUPPORT
if (strcmp (entdata->timestamp, "D") != 0)
#endif
{
vers_ts->vn_user = xstrdup (entdata->version);
vers_ts->ts_rcs = xstrdup (entdata->timestamp);
vers_ts->ts_conflict = xstrdup (entdata->conflict);
if (!(tag || date) && !(sdtp && sdtp->aflag))
{
vers_ts->tag = xstrdup (entdata->tag);
vers_ts->date = xstrdup (entdata->date);
}
vers_ts->entdata = entdata;
}
if (!options || *options == '\0')
{
if (!(sdtp && sdtp->aflag))
vers_ts->options = xstrdup (entdata->options);
}
}
if (options && *options != '\0')
vers_ts->options = xstrdup (options);
else if (!vers_ts->options || *vers_ts->options == '\0')
{
if (finfo->rcs != NULL)
{
char *rcsexpand = RCS_getexpand (finfo->rcs);
if (rcsexpand != NULL)
{
if (vers_ts->options != NULL)
free (vers_ts->options);
vers_ts->options = xmalloc (strlen (rcsexpand) + 3);
strcpy (vers_ts->options, "-k");
strcat (vers_ts->options, rcsexpand);
}
}
}
if (!vers_ts->options)
vers_ts->options = xstrdup ("");
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);
vers_ts->nonbranch = sdtp->nonbranch;
}
if (!vers_ts->date)
vers_ts->date = xstrdup (sdtp->date);
}
if (finfo->rcs != NULL)
{
rcsdata = finfo->rcs;
rcsdata->refcount++;
}
else if (finfo->repository != NULL)
rcsdata = RCS_parse (finfo->file, finfo->repository);
else
rcsdata = NULL;
if (rcsdata != NULL)
{
vers_ts->srcfile = rcsdata;
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
{
int simple;
vers_ts->vn_rcs = RCS_getversion (rcsdata, vers_ts->tag,
vers_ts->date, force_tag_match,
&simple);
if (vers_ts->vn_rcs == NULL)
vers_ts->vn_tag = NULL;
else if (simple)
vers_ts->vn_tag = xstrdup (vers_ts->tag);
else
vers_ts->vn_tag = xstrdup (vers_ts->vn_rcs);
}
if (set_time && vers_ts->vn_rcs != NULL)
{
#ifdef SERVER_SUPPORT
if (server_active)
server_modtime (finfo, vers_ts);
else
#endif
{
struct utimbuf t;
memset (&t, 0, sizeof (t));
t.modtime = RCS_getrevtime (rcsdata, vers_ts->vn_rcs, 0, 0);
if (t.modtime != (time_t) -1)
{
(void) time (&t.actime);
#ifdef UTIME_EXPECTS_WRITABLE
if (!iswritable (finfo->file))
{
xchmod (finfo->file, 1);
change_it_back = 1;
}
#endif
(void) utime (finfo->file, &t);
#ifdef UTIME_EXPECTS_WRITABLE
if (change_it_back)
{
xchmod (finfo->file, 0);
change_it_back = 0;
}
#endif
}
}
}
}
if (finfo->entries != (List *) NULL)
{
#ifdef SERVER_SUPPORT
if (server_active)
time_stamp_server (finfo->file, vers_ts, entdata);
else
#endif
vers_ts->ts_user = time_stamp (finfo->file);
}
return (vers_ts);
}
#ifdef SERVER_SUPPORT
#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, entdata)
const char *file;
Vers_TS *vers_ts;
Entnode *entdata;
{
struct stat sb;
char *cp;
if (CVS_LSTAT (file, &sb) < 0)
{
if (! existence_error (errno))
error (1, errno, "cannot stat temp file");
if (entdata == NULL)
mark_lost (vers_ts);
else if (entdata->timestamp
&& entdata->timestamp[0] == '=')
mark_unchanged (vers_ts);
else if (entdata->timestamp
&& (entdata->timestamp[0] == 'M'
|| entdata->timestamp[0] == 'D')
&& entdata->timestamp[1] == '\0')
vers_ts->ts_user = xstrdup ("Is-modified");
else
mark_lost (vers_ts);
}
else if (sb.st_mtime == 0)
{
abort ();
}
else
{
struct tm *tm_p;
vers_ts->ts_user = xmalloc (25);
tm_p = gmtime (&sb.st_mtime);
cp = tm_p ? asctime (tm_p) : ctime (&sb.st_mtime);
cp[24] = 0;
if (cp[8] == '0') cp[8] = ' ';
(void) strcpy (vers_ts->ts_user, cp);
}
}
#endif
char *
time_stamp (file)
const char *file;
{
struct stat sb;
char *cp;
char *ts = NULL;
time_t mtime = 0L;
if (!CVS_LSTAT (file, &sb))
{
mtime = sb.st_mtime;
}
if (!CVS_STAT (file, &sb))
{
if (mtime < sb.st_mtime)
mtime = sb.st_mtime;
}
if (mtime)
{
struct tm *tm_p;
ts = xmalloc (25);
tm_p = gmtime (&sb.st_mtime);
cp = tm_p ? asctime (tm_p) : ctime (&sb.st_mtime);
cp[24] = 0;
if (cp[8] == '0') cp[8] = ' ';
(void) strcpy (ts, cp);
}
return (ts);
}
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)->vn_tag)
free ((*versp)->vn_tag);
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;
}