Future-proof source for changes in xdemitconf_t
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index 9938969fa50e8af2a4eabe96ae122111ae42fe75..d10e848c792bba581d6bf3e30204a81204177983 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -390,6 +390,7 @@ static void diff_words_show(struct diff_words_data *diff_words)
        mmfile_t minus, plus;
        int i;
 
+       memset(&xecfg, 0, sizeof(xecfg));
        minus.size = diff_words->minus.text.size;
        minus.ptr = xmalloc(minus.size);
        memcpy(minus.ptr, diff_words->minus.text.ptr, minus.size);
@@ -408,7 +409,6 @@ static void diff_words_show(struct diff_words_data *diff_words)
 
        xpp.flags = XDF_NEED_MINIMAL;
        xecfg.ctxlen = diff_words->minus.alloc + diff_words->plus.alloc;
-       xecfg.flags = 0;
        ecb.outf = xdiff_outf;
        ecb.priv = diff_words;
        diff_words->xm.consume = fn_out_diff_words_aux;
@@ -1102,30 +1102,45 @@ static void setup_diff_attr_check(struct git_attr_check *check)
 {
        static struct git_attr *attr_diff;
 
-       if (!attr_diff)
+       if (!attr_diff) {
                attr_diff = git_attr("diff", 4);
-       check->attr = attr_diff;
+       }
+       check[0].attr = attr_diff;
 }
 
