cvs-cvs
[Top][All Lists]
Advanced

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

[Cvs-cvs] ccvs/src ChangeLog add.c client.c cvs.h entries...


From: Derek Robert Price
Subject: [Cvs-cvs] ccvs/src ChangeLog add.c client.c cvs.h entries...
Date: Wed, 12 Sep 2007 02:45:24 +0000

CVSROOT:        /cvsroot/cvs
Module name:    ccvs
Changes by:     Derek Robert Price <dprice>     07/09/12 02:45:24

Modified files:
        src            : ChangeLog add.c client.c cvs.h entries.c 
                         entries.h find_names.c ignore.c import.c 
                         recurse.c sanity.sh subr.c subr.h update.c 
                         update.h vers_ts.c 

Log message:
        * add.c, import.c, update.c: Call Entries_Open() & Entries_Close() with
        UPDATE_DIR.
        * client.c, recurse.c: Ditto, and use new Find_Names() and
        Find_Directories() APIs.
        * cvs.h (struct stickydirtag): Move to private entries.c struct.
        (Entries_Open, Entries_Close): Move prototypes to entries.h.
        (Find_Names, Find_Directories): Move prototypes to find-names.h.
        * entries.c: Include GNULIB's "quote.h".
        (struct stickydirtag): Moved in from cvs.h.
        (write_entries): Accept and process DIR and UPDATE_DIR.
        (entriesHasSticky, entriesHasAllSubdirs, entriesGetAflag,
        entriesGetTag, entriesGetNonbranch, entriesGetDate, Entries_Open_Dir,
        Entries_Close_Dir): New functions.
        (Entries_Open): Wrap new Entries_Open_Dir().
        (Entries_Close): Wrap new Entries_Close_Dir().
        * entries.h (Entries_Close, Entries_Open_Dir, Entries_Open,
        entriesHasSticky, entriesHasAllSubdirs, entriesGetAflag,
        entriesGetTag, entriesGetNonbranch, entriesGetDate): New prototypes.
        * find_names.c: Include GNULIB's "quote.h".
        (Find_Names, Find_Directories): Accept and process new UPDATE_DIR
        argument.  Make REPOSITORY arg const.
        (find_dirs): Make DIR arg const. - Move to eliminate prototype.
        * find-names.h: New file.
        * ignore.c, vers_ts.c: Use new entries.c APIs.
        * subr.c (dir_append_dirs, dir_append): New functions.
        * subr.h (dir_append_dirs, dir_append): Prototypes for same.
        * sanity.sh: Update to compensate.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/ChangeLog?cvsroot=cvs&r1=1.3534&r2=1.3535
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/add.c?cvsroot=cvs&r1=1.131&r2=1.132
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/client.c?cvsroot=cvs&r1=1.464&r2=1.465
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/cvs.h?cvsroot=cvs&r1=1.353&r2=1.354
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/entries.c?cvsroot=cvs&r1=1.70&r2=1.71
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/entries.h?cvsroot=cvs&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/find_names.c?cvsroot=cvs&r1=1.46&r2=1.47
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/ignore.c?cvsroot=cvs&r1=1.59&r2=1.60
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/import.c?cvsroot=cvs&r1=1.185&r2=1.186
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/recurse.c?cvsroot=cvs&r1=1.120&r2=1.121
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/sanity.sh?cvsroot=cvs&r1=1.1187&r2=1.1188
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/subr.c?cvsroot=cvs&r1=1.159&r2=1.160
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/subr.h?cvsroot=cvs&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/update.c?cvsroot=cvs&r1=1.271&r2=1.272
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/update.h?cvsroot=cvs&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/ccvs/src/vers_ts.c?cvsroot=cvs&r1=1.69&r2=1.70

Patches:
Index: ChangeLog
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/ChangeLog,v
retrieving revision 1.3534
retrieving revision 1.3535
diff -u -b -r1.3534 -r1.3535
--- ChangeLog   11 Sep 2007 20:56:46 -0000      1.3534
+++ ChangeLog   12 Sep 2007 02:45:21 -0000      1.3535
@@ -1,5 +1,33 @@
 2007-09-11  Derek Price  <address@hidden>
 
+       * add.c, import.c, update.c: Call Entries_Open() & Entries_Close() with
+       UPDATE_DIR.
+       * client.c, recurse.c: Ditto, and use new Find_Names() and
+       Find_Directories() APIs.
+       * cvs.h (struct stickydirtag): Move to private entries.c struct.
+       (Entries_Open, Entries_Close): Move prototypes to entries.h.
+       (Find_Names, Find_Directories): Move prototypes to find-names.h.
+       * entries.c: Include GNULIB's "quote.h".
+       (struct stickydirtag): Moved in from cvs.h.
+       (write_entries): Accept and process DIR and UPDATE_DIR.
+       (entriesHasSticky, entriesHasAllSubdirs, entriesGetAflag,
+       entriesGetTag, entriesGetNonbranch, entriesGetDate, Entries_Open_Dir,
+       Entries_Close_Dir): New functions.
+       (Entries_Open): Wrap new Entries_Open_Dir().
+       (Entries_Close): Wrap new Entries_Close_Dir().
+       * entries.h (Entries_Close, Entries_Open_Dir, Entries_Open,
+       entriesHasSticky, entriesHasAllSubdirs, entriesGetAflag,
+       entriesGetTag, entriesGetNonbranch, entriesGetDate): New prototypes.
+       * find_names.c: Include GNULIB's "quote.h".
+       (Find_Names, Find_Directories): Accept and process new UPDATE_DIR
+       argument.  Make REPOSITORY arg const.
+       (find_dirs): Make DIR arg const. - Move to eliminate prototype.
+       * find-names.h: New file.
+       * ignore.c, vers_ts.c: Use new entries.c APIs.
+       * subr.c (dir_append_dirs, dir_append): New functions.
+       * subr.h (dir_append_dirs, dir_append): Prototypes for same.
+       * sanity.sh: Update to compensate.
+
        * main.c (main): Suppress warnings.
 
 2007-08-29  Derek Price  <address@hidden>

Index: add.c
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/add.c,v
retrieving revision 1.131
retrieving revision 1.132
diff -u -b -r1.131 -r1.132
--- add.c       25 Aug 2007 03:17:57 -0000      1.131
+++ add.c       12 Sep 2007 02:45:21 -0000      1.132
@@ -367,7 +367,7 @@
                       CVSNULLREPOS) == 0)
            error (1, 0, "cannot add to `%s'", repository);
 
-       entries = Entries_Open (0, NULL);
+       entries = Entries_Open (0, finfo.update_dir);
 
        finfo.repository = repository;
        finfo.entries = entries;
@@ -723,7 +723,7 @@
 
 skip_this_file:
        free (repository);
