diff options
-rw-r--r-- | cache.h | 2 | ||||
-rw-r--r-- | diff-cache.c | 2 | ||||
-rw-r--r-- | read-tree.c | 2 | ||||
-rw-r--r-- | tree.c | 55 |
4 files changed, 54 insertions, 7 deletions
@@ -191,7 +191,7 @@ extern char *write_sha1_file_prepare(void *buf, extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type); /* Read a tree into the cache */ -extern int read_tree(void *buffer, unsigned long size, int stage); +extern int read_tree(void *buffer, unsigned long size, int stage, char **paths); extern int write_sha1_from_fd(const unsigned char *sha1, int fd); extern int write_sha1_to_fd(int fd, const unsigned char *sha1); diff --git a/diff-cache.c b/diff-cache.c index c435844a2..d78cbb5d6 100644 --- a/diff-cache.c +++ b/diff-cache.c @@ -278,7 +278,7 @@ int main(int argc, const char **argv) tree = read_object_with_reference(sha1, "tree", &size, NULL); if (!tree) die("bad tree object %s", tree_name); - if (read_tree(tree, size, 1)) + if (read_tree(tree, size, 1, NULL)) die("unable to read tree object %s", tree_name); ret = diff_cache(active_cache, active_nr); diff --git a/read-tree.c b/read-tree.c index 0d5ded502..65f2d9a5d 100644 --- a/read-tree.c +++ b/read-tree.c @@ -17,7 +17,7 @@ static int unpack_tree(unsigned char *sha1) buffer = read_object_with_reference(sha1, "tree", &size, NULL); if (!buffer) return -1; - ret = read_tree(buffer, size, stage); + ret = read_tree(buffer, size, stage, NULL); free(buffer); return ret; } @@ -21,8 +21,51 @@ static int read_one_entry(unsigned char *sha1, const char *base, int baselen, co return add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_SKIP_DFCHECK); } +static int match_tree_entry(const char *base, int baselen, const char *path, unsigned int mode, char **paths) +{ + char *match; + int pathlen; + + if (!paths) + return 1; + pathlen = strlen(path); + while ((match = *paths++) != NULL) { + int matchlen = strlen(match); + + if (baselen >= matchlen) { + /* If it doesn't match, move along... */ + if (strncmp(base, match, matchlen)) + continue; + /* The base is a subdirectory of a path which was specified. */ + return 1; + } + + /* Does the base match? */ + if (strncmp(base, match, baselen)) + continue; + + match += baselen; + matchlen -= baselen; + + if (pathlen > matchlen) + continue; + + if (matchlen > pathlen) { + if (match[pathlen] != '/') + continue; + if (!S_ISDIR(mode)) + continue; + } + + if (strncmp(path, match, pathlen)) + continue; + } + return 0; +} + static int read_tree_recursive(void *buffer, unsigned long size, - const char *base, int baselen, int stage) + const char *base, int baselen, + int stage, char **match) { while (size) { int len = strlen(buffer)+1; @@ -36,6 +79,9 @@ static int read_tree_recursive(void *buffer, unsigned long size, buffer = sha1 + 20; size -= len + 20; + if (!match_tree_entry(base, baselen, path, mode, match)) + continue; + if (S_ISDIR(mode)) { int retval; int pathlen = strlen(path); @@ -55,7 +101,8 @@ static int read_tree_recursive(void *buffer, unsigned long size, newbase[baselen + pathlen] = '/'; retval = read_tree_recursive(eltbuf, eltsize, newbase, - baselen + pathlen + 1, stage); + baselen + pathlen + 1, + stage, match); free(eltbuf); free(newbase); if (retval) @@ -68,9 +115,9 @@ static int read_tree_recursive(void *buffer, unsigned long size, return 0; } -int read_tree(void *buffer, unsigned long size, int stage) +int read_tree(void *buffer, unsigned long size, int stage, char **match) { - return read_tree_recursive(buffer, size, "", 0, stage); + return read_tree_recursive(buffer, size, "", 0, stage, match); } struct tree *lookup_tree(const unsigned char *sha1) |