Browse Source

Move pathspec matching from builtin-add.c into dir.c

I'll use it for builtin-rm.c too.

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
maint
Linus Torvalds 19 years ago committed by Junio C Hamano
parent
commit
3c6a370b0e
  1. 82
      builtin-add.c
  2. 80
      dir.c
  3. 3
      dir.h

82
builtin-add.c

@ -12,86 +12,6 @@
static const char builtin_add_usage[] = static const char builtin_add_usage[] =
"git-add [-n] [-v] <filepattern>..."; "git-add [-n] [-v] <filepattern>...";


static int common_prefix(const char **pathspec)
{
const char *path, *slash, *next;
int prefix;

if (!pathspec)
return 0;

path = *pathspec;
slash = strrchr(path, '/');
if (!slash)
return 0;

prefix = slash - path + 1;
while ((next = *++pathspec) != NULL) {
int len = strlen(next);
if (len >= prefix && !memcmp(path, next, len))
continue;
for (;;) {
if (!len)
return 0;
if (next[--len] != '/')
continue;
if (memcmp(path, next, len+1))
continue;
prefix = len + 1;
break;
}
}
return prefix;
}

static int match_one(const char *match, const char *name, int namelen)
{
int matchlen;

/* If the match was just the prefix, we matched */
matchlen = strlen(match);
if (!matchlen)
return 1;

/*
* If we don't match the matchstring exactly,
* we need to match by fnmatch
*/
if (strncmp(match, name, matchlen))
return !fnmatch(match, name, 0);

/*
* If we did match the string exactly, we still
* need to make sure that it happened on a path
* component boundary (ie either the last character
* of the match was '/', or the next character of
* the name was '/' or the terminating NUL.
*/
return match[matchlen-1] == '/' ||
name[matchlen] == '/' ||
!name[matchlen];
}

static int match(const char **pathspec, const char *name, int namelen, int prefix, char *seen)
{
int retval;
const char *match;

name += prefix;
namelen -= prefix;

for (retval = 0; (match = *pathspec++) != NULL; seen++) {
if (retval & *seen)
continue;
match += prefix;
if (match_one(match, name, namelen)) {
retval = 1;
*seen = 1;
}
}
return retval;
}

static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix) static void prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
{ {
char *seen; char *seen;
@ -107,7 +27,7 @@ static void prune_directory(struct dir_struct *dir, const char **pathspec, int p
i = dir->nr; i = dir->nr;
while (--i >= 0) { while (--i >= 0) {
struct dir_entry *entry = *src++; struct dir_entry *entry = *src++;
if (!match(pathspec, entry->name, entry->len, prefix, seen)) { if (!match_pathspec(pathspec, entry->name, entry->len, prefix, seen)) {
free(entry); free(entry);
continue; continue;
} }

80
dir.c

@ -11,6 +11,86 @@
#include "cache.h" #include "cache.h"
#include "dir.h" #include "dir.h"


int common_prefix(const char **pathspec)
{
const char *path, *slash, *next;
int prefix;

if (!pathspec)
return 0;

path = *pathspec;
slash = strrchr(path, '/');
if (!slash)
return 0;

prefix = slash - path + 1;
while ((next = *++pathspec) != NULL) {
int len = strlen(next);
if (len >= prefix && !memcmp(path, next, len))
continue;
for (;;) {
if (!len)
return 0;
if (next[--len] != '/')
continue;
if (memcmp(path, next, len+1))
continue;
prefix = len + 1;
break;
}
}
return prefix;
}

static int match_one(const char *match, const char *name, int namelen)
{
int matchlen;

/* If the match was just the prefix, we matched */
matchlen = strlen(match);
if (!matchlen)
return 1;

/*
* If we don't match the matchstring exactly,
* we need to match by fnmatch
*/
if (strncmp(match, name, matchlen))
return !fnmatch(match, name, 0);

/*
* If we did match the string exactly, we still
* need to make sure that it happened on a path
* component boundary (ie either the last character
* of the match was '/', or the next character of
* the name was '/' or the terminating NUL.
*/
return match[matchlen-1] == '/' ||
name[matchlen] == '/' ||
!name[matchlen];
}

int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen)
{
int retval;
const char *match;

name += prefix;
namelen -= prefix;

for (retval = 0; (match = *pathspec++) != NULL; seen++) {
if (retval & *seen)
continue;
match += prefix;
if (match_one(match, name, namelen)) {
retval = 1;
*seen = 1;
}
}
return retval;
}

void add_exclude(const char *string, const char *base, void add_exclude(const char *string, const char *base,
int baselen, struct exclude_list *which) int baselen, struct exclude_list *which)
{ {

3
dir.h

@ -39,6 +39,9 @@ struct dir_struct {
struct exclude_list exclude_list[3]; struct exclude_list exclude_list[3];
}; };


extern int common_prefix(const char **pathspec);
extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen);

extern int read_directory(struct dir_struct *, const char *path, const char *base, int baselen); extern int read_directory(struct dir_struct *, const char *path, const char *base, int baselen);
extern int excluded(struct dir_struct *, const char *); extern int excluded(struct dir_struct *, const char *);
extern void add_excludes_from_file(struct dir_struct *, const char *fname); extern void add_excludes_from_file(struct dir_struct *, const char *fname);

Loading…
Cancel
Save