-       Entries_Close (entries);
+       Entries_Close (entries, finfo.update_dir);
 
        if (restore_cwd (&cwd))
            error (1, errno, "Failed to restore current directory, `%s'.",

Index: client.c
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/client.c,v
retrieving revision 1.464
retrieving revision 1.465
diff -u -b -r1.464 -r1.465
--- client.c    27 Aug 2007 02:11:05 -0000      1.464
+++ client.c    12 Sep 2007 02:45:22 -0000      1.465
@@ -36,6 +36,7 @@
 #include "diff.h"
 #include "difflib.h"
 #include "edit.h"
+#include "find-names.h"
 #include "gpg.h"
 #include "ignore.h"
 #include "recurse.h"
@@ -1047,7 +1048,8 @@
 
     if (strcmp (cvs_cmd_name, "export"))
     {
-       last_entries = Entries_Open (0, dir_name);
+       last_entries = Entries_Open (0, strcmp (pathname, "./")
+                                       ? pathname : "");
 
        /* If this is a newly created directory, we will record
           all subdirectory information, so call Subdirs_Known in
@@ -1065,14 +1067,17 @@
        {
            List *dirlist;
 
-           dirlist = Find_Directories (NULL, W_LOCAL, last_entries);
+           dirlist = Find_Directories (NULL,
+                                       strcmp (pathname, "./")
+                                       ? pathname : "",
+                                       W_LOCAL, last_entries);
            dellist (&dirlist);
        }
     }
     free (reposdirname);
     (*func) (data, last_entries, short_pathname, filename);
     if (last_entries)
-       Entries_Close (last_entries);
+       Entries_Close (last_entries, strcmp (pathname, "./") ? pathname : "");
     free (dir_name);
     free (short_pathname);
     free (reposname);
@@ -3219,7 +3224,7 @@
     }
     for (p = prune_candidates; p; )
     {
-       if (isemptydir (p->dir, 1))
+       if (isemptydir ("", p->dir, 1))
        {
            char *b;
 
@@ -5812,6 +5817,7 @@
            size_t line_len = 0;
            char *q, *r;
            struct saved_cwd sdir;
+           char *update_dir;
 
            /* Split the argument onto the stack.  */
            stack = getlist();
@@ -5825,7 +5831,8 @@
 
            /* Normalize the path into outstr. */
            save_cwd (&sdir);
-           while ((q = pop (stack)) != NULL)
+           update_dir = xstrdup ("");
+           while (q = pop (stack))
            {
                Node *node = NULL;
                if (isdir (CVSADM))
@@ -5839,7 +5846,7 @@
                       command line, not the case of the
                       directory in the filesystem.  This
                       is correct behavior.  */
-                   entries = Entries_Open (0, NULL);
+                   entries = Entries_Open (0, update_dir);
                    node = findnode_fn (entries, q);
                    if (node)
                    {
@@ -5849,7 +5856,7 @@
                        xrealloc_and_strcat (&line, &line_len, node->key);
                        delnode (node);
                    }
-                   Entries_Close (entries);
+                   Entries_Close (entries, update_dir);
                }
 
                /* If node is still NULL then we either didn't find CVSADM or
@@ -5866,14 +5873,20 @@
 
                /* And descend the tree. */
                if (isdir (q))
+               {
+                   char *tmp_update_dir = dir_append (update_dir, q);
+                   free (update_dir);
+                   update_dir = tmp_update_dir;
                    CVS_CHDIR (q);
+               }
                free (q);
            }
            restore_cwd (&sdir);
+           free (update_dir);
            free_cwd (&sdir);
 
            /* Now put everything we didn't find entries for back on. */
-           while ((q = pop (stack)) != NULL)
+           while (q = pop (stack))
            {
                if (line_len)
                    xrealloc_and_strcat (&line, &line_len, "/");

Index: cvs.h
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/cvs.h,v
retrieving revision 1.353
retrieving revision 1.354
diff -u -b -r1.353 -r1.354
--- cvs.h       28 Aug 2007 00:15:09 -0000      1.353
+++ cvs.h       12 Sep 2007 02:45:22 -0000      1.354
@@ -93,7 +93,7 @@
 #define CVSADM_BASEREV   "CVS/Baserev."
 #define CVSADM_BASEREVTMP "CVS/Baserev.tmp"
 #define CVSADM_TEMPLATE "CVS/Template."
-#else /* USE_VMS_FILENAMES */
+#else /* !USE_VMS_FILENAMES */
 #define        CVSADM          "CVS"
 #define        CVSADM_ENT      "CVS/Entries"
 #define        CVSADM_ENTBAK   "CVS/Entries.Backup"
@@ -272,24 +272,7 @@
     CHECKOUT, TAG, PATCH, EXPORT, MISC
 };
 
-/*
- * structure used for list-private storage by Entries_Open() and
- * Version_TS() and Find_Directories().
- */
-struct stickydirtag
-{
-    /* These fields pass sticky tag information from Entries_Open() to
-       Version_TS().  */
-    int aflag;
-    char *tag;
-    char *date;
-    int nonbranch;
-
-    /* This field is set by Entries_Open() if there was subdirectory
-       information; Find_Directories() uses it to see whether it needs
-       to scan the directory itself.  */
-    int subdirs;
-};
+
 
 /* Option flags for Parse_Info() */
 #define PIOPT_ALL 1    /* accept "all" keyword */
@@ -381,9 +364,6 @@
 
 
 DBM *open_module (void);
-List *Find_Directories (char *repository, int which, List *entries);
-void Entries_Close (List *entries);
-List *Entries_Open (int aflag, char *update_dir);
 void Subdirs_Known (List *entries);
 void Subdir_Register (List *, const char *, const char *);
 void Subdir_Deregister (List *, const char *, const char *);
@@ -482,8 +462,6 @@
 
 void update_delproc (Node * p);
 void usage (const char *const *cpp);
-List *Find_Names (char *repository, int which, int aflag,
-                 List ** optentries);
 void Update_Logfile (const char *repository, const char *xmessage,
                      FILE *xlogfp, List *xchanges);
 void do_editor (const char *dir, char **messagep,

Index: entries.c
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/entries.c,v
retrieving revision 1.70
retrieving revision 1.71
diff -u -b -r1.70 -r1.71
--- entries.c   27 Aug 2007 02:11:05 -0000      1.70
+++ entries.c   12 Sep 2007 02:45:22 -0000      1.71
@@ -24,6 +24,9 @@
 /* Validate API.  */
 #include "entries.h"
 
+/* GNULIB */
+#include "quote.h"
+
 /* CVS */
 #include "base.h"
 
@@ -44,6 +47,27 @@
 
 
 /*
+ * structure used for list-private storage by Entries_Open() and
+ * Version_TS() and Find_Directories().
+ */
+struct stickydirtag
+{
+    /* These fields pass sticky tag information from Entries_Open() to
+       Version_TS().  */
+    int aflag;
+    char *tag;
+    char *date;
+    int nonbranch;
+
+    /* This field is set by Entries_Open() if there was subdirectory
+       information; Find_Directories() uses it to see whether it needs
+       to scan the directory itself.  */
+    int subdirs;
+};
+
+
+
+/*
  * Construct an Entnode
  */
 static Entnode *
@@ -118,16 +142,25 @@
  * first of course
  */
 static void
-write_entries (List *list)
+write_entries (List *list, const char *update_dir, const char *dir)
 {
     int sawdir;
+    char *update_file;
+    char *bakfilename;
+    char *entfilename;
+
+    assert (update_dir);
+    assert (dir);
+
+    TRACE (TRACE_FUNCTION, "write_entries (%s, %s)", update_dir, dir);
 
     sawdir = 0;
 
     /* open the new one and walk the list writing entries */
-    entfilename = CVSADM_ENTBAK;
-    entfile = CVS_FOPEN (entfilename, "w+");
-    if (entfile == NULL)
+    bakfilename = dir_append (dir, CVSADM_ENTBAK);
+    update_file = dir_append_dirs (update_dir, dir, CVSADM_ENTBAK, NULL);
+    entfile = CVS_FOPEN (bakfilename, "w+");
+    if (!entfile)
     {
        /* Make this a warning, not an error.  For example, one user might
           have checked out a working directory which, for whatever reason,
@@ -136,39 +169,47 @@
           problem rewriting Entries shouldn't affect the ability of "cvs log"
           to work, although the warning is probably a good idea so that
           whether Entries gets rewritten is not an inexplicable process.  */
-       /* FIXME: should be including update_dir in message.  */
-       error (0, errno, "cannot rewrite %s", entfilename);
+       error (0, errno, "cannot rewrite %s", quote (update_file));
 
        /* Now just return.  We leave the Entries.Log file around.  As far
           as I know, there is never any data lying around in 'list' that
           is not in Entries.Log at this time (if there is an error writing
           Entries.Log that is a separate problem).  */
-       return;
+       goto done;
     }
 
-    (void) walklist (list, write_ent_proc, (void *) &sawdir);
-    if (! sawdir)
+    walklist (list, write_ent_proc, &sawdir);
+    if (!sawdir)
     {
-       struct stickydirtag *sdtp;
-
        /* We didn't write out any directories.  Check the list
            private data to see whether subdirectory information is
            known.  If it is, we need to write out an empty D line.  */
-       sdtp = list->list->data;
-       if (sdtp == NULL || sdtp->subdirs)
+       if (entriesHasAllSubdirs (list))
            if (fprintf (entfile, "D\n") < 0)
-               error (1, errno, "cannot write %s", entfilename);
+               error (1, errno, "cannot write %s", quote (update_file));
     }
     if (fclose (entfile) == EOF)
-       error (1, errno, "error closing %s", entfilename);
+       error (1, errno, "error closing %s", quote (update_file));
 
     /* now, atomically (on systems that support it) rename it */
-    rename_file (entfilename, CVSADM_ENT);
+    entfilename = dir_append (dir, CVSADM_ENT);
+    rename_file (bakfilename, entfilename);
+    free (entfilename);
 
+    entfilename = dir_append (dir, CVSADM_ENTLOG);
     /* now, remove the log file */
-    if (unlink_file (CVSADM_ENTLOG) < 0
-       && !existence_error (errno))
-       error (0, errno, "cannot remove %s", CVSADM_ENTLOG);
+    if (unlink_file (entfilename) < 0 && !existence_error (errno))
+    {
+       char *newupdate_file = dir_append_dirs (update_dir, dir, CVSADM_ENTLOG,
+                                               NULL);
+       error (0, errno, "cannot remove %s", quote (newupdate_file));
+       free (newupdate_file);
+    }
+    free (entfilename);
+
+done:
+    free (bakfilename);
+    free (update_file);
 }
 
 
@@ -281,6 +322,106 @@
     free ((char *) sdtp);
 }
 
+
+
+/* Return true iff ENTRIES && SDTP && (SDTP->tag || SDTP->date).
+ */
+bool
+entriesHasSticky (List *entries)
+{
+    struct stickydirtag *sdtp;
+
+    if (!entries) return false;
+
+    assert (entries->list);
+
+    sdtp = entries->list->data;
+    return sdtp && (sdtp->tag || sdtp->date);
+}
+
+
+
+/* When SDTP is NULL, or SDTP->subdirs is nonzero, then all subdirectory
+ * information is recorded in ENTRIES.
+ */
+bool
+entriesHasAllSubdirs (List *entries)
+{
+    struct stickydirtag *sdtp;
+
+    assert (entries);
+    assert (entries->list);
+
+    sdtp = entries->list->data;
+    return !sdtp || sdtp->subdirs;
+}
+
+
+
+/* Returns false if !ENTRIES || !SDTP.  Otherwise, returns SDTP->aflag.
+ */
+bool
+entriesGetAflag (List *entries)
+{
+    struct stickydirtag *sdtp;
+
+    if (!entries) return false;
+
+    assert (entries->list);
+
+    sdtp = entries->list->data;
+    if (!sdtp) return false;
+
+    return sdtp->aflag;
+}
+
+
+
+const char *
+entriesGetTag (List *entries)
+{
+    struct stickydirtag *sdtp;
+
+    assert (entries);
+    assert (entries->list);
+    assert (entries->list->data);
+
+    sdtp = entries->list->data;
+    return sdtp->tag;
+}
+
+
+
+int
+entriesGetNonbranch (List *entries)
+{
+    struct stickydirtag *sdtp;
+
+    assert (entries);
+    assert (entries->list);
+    assert (entries->list->data);
+
+    sdtp = entries->list->data;
+    return sdtp->nonbranch;
+}
+
+
+
+const char *
+entriesGetDate (List *entries)
+{
+    struct stickydirtag *sdtp;
+
+    assert (entries);
+    assert (entries->list);
+    assert (entries->list->data);
+
+    sdtp = entries->list->data;
+    return sdtp->date;
+}
+
+
+
 /* Return the next real Entries line.  On end of file, returns NULL.
    On error, prints an error message and returns NULL.  */
 
@@ -447,13 +588,14 @@
 }
 
 
