/[cvs]/ccvs/src/entries.c
ViewVC logotype

Diff of /ccvs/src/entries.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.66 by dprice, Thu Sep 22 02:22:41 2005 UTC revision 1.66.4.1 by dprice, Thu Nov 10 04:47:44 2005 UTC
# Line 931  Subdir_Deregister (List *entries, const Line 931  Subdir_Deregister (List *entries, const
931              delnode (p);              delnode (p);
932      }      }
933  }  }
   
   
   
 /* OK, the following base_* code tracks the revisions of the files in  
    CVS/Base.  We do this in a file CVS/Baserev.  Separate from  
    CVS/Entries because it needs to go in separate data structures  
    anyway (the name in Entries must be unique), so this seemed  
    cleaner.  The business of rewriting the whole file in  
    base_deregister and base_register is the kind of thing we used to  
    do for Entries and which turned out to be slow, which is why there  
    is now the Entries.Log machinery.  So maybe from that point of  
    view it is a mistake to do this separately from Entries, I dunno.  */  
   
 enum base_walk  
 {  
     /* Set the revision for FILE to *REV.  */  
     BASE_REGISTER,  
     /* Get the revision for FILE and put it in a newly malloc'd string  
        in *REV, or put NULL if not mentioned.  */  
     BASE_GET,  
     /* Remove FILE.  */  
     BASE_DEREGISTER  
 };  
   
 static void base_walk (enum base_walk, struct file_info *, char **);  
   
 /* Read through the lines in CVS/Baserev, taking the actions as documented  
    for CODE.  */  
   
 static void  
 base_walk (enum base_walk code, struct file_info *finfo, char **rev)  
 {  
     FILE *fp;  
     char *line;  
     size_t line_allocated;  
     FILE *newf;  
     char *baserev_fullname;  
     char *baserevtmp_fullname;  
   
     line = NULL;  
     line_allocated = 0;  
     newf = NULL;  
   
     /* First compute the fullnames for the error messages.  This  
        computation probably should be broken out into a separate function,  
        as recurse.c does it too and places like Entries_Open should be  
        doing it.  */  
     if (finfo->update_dir[0] != '\0')  
     {  
         baserev_fullname = Xasprintf ("%s/%s", finfo->update_dir,  
                                       CVSADM_BASEREV);  
         baserevtmp_fullname = Xasprintf ("%s/%s", finfo->update_dir,  
                                          CVSADM_BASEREVTMP);  
     }  
     else  
     {  
         baserev_fullname = xstrdup (CVSADM_BASEREV);  
         baserevtmp_fullname = xstrdup (CVSADM_BASEREVTMP);  
     }  
   
     fp = CVS_FOPEN (CVSADM_BASEREV, "r");  
     if (fp == NULL)  
     {  
         if (!existence_error (errno))  
         {  
             error (0, errno, "cannot open %s for reading", baserev_fullname);  
             goto out;  
         }  
     }  
   
     switch (code)  
     {  
         case BASE_REGISTER:  
         case BASE_DEREGISTER:  
             newf = CVS_FOPEN (CVSADM_BASEREVTMP, "w");  
             if (newf == NULL)  
             {  
                 error (0, errno, "cannot open %s for writing",  
                        baserevtmp_fullname);  
                 goto out;  
             }  
             break;  
         case BASE_GET:  
             *rev = NULL;  
             break;  
     }  
   
     if (fp != NULL)  
     {  
         while (getline (&line, &line_allocated, fp) >= 0)  
         {  
             char *linefile;  
             char *p;  
             char *linerev;  
   
             if (line[0] != 'B')  
                 /* Ignore, for future expansion.  */  
                 continue;  
   
             linefile = line + 1;  
             p = strchr (linefile, '/');  
             if (p == NULL)  
                 /* Syntax error, ignore.  */  
                 continue;  
             linerev = p + 1;  
             p = strchr (linerev, '/');  
             if (p == NULL)  
                 continue;  
   
             linerev[-1] = '\0';  
             if (fncmp (linefile, finfo->file) == 0)  
             {  
                 switch (code)  
                 {  
                 case BASE_REGISTER:  
                 case BASE_DEREGISTER:  
                     /* Don't copy over the old entry, we don't want it.  */  
                     break;  
                 case BASE_GET:  
                     *p = '\0';  
                     *rev = xstrdup (linerev);  
                     *p = '/';  
                     goto got_it;  
                 }  
             }  
             else  
             {  
                 linerev[-1] = '/';  
                 switch (code)  
                 {  
                 case BASE_REGISTER:  
                 case BASE_DEREGISTER:  
                     if (fprintf (newf, "%s\n", line) < 0)  
                         error (0, errno, "error writing %s",  
                                baserevtmp_fullname);  
                     break;  
                 case BASE_GET:  
                     break;  
                 }  
             }  
         }  
         if (ferror (fp))  
             error (0, errno, "cannot read %s", baserev_fullname);  
     }  
  got_it:  
   
     if (code == BASE_REGISTER)  
     {  
         if (fprintf (newf, "B%s/%s/\n", finfo->file, *rev) < 0)  
             error (0, errno, "error writing %s",  
                    baserevtmp_fullname);  
     }  
   
  out:  
   
     if (line != NULL)  
         free (line);  
   
     if (fp != NULL)  
     {  
         if (fclose (fp) < 0)  
             error (0, errno, "cannot close %s", baserev_fullname);  
     }  
     if (newf != NULL)  
     {  
         if (fclose (newf) < 0)  
             error (0, errno, "cannot close %s", baserevtmp_fullname);  
         rename_file (CVSADM_BASEREVTMP, CVSADM_BASEREV);  
     }  
   
     free (baserev_fullname);  
     free (baserevtmp_fullname);  
 }  
   
 /* Return, in a newly malloc'd string, the revision for FILE in CVS/Baserev,  
    or NULL if not listed.  */  
   
 char *  
 base_get (struct file_info *finfo)  
 {  
     char *rev;  
     base_walk (BASE_GET, finfo, &rev);  
     return rev;  
 }  
   
 /* Set the revision for FILE to REV.  */  
   
 void  
 base_register (struct file_info *finfo, char *rev)  
 {  
     base_walk (BASE_REGISTER, finfo, &rev);  
 }  
   
 /* Remove FILE.  */  
   
 void  
 base_deregister (struct file_info *finfo)  
 {  
     base_walk (BASE_DEREGISTER, finfo, NULL);  
 }  

Legend:
Removed from v.1.66  
changed lines
  Added in v.1.66.4.1

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26