Start adding interfaces to read in partial trees
authorLinus Torvalds <torvalds@g5.osdl.org>
Thu, 14 Jul 2005 18:26:31 +0000 (11:26 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 14 Jul 2005 18:26:31 +0000 (11:26 -0700)
The same way "git-diff-tree" can limit its output to just a set of matches,
we can read in just a partial tree for comparison purposes.

cache.h
diff-cache.c
read-tree.c
tree.c

diff --git a/cache.h b/cache.h
index a42ce7e..53e3066 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -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);
index c435844..d78cbb5 100644 (file)
@@ -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);
index 0d5ded5..65f2d9a 100644 (file)
@@ -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;
 }
diff --git a/tree.c b/tree.c
index 96f78f6..8dc27e3 100644 (file)
--- a/tree.c
+++ b/tree.c
@@ -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)