+
 /* Read the entries file into a list, hashing on the file name.
 
    UPDATE_DIR is the name of the current directory, for use in error
    messages, or NULL if not known (that is, noone has gotten around
    to updating the caller to pass in the information).  */
 List *
-Entries_Open (int aflag, char *update_dir)
+Entries_Open_Dir (int aflag, const char *update_dir_i, const char *dir)
 {
     List *entries;
     struct stickydirtag *sdtp = NULL;
@@ -463,8 +605,13 @@
     int do_rewrite = 0;
     FILE *fpin;
     int sawdir;
+    char *entfile;
+    char *update_dir;
+
+    assert (update_dir_i);
+    assert (dir);
 
-    TRACE (TRACE_FLOW, "EntriesOpen (%s)", update_dir);
+    TRACE (TRACE_FLOW, "Entries_Open_Dir (%s, %s)", update_dir, dir);
 
     /* get a fresh list... */
     entries = getlist ();
@@ -476,8 +623,7 @@
     ParseTag (&dirtag, &dirdate, &dirnonbranch);
     if (aflag || dirtag || dirdate)
     {
-       sdtp = xmalloc (sizeof (*sdtp));
-       memset (sdtp, 0, sizeof (*sdtp));
+       sdtp = xzalloc (sizeof (*sdtp));
        sdtp->aflag = aflag;
        sdtp->tag = xstrdup (dirtag);
        sdtp->date = xstrdup (dirdate);
@@ -490,27 +636,33 @@
 
     sawdir = 0;
 
-    fpin = CVS_FOPEN (CVSADM_ENT, "r");
-    if (fpin == NULL)
-    {
-       if (update_dir != NULL)
-           error (0, 0, "in directory %s:", update_dir);
-       error (0, errno, "cannot open %s for reading", CVSADM_ENT);
-    }
-    else
+    update_dir = dir_append (update_dir_i, dir);
+    entfile = dir_append (dir, CVSADM_ENT);
+    fpin = CVS_FOPEN (entfile, "r");
+    if (fpin)
     {
-       while ((ent = fgetentent (fpin, NULL, &sawdir)) != NULL) 
-       {
-           (void) AddEntryNode (entries, ent);
-       }
+       while (ent = fgetentent (fpin, NULL, &sawdir)) 
+           AddEntryNode (entries, ent);
 
        if (fclose (fpin) < 0)
+       {
            /* FIXME-update-dir: should include update_dir in message.  */
-           error (0, errno, "cannot close %s", CVSADM_ENT);
+           char *update_file = dir_append (update_dir, CVSADM_ENT);
+           error (0, errno, "cannot close %s", quote (update_file));
+           free (update_file);
     }
-
-    fpin = CVS_FOPEN (CVSADM_ENTLOG, "r");
-    if (fpin != NULL) 
+    }
+    else
+    {
+       char *update_file = dir_append (update_dir, CVSADM_ENT);
+       error (0, errno, "cannot open %s for reading", quote (update_file));
+       free (update_file);
+    }
+    free (entfile);
+
+    entfile = dir_append (dir, CVSADM_ENTLOG);
+    fpin = CVS_FOPEN (entfile, "r");
+    if (fpin) 
     {
        char cmd;
        Node *node;
@@ -524,8 +676,7 @@
                break;
            case 'R':
                node = findnode_fn (entries, ent->user);
-               if (node != NULL)
-                   delnode (node);
+               if (node) delnode (node);
                Entnode_Destroy (ent);
                break;
            default:
@@ -536,28 +687,32 @@
        }
        do_rewrite = 1;
        if (fclose (fpin) < 0)
-           /* FIXME-update-dir: should include update_dir in message.  */
-           error (0, errno, "cannot close %s", CVSADM_ENTLOG);
+       {
+           char *update_file = dir_append (update_dir, CVSADM_ENTLOG);
+           error (0, errno, "cannot close %s", quote (update_file));
+           free (update_file);
+       }
     }
+    free (entfile);
 
     /* Update the list private data to indicate whether subdirectory
        information is known.  Nonexistent list private data is taken
        to mean that it is known.  */
-    if (sdtp != NULL)
+    if (sdtp)
        sdtp->subdirs = sawdir;
-    else if (! sawdir)
+    else if (!sawdir)
     {
-       sdtp = xmalloc (sizeof (*sdtp));
-       memset (sdtp, 0, sizeof (*sdtp));
+       sdtp = xzalloc (sizeof (*sdtp));
        sdtp->subdirs = 0;
        entries->list->data = sdtp;
        entries->list->delproc = freesdt;
     }
 
     if (do_rewrite && !noexec)
-       write_entries (entries);
+       write_entries (entries, update_dir_i, dir);
 
     /* clean up and return */
+    free (update_dir);
     if (dirtag)
        free (dirtag);
     if (dirdate)
@@ -565,21 +720,45 @@
     return entries;
 }
 
