home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / cvs-1.8.7-src.tgz / tar.out / fsf / cvs / src / vers_ts.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  9KB  |  349 lines

  1. /*
  2.  * Copyright (c) 1992, Brian Berliner and Jeff Polk
  3.  * Copyright (c) 1989-1992, Brian Berliner
  4.  * 
  5.  * You may distribute under the terms of the GNU General Public License as
  6.  * specified in the README file that comes with the CVS 1.4 kit.
  7.  */
  8.  
  9. #include "cvs.h"
  10.  
  11. #ifdef SERVER_SUPPORT
  12. static void time_stamp_server PROTO((char *, Vers_TS *));
  13. #endif
  14.  
  15. /*
  16.  * Fill in and return a Vers_TS structure "user" is the name of the local
  17.  * file; entries is the entries file - preparsed for our pleasure. rcs is
  18.  * the current source control file - preparsed for our pleasure.
  19.  */
  20. Vers_TS *
  21. Version_TS (finfo, options, tag, date, force_tag_match, set_time)
  22.     struct file_info *finfo;
  23.     char *options;
  24.     char *tag;
  25.     char *date;
  26.     int force_tag_match;
  27.     int set_time;
  28. {
  29.     Node *p;
  30.     RCSNode *rcsdata;
  31.     Vers_TS *vers_ts;
  32.     struct stickydirtag *sdtp;
  33.  
  34.     /* get a new Vers_TS struct */
  35.     vers_ts = (Vers_TS *) xmalloc (sizeof (Vers_TS));
  36.     memset ((char *) vers_ts, 0, sizeof (*vers_ts));
  37.  
  38.     /*
  39.      * look up the entries file entry and fill in the version and timestamp
  40.      * if entries is NULL, there is no entries file so don't bother trying to
  41.      * look it up (used by checkout -P)
  42.      */
  43.     if (finfo->entries == NULL)
  44.     {
  45.     sdtp = NULL;
  46.     p = NULL;
  47.     }
  48.     else
  49.     {
  50.     p = findnode_fn (finfo->entries, finfo->file);
  51.     sdtp = (struct stickydirtag *) finfo->entries->list->data; /* list-private */
  52.     }
  53.  
  54.     if (p != NULL)
  55.     {
  56.     Entnode *entdata = (Entnode *) p->data;
  57.  
  58.     vers_ts->vn_user = xstrdup (entdata->version);
  59.     vers_ts->ts_rcs = xstrdup (entdata->timestamp);
  60.     vers_ts->ts_conflict = xstrdup (entdata->conflict);
  61.     if (!tag)
  62.     {
  63.         if (!(sdtp && sdtp->aflag))
  64.         vers_ts->tag = xstrdup (entdata->tag);
  65.     }
  66.     if (!date)
  67.     {
  68.         if (!(sdtp && sdtp->aflag))
  69.         vers_ts->date = xstrdup (entdata->date);
  70.     }
  71.     if (!options || (options && *options == '\0'))
  72.     {
  73.         if (!(sdtp && sdtp->aflag))
  74.         vers_ts->options = xstrdup (entdata->options);
  75.     }
  76.     vers_ts->entdata = entdata;
  77.     }
  78.  
  79.     /*
  80.      * -k options specified on the command line override (and overwrite)
  81.      * options stored in the entries file
  82.      */
  83.     if (options)
  84.     vers_ts->options = xstrdup (options);
  85.     else if (!vers_ts->options)
  86.     {
  87.     if (finfo->rcs != NULL)
  88.     {
  89.         /* If no keyword expansion was specified on command line,
  90.            use whatever was in the rcs file (if there is one).  This
  91.            is how we, if we are the server, tell the client whether
  92.            a file is binary.  */
  93.         char *rcsexpand = RCS_getexpand (finfo->rcs);
  94.         if (rcsexpand != NULL)
  95.         {
  96.         vers_ts->options = xmalloc (strlen (rcsexpand) + 3);
  97.         strcpy (vers_ts->options, "-k");
  98.         strcat (vers_ts->options, rcsexpand);
  99.         }
  100.     }
  101.     }
  102.     if (!vers_ts->options)
  103.     vers_ts->options = xstrdup ("");
  104.  
  105.     /*
  106.      * if tags were specified on the command line, they override what is in
  107.      * the Entries file
  108.      */
  109.     if (tag || date)
  110.     {
  111.     vers_ts->tag = xstrdup (tag);
  112.     vers_ts->date = xstrdup (date);
  113.     }
  114.     else if (!vers_ts->entdata && (sdtp && sdtp->aflag == 0))
  115.     {
  116.     if (!vers_ts->tag)
  117.         vers_ts->tag = xstrdup (sdtp->tag);
  118.     if (!vers_ts->date)
  119.         vers_ts->date = xstrdup (sdtp->date);
  120.     }
  121.  
  122.     /* Now look up the info on the source controlled file */
  123.     if (finfo->rcs != NULL)
  124.     {
  125.     rcsdata = finfo->rcs;
  126.     rcsdata->refcount++;
  127.     }
  128.     else if (finfo->repository != NULL)
  129.     rcsdata = RCS_parse (finfo->file, finfo->repository);
  130.     else
  131.     rcsdata = NULL;
  132.  
  133.     if (rcsdata != NULL)
  134.     {
  135.     /* squirrel away the rcsdata pointer for others */
  136.     vers_ts->srcfile = rcsdata;
  137.  
  138.     if (vers_ts->tag && strcmp (vers_ts->tag, TAG_BASE) == 0)
  139.     {
  140.         vers_ts->vn_rcs = xstrdup (vers_ts->vn_user);
  141.         vers_ts->vn_tag = xstrdup (vers_ts->vn_user);
  142.     }
  143.     else
  144.     {
  145.         vers_ts->vn_rcs = RCS_getversion (rcsdata, vers_ts->tag,
  146.                     vers_ts->date, force_tag_match, 1);
  147.         if (vers_ts->vn_rcs == NULL)
  148.         vers_ts->vn_tag = NULL;
  149.         else
  150.         {
  151.         char *colon = strchr (vers_ts->vn_rcs, ':');
  152.         if (colon)
  153.         {
  154.             vers_ts->vn_tag = xstrdup (colon+1);
  155.             *colon = '\0';
  156.         }
  157.         else
  158.             vers_ts->vn_tag = xstrdup (vers_ts->vn_rcs);
  159.         }
  160.     }
  161.  
  162.     /*
  163.      * If the source control file exists and has the requested revision,
  164.      * get the Date the revision was checked in.  If "user" exists, set
  165.      * its mtime.
  166.      */
  167.     if (set_time)
  168.     {
  169.         struct utimbuf t;
  170.  
  171.         memset ((char *) &t, 0, sizeof (t));
  172.         if (vers_ts->vn_rcs &&
  173.         (t.actime = t.modtime = RCS_getrevtime (rcsdata,
  174.          vers_ts->vn_rcs, (char *) 0, 0)) != -1)
  175.         (void) utime (finfo->file, &t);
  176.     }
  177.     }
  178.  
  179.     /* get user file time-stamp in ts_user */
  180.     if (finfo->entries != (List *) NULL)
  181.     {
  182. #ifdef SERVER_SUPPORT
  183.     if (server_active)
  184.         time_stamp_server (finfo->file, vers_ts);
  185.     else
  186. #endif
  187.         vers_ts->ts_user = time_stamp (finfo->file);
  188.     }
  189.  
  190.     return (vers_ts);
  191. }
  192.  
  193. #ifdef SERVER_SUPPORT
  194.  
  195. /* Set VERS_TS->TS_USER to time stamp for FILE.  */
  196.  
  197. /* Separate these out to keep the logic below clearer.  */
  198. #define mark_lost(V)        ((V)->ts_user = 0)
  199. #define mark_unchanged(V)    ((V)->ts_user = xstrdup ((V)->ts_rcs))
  200.  
  201. static void
  202. time_stamp_server (file, vers_ts)
  203.     char *file;
  204.     Vers_TS *vers_ts;
  205. {
  206.     struct stat sb;
  207.     char *cp;
  208.  
  209.     if ( CVS_STAT (file, &sb) < 0)
  210.     {
  211.     if (! existence_error (errno))
  212.         error (1, errno, "cannot stat temp file");
  213.     if (use_unchanged)
  214.       {
  215.         /* Missing file means lost or unmodified; check entries
  216.            file to see which.
  217.  
  218.            XXX FIXME - If there's no entries file line, we
  219.            wouldn't be getting the file at all, so consider it
  220.            lost.  I don't know that that's right, but it's not
  221.            clear to me that either choice is.  Besides, would we
  222.            have an RCS string in that case anyways?  */
  223.         if (vers_ts->entdata == NULL)
  224.           mark_lost (vers_ts);
  225.         else if (vers_ts->entdata->timestamp
  226.              && vers_ts->entdata->timestamp[0] == '=')
  227.           mark_unchanged (vers_ts);
  228.         else
  229.           mark_lost (vers_ts);
  230.       }
  231.     else
  232.       {
  233.         /* Missing file in the temp directory means that the file
  234.            was not modified.  */
  235.         mark_unchanged (vers_ts);
  236.       }
  237.     }
  238.     else if (sb.st_mtime == 0)
  239.     {
  240.     if (use_unchanged)
  241.       /* We shouldn't reach this case any more!  */
  242.       abort ();
  243.  
  244.     /* Special code used by server.c to indicate the file was lost.  */
  245.     mark_lost (vers_ts);
  246.     }
  247.     else
  248.     {
  249.         struct tm *tm_p;
  250.         struct tm local_tm;
  251.  
  252.     vers_ts->ts_user = xmalloc (25);
  253.     /* We want to use the same timestamp format as is stored in the
  254.        st_mtime.  For unix (and NT I think) this *must* be universal
  255.        time (UT), so that files don't appear to be modified merely
  256.        because the timezone has changed.  For VMS, or hopefully other
  257.        systems where gmtime returns NULL, the modification time is
  258.        stored in local time, and therefore it is not possible to cause
  259.        st_mtime to be out of sync by changing the timezone.  */
  260.     tm_p = gmtime (&sb.st_mtime);
  261.     if (tm_p)
  262.     {
  263.         memcpy (&local_tm, tm_p, sizeof (local_tm));
  264.         cp = asctime (&local_tm);    /* copy in the modify time */
  265.     }
  266.     else
  267.         cp = ctime (&sb.st_mtime);
  268.  
  269.     cp[24] = 0;
  270.     (void) strcpy (vers_ts->ts_user, cp);
  271.     }
  272. }
  273.  
  274. #endif /* SERVER_SUPPORT */
  275. /*
  276.  * Gets the time-stamp for the file "file" and returns it in space it
  277.  * allocates
  278.  */
  279. char *
  280. time_stamp (file)
  281.     char *file;
  282. {
  283.     struct stat sb;
  284.     char *cp;
  285.     char *ts;
  286.  
  287.     if ( CVS_STAT (file, &sb) < 0)
  288.     {
  289.     ts = NULL;
  290.     }
  291.     else
  292.     {
  293.     struct tm *tm_p;
  294.         struct tm local_tm;
  295.     ts = xmalloc (25);
  296.     /* We want to use the same timestamp format as is stored in the
  297.        st_mtime.  For unix (and NT I think) this *must* be universal
  298.        time (UT), so that files don't appear to be modified merely
  299.        because the timezone has changed.  For VMS, or hopefully other
  300.        systems where gmtime returns NULL, the modification time is
  301.        stored in local time, and therefore it is not possible to cause
  302.        st_mtime to be out of sync by changing the timezone.  */
  303.     tm_p = gmtime (&sb.st_mtime);
  304.     if (tm_p)
  305.     {
  306.         memcpy (&local_tm, tm_p, sizeof (local_tm));
  307.         cp = asctime (&local_tm);    /* copy in the modify time */
  308.     }
  309.     else
  310.         cp = ctime(&sb.st_mtime);
  311.  
  312.     cp[24] = 0;
  313.     (void) strcpy (ts, cp);
  314.     }
  315.  
  316.     return (ts);
  317. }
  318.  
  319. /*
  320.  * free up a Vers_TS struct
  321.  */
  322. void
  323. freevers_ts (versp)
  324.     Vers_TS **versp;
  325. {
  326.     if ((*versp)->srcfile)
  327.     freercsnode (&((*versp)->srcfile));
  328.     if ((*versp)->vn_user)
  329.     free ((*versp)->vn_user);
  330.     if ((*versp)->vn_rcs)
  331.     free ((*versp)->vn_rcs);
  332.     if ((*versp)->vn_tag)
  333.     free ((*versp)->vn_tag);
  334.     if ((*versp)->ts_user)
  335.     free ((*versp)->ts_user);
  336.     if ((*versp)->ts_rcs)
  337.     free ((*versp)->ts_rcs);
  338.     if ((*versp)->options)
  339.     free ((*versp)->options);
  340.     if ((*versp)->tag)
  341.     free ((*versp)->tag);
  342.     if ((*versp)->date)
  343.     free ((*versp)->date);
  344.     if ((*versp)->ts_conflict)
  345.     free ((*versp)->ts_conflict);
  346.     free ((char *) *versp);
  347.     *versp = (Vers_TS *) NULL;
  348. }
  349.