gitweb: link to 7-char+ SHA-1s, not only 8-char+
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index 7d0341988083dae44f8833875762b0b978bbafc0..7a4309397cb7fd6819d6f643b259c2bc3abe202f 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -354,7 +354,6 @@ struct emit_callback {
        const char **label_path;
        struct diff_words_data *diff_words;
        struct diff_options *opt;
-       int *found_changesp;
        struct strbuf *header;
 };
 
@@ -722,7 +721,6 @@ static void emit_rewrite_diff(const char *name_a,
 
        memset(&ecbdata, 0, sizeof(ecbdata));
        ecbdata.color_diff = want_color(o->use_color);
-       ecbdata.found_changesp = &o->found_changes;
        ecbdata.ws_rule = whitespace_rule(name_b);
        ecbdata.opt = o;
        if (ecbdata.ws_rule & WS_BLANK_AT_EOF) {
@@ -951,7 +949,8 @@ static int find_word_boundaries(mmfile_t *buffer, regex_t *word_regex,
 {
        if (word_regex && *begin < buffer->size) {
                regmatch_t match[1];
-               if (!regexec(word_regex, buffer->ptr + *begin, 1, match, 0)) {
+               if (!regexec_buf(word_regex, buffer->ptr + *begin,
+                                buffer->size - *begin, 1, match, 0)) {
                        char *p = memchr(buffer->ptr + *begin + match[0].rm_so,
                                        '\n', match[0].rm_eo - match[0].rm_so);
                        *end = p ? p - buffer->ptr : match[0].rm_eo + *begin;
@@ -1216,12 +1215,13 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
        struct diff_options *o = ecbdata->opt;
        const char *line_prefix = diff_line_prefix(o);
 
+       o->found_changes = 1;
+
        if (ecbdata->header) {
-               fprintf(ecbdata->opt->file, "%s", ecbdata->header->buf);
+               fprintf(o->file, "%s", ecbdata->header->buf);
                strbuf_reset(ecbdata->header);
                ecbdata->header = NULL;
        }
-       *(ecbdata->found_changesp) = 1;
 
        if (ecbdata->label_path[0]) {
                const char *name_a_tab, *name_b_tab;
@@ -1229,9 +1229,9 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
                name_a_tab = strchr(ecbdata->label_path[0], ' ') ? "\t" : "";
                name_b_tab = strchr(ecbdata->label_path[1], ' ') ? "\t" : "";
 
-               fprintf(ecbdata->opt->file, "%s%s--- %s%s%s\n",
+               fprintf(o->file, "%s%s--- %s%s%s\n",
                        line_prefix, meta, ecbdata->label_path[0], reset, name_a_tab);
-               fprintf(ecbdata->opt->file, "%s%s+++ %s%s%s\n",
+               fprintf(o->file, "%s%s+++ %s%s%s\n",
                        line_prefix, meta, ecbdata->label_path[1], reset, name_b_tab);
                ecbdata->label_path[0] = ecbdata->label_path[1] = NULL;
        }
@@ -1249,15 +1249,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
                find_lno(line, ecbdata);
                emit_hunk_header(ecbdata, line, len);
                if (line[len-1] != '\n')
-                       putc('\n', ecbdata->opt->file);
-               return;
-       }
-
-       if (len < 1) {
-               emit_line(ecbdata->opt, reset, reset, line, len);
-               if (ecbdata->diff_words
-                   && ecbdata->diff_words->type == DIFF_WORDS_PORCELAIN)
-                       fputs("~\n", ecbdata->opt->file);
+                       putc('\n', o->file);
                return;
        }
 
@@ -1282,8 +1274,8 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
                }
                diff_words_flush(ecbdata);
                if (ecbdata->diff_words->type == DIFF_WORDS_PORCELAIN) {
-                       emit_line(ecbdata->opt, context, reset, line, len);
-                       fputs("~\n", ecbdata->opt->file);
+                       emit_line(o, context, reset, line, len);
+                       fputs("~\n", o->file);
                } else {
                        /*
                         * Skip the prefix character, if any.  With
@@ -1294,7 +1286,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
                              line++;
                              len--;
                        }
-                       emit_line(ecbdata->opt, context, reset, line, len);
+                       emit_line(o, context, reset, line, len);
                }
                return;
        }
@@ -1316,8 +1308,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
        default:
                /* incomplete line at the end */
                ecbdata->lno_in_preimage++;
-               emit_line(ecbdata->opt,
-                         diff_get_color(ecbdata->color_diff, DIFF_CONTEXT),
+               emit_line(o, diff_get_color(ecbdata->color_diff, DIFF_CONTEXT),
                          reset, line, len);
                break;
        }
@@ -2438,7 +2429,6 @@ static void builtin_diff(const char *name_a,
                memset(&ecbdata, 0, sizeof(ecbdata));
                ecbdata.label_path = lbl;
                ecbdata.color_diff = want_color(o->use_color);
-               ecbdata.found_changesp = &o->found_changes;
                ecbdata.ws_rule = whitespace_rule(name_b);
                if (ecbdata.ws_rule & WS_BLANK_AT_EOF)
                        check_blank_at_eof(&mf1, &mf2, &ecbdata);
@@ -2683,6 +2673,13 @@ static int reuse_worktree_file(const char *name, const unsigned char *sha1, int
        if (!FAST_WORKING_DIRECTORY && !want_file && has_sha1_pack(sha1))
                return 0;
 
+       /*
+        * Similarly, if we'd have to convert the file contents anyway, that
+        * makes the optimization not worthwhile.
+        */
+       if (!want_file && would_convert_to_git(name))
+               return 0;
+
        len = strlen(name);
        pos = cache_name_pos(name, len);
        if (pos < 0)
@@ -4455,7 +4452,7 @@ static void patch_id_consume(void *priv, char *line, unsigned long len)
 }
 
 /* returns 0 upon success, and writes result into sha1 */
-static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
+static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1, int diff_header_only)
 {
        struct diff_queue_struct *q = &diff_queued_diff;
        int i;
@@ -4490,9 +4487,6 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
 
                diff_fill_sha1_info(p->one);
                diff_fill_sha1_info(p->two);
-               if (fill_mmfile(&mf1, p->one) < 0 ||
-                               fill_mmfile(&mf2, p->two) < 0)
-                       return error("unable to read files to diff");
 
                len1 = remove_space(p->one->path, strlen(p->one->path));
                len2 = remove_space(p->two->path, strlen(p->two->path));
@@ -4527,6 +4521,13 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
                                        len2, p->two->path);
                git_SHA1_Update(&ctx, buffer, len1);
 
+               if (diff_header_only)
+                       continue;
+
+               if (fill_mmfile(&mf1, p->one) < 0 ||
+                   fill_mmfile(&mf2, p->two) < 0)
+                       return error("unable to read files to diff");
+
                if (diff_filespec_is_binary(p->one) ||
                    diff_filespec_is_binary(p->two)) {
                        git_SHA1_Update(&ctx, oid_to_hex(&p->one->oid),
@@ -4549,11 +4550,11 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
        return 0;
 }
 
-int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1)
+int diff_flush_patch_id(struct diff_options *options, unsigned char *sha1, int diff_header_only)
 {
        struct diff_queue_struct *q = &diff_queued_diff;
        int i;
-       int result = diff_get_patch_id(options, sha1);
+       int result = diff_get_patch_id(options, sha1, diff_header_only);
 
        for (i = 0; i < q->nr; i++)
                diff_free_filepair(q->queue[i]);