+
+
+List *
+Entries_Open (int aflag, const char *update_dir)
+{
+    return Entries_Open_Dir (aflag, update_dir, ".");
+}
+
+
+
 void
-Entries_Close (List *list)
+Entries_Close_Dir (List *list, const char *update_dir, const char *dir)
 {
+    assert (dir);
+    assert (update_dir);
+
     if (list)
     {
        if (!noexec) 
         {
-            if (isfile (CVSADM_ENTLOG))
-               write_entries (list);
+           char *entfile = dir_append (dir, CVSADM_ENTLOG);
+           if (isfile (entfile))
+               write_entries (list, update_dir, dir);
+           free (entfile);
        }
        dellist (&list);
     }
 }
 
 
+
+void
+Entries_Close (List *list, const char *update_dir)
+{
+    Entries_Close_Dir (list, update_dir, ".");
+}
+
+
+
 /*
  * Free up the memory associated with the data section of an ENTRIES type
  * node

Index: entries.h
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/entries.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- entries.h   24 Apr 2006 18:50:26 -0000      1.2
+++ entries.h   12 Sep 2007 02:45:22 -0000      1.3
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 The Free Software Foundation, Inc.
+ * Copyright (C) 2005-2007 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
@@ -19,6 +19,10 @@
 #ifndef ENTRIES_H
 #define ENTRIES_H
 
+/* ANSI C */
+#include <stdbool.h>
+
+/* CVS */
 #include "hash.h"
 
 /* The type of an entnode.  */
@@ -46,7 +50,19 @@
 };
 typedef struct entnode Entnode;
 
+void Entries_Close (List *entries, const char *update_dir);
+List *Entries_Open_Dir (int aflag, const char *update_dir, const char *dir);
+List *Entries_Open (int aflag, const char *update_dir);
+
 void Register (List *list, const char *fname, const char *vn,
               const char *ts, const char *options, const char *tag,
               const char *date, const char *ts_conflict);
+
+bool entriesHasSticky (List *entries);
+bool entriesHasAllSubdirs (List *entries);
+bool entriesGetAflag (List *entries);
+const char *entriesGetTag (List *entries);
+int entriesGetNonbranch (List *entries);
+const char *entriesGetDate (List *entries);
+
 #endif /* !defined ENTRIES_H */

Index: find_names.c
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/find_names.c,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -b -r1.46 -r1.47
--- find_names.c        29 Aug 2007 00:27:45 -0000      1.46
+++ find_names.c        12 Sep 2007 02:45:22 -0000      1.47
@@ -1,7 +1,8 @@
 /*
- * Copyright (C) 1986-2006 The Free Software Foundation, Inc.
+ * Copyright (C) 1986-2007 The Free Software Foundation, Inc.
  *
- * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
+ * Portions Copyright (C) 1998-2007 Derek Price,
+ *                                  Ximbiot LLC <http://ximbiot.com>,
  *                                  and others.
  *
  * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
@@ -25,19 +26,23 @@
 # include <config.h>
 #endif
 
-/* ANSI C headers.  */
+/* Verify Interface.  */
+#include "find-names.h"
+
+/* ANSI C */
 #include <assert.h>
 #include <glob.h>
 
-/* CVS headers.  */
+/* GNULIB */
+#include "quote.h"
+
+/* CVS */
 #include "recurse.h"
 
 #include "cvs.h"
 
 
 
-static int find_dirs (char *dir, List * list, int checkadm,
-                           List *entries);
 static int find_rcs (const char *dir, List * list);
 static int add_subdir_proc (Node *, void *);
 static int register_subdir_proc (Node *, void *);
@@ -70,7 +75,8 @@
    list).  */
 
 List *
-Find_Names (char *repository, int which, int aflag, List **optentries)
+Find_Names (const char *repository, const char *update_dir,
+           int which, int aflag, List **optentries)
 {
     List *entries;
     List *files;
@@ -82,17 +88,17 @@
     if (which & W_LOCAL)
     {
        /* parse the entries file (if it exists) */
-       entries = Entries_Open (aflag, NULL);
-       if (entries != NULL)
+       entries = Entries_Open (aflag, update_dir);
+       if (entries)
        {
            /* walk the entries file adding elements to the files list */
-           (void) walklist (entries, add_entries_proc, files);
+           walklist (entries, add_entries_proc, files);
 
            /* if our caller wanted the entries list, return it; else free it */
            if (optentries != NULL)
                *optentries = entries;
            else
-               Entries_Close (entries);
+               Entries_Close (entries, update_dir);
        }
     }
 
@@ -165,11 +171,125 @@
     return 0;
 }
 
