Fix double "close()" in ce_compare_data
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index f350c6ba910dfc5ac11aa75ba0af668237cd1f8e..6a713764831e7521958f4b280f2e1d3911fb3cea 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -17,23 +17,15 @@ static int diff_detect_rename_default = 0;
 static int diff_rename_limit_default = -1;
 static int diff_use_color_default = 0;
 
-enum color_diff {
-       DIFF_RESET = 0,
-       DIFF_PLAIN = 1,
-       DIFF_METAINFO = 2,
-       DIFF_FRAGINFO = 3,
-       DIFF_FILE_OLD = 4,
-       DIFF_FILE_NEW = 5,
-};
-
-/* "\033[1;30;47m\0" is 11 bytes */
-static char diff_colors[][16] = {
+/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
+static char diff_colors[][24] = {
        "\033[m",       /* reset */
        "",             /* normal */
        "\033[1m",      /* bold */
        "\033[36m",     /* cyan */
        "\033[31m",     /* red */
-       "\033[32m"      /* green */
+       "\033[32m",     /* green */
+       "\033[33m"      /* yellow */
 };
 
 static int parse_diff_color_slot(const char *var, int ofs)
@@ -48,6 +40,8 @@ static int parse_diff_color_slot(const char *var, int ofs)
                return DIFF_FILE_OLD;
        if (!strcasecmp(var+ofs, "new"))
                return DIFF_FILE_NEW;
+       if (!strcasecmp(var+ofs, "commit"))
+               return DIFF_COMMIT;
        die("bad config variable '%s'", var);
 }
 
@@ -57,12 +51,16 @@ static int parse_color(const char *name, int len)
                "normal", "black", "red", "green", "yellow",
                "blue", "magenta", "cyan", "white"
        };
+       char *end;
        int i;
        for (i = 0; i < ARRAY_SIZE(color_names); i++) {
                const char *str = color_names[i];
                if (!strncasecmp(name, str, len) && !str[len])
                        return i - 1;
        }
+       i = strtol(name, &end, 10);
+       if (*name && !*end && i >= -1 && i <= 255)
+               return i;
        return -2;
 }
 
@@ -135,14 +133,22 @@ static void parse_diff_color_value(const char *value, const char *var, char *dst
                if (fg >= 0) {
                        if (sep++)
                                *dst++ = ';';
-                       *dst++ = '3';
-                       *dst++ = '0' + fg;
+                       if (fg < 8) {
+                               *dst++ = '3';
+                               *dst++ = '0' + fg;
+                       } else {
+                               dst += sprintf(dst, "38;5;%d", fg);
+                       }
                }
                if (bg >= 0) {
                        if (sep++)
                                *dst++ = ';';
-                       *dst++ = '4';
-                       *dst++ = '0' + bg;
+                       if (bg < 8) {
+                               *dst++ = '4';
+                               *dst++ = '0' + bg;
+                       } else {
+                               dst += sprintf(dst, "48;5;%d", bg);
+                       }
                }
                *dst++ = 'm';
        }
@@ -358,7 +364,7 @@ struct emit_callback {
        const char **label_path;
 };
 
-static inline const char *get_color(int diff_use_color, enum color_diff ix)
+const char *diff_get_color(int diff_use_color, enum color_diff ix)
 {
        if (diff_use_color)
                return diff_colors[ix];
@@ -369,8 +375,8 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
 {
        int i;
        struct emit_callback *ecbdata = priv;
-       const char *set = get_color(ecbdata->color_diff, DIFF_METAINFO);
-       const char *reset = get_color(ecbdata->color_diff, DIFF_RESET);
+       const char *set = diff_get_color(ecbdata->color_diff, DIFF_METAINFO);
+       const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);
 
        if (ecbdata->label_path[0]) {
                printf("%s--- %s%s\n", set, ecbdata->label_path[0], reset);
@@ -385,7 +391,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
                ;
        if (2 <= i && i < len && line[i] == ' ') {
                ecbdata->nparents = i - 1;
-               set = get_color(ecbdata->color_diff, DIFF_FRAGINFO);
+               set = diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO);
        }
        else if (len < ecbdata->nparents)
                set = reset;
@@ -398,7 +404,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
                        else if (line[i] == '+')
                                color = DIFF_FILE_NEW;
                }
-               set = get_color(ecbdata->color_diff, color);
+               set = diff_get_color(ecbdata->color_diff, color);
        }
        if (len > 0 && line[len-1] == '\n')
                len--;
@@ -755,8 +761,8 @@ static void builtin_diff(const char *name_a,
        mmfile_t mf1, mf2;
        const char *lbl[2];
        char *a_one, *b_two;
-       const char *set = get_color(o->color_diff, DIFF_METAINFO);
-       const char *reset = get_color(o->color_diff, DIFF_RESET);
+       const char *set = diff_get_color(o->color_diff, DIFF_METAINFO);
+       const char *reset = diff_get_color(o->color_diff, DIFF_RESET);
 
        a_one = quote_two("a/", name_a);
        b_two = quote_two("b/", name_b);