-static int file_is_binary(struct diff_filespec *one)
+static void diff_filespec_check_attr(struct diff_filespec *one)
 {
-       struct git_attr_check attr_diff_check;
+       struct git_attr_check attr_diff_check[1];
 
-       setup_diff_attr_check(&attr_diff_check);
-       if (!git_checkattr(one->path, 1, &attr_diff_check)) {
-               const char *value = attr_diff_check.value;
+       if (one->checked_attr)
+               return;
+
+       setup_diff_attr_check(attr_diff_check);
+       one->is_binary = 0;
+
+       if (!git_checkattr(one->path, ARRAY_SIZE(attr_diff_check), attr_diff_check)) {
+               const char *value;
+
+               /* binaryness */
+               value = attr_diff_check[0].value;
                if (ATTR_TRUE(value))
-                       return 0;
+                       ;
                else if (ATTR_FALSE(value))
-                       return 1;
+                       one->is_binary = 1;
        }
 
-       if (!one->data) {
-               if (!DIFF_FILE_VALID(one))
-                       return 0;
+       if (!one->data && DIFF_FILE_VALID(one))
                diff_populate_filespec(one, 0);
-       }
-       return buffer_is_binary(one->data, one->size);
+
+       if (one->data)
+               one->is_binary = buffer_is_binary(one->data, one->size);
+
+}
+
+int diff_filespec_is_binary(struct diff_filespec *one)
+{
+       diff_filespec_check_attr(one);
+       return one->is_binary;
 }
 
 static void builtin_diff(const char *name_a,
@@ -1182,7 +1197,8 @@ static void builtin_diff(const char *name_a,
        if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
                die("unable to read files to diff");
 
-       if (!o->text && (file_is_binary(one) || file_is_binary(two))) {
+       if (!o->text &&
+           (diff_filespec_is_binary(one) || diff_filespec_is_binary(two))) {
                /* Quite common confusing case */
                if (mf1.size == mf2.size &&
                    !memcmp(mf1.ptr, mf2.ptr, mf1.size))
@@ -1202,6 +1218,7 @@ static void builtin_diff(const char *name_a,
                xdemitcb_t ecb;
                struct emit_callback ecbdata;
 
+               memset(&xecfg, 0, sizeof(xecfg));
                memset(&ecbdata, 0, sizeof(ecbdata));
                ecbdata.label_path = lbl;
                ecbdata.color_diff = o->color_diff;
@@ -1260,7 +1277,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
        if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
                die("unable to read files to diff");
 
-       if (file_is_binary(one) || file_is_binary(two)) {
+       if (diff_filespec_is_binary(one) || diff_filespec_is_binary(two)) {
                data->is_binary = 1;
                data->added = mf2.size;
                data->deleted = mf1.size;
@@ -1270,9 +1287,8 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
                xdemitconf_t xecfg;
                xdemitcb_t ecb;
 
+               memset(&xecfg, 0, sizeof(xecfg));
                xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
-               xecfg.ctxlen = 0;
-               xecfg.flags = 0;
                ecb.outf = xdiff_outf;
                ecb.priv = diffstat;
                xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
@@ -1302,7 +1318,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
        if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
                die("unable to read files to diff");
 
-       if (file_is_binary(two))
+       if (diff_filespec_is_binary(two))
                goto free_and_return;
        else {
                /* Crazy xdl interfaces.. */
@@ -1310,9 +1326,8 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
                xdemitconf_t xecfg;
                xdemitcb_t ecb;
 
+               memset(&xecfg, 0, sizeof(xecfg));
                xpp.flags = XDF_NEED_MINIMAL;
-               xecfg.ctxlen = 0;
-               xecfg.flags = 0;
                ecb.outf = xdiff_outf;
                ecb.priv = &data;
                xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
@@ -1813,6 +1828,11 @@ static void diff_fill_sha1_info(struct diff_filespec *one)
                hashclr(one->sha1);
 }
 
+static int similarity_index(struct diff_filepair *p)
+{
+       return p->score * 100 / MAX_SCORE;
+}
+
 static void run_diff(struct diff_filepair *p, struct diff_options *o)
 {
        const char *pgm = external_diff();
@@ -1847,23 +1867,20 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
                                "similarity index %d%%\n"
                                "copy from %s\n"
                                "copy to %s\n",
-                               (int)(0.5 + p->score * 100.0/MAX_SCORE),
-                               name_munged, other_munged);
+                               similarity_index(p), name_munged, other_munged);
                break;
        case DIFF_STATUS_RENAMED:
                len += snprintf(msg + len, sizeof(msg) - len,
                                "similarity index %d%%\n"
                                "rename from %s\n"
                                "rename to %s\n",
-                               (int)(0.5 + p->score * 100.0/MAX_SCORE),
-                               name_munged, other_munged);
+                               similarity_index(p), name_munged, other_munged);
                break;
        case DIFF_STATUS_MODIFIED:
                if (p->score) {
                        len += snprintf(msg + len, sizeof(msg) - len,
                                        "dissimilarity index %d%%\n",
-                                       (int)(0.5 + p->score *
-                                             100.0/MAX_SCORE));
+                                       similarity_index(p));
                        complete_rewrite = 1;
                        break;
                }
@@ -1878,8 +1895,8 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
 
                if (o->binary) {
                        mmfile_t mf;
-                       if ((!fill_mmfile(&mf, one) && file_is_binary(one)) ||
-                           (!fill_mmfile(&mf, two) && file_is_binary(two)))
+                       if ((!fill_mmfile(&mf, one) && diff_filespec_is_binary(one)) ||
+                           (!fill_mmfile(&mf, two) && diff_filespec_is_binary(two)))
                                abbrev = 40;
                }
                len += snprintf(msg + len, sizeof(msg) - len,
@@ -2239,6 +2256,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
                options->exit_with_status = 1;
        else if (!strcmp(arg, "--quiet"))
                options->quiet = 1;
+       else if (!strcmp(arg, "--ext-diff"))
+               options->allow_external = 1;
+       else if (!strcmp(arg, "--no-ext-diff"))
+               options->allow_external = 0;
        else
                return 0;
        return 1;
@@ -2387,8 +2408,7 @@ static void diff_flush_raw(struct diff_filepair *p,
        }
 
        if (p->score)
-               sprintf(status, "%c%03d", p->status,
-                       (int)(0.5 + p->score * 100.0/MAX_SCORE));
+               sprintf(status, "%c%03d", p->status, similarity_index(p));
        else {
                status[0] = p->status;
                status[1] = 0;
@@ -2413,7 +2433,8 @@ static void diff_flush_raw(struct diff_filepair *p,
                printf("%s ",
                       diff_unique_abbrev(p->two->sha1, abbrev));
        }
-       printf("%s%c%s", status, inter_name_termination, path_one);
+       printf("%s%c%s", status, inter_name_termination,
+                       two_paths || p->one->mode ?  path_one : path_two);
        if (two_paths)
                printf("%c%s", inter_name_termination, path_two);
        putchar(line_termination);
@@ -2670,8 +2691,7 @@ static void show_rename_copy(const char *renamecopy, struct diff_filepair *p)
 {
        char *names = pprint_rename(p->one->path, p->two->path);
 
-       printf(" %s %s (%d%%)\n", renamecopy, names,
-              (int)(0.5 + p->score * 100.0/MAX_SCORE));
+       printf(" %s %s (%d%%)\n", renamecopy, names, similarity_index(p));
        free(names);
        show_mode_change(p, 0);
 }
@@ -2695,7 +2715,7 @@ static void diff_summary(struct diff_filepair *p)
                if (p->score) {
                        char *name = quote_one(p->two->path);
                        printf(" rewrite %s (%d%%)\n", name,
-                               (int)(0.5 + p->score * 100.0/MAX_SCORE));
+                              similarity_index(p));
                        free(name);
                        show_mode_change(p, 0);
                } else  show_mode_change(p, 1);
@@ -2759,6 +2779,7 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
                struct diff_filepair *p = q->queue[i];
                int len1, len2;
 
+               memset(&xecfg, 0, sizeof(xecfg));
                if (p->status == 0)
                        return error("internal diff status error");
                if (p->status == DIFF_STATUS_UNKNOWN)
@@ -2778,7 +2799,7 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
                        return error("unable to read files to diff");
 
                /* Maybe hash p->two? into the patch id? */
-               if (file_is_binary(p->two))
+               if (diff_filespec_is_binary(p->two))
                        continue;
 
                len1 = remove_space(p->one->path, strlen(p->one->path));
@@ -3005,6 +3026,7 @@ void diffcore_std(struct diff_options *options)
 {
        if (options->quiet)
                return;
+
        if (options->break_opt != -1)
                diffcore_break(options->break_opt);
        if (options->detect_rename)