revised^2: git-daemon extra paranoia, and path DWIM
[gitweb.git] / tree.c
diff --git a/tree.c b/tree.c
index 8dc27e3b7354b8b8cc7d7491621929c78325a645..315b6a5d1ce0e83fc75a399a3b74e51f46c5b392 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -1,5 +1,7 @@
 #include "tree.h"
 #include "blob.h"
+#include "commit.h"
+#include "tag.h"
 #include "cache.h"
 #include <stdlib.h>
 
@@ -21,9 +23,9 @@ 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)
+static int match_tree_entry(const char *base, int baselen, const char *path, unsigned int mode, const char **paths)
 {
-       char *match;
+       const char *match;
        int pathlen;
 
        if (!paths)
@@ -59,13 +61,15 @@ static int match_tree_entry(const char *base, int baselen, const char *path, uns
 
                if (strncmp(path, match, pathlen))
                        continue;
+
+               return 1;
        }
        return 0;
 }
 
 static int read_tree_recursive(void *buffer, unsigned long size,
                               const char *base, int baselen,
-                              int stage, char **match)
+                              int stage, const char **match)
 {
        while (size) {
                int len = strlen(buffer)+1;
@@ -115,7 +119,7 @@ static int read_tree_recursive(void *buffer, unsigned long size,
        return 0;
 }
 
-int read_tree(void *buffer, unsigned long size, int stage, char **match)
+int read_tree(void *buffer, unsigned long size, int stage, const char **match)
 {
        return read_tree_recursive(buffer, size, "", 0, stage, match);
 }
@@ -165,6 +169,7 @@ int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size)
                entry->directory = S_ISDIR(mode) != 0;
                entry->executable = (mode & S_IXUSR) != 0;
                entry->symlink = S_ISLNK(mode) != 0;
+               entry->zeropad = *(char *)bufptr == '0';
                entry->mode = mode;
                entry->next = NULL;
 
@@ -209,3 +214,22 @@ int parse_tree(struct tree *item)
        free(buffer);
        return ret;
 }
+
+struct tree *parse_tree_indirect(const unsigned char *sha1)
+{
+       struct object *obj = parse_object(sha1);
+       do {
+               if (!obj)
+                       return NULL;
+               if (obj->type == tree_type)
+                       return (struct tree *) obj;
+               else if (obj->type == commit_type)
+                       obj = &(((struct commit *) obj)->tree->object);
+               else if (obj->type == tag_type)
+                       obj = ((struct tag *) obj)->tagged;
+               else
+                       return NULL;
+               if (!obj->parsed)
+                       parse_object(obj->sha1);
+       } while (1);
+}