+
+
+/*
+ * Finds all the subdirectories of the argument dir and adds them to
+ * the specified list.  Sub-directories without a CVS administration
+ * directory are optionally ignored.  If ENTRIES is not NULL, all
+ * files on the list are ignored.  Returns 0 for success or 1 on
+ * error, in which case errno is set to indicate the error.
+ */
+static int
+find_dirs (const char *dir, List *list, int checkadm, List *entries)
+{
+    Node *p;
+    char *tmp = NULL;
+    size_t tmp_size = 0;
+    struct dirent *dp;
+    DIR *dirp;
+    int skip_emptydir = 0;
+
+    /* First figure out whether we need to skip directories named
+       Emptydir.  Except in the CVSNULLREPOS case, Emptydir is just
+       a normal directory name.  */
+    if (ISABSOLUTE (dir)
+       && strncmp (dir, current_parsed_root->directory, strlen 
(current_parsed_root->directory)) == 0
+       && ISSLASH (dir[strlen (current_parsed_root->directory)])
+       && strcmp (dir + strlen (current_parsed_root->directory) + 1, 
CVSROOTADM) == 0)
+       skip_emptydir = 1;
+
+    /* set up to read the dir */
+    if ((dirp = CVS_OPENDIR (dir)) == NULL)
+       return (1);
+
+    /* read the dir, grabbing sub-dirs */
+    errno = 0;
+    while ((dp = CVS_READDIR (dirp)) != NULL)
+    {
+       if (strcmp (dp->d_name, ".") == 0 ||
+           strcmp (dp->d_name, "..") == 0 ||
+           strcmp (dp->d_name, CVSATTIC) == 0 ||
+           strcmp (dp->d_name, CVSLCK) == 0 ||
+           strcmp (dp->d_name, CVSREP) == 0)
+           goto do_it_again;
+
+       /* findnode() is going to be significantly faster than stat()
+          because it involves no system calls.  That is why we bother
+          with the entries argument, and why we check this first.  */
+       if (entries != NULL && findnode (entries, dp->d_name) != NULL)
+           goto do_it_again;
+
+       if (skip_emptydir
+           && strcmp (dp->d_name, CVSNULLREPOS) == 0)
+           goto do_it_again;
+
+       if (!DIRENT_MIGHT_BE_DIR(dp))
+           goto do_it_again;
+
+       /* don't bother stating ,v files */
+       if (CVS_FNMATCH (RCSPAT, dp->d_name, 0) == 0)
+           goto do_it_again;
+
+       if (!DIRENT_MUST_BE(dp, DT_DIR))
+       {
+           expand_string (&tmp,
+                          &tmp_size,
+                          strlen (dir) + strlen (dp->d_name) + 10);
+           sprintf (tmp, "%s/%s", dir, dp->d_name);
+           if (!isdir (tmp))
+               goto do_it_again;
+       }
+
+       /* check for administration directories (if needed) */
+       if (checkadm)
+       {
+           /* blow off symbolic links to dirs in local dir */
+           if (DIRENT_MUST_BE(dp, DT_LNK)
+               || DIRENT_MIGHT_BE_SYMLINK(dp) && islink(tmp))
+               goto do_it_again;
+
+           /* check for new style */
+           expand_string (&tmp,
+                          &tmp_size,
+                          (strlen (dir) + strlen (dp->d_name)
+                           + sizeof (CVSADM) + 10));
+           (void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, CVSADM);
+           if (!isdir (tmp))
+               goto do_it_again;
+       }
+
+       /* put it in the list */
+       p = getnode ();
+       p->type = DIRS;
+       p->key = xstrdup (dp->d_name);
+       if (addnode (list, p) != 0)
+           freenode (p);
+
+    do_it_again:
+       errno = 0;
+    }
+    if (errno != 0)
+    {
+       int save_errno = errno;
+       (void) CVS_CLOSEDIR (dirp);
+       errno = save_errno;
+       return 1;
+    }
+    (void) CVS_CLOSEDIR (dirp);
+    if (tmp != NULL)
+       free (tmp);
+    return (0);
+}
+
+
+
 /*
  * create a list of directories to traverse from the current directory
  */
 List *
-Find_Directories (char *repository, int which, List *entries)
+Find_Directories (const char *repository, const char *update_dir,
+                 int which, List *entries)
 {
     List *dirlist;
 
@@ -180,25 +300,21 @@
     if (which & W_LOCAL)
     {
        List *tmpentries;
-       struct stickydirtag *sdtp;
 
        /* Look through the Entries file.  */
 
-       if (entries != NULL)
+       if (entries)
            tmpentries = entries;
        else if (isfile (CVSADM_ENT))
-           tmpentries = Entries_Open (0, NULL);
+           tmpentries = Entries_Open (0, update_dir);
        else
            tmpentries = NULL;
 
-       if (tmpentries != NULL)
-           sdtp = tmpentries->list->data;
-
        /* If we do have an entries list, then if sdtp is NULL, or if
            sdtp->subdirs is nonzero, all subdirectory information is
            recorded in the entries list.  */
-       if (tmpentries != NULL && (sdtp == NULL || sdtp->subdirs))
-           walklist (tmpentries, add_subdir_proc, (void *) dirlist);
+       if (tmpentries && entriesHasAllSubdirs (tmpentries))
+           walklist (tmpentries, add_subdir_proc, dirlist);
        else
        {
            /* This is an old working directory, in which subdirectory
@@ -215,23 +331,22 @@
               hacking on the CVS/Entries file).  */
 
            if (find_dirs (".", dirlist, 1, tmpentries) != 0)
-               error (1, errno, "cannot open current directory");
-           if (tmpentries != NULL)
+               error (1, errno, "cannot open %s", quote (update_dir));
+           if (tmpentries)
            {
-               if (! list_isempty (dirlist))
-                   walklist (dirlist, register_subdir_proc,
-                             (void *) tmpentries);
+               if (!list_isempty (dirlist))
+                   walklist (dirlist, register_subdir_proc, tmpentries);
                else
                    Subdirs_Known (tmpentries);
            }
        }
 
-       if (entries == NULL && tmpentries != NULL)
-           Entries_Close (tmpentries);
+       if (!entries && tmpentries)
+           Entries_Close (tmpentries, update_dir);
     }
 
     /* look for sub-dirs in the repository */
-    if ((which & W_REPOS) && repository)
+    if (which & W_REPOS && repository)
     {
        /* search the repository */
        if (find_dirs (repository, dirlist, 0, entries) != 0)
@@ -246,7 +361,7 @@
 
     /* sort the list into alphabetical order and return it */
     sortlist (dirlist, fsortcmp);
-    return (dirlist);
+    return dirlist;
 }
 
 
@@ -418,114 +533,3 @@
     mergelists (list, &newlist);
     return 0;
 }
