Update draft Release Notes for 1.5.4
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index 67cce8b72ec094b516c50592afe2f168b18c0d4c..f780e3e8e67f4b1e07ef1d70ab3b9f101ff6b868 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -146,7 +146,7 @@ int git_diff_ui_config(const char *var, const char *value)
                return 0;
        }
        if (!strcmp(var, "diff.color") || !strcmp(var, "color.diff")) {
-               diff_use_color_default = git_config_colorbool(var, value);
+               diff_use_color_default = git_config_colorbool(var, value, -1);
                return 0;
        }
        if (!strcmp(var, "diff.renames")) {
@@ -454,6 +454,7 @@ static void diff_words_show(struct diff_words_data *diff_words)
 struct emit_callback {
        struct xdiff_emit_state xm;
        int nparents, color_diff;
+       unsigned ws_rule;
        const char **label_path;
        struct diff_words_data *diff_words;
        int *found_changesp;
@@ -493,8 +494,8 @@ static void emit_line(const char *set, const char *reset, const char *line, int
 }
 
 static void emit_line_with_ws(int nparents,
-               const char *set, const char *reset, const char *ws,
-               const char *line, int len)
+                             const char *set, const char *reset, const char *ws,
+                             const char *line, int len, unsigned ws_rule)
 {
        int col0 = nparents;
        int last_tab_in_indent = -1;
@@ -502,13 +503,17 @@ static void emit_line_with_ws(int nparents,
        int i;
        int tail = len;
        int need_highlight_leading_space = 0;
-       /* The line is a newly added line.  Does it have funny leading
-        * whitespaces?  In indent, SP should never precede a TAB.
+       /*
+        * The line is a newly added line.  Does it have funny leading
+        * whitespaces?  In indent, SP should never precede a TAB.  In
+        * addition, under "indent with non tab" rule, there should not
+        * be more than 8 consecutive spaces.
         */
        for (i = col0; i < len; i++) {
                if (line[i] == '\t') {
                        last_tab_in_indent = i;
-                       if (0 <= last_space_in_indent)
+                       if ((ws_rule & WS_SPACE_BEFORE_TAB) &&
+                           0 <= last_space_in_indent)
                                need_highlight_leading_space = 1;
                }
                else if (line[i] == ' ')
@@ -516,6 +521,13 @@ static void emit_line_with_ws(int nparents,
                else
                        break;
        }
+       if ((ws_rule & WS_INDENT_WITH_NON_TAB) &&
+           0 <= last_space_in_indent &&
+           last_tab_in_indent < 0 &&
+           8 <= (i - col0)) {
+               last_tab_in_indent = i;
+               need_highlight_leading_space = 1;
+       }
        fputs(set, stdout);
        fwrite(line, col0, 1, stdout);
        fputs(reset, stdout);
@@ -540,10 +552,12 @@ static void emit_line_with_ws(int nparents,
        tail = len - 1;
        if (line[tail] == '\n' && i < tail)
                tail--;
-       while (i < tail) {
-               if (!isspace(line[tail]))
-                       break;
-               tail--;
+       if (ws_rule & WS_TRAILING_SPACE) {
+               while (i < tail) {
+                       if (!isspace(line[tail]))
+                               break;
+                       tail--;
+               }
        }
        if ((i < tail && line[tail + 1] != '\n')) {
                /* This has whitespace between tail+1..len */
@@ -565,7 +579,7 @@ static void emit_add_line(const char *reset, struct emit_callback *ecbdata, cons
                emit_line(set, reset, line, len);
        else
                emit_line_with_ws(ecbdata->nparents, set, reset, ws,
-                               line, len);
+                                 line, len, ecbdata->ws_rule);
 }
 
 static void fn_out_consume(void *priv, char *line, unsigned long len)
@@ -981,6 +995,7 @@ struct checkdiff_t {
        struct xdiff_emit_state xm;
        const char *filename;
        int lineno, color_diff;
+       unsigned ws_rule;
 };
 
 static void checkdiff_consume(void *priv, char *line, unsigned long len)
@@ -1016,7 +1031,8 @@ static void checkdiff_consume(void *priv, char *line, unsigned long len)
                        if (white_space_at_end)
                                printf("white space at end");
                        printf(":%s ", reset);
-                       emit_line_with_ws(1, set, reset, ws, line, len);
+                       emit_line_with_ws(1, set, reset, ws, line, len,
+                                         data->ws_rule);
                }
 
                data->lineno++;
@@ -1317,6 +1333,7 @@ static void builtin_diff(const char *name_a,
                ecbdata.label_path = lbl;
                ecbdata.color_diff = DIFF_OPT_TST(o, COLOR_DIFF);
                ecbdata.found_changesp = &o->found_changes;
+               ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a);
                xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
                xecfg.ctxlen = o->context;
                xecfg.flags = XDL_EMIT_FUNCNAMES;
@@ -1410,6 +1427,7 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
        data.filename = name_b ? name_b : name_a;
        data.lineno = 0;
        data.color_diff = DIFF_OPT_TST(o, COLOR_DIFF);
+       data.ws_rule = whitespace_rule(data.filename);
 
        if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
                die("unable to read files to diff");
@@ -2185,6 +2203,8 @@ static int diff_scoreopt_parse(const char *opt);
 int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 {
        const char *arg = av[0];
+
+       /* Output format options */
        if (!strcmp(arg, "-p") || !strcmp(arg, "-u"))
                options->output_format |= DIFF_FORMAT_PATCH;
        else if (opt_arg(arg, 'U', "unified", &options->context))
@@ -2197,6 +2217,18 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
                options->output_format |= DIFF_FORMAT_NUMSTAT;
        else if (!strcmp(arg, "--shortstat"))
                options->output_format |= DIFF_FORMAT_SHORTSTAT;
+       else if (!strcmp(arg, "--check"))
+               options->output_format |= DIFF_FORMAT_CHECKDIFF;
+       else if (!strcmp(arg, "--summary"))
+               options->output_format |= DIFF_FORMAT_SUMMARY;
+       else if (!strcmp(arg, "--patch-with-stat"))
+               options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_DIFFSTAT;
+       else if (!strcmp(arg, "--name-only"))
+               options->output_format |= DIFF_FORMAT_NAME;
+       else if (!strcmp(arg, "--name-status"))
+               options->output_format |= DIFF_FORMAT_NAME_STATUS;
+       else if (!strcmp(arg, "-s"))
+               options->output_format |= DIFF_FORMAT_NO_OUTPUT;
        else if (!prefixcmp(arg, "--stat")) {
                char *end;
                int width = options->stat_width;
@@ -2224,42 +2256,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
                options->stat_name_width = name_width;
                options->stat_width = width;
        }
-       else if (!strcmp(arg, "--check"))
-               options->output_format |= DIFF_FORMAT_CHECKDIFF;
-       else if (!strcmp(arg, "--summary"))
-               options->output_format |= DIFF_FORMAT_SUMMARY;
-       else if (!strcmp(arg, "--patch-with-stat"))
-               options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_DIFFSTAT;
-       else if (!strcmp(arg, "-z"))
-               options->line_termination = 0;
-       else if (!prefixcmp(arg, "-l"))
-               options->rename_limit = strtoul(arg+2, NULL, 10);
-       else if (!strcmp(arg, "--full-index"))
-               DIFF_OPT_SET(options, FULL_INDEX);
-       else if (!strcmp(arg, "--binary")) {
-               options->output_format |= DIFF_FORMAT_PATCH;
-               DIFF_OPT_SET(options, BINARY);
-       }
-       else if (!strcmp(arg, "-a") || !strcmp(arg, "--text"))
-               DIFF_OPT_SET(options, TEXT);
-       else if (!strcmp(arg, "--name-only"))
-               options->output_format |= DIFF_FORMAT_NAME;
-       else if (!strcmp(arg, "--name-status"))
-               options->output_format |= DIFF_FORMAT_NAME_STATUS;
-       else if (!strcmp(arg, "-R"))
-               DIFF_OPT_SET(options, REVERSE_DIFF);
-       else if (!prefixcmp(arg, "-S"))
-               options->pickaxe = arg + 2;
-       else if (!strcmp(arg, "-s"))
-               options->output_format |= DIFF_FORMAT_NO_OUTPUT;
-       else if (!prefixcmp(arg, "-O"))
-               options->orderfile = arg + 2;
-       else if (!prefixcmp(arg, "--diff-filter="))
-               options->filter = arg + 14;
-       else if (!strcmp(arg, "--pickaxe-all"))
-               options->pickaxe_opts = DIFF_PICKAXE_ALL;
-       else if (!strcmp(arg, "--pickaxe-regex"))
-               options->pickaxe_opts = DIFF_PICKAXE_REGEX;
+
+       /* renames options */
        else if (!prefixcmp(arg, "-B")) {
                if ((options->break_opt = diff_scoreopt_parse(arg)) == -1)
                        return -1;
@@ -2276,33 +2274,38 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
                        return -1;
                options->detect_rename = DIFF_DETECT_COPY;
        }
+       else if (!strcmp(arg, "--no-renames"))
+               options->detect_rename = 0;
+
+       /* xdiff options */
+       else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space"))
+               options->xdl_opts |= XDF_IGNORE_WHITESPACE;
+       else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
+               options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
+       else if (!strcmp(arg, "--ignore-space-at-eol"))
+               options->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL;
+
+       /* flags options */
+       else if (!strcmp(arg, "--binary")) {
+               options->output_format |= DIFF_FORMAT_PATCH;
+               DIFF_OPT_SET(options, BINARY);
+       }
+       else if (!strcmp(arg, "--full-index"))
+               DIFF_OPT_SET(options, FULL_INDEX);
+       else if (!strcmp(arg, "-a") || !strcmp(arg, "--text"))
+               DIFF_OPT_SET(options, TEXT);
+       else if (!strcmp(arg, "-R"))
+               DIFF_OPT_SET(options, REVERSE_DIFF);
        else if (!strcmp(arg, "--find-copies-harder"))
                DIFF_OPT_SET(options, FIND_COPIES_HARDER);
        else if (!strcmp(arg, "--follow"))
                DIFF_OPT_SET(options, FOLLOW_RENAMES);
-       else if (!strcmp(arg, "--abbrev"))
-               options->abbrev = DEFAULT_ABBREV;
-       else if (!prefixcmp(arg, "--abbrev=")) {
-               options->abbrev = strtoul(arg + 9, NULL, 10);
-               if (options->abbrev < MINIMUM_ABBREV)
-                       options->abbrev = MINIMUM_ABBREV;
-               else if (40 < options->abbrev)
-                       options->abbrev = 40;
-       }
        else if (!strcmp(arg, "--color"))
                DIFF_OPT_SET(options, COLOR_DIFF);
        else if (!strcmp(arg, "--no-color"))
                DIFF_OPT_CLR(options, COLOR_DIFF);
-       else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space"))
-               options->xdl_opts |= XDF_IGNORE_WHITESPACE;
-       else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
-               options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
-       else if (!strcmp(arg, "--ignore-space-at-eol"))
-               options->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL;
        else if (!strcmp(arg, "--color-words"))
                options->flags |= DIFF_OPT_COLOR_DIFF | DIFF_OPT_COLOR_DIFF_WORDS;
-       else if (!strcmp(arg, "--no-renames"))
-               options->detect_rename = 0;
        else if (!strcmp(arg, "--exit-code"))
                DIFF_OPT_SET(options, EXIT_WITH_STATUS);
        else if (!strcmp(arg, "--quiet"))
@@ -2311,6 +2314,31 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
                DIFF_OPT_SET(options, ALLOW_EXTERNAL);
        else if (!strcmp(arg, "--no-ext-diff"))
                DIFF_OPT_CLR(options, ALLOW_EXTERNAL);
+
+       /* misc options */
+       else if (!strcmp(arg, "-z"))
+               options->line_termination = 0;
+       else if (!prefixcmp(arg, "-l"))
+               options->rename_limit = strtoul(arg+2, NULL, 10);
+       else if (!prefixcmp(arg, "-S"))
+               options->pickaxe = arg + 2;
+       else if (!strcmp(arg, "--pickaxe-all"))
+               options->pickaxe_opts = DIFF_PICKAXE_ALL;
+       else if (!strcmp(arg, "--pickaxe-regex"))
+               options->pickaxe_opts = DIFF_PICKAXE_REGEX;
+       else if (!prefixcmp(arg, "-O"))
+               options->orderfile = arg + 2;
+       else if (!prefixcmp(arg, "--diff-filter="))
+               options->filter = arg + 14;
+       else if (!strcmp(arg, "--abbrev"))
+               options->abbrev = DEFAULT_ABBREV;
+       else if (!prefixcmp(arg, "--abbrev=")) {
+               options->abbrev = strtoul(arg + 9, NULL, 10);
+               if (options->abbrev < MINIMUM_ABBREV)
+                       options->abbrev = MINIMUM_ABBREV;
+               else if (40 < options->abbrev)
+                       options->abbrev = 40;
+       }
        else
                return 0;
        return 1;
@@ -2706,7 +2734,7 @@ static void diff_summary(struct diff_filepair *p)
                break;
        default:
                if (p->score) {
-                       puts(" rewrite ");
+                       fputs(" rewrite ", stdout);
                        write_name_quoted(p->two->path, stdout, ' ');
                        printf("(%d%%)\n", similarity_index(p));
                }