#include "cvs.h"
#include "getline.h"
#include "lstat.h"
static char **ign_list;
static char **s_ign_list = NULL;
static int ign_count;
static int s_ign_count = 0;
static int ign_size;
static int ign_hold = -1;
const char *ign_default = ". .. core RCSLOG tags TAGS RCS SCCS .make.state\
.nse_depinfo #* .#* cvslog.* ,* CVS CVS.adm .del-* *.a *.olb *.o *.obj\
*.so *.Z *~ *.old *.elc *.ln *.bak *.BAK *.orig *.rej *.exe _$* *$ ._*";
#define IGN_GROW 16
int ign_inhibit_server;
void
ign_setup (void)
{
char *home_dir;
char *tmp;
ign_inhibit_server = 0;
tmp = xstrdup (ign_default);
ign_add (tmp, 0);
free (tmp);
if (!current_parsed_root->isremote)
{
char *file = Xasprintf ("%s/%s/%s", current_parsed_root->directory,
CVSROOTADM, CVSROOTADM_IGNORE);
ign_add_file (file, 0);
free (file);
}
home_dir = get_homedir ();
if (home_dir)
{
char *file = strcat_filename_onto_homedir (home_dir, CVSDOTIGNORE);
ign_add_file (file, 0);
free (file);
}
ign_add (getenv (IGNORE_ENV), 0);
}
void
ign_add_file (char *file, int hold)
{
FILE *fp;
char *line = NULL;
size_t line_allocated = 0;
if (s_ign_list != NULL)
{
int i;
for (i = 0; i < s_ign_count; i++)
ign_list[i] = s_ign_list[i];
ign_count = s_ign_count;
ign_list[ign_count] = NULL;
s_ign_count = 0;
free (s_ign_list);
s_ign_list = NULL;
}
if (hold)
{
if (ign_hold >= 0)
{
int i;
for (i = ign_hold; i < ign_count; i++)
free (ign_list[i]);
ign_count = ign_hold;
ign_list[ign_count] = NULL;
}
else
{
ign_hold = ign_count;
}
}
fp = CVS_FOPEN (file, "r");
if (fp == NULL)
{
if (! existence_error (errno))
error (0, errno, "cannot open %s", file);
return;
}
while (getline (&line, &line_allocated, fp) >= 0)
ign_add (line, hold);
if (ferror (fp))
error (0, errno, "cannot read %s", file);
if (fclose (fp) < 0)
error (0, errno, "cannot close %s", file);
free (line);
}
void
ign_add (char *ign, int hold)
{
if (!ign || !*ign)
return;
for (; *ign; ign++)
{
char *mark;
char save;
if (isspace ((unsigned char) *ign))
continue;
if (ign_count >= ign_size)
{
ign_size += IGN_GROW;
ign_list = xnrealloc (ign_list, ign_size + 1, sizeof (char *));
}
if ((!*(ign+1) || isspace ((unsigned char) *(ign+1)))
&& (*ign == '!' || *ign == '*'))
{
if (!hold)
{
int i;
for (i = 0; i < ign_count; i++)
free (ign_list[i]);
ign_count = 1;
ign_list[0] = xstrdup ("CVS");
ign_list[1] = NULL;
if (*ign == '!')
{
ign_inhibit_server = 1;
continue;
}
}
else if (*ign == '!')
{
int i;
if (ign_hold >= 0)
{
for (i = ign_hold; i < ign_count; i++)
free (ign_list[i]);
ign_hold = -1;
}
if (s_ign_list)
{
for (i = 0; i < ign_count; i++)
free (ign_list[i]);
}
else
{
s_ign_list = xnmalloc (ign_count, sizeof (char *));
for (i = 0; i < ign_count; i++)
s_ign_list[i] = ign_list[i];
s_ign_count = ign_count;
}
ign_count = 1;
ign_list[0] = xstrdup ("CVS");
ign_list[1] = NULL;
continue;
}
}
for (mark = ign; *mark && !isspace ((unsigned char) *mark); mark++)
;
save = *mark;
*mark = '\0';
ign_list[ign_count++] = xstrdup (ign);
ign_list[ign_count] = NULL;
*mark = save;
if (save)
ign = mark;
else
ign = mark - 1;
}
}
int
ign_name (char *name)
{
char **cpp = ign_list;
if (cpp == NULL)
return 0;
while (*cpp)
if (CVS_FNMATCH (*cpp++, name, 0) == 0)
return 1;
return 0;
}
static char **dir_ign_list = NULL;
static int dir_ign_max = 0;
static int dir_ign_current = 0;
void
ign_dir_add (char *name)
{
if (dir_ign_current <= dir_ign_max)
{
dir_ign_max += IGN_GROW;
dir_ign_list = xnrealloc (dir_ign_list,
dir_ign_max + 1, sizeof (char *));
}
dir_ign_list[dir_ign_current++] = xstrdup (name);
}
int
ignore_directory (const char *name)
{
int i;
if (!dir_ign_list)
return 0;
i = dir_ign_current;
while (i--)
{
if (strncmp (name, dir_ign_list[i], strlen (dir_ign_list[i])+1) == 0)
return 1;
}
return 0;
}
void
ignore_files (List *ilist, List *entries, const char *update_dir,
Ignore_proc proc)
{
int subdirs;
DIR *dirp;
struct dirent *dp;
struct stat sb;
char *file;
const char *xdir;
List *files;
Node *p;
if (entries == NULL)
subdirs = 0;
else
{
struct stickydirtag *sdtp = entries->list->data;
subdirs = sdtp == NULL || sdtp->subdirs;
}
if (strcmp (update_dir, ".") == 0)
xdir = "";
else
xdir = update_dir;
dirp = CVS_OPENDIR (".");
if (dirp == NULL)
{
error (0, errno, "cannot open current directory");
return;
}
ign_add_file (CVSDOTIGNORE, 1);
wrap_add_file (CVSDOTWRAPPER, 1);
files = getlist ();
while (errno = 0, (dp = CVS_READDIR (dirp)) != NULL)
{
file = dp->d_name;
if (strcmp (file, ".") == 0 || strcmp (file, "..") == 0)
continue;
if (findnode_fn (ilist, file) != NULL)
continue;
if (subdirs)
{
Node *node;
node = findnode_fn (entries, file);
if (node != NULL
&& ((Entnode *) node->data)->type == ENT_SUBDIR)
{
char *p;
int dir;
p = Xasprintf ("%s/%s", file, CVSADM);
dir = isdir (p);
free (p);
if (dir)
continue;
}
}
if (ign_name (file))
continue;
if (
#ifdef DT_DIR
dp->d_type != DT_UNKNOWN ||
#endif
lstat (file, &sb) != -1)
{
if (
#ifdef DT_DIR
dp->d_type == DT_DIR
|| (dp->d_type == DT_UNKNOWN && S_ISDIR (sb.st_mode))
#else
S_ISDIR (sb.st_mode)
#endif
)
{
if (!subdirs)
{
char *temp = Xasprintf ("%s/%s", file, CVSADM);
if (isdir (temp))
{
free (temp);
continue;
}
free (temp);
}
}
#ifdef S_ISLNK
else if (
#ifdef DT_DIR
dp->d_type == DT_LNK
|| (dp->d_type == DT_UNKNOWN && S_ISLNK (sb.st_mode))
#else
S_ISLNK (sb.st_mode)
#endif
)
{
continue;
}
#endif
}
p = getnode ();
p->type = FILES;
p->key = xstrdup (file);
(void) addnode (files, p);
}
if (errno != 0)
error (0, errno, "error reading current directory");
(void) CVS_CLOSEDIR (dirp);
sortlist (files, fsortcmp);
for (p = files->list->next; p != files->list; p = p->next)
(*proc) (p->key, xdir);
dellist (&files);
}