-
-
-
-/*
- * Finds all the subdirectories of the argument dir and adds them to
- * the specified list.  Sub-directories without a CVS administration
- * directory are optionally ignored.  If ENTRIES is not NULL, all
- * files on the list are ignored.  Returns 0 for success or 1 on
- * error, in which case errno is set to indicate the error.
- */
-static int
-find_dirs (char *dir, List *list, int checkadm, List *entries)
-{
-    Node *p;
-    char *tmp = NULL;
-    size_t tmp_size = 0;
-    struct dirent *dp;
-    DIR *dirp;
-    int skip_emptydir = 0;
-
-    /* First figure out whether we need to skip directories named
-       Emptydir.  Except in the CVSNULLREPOS case, Emptydir is just
-       a normal directory name.  */
-    if (ISABSOLUTE (dir)
-       && strncmp (dir, current_parsed_root->directory, strlen 
(current_parsed_root->directory)) == 0
-       && ISSLASH (dir[strlen (current_parsed_root->directory)])
-       && strcmp (dir + strlen (current_parsed_root->directory) + 1, 
CVSROOTADM) == 0)
-       skip_emptydir = 1;
-
-    /* set up to read the dir */
-    if ((dirp = CVS_OPENDIR (dir)) == NULL)
-       return (1);
-
-    /* read the dir, grabbing sub-dirs */
-    errno = 0;
-    while ((dp = CVS_READDIR (dirp)) != NULL)
-    {
-       if (strcmp (dp->d_name, ".") == 0 ||
-           strcmp (dp->d_name, "..") == 0 ||
-           strcmp (dp->d_name, CVSATTIC) == 0 ||
-           strcmp (dp->d_name, CVSLCK) == 0 ||
-           strcmp (dp->d_name, CVSREP) == 0)
-           goto do_it_again;
-
-       /* findnode() is going to be significantly faster than stat()
-          because it involves no system calls.  That is why we bother
-          with the entries argument, and why we check this first.  */
-       if (entries != NULL && findnode (entries, dp->d_name) != NULL)
-           goto do_it_again;
-
-       if (skip_emptydir
-           && strcmp (dp->d_name, CVSNULLREPOS) == 0)
-           goto do_it_again;
-
-       if (!DIRENT_MIGHT_BE_DIR(dp))
-           goto do_it_again;
-
-       /* don't bother stating ,v files */
-       if (CVS_FNMATCH (RCSPAT, dp->d_name, 0) == 0)
-           goto do_it_again;
-
-       if (!DIRENT_MUST_BE(dp, DT_DIR))
-       {
-           expand_string (&tmp,
-                          &tmp_size,
-                          strlen (dir) + strlen (dp->d_name) + 10);
-           sprintf (tmp, "%s/%s", dir, dp->d_name);
-           if (!isdir (tmp))
-               goto do_it_again;
-       }
-
-       /* check for administration directories (if needed) */
-       if (checkadm)
-       {
-           /* blow off symbolic links to dirs in local dir */
-           if (DIRENT_MUST_BE(dp, DT_LNK)
-               || DIRENT_MIGHT_BE_SYMLINK(dp) && islink(tmp))
-               goto do_it_again;
-
-           /* check for new style */
-           expand_string (&tmp,
-                          &tmp_size,
-                          (strlen (dir) + strlen (dp->d_name)
-                           + sizeof (CVSADM) + 10));
-           (void) sprintf (tmp, "%s/%s/%s", dir, dp->d_name, CVSADM);
-           if (!isdir (tmp))
-               goto do_it_again;
-       }
-
-       /* put it in the list */
-       p = getnode ();
-       p->type = DIRS;
-       p->key = xstrdup (dp->d_name);
-       if (addnode (list, p) != 0)
-           freenode (p);
-
-    do_it_again:
-       errno = 0;
-    }
-    if (errno != 0)
-    {
-       int save_errno = errno;
-       (void) CVS_CLOSEDIR (dirp);
-       errno = save_errno;
-       return 1;
-    }
-    (void) CVS_CLOSEDIR (dirp);
-    if (tmp != NULL)
-       free (tmp);
-    return (0);
-}

Index: ignore.c
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/ignore.c,v
retrieving revision 1.59
retrieving revision 1.60
diff -u -b -r1.59 -r1.60
--- ignore.c    29 Aug 2007 00:27:45 -0000      1.59
+++ ignore.c    12 Sep 2007 02:45:22 -0000      1.60
@@ -23,10 +23,11 @@
 /* Verify interface.  */
 #include "ignore.h"
 
-/* GNULIB headers.  */
+/* GNULIB */
 #include "lstat.h"
+#include "quote.h"
 
-/* CVS headers.  */
+/* CVS */
 #include "wrapper.h"
 
 #include "cvs.h"
