cvs-cvs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Cvs-cvs] Changes to ccvs/src/base.c [signed-commits2]


From: Derek Robert Price
Subject: [Cvs-cvs] Changes to ccvs/src/base.c [signed-commits2]
Date: Wed, 09 Nov 2005 23:47:48 -0500

Index: ccvs/src/base.c
diff -u /dev/null ccvs/src/base.c:1.1.2.1
--- /dev/null   Thu Nov 10 04:47:48 2005
+++ ccvs/src/base.c     Thu Nov 10 04:47:44 2005
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2005 The Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Verify interface.  */
+#include "base.h"
+
+/* Standard headers.  */
+#include <assert.h>
+
+/* GNULIB headers.  */
+
+/* CVS headers.  */
+#include "subr.h"
+#include "cvs.h"       /* For CVSADM_BASE. */
+
+
+
+char *
+make_base_file_name (const char *filename, const char *rev)
+{
+    return Xasprintf ("%s/.#%s.%s", CVSADM_BASE, filename, rev);
+}
+
+
+
+/* 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
+};
+
+
+
+/* Read through the lines in CVS/Baserev, taking the actions as documented
+   for CODE.  */
+static void
+base_walk (enum base_walk code, const char *update_dir, const char *file,
+          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 (update_dir[0] != '\0')
+    {
+       baserev_fullname = Xasprintf ("%s/%s", update_dir,
+                                     CVSADM_BASEREV);
+       baserevtmp_fullname = Xasprintf ("%s/%s", update_dir,
+                                        CVSADM_BASEREVTMP);
+    }
+    else
+    {
+       baserev_fullname = xstrdup (CVSADM_BASEREV);
+       baserevtmp_fullname = xstrdup (CVSADM_BASEREVTMP);
+    }
+
+    fp = CVS_FOPEN (CVSADM_BASEREV, "r");
+    if (fp)
+    {
+       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)
+           {
+               error (0, errno, "cannot open %s for writing",
+                      baserevtmp_fullname);
+               goto out;
+           }
+           break;
+       case BASE_GET:
+           *rev = NULL;
+           break;
+    }
+
+    if (fp)
+    {
+       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)
+               /* Syntax error, ignore.  */
+               continue;
+           linerev = p + 1;
+           p = strchr (linerev, '/');
+           if (!p) continue;
+
+           linerev[-1] = '\0';
+           if (fncmp (linefile, 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", file, *rev) < 0)
+           error (0, errno, "error writing %s",
+                  baserevtmp_fullname);
+    }
+
+ out:
+
+    if (line) free (line);
+
+    if (fp)
+    {
+       if (fclose (fp) < 0)
+           error (0, errno, "cannot close %s", baserev_fullname);
+    }
+    if (newf)
+    {
+       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 (const char *update_dir, const char *file)
+{
+    char *rev;
+    base_walk (BASE_GET, update_dir, file, &rev);
+    return rev;
+}
+
+
+
+/* Set the revision for FILE to REV.  */
+void
+base_register (const char *update_dir, const char *file, char *rev)
+{
+    base_walk (BASE_REGISTER, update_dir, file, &rev);
+}
+
+
+
+/* Remove FILE.  */
+void
+base_deregister (const char *update_dir, const char *file)
+{
+    base_walk (BASE_DEREGISTER, update_dir, file, NULL);
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]