strbuf: add strbuf_reencode helper
[gitweb.git] / tree-diff.c
index f760740a1174820349ddb0ac9c583e7e726dcfb5..11c3550177dbaab30596be2fc3c1633f2a0485f8 100644 (file)
@@ -49,12 +49,12 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2,
        if (DIFF_OPT_TST(opt, RECURSIVE) && S_ISDIR(mode1)) {
                if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE)) {
                        opt->change(opt, mode1, mode2,
-                                   sha1, sha2, base->buf, 0, 0);
+                                   sha1, sha2, 1, 1, base->buf, 0, 0);
                }
                strbuf_addch(base, '/');
                diff_tree_sha1(sha1, sha2, base->buf, opt);
        } else {
-               opt->change(opt, mode1, mode2, sha1, sha2, base->buf, 0, 0);
+               opt->change(opt, mode1, mode2, sha1, sha2, 1, 1, base->buf, 0, 0);
        }
        strbuf_setlen(base, old_baselen);
        return 0;
@@ -100,7 +100,7 @@ static void show_entry(struct diff_options *opt, const char *prefix,
                        die("corrupt tree sha %s", sha1_to_hex(sha1));
 
                if (DIFF_OPT_TST(opt, TREE_IN_RECURSIVE))
-                       opt->add_remove(opt, *prefix, mode, sha1, base->buf, 0);
+                       opt->add_remove(opt, *prefix, mode, sha1, 1, base->buf, 0);
 
                strbuf_addch(base, '/');
 
@@ -108,7 +108,7 @@ static void show_entry(struct diff_options *opt, const char *prefix,
                show_tree(opt, prefix, &inner, base);
                free(tree);
        } else
-               opt->add_remove(opt, prefix[0], mode, sha1, base->buf, 0);
+               opt->add_remove(opt, prefix[0], mode, sha1, 1, base->buf, 0);
 
        strbuf_setlen(base, old_baselen);
 }
@@ -138,7 +138,6 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
 
        /* Enable recursion indefinitely */
        opt->pathspec.recursive = DIFF_OPT_TST(opt, RECURSIVE);
-       opt->pathspec.max_depth = -1;
 
        strbuf_init(&base, PATH_MAX);
        strbuf_add(&base, base_str, baselen);
@@ -196,9 +195,27 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co
        struct diff_options diff_opts;
        struct diff_queue_struct *q = &diff_queued_diff;
        struct diff_filepair *choice;
-       const char *paths[1];
        int i;
 
+       /*
+        * follow-rename code is very specific, we need exactly one
+        * path. Magic that matches more than one path is not
+        * supported.
+        */
+       GUARD_PATHSPEC(&opt->pathspec, PATHSPEC_FROMTOP | PATHSPEC_LITERAL);
+#if 0
+       /*
+        * We should reject wildcards as well. Unfortunately we
+        * haven't got a reliable way to detect that 'foo\*bar' in
+        * fact has no wildcards. nowildcard_len is merely a hint for
+        * optimization. Let it slip for now until wildmatch is taught
+        * about dry-run mode and returns wildcard info.
+        */
+       if (opt->pathspec.has_wildcard)
+               die("BUG:%s:%d: wildcards are not supported",
+                   __FILE__, __LINE__);
+#endif
+
        /* Remove the file creation entry from the diff queue, and remember it */
        choice = q->queue[0];
        q->nr = 0;
@@ -207,15 +224,13 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co
        DIFF_OPT_SET(&diff_opts, RECURSIVE);
        DIFF_OPT_SET(&diff_opts, FIND_COPIES_HARDER);
        diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT;
-       diff_opts.single_follow = opt->pathspec.raw[0];
+       diff_opts.single_follow = opt->pathspec.items[0].match;
        diff_opts.break_opt = opt->break_opt;
        diff_opts.rename_score = opt->rename_score;
-       paths[0] = NULL;
-       diff_tree_setup_paths(paths, &diff_opts);
        diff_setup_done(&diff_opts);
        diff_tree(t1, t2, base, &diff_opts);
        diffcore_std(&diff_opts);
-       diff_tree_release_paths(&diff_opts);
+       free_pathspec(&diff_opts.pathspec);
 
        /* Go through the new set of filepairing, and see if we find a more interesting one */
        opt->found_follow = 0;
@@ -228,15 +243,20 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co
                 * the future!
                 */
                if ((p->status == 'R' || p->status == 'C') &&
-                   !strcmp(p->two->path, opt->pathspec.raw[0])) {
+                   !strcmp(p->two->path, opt->pathspec.items[0].match)) {
+                       const char *path[2];
+
                        /* Switch the file-pairs around */
                        q->queue[i] = choice;
                        choice = p;
 
                        /* Update the path we use from now on.. */
-                       diff_tree_release_paths(opt);
-                       opt->pathspec.raw[0] = xstrdup(p->one->path);
-                       diff_tree_setup_paths(opt->pathspec.raw, opt);
+                       path[0] = p->one->path;
+                       path[1] = NULL;
+                       free_pathspec(&opt->pathspec);
+                       parse_pathspec(&opt->pathspec,
+                                      PATHSPEC_ALL_MAGIC & ~PATHSPEC_LITERAL,
+                                      PATHSPEC_LITERAL_PATH, "", path);
 
                        /*
                         * The caller expects us to return a set of vanilla
@@ -274,14 +294,10 @@ int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const cha
        unsigned long size1, size2;
        int retval;
 
-       tree1 = read_object_with_reference(old, tree_type, &size1, NULL);
-       if (!tree1)
-               die("unable to read source tree (%s)", sha1_to_hex(old));
-       tree2 = read_object_with_reference(new, tree_type, &size2, NULL);
-       if (!tree2)
-               die("unable to read destination tree (%s)", sha1_to_hex(new));
-       init_tree_desc(&t1, tree1, size1);
-       init_tree_desc(&t2, tree2, size2);
+       tree1 = fill_tree_descriptor(&t1, old);
+       tree2 = fill_tree_descriptor(&t2, new);
+       size1 = t1.size;
+       size2 = t2.size;
        retval = diff_tree(&t1, &t2, base, opt);
        if (!*base && DIFF_OPT_TST(opt, FOLLOW_RENAMES) && diff_might_be_rename()) {
                init_tree_desc(&t1, tree1, size1);
@@ -295,28 +311,5 @@ int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const cha
 
 int diff_root_tree_sha1(const unsigned char *new, const char *base, struct diff_options *opt)
 {
-       int retval;
-       void *tree;
-       unsigned long size;
-       struct tree_desc empty, real;
-
-       tree = read_object_with_reference(new, tree_type, &size, NULL);
-       if (!tree)
-               die("unable to read root tree (%s)", sha1_to_hex(new));
-       init_tree_desc(&real, tree, size);
-
-       init_tree_desc(&empty, "", 0);
-       retval = diff_tree(&empty, &real, base, opt);
-       free(tree);
-       return retval;
-}
-
-void diff_tree_release_paths(struct diff_options *opt)
-{
-       free_pathspec(&opt->pathspec);
-}
-
-void diff_tree_setup_paths(const char **p, struct diff_options *opt)
-{
-       init_pathspec(&opt->pathspec, p);
+       return diff_tree_sha1(NULL, new, base, opt);
 }