diff options
Diffstat (limited to 'contrib/cvs/src/find_names.c')
-rw-r--r-- | contrib/cvs/src/find_names.c | 154 |
1 files changed, 130 insertions, 24 deletions
diff --git a/contrib/cvs/src/find_names.c b/contrib/cvs/src/find_names.c index 48854377a753b..a7a91bbfd3ec9 100644 --- a/contrib/cvs/src/find_names.c +++ b/contrib/cvs/src/find_names.c @@ -18,8 +18,11 @@ #include "cvs.h" -static int find_dirs PROTO((char *dir, List * list, int checkadm)); +static int find_dirs PROTO((char *dir, List * list, int checkadm, + List *entries)); static int find_rcs PROTO((char *dir, List * list)); +static int add_subdir_proc PROTO((Node *, void *)); +static int register_subdir_proc PROTO((Node *, void *)); static List *filelist; @@ -32,8 +35,13 @@ add_entries_proc (node, closure) Node *node; void *closure; { + Entnode *entnode; Node *fnode; + entnode = (Entnode *) node->data; + if (entnode->type != ENT_FILE) + return (0); + fnode = getnode (); fnode->type = FILES; fnode->key = xstrdup (node->key); @@ -63,7 +71,6 @@ Find_Names (repository, which, aflag, optentries) { List *entries; List *files; - char dir[PATH_MAX]; /* make a list for the files */ files = filelist = getlist (); @@ -95,8 +102,11 @@ Find_Names (repository, which, aflag, optentries) /* search the attic too */ if (which & W_ATTIC) { + char *dir; + dir = xmalloc (strlen (repository) + sizeof (CVSATTIC) + 10); (void) sprintf (dir, "%s/%s", repository, CVSATTIC); (void) find_rcs (dir, files); + free (dir); } } @@ -106,12 +116,55 @@ Find_Names (repository, which, aflag, optentries) } /* + * Add an entry from the subdirs list to the directories list. This + * is called via walklist. + */ + +static int +add_subdir_proc (p, closure) + Node *p; + void *closure; +{ + List *dirlist = (List *) closure; + Entnode *entnode; + Node *dnode; + + entnode = (Entnode *) p->data; + if (entnode->type != ENT_SUBDIR) + return 0; + + dnode = getnode (); + dnode->type = DIRS; + dnode->key = xstrdup (entnode->user); + if (addnode (dirlist, dnode) != 0) + freenode (dnode); + return 0; +} + +/* + * Register a subdirectory. This is called via walklist. + */ + +/*ARGSUSED*/ +static int +register_subdir_proc (p, closure) + Node *p; + void *closure; +{ + List *entries = (List *) closure; + + Subdir_Register (entries, (char *) NULL, p->key); + return 0; +} + +/* * create a list of directories to traverse from the current directory */ List * -Find_Directories (repository, which) +Find_Directories (repository, which, entries) char *repository; int which; + List *entries; { List *dirlist; @@ -121,28 +174,60 @@ Find_Directories (repository, which) /* find the local ones */ if (which & W_LOCAL) { - /* look only for CVS controlled sub-directories */ - if (find_dirs (".", dirlist, 1) != 0) - error (1, errno, "cannot open current directory"); + List *tmpentries; + struct stickydirtag *sdtp; + + /* Look through the Entries file. */ + + if (entries != NULL) + tmpentries = entries; + else if (isfile (CVSADM_ENT)) + tmpentries = Entries_Open (0); + else + tmpentries = NULL; + + if (tmpentries != NULL) + sdtp = (struct stickydirtag *) 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); + else + { + /* This is an old working directory, in which subdirectory + information is not recorded in the Entries file. Find + the subdirectories the hard way, and, if possible, add + it to the Entries file for next time. */ + if (find_dirs (".", dirlist, 1, tmpentries) != 0) + error (1, errno, "cannot open current directory"); + if (tmpentries != NULL) + { + if (! list_isempty (dirlist)) + walklist (dirlist, register_subdir_proc, + (void *) tmpentries); + else + Subdirs_Known (tmpentries); + } + } + + if (entries == NULL && tmpentries != NULL) + Entries_Close (tmpentries); } /* look for sub-dirs in the repository */ if ((which & W_REPOS) && repository) { /* search the repository */ - if (find_dirs (repository, dirlist, 0) != 0) + if (find_dirs (repository, dirlist, 0, entries) != 0) error (1, errno, "cannot open directory %s", repository); -#ifdef ATTIC_DIR_SUPPORT /* XXX - FIXME */ - /* search the attic too */ - if (which & W_ATTIC) - { - char dir[PATH_MAX]; - - (void) sprintf (dir, "%s/%s", repository, CVSATTIC); - (void) find_dirs (dir, dirlist, 0); - } -#endif + /* We don't need to look in the attic because directories + never go in the attic. In the future, there hopefully will + be a better mechanism for detecting whether a directory in + the repository is alive or dead; it may or may not involve + moving directories to the attic. */ } /* sort the list into alphabetical order and return it */ @@ -165,7 +250,7 @@ find_rcs (dir, list) DIR *dirp; /* set up to read the dir */ - if ((dirp = opendir (dir)) == NULL) + if ((dirp = CVS_OPENDIR (dir)) == NULL) return (1); /* read the dir, grabbing the ,v files */ @@ -189,23 +274,27 @@ find_rcs (dir, list) } /* - * 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 Returns 0 for success or 1 on error. + * 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. */ static int -find_dirs (dir, list, checkadm) +find_dirs (dir, list, checkadm, entries) char *dir; List *list; int checkadm; + List *entries; { Node *p; - char tmp[PATH_MAX]; + char *tmp = NULL; + size_t tmp_size = 0; struct dirent *dp; DIR *dirp; /* set up to read the dir */ - if ((dirp = opendir (dir)) == NULL) + if ((dirp = CVS_OPENDIR (dir)) == NULL) return (1); /* read the dir, grabbing sub-dirs */ @@ -218,6 +307,12 @@ find_dirs (dir, list, checkadm) strcmp (dp->d_name, CVSREP) == 0) continue; + /* 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) + continue; + #ifdef DT_DIR if (dp->d_type != DT_DIR) { @@ -228,6 +323,9 @@ find_dirs (dir, list, checkadm) if (fnmatch (RCSPAT, dp->d_name, 0) == 0) continue; + expand_string (&tmp, + &tmp_size, + strlen (dir) + strlen (dp->d_name) + 10); sprintf (tmp, "%s/%s", dir, dp->d_name); if (!isdir (tmp)) continue; @@ -247,6 +345,8 @@ find_dirs (dir, list, checkadm) if (dp->d_type == DT_LNK) continue; #endif + /* Note that we only get here if we already set tmp + above. */ if (islink (tmp)) continue; #ifdef DT_DIR @@ -254,6 +354,10 @@ find_dirs (dir, list, checkadm) #endif /* 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)) continue; @@ -267,5 +371,7 @@ find_dirs (dir, list, checkadm) freenode (p); } (void) closedir (dirp); + if (tmp != NULL) + free (tmp); return (0); } |