subtree: improve decision on merges kept in split
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index 7a23adf254d24a1b25c9d78eaac54f0721998a62..f0c7557b40443da060c3070c602dd03f49b0d689 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -283,10 +283,12 @@ static int parse_color_moved(const char *arg)
                return COLOR_MOVED_ZEBRA;
        else if (!strcmp(arg, "default"))
                return COLOR_MOVED_DEFAULT;
+       else if (!strcmp(arg, "dimmed-zebra"))
+               return COLOR_MOVED_ZEBRA_DIM;
        else if (!strcmp(arg, "dimmed_zebra"))
                return COLOR_MOVED_ZEBRA_DIM;
        else
-               return error(_("color moved setting must be one of 'no', 'default', 'blocks', 'zebra', 'dimmed_zebra', 'plain'"));
+               return error(_("color moved setting must be one of 'no', 'default', 'blocks', 'zebra', 'dimmed-zebra', 'plain'"));
 }
 
 static int parse_color_moved_ws(const char *arg)
@@ -626,43 +628,50 @@ static void emit_line_0(struct diff_options *o,
                        int first, const char *line, int len)
 {
        int has_trailing_newline, has_trailing_carriage_return;
-       int nofirst;
+       int needs_reset = 0; /* at the end of the line */
        FILE *file = o->file;
 
        fputs(diff_line_prefix(o), file);
 
-       if (len == 0) {
-               has_trailing_newline = (first == '\n');
-               has_trailing_carriage_return = (!has_trailing_newline &&
-                                               (first == '\r'));
-               nofirst = has_trailing_newline || has_trailing_carriage_return;
-       } else {
-               has_trailing_newline = (len > 0 && line[len-1] == '\n');
-               if (has_trailing_newline)
-                       len--;
-               has_trailing_carriage_return = (len > 0 && line[len-1] == '\r');
-               if (has_trailing_carriage_return)
-                       len--;
-               nofirst = 0;
-       }
-
-       if (len || !nofirst) {
-               if (reverse && want_color(o->use_color))
-                       fputs(GIT_COLOR_REVERSE, file);
-               if (set_sign)
-                       fputs(set_sign, file);
-               if (first && !nofirst)
-                       fputc(first, file);
-               if (len) {
-                       if (set && set != set_sign) {
-                               if (set_sign)
-                                       fputs(reset, file);
-                               fputs(set, file);
-                       }
-                       fwrite(line, len, 1, file);
-               }
-               fputs(reset, file);
+       has_trailing_newline = (len > 0 && line[len-1] == '\n');
+       if (has_trailing_newline)
+               len--;
+
+       has_trailing_carriage_return = (len > 0 && line[len-1] == '\r');
+       if (has_trailing_carriage_return)
+               len--;
+
+       if (!len && !first)
+               goto end_of_line;
+
+       if (reverse && want_color(o->use_color)) {
+               fputs(GIT_COLOR_REVERSE, file);
+               needs_reset = 1;
        }
+
+       if (set_sign) {
+               fputs(set_sign, file);
+               needs_reset = 1;
+       }
+
+       if (first)
+               fputc(first, file);
+
+       if (!len)
+               goto end_of_line;
+
+       if (set) {
+               if (set_sign && set != set_sign)
+                       fputs(reset, file);
+               fputs(set, file);
+               needs_reset = 1;
+       }
+       fwrite(line, len, 1, file);
+       needs_reset = 1; /* 'line' may contain color codes. */
+
+end_of_line:
+       if (needs_reset)
+               fputs(reset, file);
        if (has_trailing_carriage_return)
                fputc('\r', file);
        if (has_trailing_newline)
@@ -672,7 +681,7 @@ static void emit_line_0(struct diff_options *o,
 static void emit_line(struct diff_options *o, const char *set, const char *reset,
                      const char *line, int len)
 {
-       emit_line_0(o, set, NULL, 0, reset, line[0], line+1, len-1);
+       emit_line_0(o, set, NULL, 0, reset, 0, line, len);
 }
 
 enum diff_symbol {
@@ -971,8 +980,13 @@ static void pmb_advance_or_null_multi_match(struct diff_options *o,
                        /* Carry the white space delta forward */
                        pmb[i]->next_line->wsd = pmb[i]->wsd;
                        pmb[i] = pmb[i]->next_line;
-               } else
+               } else {
+                       if (pmb[i]->wsd) {
+                               free(pmb[i]->wsd->string);
+                               FREE_AND_NULL(pmb[i]->wsd);
+                       }
                        pmb[i] = NULL;
+               }
        }
 }
 
@@ -993,10 +1007,6 @@ static int shrink_potential_moved_blocks(struct moved_entry **pmb,
 
                if (lp < pmb_nr && rp > -1 && lp < rp) {
                        pmb[lp] = pmb[rp];
-                       if (pmb[rp]->wsd) {
-                               free(pmb[rp]->wsd->string);
-                               FREE_AND_NULL(pmb[rp]->wsd);
-                       }
                        pmb[rp] = NULL;
                        rp--;
                        lp++;
@@ -1274,7 +1284,9 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
                        else if (c == '-')
                                set = diff_get_color_opt(o, DIFF_FILE_OLD);
                }
-               emit_line_ws_markup(o, set_sign, set, reset, ' ', line, len,
+               emit_line_ws_markup(o, set_sign, set, reset,
+                                   o->output_indicators[OUTPUT_INDICATOR_CONTEXT],
+                                   line, len,
                                    flags & (DIFF_SYMBOL_CONTENT_WS_MASK), 0);
                break;
        case DIFF_SYMBOL_PLUS:
@@ -1317,7 +1329,9 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
                                set = diff_get_color_opt(o, DIFF_CONTEXT_BOLD);
                        flags &= ~DIFF_SYMBOL_CONTENT_WS_MASK;
                }
-               emit_line_ws_markup(o, set_sign, set, reset, '+', line, len,
+               emit_line_ws_markup(o, set_sign, set, reset,
+                                   o->output_indicators[OUTPUT_INDICATOR_NEW],
+                                   line, len,
                                    flags & DIFF_SYMBOL_CONTENT_WS_MASK,
                                    flags & DIFF_SYMBOL_CONTENT_BLANK_LINE_EOF);
                break;
@@ -1360,7 +1374,9 @@ static void emit_diff_symbol_from_struct(struct diff_options *o,
                        else
                                set = diff_get_color_opt(o, DIFF_CONTEXT_DIM);
                }
-               emit_line_ws_markup(o, set_sign, set, reset, '-', line, len,
+               emit_line_ws_markup(o, set_sign, set, reset,
+                                   o->output_indicators[OUTPUT_INDICATOR_OLD],
+                                   line, len,
                                    flags & DIFF_SYMBOL_CONTENT_WS_MASK, 0);
                break;
        case DIFF_SYMBOL_WORDS_PORCELAIN:
@@ -2141,8 +2157,8 @@ static void init_diff_words_data(struct emit_callback *ecbdata,
                if (regcomp(ecbdata->diff_words->word_regex,
                            o->word_regex,
                            REG_EXTENDED | REG_NEWLINE))
-                       die ("Invalid regular expression: %s",
-                            o->word_regex);
+                       die("invalid regular expression: %s",
+                           o->word_regex);
        }
        for (i = 0; i < ARRAY_SIZE(diff_words_styles); i++) {
                if (o->word_diff == diff_words_styles[i].type) {
@@ -2933,16 +2949,11 @@ static void show_dirstat(struct diff_options *options)
                struct diff_filepair *p = q->queue[i];
                const char *name;
                unsigned long copied, added, damage;
-               int content_changed;
 
                name = p->two->path ? p->two->path : p->one->path;
 
-               if (p->one->oid_valid && p->two->oid_valid)
-                       content_changed = oidcmp(&p->one->oid, &p->two->oid);
-               else
-                       content_changed = 1;
-
-               if (!content_changed) {
+               if (p->one->oid_valid && p->two->oid_valid &&
+                   oideq(&p->one->oid, &p->two->oid)) {
                        /*
                         * The SHA1 has not changed, so pre-/post-content is
                         * identical. We can therefore skip looking at the
@@ -2989,7 +3000,7 @@ static void show_dirstat(struct diff_options *options)
                 * made to the preimage.
                 * If the resulting damage is zero, we know that
                 * diffcore_count_changes() considers the two entries to
-                * be identical, but since content_changed is true, we
+                * be identical, but since the oid changed, we
                 * know that there must have been _some_ kind of change,
                 * so we force all entries to have damage > 0.
                 */
@@ -3404,7 +3415,7 @@ static void builtin_diff(const char *name_a,
                if (!one->data && !two->data &&
                    S_ISREG(one->mode) && S_ISREG(two->mode) &&
                    !o->flags.binary) {
-                       if (!oidcmp(&one->oid, &two->oid)) {
+                       if (oideq(&one->oid, &two->oid)) {
                                if (must_show_header)
                                        emit_diff_symbol(o, DIFF_SYMBOL_HEADER,
                                                         header.buf, header.len,
@@ -3569,7 +3580,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
                return;
        }
 
-       same_contents = !oidcmp(&one->oid, &two->oid);
+       same_contents = oideq(&one->oid, &two->oid);
 
        if (diff_filespec_is_binary(one) || diff_filespec_is_binary(two)) {
                data->is_binary = 1;
@@ -3765,7 +3776,7 @@ static int reuse_worktree_file(const char *name, const struct object_id *oid, in
         * This is not the sha1 we are looking for, or
         * unreusable because it is not a regular file.
         */
-       if (oidcmp(oid, &ce->oid) || !S_ISREG(ce->ce_mode))
+       if (!oideq(oid, &ce->oid) || !S_ISREG(ce->ce_mode))
                return 0;
 
        /*
@@ -3968,7 +3979,7 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
        temp->tempfile = mks_tempfile_ts(tempfile.buf, strlen(base) + 1);
        if (!temp->tempfile)
                die_errno("unable to create temp-file");
-       if (convert_to_working_tree(path,
+       if (convert_to_working_tree(&the_index, path,
                        (const char *)blob, (size_t)size, &buf)) {
                blob = buf.buf;
                size = buf.len;
@@ -4170,7 +4181,7 @@ static void fill_metainfo(struct strbuf *msg,
        default:
                *must_show_header = 0;
        }
-       if (one && two && oidcmp(&one->oid, &two->oid)) {
+       if (one && two && !oideq(&one->oid, &two->oid)) {
                const unsigned hexsz = the_hash_algo->hexsz;
                int abbrev = o->flags.full_index ? hexsz : DEFAULT_ABBREV;
 
@@ -4375,6 +4386,9 @@ void diff_setup(struct diff_options *options)
 
        options->file = stdout;
 
+       options->output_indicators[OUTPUT_INDICATOR_NEW] = '+';
+       options->output_indicators[OUTPUT_INDICATOR_OLD] = '-';
+       options->output_indicators[OUTPUT_INDICATOR_CONTEXT] = ' ';
        options->abbrev = DEFAULT_ABBREV;
        options->line_termination = '\n';
        options->break_opt = -1;
@@ -4489,16 +4503,6 @@ void diff_setup_done(struct diff_options *options)
 
        if (options->detect_rename && options->rename_limit < 0)
                options->rename_limit = diff_rename_limit_default;
-       if (options->setup & DIFF_SETUP_USE_CACHE) {
-               if (!active_cache)
-                       /* read-cache does not die even when it fails
-                        * so it is safe for us to do this here.  Also
-                        * it does not smudge active_cache or active_nr
-                        * when it fails, so we do not have to worry about
-                        * cleaning it up ourselves either.
-                        */
-                       read_cache();
-       }
        if (hexsz < options->abbrev)
                options->abbrev = hexsz; /* full */
 
@@ -4862,6 +4866,12 @@ int diff_opt_parse(struct diff_options *options,
                 options->output_format |= DIFF_FORMAT_DIFFSTAT;
        } else if (!strcmp(arg, "--no-compact-summary"))
                 options->flags.stat_with_summary = 0;
+       else if (skip_prefix(arg, "--output-indicator-new=", &arg))
+               options->output_indicators[OUTPUT_INDICATOR_NEW] = arg[0];
+       else if (skip_prefix(arg, "--output-indicator-old=", &arg))
+               options->output_indicators[OUTPUT_INDICATOR_OLD] = arg[0];
+       else if (skip_prefix(arg, "--output-indicator-context=", &arg))
+               options->output_indicators[OUTPUT_INDICATOR_CONTEXT] = arg[0];
 
        /* renames options */
        else if (starts_with(arg, "-B") ||
@@ -5333,7 +5343,7 @@ int diff_unmodified_pair(struct diff_filepair *p)
         * dealing with a change.
         */
        if (one->oid_valid && two->oid_valid &&
-           !oidcmp(&one->oid, &two->oid) &&
+           oideq(&one->oid, &two->oid) &&
            !one->dirty_submodule && !two->dirty_submodule)
                return 1; /* no change */
        if (!one->oid_valid && !two->oid_valid)
@@ -5467,7 +5477,7 @@ static void diff_resolve_rename_copy(void)
                        else
                                p->status = DIFF_STATUS_RENAMED;
                }
-               else if (oidcmp(&p->one->oid, &p->two->oid) ||
+               else if (!oideq(&p->one->oid, &p->two->oid) ||
                         p->one->mode != p->two->mode ||
                         p->one->dirty_submodule ||
                         p->two->dirty_submodule ||