tree/filter.c

187 lines
4.4 KiB
C

/* $Copyright: $
* Copyright (c) 1996 - 2022 by Steve Baker (ice@mama.indstate.edu)
*
* 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 of the License, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "tree.h"
struct ignorefile *filterstack = NULL;
static char fpattern[PATH_MAX];
void gittrim(char *s)
{
int i, e = strlen(s)-1;
if (s[e] == '\n') e--;
for(i = e; i >= 0; i--) {
if (s[i] != ' ') break;
if (i && s[i-1] != '\\') e--;
}
s[e+1] = '\0';
for(i = e = 0; s[i] != '\0';) {
if (s[i] == '\\') i++;
s[e++] = s[i++];
}
s[e] = '\0';
}
struct pattern *new_pattern(char *pattern)
{
struct pattern *p = xmalloc(sizeof(struct pattern));
p->pattern = scopy(pattern + ((pattern[0] == '/')? 1 : 0));
p->relative = (strchr(pattern,'/') == NULL);
p->next = NULL;
return p;
}
struct ignorefile *new_ignorefile(char *path)
{
char buf[PATH_MAX];
struct ignorefile *ig;
struct pattern *remove = NULL, *remend, *p;
struct pattern *reverse = NULL, *revend;
int rev;
FILE *fp;
snprintf(buf, PATH_MAX, "%s/.gitignore", path);
fp = fopen(buf, "r");
if (fp == NULL) return NULL;
while (fgets(buf, PATH_MAX, fp) != NULL) {
if (buf[0] == '#') continue;
rev = (buf[0] == '!');
gittrim(buf);
if (strlen(buf) == 0) continue;
p = new_pattern(buf + (rev? 1 : 0));
if (rev) {
if (reverse == NULL) reverse = revend = p;
else {
revend->next = p;
revend = p;
}
} else {
if (remove == NULL) remove = remend = p;
else {
remend->next = p;
remend = p;
}
}
}
fclose(fp);
ig = xmalloc(sizeof(struct ignorefile));
ig->remove = remove;
ig->reverse = reverse;
ig->path = scopy(path);
ig->next = NULL;
return ig;
}
void push_filterstack(struct ignorefile *ig)
{
if (ig == NULL) return;
ig->next = filterstack;
filterstack = ig;
}
struct ignorefile *pop_filterstack(void)
{
struct ignorefile *ig = filterstack;
struct pattern *p, *c;
filterstack = filterstack->next;
for(p=c=ig->remove; p != NULL; c = p) {
p=p->next;
free(c->pattern);
}
for(p=c=ig->reverse; p != NULL; c = p) {
p=p->next;
free(c->pattern);
}
free(ig->path);
free(ig);
return NULL;
}
/**
* true if remove filter matches and no reverse filter matches.
*/
int filtercheck(char *path, char *name, int isdir)
{
int filter = 0;
struct ignorefile *ig;
struct pattern *p;
for(ig = filterstack; !filter && ig; ig = ig->next) {
int fpos = sprintf(fpattern, "%s/", ig->path);
for(p = ig->remove; p != NULL; p = p->next) {
if (p->relative) {
if (patmatch(name, p->pattern, isdir) == 1) {
// printf("> name: %s, pattern: %s\n", path, p->pattern);
filter = 1;
break;
}
} else {
sprintf(fpattern + fpos, "%s", p->pattern);
// printf("> path: %s, fpattern: %s\n", path, fpattern);
if (patmatch(path, fpattern, isdir) == 1) {
// printf("Matched path: %s, fpattern: %s\n", path, fpattern);
filter = 1;
break;
}
}
// if (patmatch(path, p->pattern, isdir) == 1) {
// filter = 1;
// break;
// }
// if (p->pattern[0] == '/') continue;
// sprintf(fpattern + fpos, "%s", p->pattern);
// if (patmatch(path, fpattern, isdir) == 1) {
// filter = 1;
// break;
// }
}
}
if (!filter) return 0;
for(ig = filterstack; ig; ig = ig->next) {
int fpos = sprintf(fpattern, "%s/", ig->path);
for(p = ig->reverse; p != NULL; p = p->next) {
if (p->relative) {
if (patmatch(name, p->pattern, isdir) == 1) return 0;
} else {
sprintf(fpattern + fpos, "%s", p->pattern);
if (patmatch(path, fpattern, isdir) == 1) return 0;
}
// if (patmatch(path, p->pattern, isdir) == 1) return 0;
//
// if (p->pattern[0] == '/') continue;
// sprintf(fpattern + fpos, "%s", p->pattern);
//
// if (patmatch(path, fpattern, isdir) == 1) return 0;
}
}
return 1;
}