git-branch -D: make it work even when on a yet-to-be-born branch
[gitweb.git] / tree-diff.c
index 7bb6109111c0e8d4de11597fd64acb2a8b346879..37d235e06e2cbfbd761fd02d7e73648a14a60daf 100644 (file)
@@ -3,11 +3,7 @@
  */
 #include "cache.h"
 #include "diff.h"
-
-// What paths are we interested in?
-static int nr_paths = 0;
-static const char **paths = NULL;
-static int *pathlens = NULL;
+#include "tree.h"
 
 static char *malloc_base(const char *base, const char *path, int pathlen)
 {
@@ -19,7 +15,8 @@ static char *malloc_base(const char *base, const char *path, int pathlen)
        return newbase;
 }
 
-static int show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base);
+static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc,
+                      const char *base);
 
 static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt)
 {
@@ -42,8 +39,7 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
                show_entry(opt, "+", t2, base);
                return 1;
        }
-       if (!opt->find_copies_harder &&
-           !memcmp(sha1, sha2, 20) && mode1 == mode2)
+       if (!opt->find_copies_harder && !hashcmp(sha1, sha2) && mode1 == mode2)
                return 0;
 
        /*
@@ -71,14 +67,14 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
        return 0;
 }
 
-static int interesting(struct tree_desc *desc, const char *base)
+static int interesting(struct tree_desc *desc, const char *base, struct diff_options *opt)
 {
        const char *path;
        unsigned mode;
        int i;
        int baselen, pathlen;
 
-       if (!nr_paths)
+       if (!opt->nr_paths)
                return 1;
 
        (void)tree_entry_extract(desc, &path, &mode);
@@ -86,9 +82,9 @@ static int interesting(struct tree_desc *desc, const char *base)
        pathlen = strlen(path);
        baselen = strlen(base);
 
-       for (i=0; i < nr_paths; i++) {
-               const char *match = paths[i];
-               int matchlen = pathlens[i];
+       for (i=0; i < opt->nr_paths; i++) {
+               const char *match = opt->paths[i];
+               int matchlen = opt->pathlens[i];
 
                if (baselen >= matchlen) {
                        /* If it doesn't match, move along... */
@@ -128,14 +124,15 @@ static int interesting(struct tree_desc *desc, const char *base)
 static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base)
 {
        while (desc->size) {
-               if (interesting(desc, base))
+               if (interesting(desc, base, opt))
                        show_entry(opt, prefix, desc, base);
                update_tree_entry(desc);
        }
 }
 
 /* A file entry went away or appeared */
-static int show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base)
+static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc,
+                      const char *base)
 {
        unsigned mode;
        const char *path;
@@ -148,7 +145,7 @@ static int show_entry(struct diff_options *opt, const char *prefix, struct tree_
                void *tree;
 
                tree = read_sha1_file(sha1, type, &inner.size);
-               if (!tree || strcmp(type, "tree"))
+               if (!tree || strcmp(type, tree_type))
                        die("corrupt tree sha %s", sha1_to_hex(sha1));
 
                inner.buf = tree;
@@ -156,21 +153,19 @@ static int show_entry(struct diff_options *opt, const char *prefix, struct tree_
 
                free(tree);
                free(newbase);
-               return 0;
+       } else {
+               opt->add_remove(opt, prefix[0], mode, sha1, base, path);
        }
-
-       opt->add_remove(opt, prefix[0], mode, sha1, base, path);
-       return 0;
 }
 
 int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt)
 {
        while (t1->size | t2->size) {
-               if (nr_paths && t1->size && !interesting(t1, base)) {
+               if (opt->nr_paths && t1->size && !interesting(t1, base, opt)) {
                        update_tree_entry(t1);
                        continue;
                }
-               if (nr_paths && t2->size && !interesting(t2, base)) {
+               if (opt->nr_paths && t2->size && !interesting(t2, base, opt)) {
                        update_tree_entry(t2);
                        continue;
                }
@@ -206,10 +201,10 @@ int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const cha
        struct tree_desc t1, t2;
        int retval;
 
-       tree1 = read_object_with_reference(old, "tree", &t1.size, NULL);
+       tree1 = read_object_with_reference(old, tree_type, &t1.size, NULL);
        if (!tree1)
                die("unable to read source tree (%s)", sha1_to_hex(old));
-       tree2 = read_object_with_reference(new, "tree", &t2.size, NULL);
+       tree2 = read_object_with_reference(new, tree_type, &t2.size, NULL);
        if (!tree2)
                die("unable to read destination tree (%s)", sha1_to_hex(new));
        t1.buf = tree1;
@@ -220,6 +215,24 @@ int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const cha
        return retval;
 }
 
+int diff_root_tree_sha1(const unsigned char *new, const char *base, struct diff_options *opt)
+{
+       int retval;
+       void *tree;
+       struct tree_desc empty, real;
+
+       tree = read_object_with_reference(new, tree_type, &real.size, NULL);
+       if (!tree)
+               die("unable to read root tree (%s)", sha1_to_hex(new));
+       real.buf = tree;
+
+       empty.size = 0;
+       empty.buf = "";
+       retval = diff_tree(&empty, &real, base, opt);
+       free(tree);
+       return retval;
+}
+
 static int count_paths(const char **paths)
 {
        int i = 0;
@@ -228,19 +241,28 @@ static int count_paths(const char **paths)
        return i;
 }
 
-void diff_tree_setup_paths(const char **p)
+void diff_tree_release_paths(struct diff_options *opt)
+{
+       free(opt->pathlens);
+}
+
+void diff_tree_setup_paths(const char **p, struct diff_options *opt)
 {
+       opt->nr_paths = 0;
+       opt->pathlens = NULL;
+       opt->paths = NULL;
+
        if (p) {
                int i;
 
-               paths = p;
-               nr_paths = count_paths(paths);
-               if (nr_paths == 0) {
-                       pathlens = NULL;
+               opt->paths = p;
+               opt->nr_paths = count_paths(p);
+               if (opt->nr_paths == 0) {
+                       opt->pathlens = NULL;
                        return;
                }
-               pathlens = xmalloc(nr_paths * sizeof(int));
-               for (i=0; i<nr_paths; i++)
-                       pathlens[i] = strlen(paths[i]);
+               opt->pathlens = xmalloc(opt->nr_paths * sizeof(int));
+               for (i=0; i < opt->nr_paths; i++)
+                       opt->pathlens[i] = strlen(p[i]);
        }
 }