@@ -372,7 +373,7 @@
 ignore_files (List *ilist, List *entries, const char *update_dir,
               Ignore_proc proc)
 {
-    int subdirs;
+    bool subdirs;
     DIR *dirp;
     struct dirent *dp;
     struct stat sb;
@@ -382,14 +383,10 @@
     Node *p;
 
     /* Set SUBDIRS if we have subdirectory information in ENTRIES.  */
-    if (entries == NULL)
-       subdirs = 0;
+    if (!entries)
+       subdirs = false;
     else
-    {
-       struct stickydirtag *sdtp = entries->list->data;
-
-       subdirs = sdtp == NULL || sdtp->subdirs;
-    }
+       subdirs = entriesHasAllSubdirs (entries);
 
     /* we get called with update_dir set to "." sometimes... strip it */
     if (strcmp (update_dir, ".") == 0)
@@ -398,9 +395,9 @@
        xdir = update_dir;
 
     dirp = CVS_OPENDIR (".");
-    if (dirp == NULL)
+    if (!dirp)
     {
-       error (0, errno, "cannot open current directory");
+       error (0, errno, "cannot open %s", quote (update_dir));
        return;
     }
 
@@ -410,20 +407,19 @@
     /* Make a list for the files.  */
     files = getlist ();
 
-    while (errno = 0, (dp = CVS_READDIR (dirp)) != NULL)
+    while (errno = 0, dp = CVS_READDIR (dirp))
     {
        file = dp->d_name;
-       if (strcmp (file, ".") == 0 || strcmp (file, "..") == 0)
+       if (!strcmp (file, ".") || !strcmp (file, ".."))
            continue;
-       if (findnode_fn (ilist, file) != NULL)
+       if (findnode_fn (ilist, file))
            continue;
        if (subdirs)
        {
            Node *node;
 
            node = findnode_fn (entries, file);
-           if (node != NULL
-               && ((Entnode *) node->data)->type == ENT_SUBDIR)
+           if (node && ((Entnode *) node->data)->type == ENT_SUBDIR)
            {
                char *p;
                int dir;
@@ -432,7 +428,7 @@
                   this directory if there is a CVS subdirectory.
                   This will normally be the case, but the user may
                   have messed up the working directory somehow.  */
-               p = Xasprintf ("%s/%s", file, CVSADM);
+               p = dir_append (file, CVSADM);
                dir = isdir (p);
                free (p);
                if (dir)
@@ -445,19 +441,19 @@
        if (ign_name (file))
            continue;
 
-       if (!DIRENT_MUST_BE(dp, DT_UNKNOWN)
+       if (!DIRENT_MUST_BE (dp, DT_UNKNOWN)
            || lstat (file, &sb) != -1)
        {
-           if (DIRENT_MUST_BE(dp, DT_LNK)
+           if (DIRENT_MUST_BE (dp, DT_LNK)
                || DIRENT_MIGHT_BE_SYMLINK(dp) && S_ISLNK(sb.st_mode))
                /* Skip symlinks.  */
                continue;
-           else if (DIRENT_MUST_BE(dp, DT_DIR)
-                    || DIRENT_MIGHT_BE_DIR(dp) && S_ISDIR (sb.st_mode))
+           else if (DIRENT_MUST_BE (dp, DT_DIR)
+                    || DIRENT_MIGHT_BE_DIR (dp) && S_ISDIR (sb.st_mode))
            {
                if (!subdirs)
                {
-                   char *temp = Xasprintf ("%s/%s", file, CVSADM);
+                   char *temp = dir_append (file, CVSADM);
                    if (isdir (temp))
                    {
                        free (temp);
@@ -471,11 +467,11 @@
        p = getnode ();
        p->type = FILES;
        p->key = xstrdup (file);
-       (void) addnode (files, p);
+       addnode (files, p);
     }
-    if (errno != 0)
+    if (errno)
        error (0, errno, "error reading current directory");
-    (void) CVS_CLOSEDIR (dirp);
+    CVS_CLOSEDIR (dirp);
 
     sortlist (files, fsortcmp);
     for (p = files->list->next; p != files->list; p = p->next)

Index: import.c
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/import.c,v
retrieving revision 1.185
retrieving revision 1.186
diff -u -b -r1.185 -r1.186
--- import.c    29 Aug 2007 00:27:45 -0000      1.185
+++ import.c    12 Sep 2007 02:45:22 -0000      1.186
@@ -640,7 +640,7 @@
                /* Reading all the entries for each file is fairly silly, and
                   probably slow.  But I am too lazy at the moment to do
                   anything else.  */
-               entries = Entries_Open (0, NULL);
+               entries = Entries_Open (0, repository);
                node = findnode_fn (entries, vfile);
                if (node != NULL)
                {
@@ -654,7 +654,7 @@
                        free_opt = our_opt;
                    }
                }
-               Entries_Close (entries);
+               Entries_Close (entries, repository);
            }
 #endif
 

Index: recurse.c
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/recurse.c,v
retrieving revision 1.120
retrieving revision 1.121
diff -u -b -r1.120 -r1.121
--- recurse.c   29 Aug 2007 23:36:23 -0000      1.120
+++ recurse.c   12 Sep 2007 02:45:22 -0000      1.121
@@ -26,6 +26,7 @@
 
 /* CVS headers.  */
 #include "edit.h"
+#include "find-names.h"
 #include "fileattr.h"
 #include "repos.h"
 #include "wrapper.h"
@@ -322,7 +323,7 @@
         */
        if (just_subdirs)
        {
-           dirlist = Find_Directories (NULL, W_LOCAL, NULL);
+           dirlist = Find_Directories (NULL, update_dir, W_LOCAL, NULL);
            /* If there are no sub-directories, there is a certain logic in
               favor of doing nothing, but in fact probably the user is just
               confused about what directory they are in, or whether they
@@ -353,6 +354,7 @@
                    FIXME: perhaps it would be better to write a
                    function that duplicates a list. */
                args_to_send_when_finished = Find_Directories (NULL,
+                                                              update_dir,
                                                               W_LOCAL,
                                                               NULL);
            }
@@ -802,8 +804,8 @@
            /* find the files and fill in entries if appropriate */
            if (process_this_directory)
            {
-               filelist = Find_Names (repository, lwhich, frame->aflag,
-                                      &entries);
+               filelist = Find_Names (repository, update_dir, lwhich,
+                                      frame->aflag, &entries);
                if (filelist == NULL)
                {
                    error (0, 0, "skipping directory %s", update_dir);
@@ -819,7 +821,7 @@
        if (frame->flags != R_SKIP_DIRS)
            dirlist = Find_Directories (
                process_this_directory ? repository : NULL,
-               frame->which, entries);
+               update_dir, frame->which, entries);
     }
     else
     {
@@ -828,7 +830,7 @@
        {
            /* we will process files, so pre-parse entries */
            if (frame->which & W_LOCAL)
-               entries = Entries_Open (frame->aflag, NULL);
+               entries = Entries_Open (frame->aflag, update_dir);
        }
     }
 
@@ -908,7 +910,7 @@
 
     if (entries)
     {
-       Entries_Close (entries);
+       Entries_Close (entries, update_dir);
        entries = NULL;
     }
 

Index: sanity.sh
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/sanity.sh,v
retrieving revision 1.1187
retrieving revision 1.1188
diff -u -b -r1.1187 -r1.1188
--- sanity.sh   28 Aug 2007 17:33:14 -0000      1.1187
+++ sanity.sh   12 Sep 2007 02:45:22 -0000      1.1188
@@ -16359,8 +16359,7 @@
 "$SPROG checkout: cannot make directory \`CVS': Permission denied
 $SPROG checkout: Updating top-dir" \
 "$SPROG checkout: cannot make directory \`CVS': Permission denied
-$SPROG checkout: in directory \.:
-$SPROG checkout: cannot open CVS/Entries for reading: No such file or directory
+$SPROG checkout: cannot open \`CVS/Entries' for reading: No such file or 
directory
 $SPROG checkout: Updating top-dir"
 
          chmod +w ../1
@@ -17183,11 +17182,10 @@
          # is not nice; would be good to fix remote CVS to give a clearer
          # message (e.g. the one from local CVS).  But at least it is an
          # error message.
-         dotest_fail errmsg2-16 "${testcvs} add bogus-dir/file16" \
-"${SPROG} add: in directory \`bogus-dir':
-${SPROG} \[add aborted\]: there is no version here; do .${SPROG} checkout. 
first" \
-"${CPROG} add: cannot open CVS/Entries for reading: No such file or directory
-${CPROG} \[add aborted\]: no repository"
+         dotest_fail errmsg2-16 "$testcvs add bogus-dir/file16" \
+"$SPROG \[add aborted\]: there is no version here; do \`$SPROG checkout' 
first" \
+"$CPROG add: cannot open \`bogus-dir/CVS/Entries' for reading: No such file or 
directory
+$CPROG \[add aborted\]: no repository"
          rm -r bogus-dir
 
          # One error condition we don't test for is trying to add a file

Index: subr.c
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/subr.c,v
retrieving revision 1.159
retrieving revision 1.160
diff -u -b -r1.159 -r1.160
--- subr.c      27 Aug 2007 02:11:06 -0000      1.159
+++ subr.c      12 Sep 2007 02:45:23 -0000      1.160
@@ -21,15 +21,16 @@
 /* Verify interface.  */
 #include "subr.h"
 
-/* ANSI headers.  */
+/* ANSI */
 #ifdef HAVE_CVS_ADMIN_GROUP
 # include <grp.h>
 #endif
 #include <sys/time.h>
 
-/* GNULIB headers.  */
+/* GNULIB */
 #include "canonicalize.h"
 #include "canon-host.h"
+#include "filenamecat.h"
 #include "mkdir-p.h"
 #include "mreadlink.h"
 #include "savewd.h"
@@ -2381,3 +2382,75 @@
 {
     return cvs_mkdirs_i (name, mode, update_dir, flags | MD_FATAL);
 }
+
+
+
+/* Append BASE to DIR and return it in allocated memory.  This is slightly more
+ * sophisticated than file_name_concat because it is smart enough to ignore
+ * both DIR and BASE when they are both empty and to ignore BASE when it is "."
+ * and return the original DIR or BASE as needed.
+ *
+ * EXAMPLES
+ *    dir_append ("dir", ".", &allocated)      returns the original pointer to
+ *                                             "dir"
+ *    dir_append ("dir", "", &allocated)       returns the original pointer to
+ *                                             "dir"
+ *    dir_append ("", ".", &allocated)         returns the original pointer to
+ *                                             ""
+ *    dir_append (".", "", &allocated)         returns the original pointer to
+ *                                             "."
+ *    dir_append (".", ".", &allocated)                returns the original 
pointer to
+ *                                             the first "."
+ *    dir_append ("", "dir", &allocated)       returns the original pointer to
+ *                                             "dir"
+ *    dir_append (".", "dir", &allocated)      returns "./dir" in allocated
+ *                                             memory and sets *allocated to
+ *                                             point to it as well.
+ *    dir_append ("dir", "sdir", &allocated)   returns "dir/sdir" in allocated
+ *                                             memory and sets *allocated to
+ *                                             point to it as well.
+ */
+char *
+dir_append_dirs (const char *dir, ...)
+{
+    const char *append;
+    va_list args;
+    char *retval;
+
+    va_start (args, dir);
+
+    retval = xstrdup (dir);
+    while (append = va_arg (args, const char *))
+    {
+       char *new;
+
+       TRACE (TRACE_DATA, "dir_append (%s, %s)", dir, append);
+
+       if (!strlen (append) || !strcmp (append, "."))
+           continue;
+
+       if (!strlen (retval))
+       {
+           free (retval);
+           retval = xstrdup (append);
+           continue;
+       }
+
+       /* base = clean_path_prefix (base); */
+       new = file_name_concat (retval, append, NULL);
+       free (retval);
+       retval = new;
+    }
+
+    va_end (args);
+
+    return retval;
+}
+
+
+
+char *
+dir_append (const char *dir, const char *base)
+{
+    return dir_append_dirs (dir, base, NULL);
+}

Index: subr.h
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/subr.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- subr.h      25 Aug 2007 03:17:59 -0000      1.13
+++ subr.h      12 Sep 2007 02:45:23 -0000      1.14
@@ -130,4 +130,7 @@
                 unsigned int flags);
 bool cvs_xmkdirs (const char *name, mode_t mode, const char *update_dir,
                  unsigned int flags);
+
+char *dir_append (const char *dir, const char *append);
+char *dir_append_dirs (const char *dir, ...);
 #endif /* !SUBR_H */

Index: update.c
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/update.c,v
retrieving revision 1.271
retrieving revision 1.272
diff -u -b -r1.271 -r1.272
--- update.c    29 Aug 2007 17:29:37 -0000      1.271
+++ update.c    12 Sep 2007 02:45:23 -0000      1.272
@@ -1072,7 +1072,7 @@
        /* FIXME: chdir ("..") loses with symlinks.  */
        /* Prune empty dirs on the way out - if necessary */
        (void) CVS_CHDIR ("..");
-       if (update_prune_dirs && isemptydir (dir, 0))
+       if (update_prune_dirs && isemptydir (update_dir, dir, 0))
        {
            /* I'm not sure the existence_error is actually possible (except
               in cases where we really should print a message), but since
@@ -1105,20 +1105,21 @@
    existence of the CVS directory entry.  Zero otherwise.  If MIGHT_NOT_EXIST
    and the directory doesn't exist, then just return 0.  */
 int
-isemptydir (const char *dir, int might_not_exist)
+isemptydir (const char *update_dir, const char *dir, int might_not_exist)
 {
     DIR *dirp;
     struct dirent *dp;
 
-    if ((dirp = CVS_OPENDIR (dir)) == NULL)
+    if (!(dirp = CVS_OPENDIR (dir)))
     {
        if (might_not_exist && existence_error (errno))
            return 0;
-       error (0, errno, "cannot open directory %s for empty check", dir);
+       error (0, errno, "cannot open directory %s for empty check",
+              quote (update_dir));
        return 0;
     }
     errno = 0;
-    while ((dp = CVS_READDIR (dirp)) != NULL)
+    while (dp = CVS_READDIR (dirp))
     {
        if (strcmp (dp->d_name, ".") != 0
            && strcmp (dp->d_name, "..") != 0)
@@ -1127,7 +1128,7 @@
            {
                /* An entry other than the CVS directory.  The directory
                   is certainly not empty. */
-               (void) CVS_CLOSEDIR (dirp);
+               CVS_CLOSEDIR (dirp);
                return 0;
            }
            else
@@ -1146,9 +1147,9 @@
 
                if (CVS_CHDIR (dir) < 0)
                    error (1, errno, "cannot change directory to %s", dir);
-               l = Entries_Open (0, NULL);
+               l = Entries_Open (0, update_dir);
                files_removed = walklist (l, isremoved, 0);
-               Entries_Close (l);
+               Entries_Close (l, update_dir);
 
                if (restore_cwd (&cwd))
                    error (1, errno,
@@ -1160,20 +1161,20 @@
                {
                    /* There are files that have been removed, but not
                       committed!  Do not consider the directory empty. */
-                   (void) CVS_CLOSEDIR (dirp);
+                   CVS_CLOSEDIR (dirp);
                    return 0;
                }
            }
        }
        errno = 0;
     }
-    if (errno != 0)
+    if (errno)
     {
-       error (0, errno, "cannot read directory %s", dir);
-       (void) CVS_CLOSEDIR (dirp);
+       error (0, errno, "cannot read directory %s", quote (update_dir));
+       CVS_CLOSEDIR (dirp);
        return 0;
     }
-    (void) CVS_CLOSEDIR (dirp);
+    CVS_CLOSEDIR (dirp);
     return 1;
 }
 

Index: update.h
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/update.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- update.h    23 Feb 2005 19:59:49 -0000      1.11
+++ update.h    12 Sep 2007 02:45:23 -0000      1.12
@@ -18,4 +18,5 @@
               char *preload_update_dir, int xdotemplate,
               char *repository);
 int joining (void);
-extern int isemptydir (const char *dir, int might_not_exist);
+extern int isemptydir (const char *update_dir, const char *dir,
+                      int might_not_exist);

Index: vers_ts.c
===================================================================
RCS file: /cvsroot/cvs/ccvs/src/vers_ts.c,v
retrieving revision 1.69
retrieving revision 1.70
diff -u -b -r1.69 -r1.70
--- vers_ts.c   2 Sep 2006 23:18:00 -0000       1.69
+++ vers_ts.c   12 Sep 2007 02:45:23 -0000      1.70
@@ -52,7 +52,6 @@
     Node *p;
     RCSNode *rcsdata;
     Vers_TS *vers_ts;
-    struct stickydirtag *sdtp;
     Entnode *entdata;
     char *rcsexpand = NULL;
 
@@ -71,15 +70,9 @@
      * look it up (used by checkout -P)
      */
     if (finfo->entries == NULL)
-    {
-       sdtp = NULL;
        p = NULL;
-    }
     else
-    {
        p = findnode_fn (finfo->entries, finfo->file);
-       sdtp = finfo->entries->list->data; /* list-private */
-    }
 
     if (p == NULL)
     {
@@ -114,7 +107,7 @@
            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))
+           if (!(tag || date) && !entriesGetAflag (finfo->entries))
            {
                vers_ts->tag = xstrdup (entdata->tag);
                vers_ts->date = xstrdup (entdata->date);
@@ -124,12 +117,9 @@
        /* Even if we don't have an "entries line" as such
           (vers_ts->entdata), we want to pick up options which could
           have been from a Kopt protocol request.  */
-       if (!options || *options == '\0')
-       {
-           if (!(sdtp && sdtp->aflag))
+       if ((!options || !*options) && !entriesGetAflag (finfo->entries))
                vers_ts->options = xstrdup (entdata->options);
        }
-    }
 
     /* Always look up the RCS keyword mode when we have an RCS archive.  It
      * will either be needed as a default or to avoid allowing the -k options
@@ -177,15 +167,16 @@
        vers_ts->tag = xstrdup (tag);
        vers_ts->date = xstrdup (date);
     }
-    else if (!vers_ts->entdata && (sdtp && sdtp->aflag == 0))
+    else if (!vers_ts->entdata && !entriesGetAflag (finfo->entries)
+            && entriesHasSticky (finfo->entries))
     {
        if (!vers_ts->tag)
        {
-           vers_ts->tag = xstrdup (sdtp->tag);
-           vers_ts->nonbranch = sdtp->nonbranch;
+           vers_ts->tag = xstrdup (entriesGetTag (finfo->entries));
+           vers_ts->nonbranch = entriesGetNonbranch (finfo->entries);
        }
        if (!vers_ts->date)
-           vers_ts->date = xstrdup (sdtp->date);
+           vers_ts->date = xstrdup (entriesGetDate (finfo->entries));
     }
 
     /* Now look up the info on the source controlled file */




reply via email to

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