Merge branch 'jk/color-variable-fixes'

Some places in the code confused a variable that is *not* a boolean
to enable color but is an enum that records what the user requested
to do about color.  A couple of bugs of this sort have been fixed,
while the code has been cleaned up to prevent similar bugs in the
future.

* jk/color-variable-fixes:
  config: store want_color() result in a separate bool
  add-interactive: retain colorbool values longer
  color: return bool from want_color()
  color: use git_colorbool enum type to store colorbools
  pretty: use format_commit_context.auto_color as colorbool
  diff: stop passing ecbdata->use_color as boolean
  diff: pass o->use_color directly to fill_metainfo()
  diff: don't use diff_options.use_color as a strict bool
  diff: simplify color_moved check when flushing
  grep: don't treat grep_opt.color as a strict bool
  color: return enum from git_config_colorbool()
  color: use GIT_COLOR_* instead of numeric constants
main
Junio C Hamano 2025-09-29 11:40:35 -07:00
commit a89fa2fff2
30 changed files with 114 additions and 109 deletions

View File

@ -20,14 +20,14 @@
#include "prompt.h" #include "prompt.h"
#include "tree.h" #include "tree.h"


static void init_color(struct repository *r, int use_color, static void init_color(struct repository *r, enum git_colorbool use_color,
const char *section_and_slot, char *dst, const char *section_and_slot, char *dst,
const char *default_color) const char *default_color)
{ {
char *key = xstrfmt("color.%s", section_and_slot); char *key = xstrfmt("color.%s", section_and_slot);
const char *value; const char *value;


if (!use_color) if (!want_color(use_color))
dst[0] = '\0'; dst[0] = '\0';
else if (repo_config_get_value(r, key, &value) || else if (repo_config_get_value(r, key, &value) ||
color_parse(value, dst)) color_parse(value, dst))
@ -36,13 +36,13 @@ static void init_color(struct repository *r, int use_color,
free(key); free(key);
} }


static int check_color_config(struct repository *r, const char *var) static enum git_colorbool check_color_config(struct repository *r, const char *var)
{ {
const char *value; const char *value;
int ret; enum git_colorbool ret;


if (repo_config_get_value(r, var, &value)) if (repo_config_get_value(r, var, &value))
ret = -1; ret = GIT_COLOR_UNKNOWN;
else else
ret = git_config_colorbool(var, value); ret = git_config_colorbool(var, value);


@ -51,10 +51,11 @@ static int check_color_config(struct repository *r, const char *var)
* the value parsed by git_color_config(), which may not have been * the value parsed by git_color_config(), which may not have been
* called by the main command. * called by the main command.
*/ */
if (ret < 0 && !repo_config_get_value(r, "color.ui", &value)) if (ret == GIT_COLOR_UNKNOWN &&
!repo_config_get_value(r, "color.ui", &value))
ret = git_config_colorbool("color.ui", value); ret = git_config_colorbool("color.ui", value);


return want_color(ret); return ret;
} }


void init_add_i_state(struct add_i_state *s, struct repository *r, void init_add_i_state(struct add_i_state *s, struct repository *r,
@ -75,7 +76,7 @@ void init_add_i_state(struct add_i_state *s, struct repository *r,
init_color(r, s->use_color_interactive, "interactive.error", init_color(r, s->use_color_interactive, "interactive.error",
s->error_color, GIT_COLOR_BOLD_RED); s->error_color, GIT_COLOR_BOLD_RED);
strlcpy(s->reset_color_interactive, strlcpy(s->reset_color_interactive,
s->use_color_interactive ? GIT_COLOR_RESET : "", COLOR_MAXLEN); want_color(s->use_color_interactive) ? GIT_COLOR_RESET : "", COLOR_MAXLEN);


s->use_color_diff = check_color_config(r, "color.diff"); s->use_color_diff = check_color_config(r, "color.diff");


@ -92,7 +93,7 @@ void init_add_i_state(struct add_i_state *s, struct repository *r,
init_color(r, s->use_color_diff, "diff.new", s->file_new_color, init_color(r, s->use_color_diff, "diff.new", s->file_new_color,
diff_get_color(s->use_color_diff, DIFF_FILE_NEW)); diff_get_color(s->use_color_diff, DIFF_FILE_NEW));
strlcpy(s->reset_color_diff, strlcpy(s->reset_color_diff,
s->use_color_diff ? GIT_COLOR_RESET : "", COLOR_MAXLEN); want_color(s->use_color_diff) ? GIT_COLOR_RESET : "", COLOR_MAXLEN);


FREE_AND_NULL(s->interactive_diff_filter); FREE_AND_NULL(s->interactive_diff_filter);
repo_config_get_string(r, "interactive.difffilter", repo_config_get_string(r, "interactive.difffilter",
@ -130,8 +131,8 @@ void clear_add_i_state(struct add_i_state *s)
FREE_AND_NULL(s->interactive_diff_filter); FREE_AND_NULL(s->interactive_diff_filter);
FREE_AND_NULL(s->interactive_diff_algorithm); FREE_AND_NULL(s->interactive_diff_algorithm);
memset(s, 0, sizeof(*s)); memset(s, 0, sizeof(*s));
s->use_color_interactive = -1; s->use_color_interactive = GIT_COLOR_UNKNOWN;
s->use_color_diff = -1; s->use_color_diff = GIT_COLOR_UNKNOWN;
} }


/* /*
@ -1210,7 +1211,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps,
* When color was asked for, use the prompt color for * When color was asked for, use the prompt color for
* highlighting, otherwise use square brackets. * highlighting, otherwise use square brackets.
*/ */
if (s.use_color_interactive) { if (want_color(s.use_color_interactive)) {
data.color = s.prompt_color; data.color = s.prompt_color;
data.reset = s.reset_color_interactive; data.reset = s.reset_color_interactive;
} }

View File

@ -12,8 +12,8 @@ struct add_p_opt {


struct add_i_state { struct add_i_state {
struct repository *r; struct repository *r;
int use_color_interactive; enum git_colorbool use_color_interactive;
int use_color_diff; enum git_colorbool use_color_diff;
char header_color[COLOR_MAXLEN]; char header_color[COLOR_MAXLEN];
char help_color[COLOR_MAXLEN]; char help_color[COLOR_MAXLEN];
char prompt_color[COLOR_MAXLEN]; char prompt_color[COLOR_MAXLEN];

View File

@ -7,7 +7,7 @@
#include "help.h" #include "help.h"
#include "string-list.h" #include "string-list.h"


static int advice_use_color = -1; static enum git_colorbool advice_use_color = GIT_COLOR_UNKNOWN;
static char advice_colors[][COLOR_MAXLEN] = { static char advice_colors[][COLOR_MAXLEN] = {
GIT_COLOR_RESET, GIT_COLOR_RESET,
GIT_COLOR_YELLOW, /* HINT */ GIT_COLOR_YELLOW, /* HINT */

View File

@ -200,7 +200,7 @@ static int edit_patch(struct repository *repo,


argc = setup_revisions(argc, argv, &rev, NULL); argc = setup_revisions(argc, argv, &rev, NULL);
rev.diffopt.output_format = DIFF_FORMAT_PATCH; rev.diffopt.output_format = DIFF_FORMAT_PATCH;
rev.diffopt.use_color = 0; rev.diffopt.use_color = GIT_COLOR_NEVER;
rev.diffopt.flags.ignore_dirty_submodules = 1; rev.diffopt.flags.ignore_dirty_submodules = 1;
out = xopen(file, O_CREAT | O_WRONLY | O_TRUNC, 0666); out = xopen(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
rev.diffopt.file = xfdopen(out, "w"); rev.diffopt.file = xfdopen(out, "w");

View File

@ -1408,7 +1408,7 @@ static void write_commit_patch(const struct am_state *state, struct commit *comm
rev_info.no_commit_id = 1; rev_info.no_commit_id = 1;
rev_info.diffopt.flags.binary = 1; rev_info.diffopt.flags.binary = 1;
rev_info.diffopt.flags.full_index = 1; rev_info.diffopt.flags.full_index = 1;
rev_info.diffopt.use_color = 0; rev_info.diffopt.use_color = GIT_COLOR_NEVER;
rev_info.diffopt.file = fp; rev_info.diffopt.file = fp;
rev_info.diffopt.close_file = 1; rev_info.diffopt.close_file = 1;
add_pending_object(&rev_info, &commit->object, ""); add_pending_object(&rev_info, &commit->object, "");
@ -1441,7 +1441,7 @@ static void write_index_patch(const struct am_state *state)
rev_info.disable_stdin = 1; rev_info.disable_stdin = 1;
rev_info.no_commit_id = 1; rev_info.no_commit_id = 1;
rev_info.diffopt.output_format = DIFF_FORMAT_PATCH; rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;
rev_info.diffopt.use_color = 0; rev_info.diffopt.use_color = GIT_COLOR_NEVER;
rev_info.diffopt.file = fp; rev_info.diffopt.file = fp;
rev_info.diffopt.close_file = 1; rev_info.diffopt.close_file = 1;
add_pending_object(&rev_info, &tree->object, ""); add_pending_object(&rev_info, &tree->object, "");

View File

@ -46,7 +46,7 @@ static struct object_id head_oid;
static int recurse_submodules = 0; static int recurse_submodules = 0;
static int submodule_propagate_branches = 0; static int submodule_propagate_branches = 0;


static int branch_use_color = -1; static enum git_colorbool branch_use_color = GIT_COLOR_UNKNOWN;
static char branch_colors[][COLOR_MAXLEN] = { static char branch_colors[][COLOR_MAXLEN] = {
GIT_COLOR_RESET, GIT_COLOR_RESET,
GIT_COLOR_NORMAL, /* PLAIN */ GIT_COLOR_NORMAL, /* PLAIN */

View File

@ -64,7 +64,7 @@ static const char *color_interactive_slots[] = {
[CLEAN_COLOR_RESET] = "reset", [CLEAN_COLOR_RESET] = "reset",
}; };


static int clean_use_color = -1; static enum git_colorbool clean_use_color = GIT_COLOR_UNKNOWN;
static char clean_colors[][COLOR_MAXLEN] = { static char clean_colors[][COLOR_MAXLEN] = {
[CLEAN_COLOR_ERROR] = GIT_COLOR_BOLD_RED, [CLEAN_COLOR_ERROR] = GIT_COLOR_BOLD_RED,
[CLEAN_COLOR_HEADER] = GIT_COLOR_BOLD, [CLEAN_COLOR_HEADER] = GIT_COLOR_BOLD,

View File

@ -940,7 +940,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
strbuf_addstr(&committer_ident, git_committer_info(IDENT_STRICT)); strbuf_addstr(&committer_ident, git_committer_info(IDENT_STRICT));
if (use_editor && include_status) { if (use_editor && include_status) {
int ident_shown = 0; int ident_shown = 0;
int saved_color_setting; enum git_colorbool saved_color_setting;
struct ident_split ci, ai; struct ident_split ci, ai;
const char *hint_cleanup_all = allow_empty_message ? const char *hint_cleanup_all = allow_empty_message ?
_("Please enter the commit message for your changes." _("Please enter the commit message for your changes."
@ -1020,7 +1020,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
status_printf_ln(s, GIT_COLOR_NORMAL, "%s", ""); /* Add new line for clarity */ status_printf_ln(s, GIT_COLOR_NORMAL, "%s", ""); /* Add new line for clarity */


saved_color_setting = s->use_color; saved_color_setting = s->use_color;
s->use_color = 0; s->use_color = GIT_COLOR_NEVER;
committable = run_status(s->fp, index_file, prefix, 1, s); committable = run_status(s->fp, index_file, prefix, 1, s);
s->use_color = saved_color_setting; s->use_color = saved_color_setting;
string_list_clear_func(&s->change, change_data_free); string_list_clear_func(&s->change, change_data_free);

View File

@ -568,9 +568,9 @@ static void get_color(const struct config_location_options *opts,
} }


struct get_colorbool_config_data { struct get_colorbool_config_data {
int get_colorbool_found; enum git_colorbool get_colorbool_found;
int get_diff_color_found; enum git_colorbool get_diff_color_found;
int get_color_ui_found; enum git_colorbool get_color_ui_found;
const char *get_colorbool_slot; const char *get_colorbool_slot;
}; };


@ -594,33 +594,34 @@ static int get_colorbool(const struct config_location_options *opts,
{ {
struct get_colorbool_config_data data = { struct get_colorbool_config_data data = {
.get_colorbool_slot = var, .get_colorbool_slot = var,
.get_colorbool_found = -1, .get_colorbool_found = GIT_COLOR_UNKNOWN,
.get_diff_color_found = -1, .get_diff_color_found = GIT_COLOR_UNKNOWN,
.get_color_ui_found = -1, .get_color_ui_found = GIT_COLOR_UNKNOWN,
}; };
bool result;


config_with_options(git_get_colorbool_config, &data, config_with_options(git_get_colorbool_config, &data,
&opts->source, the_repository, &opts->source, the_repository,
&opts->options); &opts->options);


if (data.get_colorbool_found < 0) { if (data.get_colorbool_found == GIT_COLOR_UNKNOWN) {
if (!strcmp(data.get_colorbool_slot, "color.diff")) if (!strcmp(data.get_colorbool_slot, "color.diff"))
data.get_colorbool_found = data.get_diff_color_found; data.get_colorbool_found = data.get_diff_color_found;
if (data.get_colorbool_found < 0) if (data.get_colorbool_found == GIT_COLOR_UNKNOWN)
data.get_colorbool_found = data.get_color_ui_found; data.get_colorbool_found = data.get_color_ui_found;
} }


if (data.get_colorbool_found < 0) if (data.get_colorbool_found == GIT_COLOR_UNKNOWN)
/* default value if none found in config */ /* default value if none found in config */
data.get_colorbool_found = GIT_COLOR_AUTO; data.get_colorbool_found = GIT_COLOR_AUTO;


data.get_colorbool_found = want_color(data.get_colorbool_found); result = want_color(data.get_colorbool_found);


if (print) { if (print) {
printf("%s\n", data.get_colorbool_found ? "true" : "false"); printf("%s\n", result ? "true" : "false");
return 0; return 0;
} else } else
return data.get_colorbool_found ? 0 : 1; return result ? 0 : 1;
} }


static void check_write(const struct git_config_source *source) static void check_write(const struct git_config_source *source)

View File

@ -1091,7 +1091,7 @@ int cmd_grep(int argc,
if (show_in_pager == default_pager) if (show_in_pager == default_pager)
show_in_pager = git_pager(the_repository, 1); show_in_pager = git_pager(the_repository, 1);
if (show_in_pager) { if (show_in_pager) {
opt.color = 0; opt.color = GIT_COLOR_NEVER;
opt.name_only = 1; opt.name_only = 1;
opt.null_following_name = 1; opt.null_following_name = 1;
opt.output_priv = &path_list; opt.output_priv = &path_list;

View File

@ -27,7 +27,7 @@ static const char * const push_usage[] = {
NULL, NULL,
}; };


static int push_use_color = -1; static enum git_colorbool push_use_color = GIT_COLOR_UNKNOWN;
static char push_colors[][COLOR_MAXLEN] = { static char push_colors[][COLOR_MAXLEN] = {
GIT_COLOR_RESET, GIT_COLOR_RESET,
GIT_COLOR_RED, /* ERROR */ GIT_COLOR_RED, /* ERROR */

View File

@ -7,6 +7,7 @@
#include "range-diff.h" #include "range-diff.h"
#include "config.h" #include "config.h"
#include "parse.h" #include "parse.h"
#include "color.h"




static const char * const builtin_range_diff_usage[] = { static const char * const builtin_range_diff_usage[] = {
@ -87,7 +88,7 @@ int cmd_range_diff(int argc,


/* force color when --dual-color was used */ /* force color when --dual-color was used */
if (!simple_color) if (!simple_color)
diffopt.use_color = 1; diffopt.use_color = GIT_COLOR_ALWAYS;


/* If `--diff-merges` was specified, imply `--merges` */ /* If `--diff-merges` was specified, imply `--merges` */
if (diff_merges_arg.nr) { if (diff_merges_arg.nr) {

View File

@ -29,7 +29,7 @@ static const char*const show_branch_usage[] = {
NULL NULL
}; };


static int showbranch_use_color = -1; static enum git_colorbool showbranch_use_color = GIT_COLOR_UNKNOWN;


static struct strvec default_args = STRVEC_INIT; static struct strvec default_args = STRVEC_INIT;



24
color.c
View File

@ -9,7 +9,7 @@
#include "pager.h" #include "pager.h"
#include "strbuf.h" #include "strbuf.h"


static int git_use_color_default = GIT_COLOR_AUTO; static enum git_colorbool git_use_color_default = GIT_COLOR_AUTO;
int color_stdout_is_tty = -1; int color_stdout_is_tty = -1;


/* /*
@ -369,29 +369,29 @@ bad:
#undef OUT #undef OUT
} }


int git_config_colorbool(const char *var, const char *value) enum git_colorbool git_config_colorbool(const char *var, const char *value)
{ {
if (value) { if (value) {
if (!strcasecmp(value, "never")) if (!strcasecmp(value, "never"))
return 0; return GIT_COLOR_NEVER;
if (!strcasecmp(value, "always")) if (!strcasecmp(value, "always"))
return 1; return GIT_COLOR_ALWAYS;
if (!strcasecmp(value, "auto")) if (!strcasecmp(value, "auto"))
return GIT_COLOR_AUTO; return GIT_COLOR_AUTO;
} }


if (!var) if (!var)
return -1; return GIT_COLOR_UNKNOWN;


/* Missing or explicit false to turn off colorization */ /* Missing or explicit false to turn off colorization */
if (!git_config_bool(var, value)) if (!git_config_bool(var, value))
return 0; return GIT_COLOR_NEVER;


/* any normal truth value defaults to 'auto' */ /* any normal truth value defaults to 'auto' */
return GIT_COLOR_AUTO; return GIT_COLOR_AUTO;
} }


static int check_auto_color(int fd) static bool check_auto_color(int fd)
{ {
static int color_stderr_is_tty = -1; static int color_stderr_is_tty = -1;
int *is_tty_p = fd == 1 ? &color_stdout_is_tty : &color_stderr_is_tty; int *is_tty_p = fd == 1 ? &color_stdout_is_tty : &color_stderr_is_tty;
@ -399,12 +399,12 @@ static int check_auto_color(int fd)
*is_tty_p = isatty(fd); *is_tty_p = isatty(fd);
if (*is_tty_p || (fd == 1 && pager_in_use() && pager_use_color)) { if (*is_tty_p || (fd == 1 && pager_in_use() && pager_use_color)) {
if (!is_terminal_dumb()) if (!is_terminal_dumb())
return 1; return true;
} }
return 0; return false;
} }


int want_color_fd(int fd, int var) bool want_color_fd(int fd, enum git_colorbool var)
{ {
/* /*
* NEEDSWORK: This function is sometimes used from multiple threads, and * NEEDSWORK: This function is sometimes used from multiple threads, and
@ -418,7 +418,7 @@ int want_color_fd(int fd, int var)
if (fd < 1 || fd >= ARRAY_SIZE(want_auto)) if (fd < 1 || fd >= ARRAY_SIZE(want_auto))
BUG("file descriptor out of range: %d", fd); BUG("file descriptor out of range: %d", fd);


if (var < 0) if (var == GIT_COLOR_UNKNOWN)
var = git_use_color_default; var = git_use_color_default;


if (var == GIT_COLOR_AUTO) { if (var == GIT_COLOR_AUTO) {
@ -426,7 +426,7 @@ int want_color_fd(int fd, int var)
want_auto[fd] = check_auto_color(fd); want_auto[fd] = check_auto_color(fd);
return want_auto[fd]; return want_auto[fd];
} }
return var; return var == GIT_COLOR_ALWAYS;
} }


int git_color_config(const char *var, const char *value, void *cb UNUSED) int git_color_config(const char *var, const char *value, void *cb UNUSED)

14
color.h
View File

@ -73,10 +73,12 @@ struct strbuf;
* returned from git_config_colorbool. The "auto" value can be returned from * returned from git_config_colorbool. The "auto" value can be returned from
* config_colorbool, and will be converted by want_color() into either 0 or 1. * config_colorbool, and will be converted by want_color() into either 0 or 1.
*/ */
#define GIT_COLOR_UNKNOWN -1 enum git_colorbool {
#define GIT_COLOR_NEVER 0 GIT_COLOR_UNKNOWN = -1,
#define GIT_COLOR_ALWAYS 1 GIT_COLOR_NEVER = 0,
#define GIT_COLOR_AUTO 2 GIT_COLOR_ALWAYS = 1,
GIT_COLOR_AUTO = 2,
};


/* A default list of colors to use for commit graphs and show-branch output */ /* A default list of colors to use for commit graphs and show-branch output */
extern const char *column_colors_ansi[]; extern const char *column_colors_ansi[];
@ -98,13 +100,13 @@ int git_color_config(const char *var, const char *value, void *cb);
* GIT_COLOR_ALWAYS for "always" or a positive boolean, * GIT_COLOR_ALWAYS for "always" or a positive boolean,
* and GIT_COLOR_AUTO for "auto". * and GIT_COLOR_AUTO for "auto".
*/ */
int git_config_colorbool(const char *var, const char *value); enum git_colorbool git_config_colorbool(const char *var, const char *value);


/* /*
* Return a boolean whether to use color, where the argument 'var' is * Return a boolean whether to use color, where the argument 'var' is
* one of GIT_COLOR_UNKNOWN, GIT_COLOR_NEVER, GIT_COLOR_ALWAYS, GIT_COLOR_AUTO. * one of GIT_COLOR_UNKNOWN, GIT_COLOR_NEVER, GIT_COLOR_ALWAYS, GIT_COLOR_AUTO.
*/ */
int want_color_fd(int fd, int var); bool want_color_fd(int fd, enum git_colorbool var);
#define want_color(colorbool) want_color_fd(1, (colorbool)) #define want_color(colorbool) want_color_fd(1, (colorbool))
#define want_color_stderr(colorbool) want_color_fd(2, (colorbool)) #define want_color_stderr(colorbool) want_color_fd(2, (colorbool))



View File

@ -749,7 +749,7 @@ static void show_line_to_eol(const char *line, int len, const char *reset)


static void dump_sline(struct sline *sline, const char *line_prefix, static void dump_sline(struct sline *sline, const char *line_prefix,
unsigned long cnt, int num_parent, unsigned long cnt, int num_parent,
int use_color, int result_deleted) enum git_colorbool use_color, int result_deleted)
{ {
unsigned long mark = (1UL<<num_parent); unsigned long mark = (1UL<<num_parent);
unsigned long no_pre_delete = (2UL<<num_parent); unsigned long no_pre_delete = (2UL<<num_parent);

44
diff.c
View File

@ -57,7 +57,7 @@ static int diff_detect_rename_default;
static int diff_indent_heuristic = 1; static int diff_indent_heuristic = 1;
static int diff_rename_limit_default = 1000; static int diff_rename_limit_default = 1000;
static int diff_suppress_blank_empty; static int diff_suppress_blank_empty;
static int diff_use_color_default = -1; static enum git_colorbool diff_use_color_default = GIT_COLOR_UNKNOWN;
static int diff_color_moved_default; static int diff_color_moved_default;
static int diff_color_moved_ws_default; static int diff_color_moved_ws_default;
static int diff_context_default = 3; static int diff_context_default = 3;
@ -1672,7 +1672,7 @@ static void emit_hunk_header(struct emit_callback *ecbdata,
const char *frag = diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO); const char *frag = diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO);
const char *func = diff_get_color(ecbdata->color_diff, DIFF_FUNCINFO); const char *func = diff_get_color(ecbdata->color_diff, DIFF_FUNCINFO);
const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET); const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);
const char *reverse = ecbdata->color_diff ? GIT_COLOR_REVERSE : ""; const char *reverse = want_color(ecbdata->color_diff) ? GIT_COLOR_REVERSE : "";
static const char atat[2] = { '@', '@' }; static const char atat[2] = { '@', '@' };
const char *cp, *ep; const char *cp, *ep;
struct strbuf msgbuf = STRBUF_INIT; struct strbuf msgbuf = STRBUF_INIT;
@ -1826,7 +1826,7 @@ static void emit_rewrite_diff(const char *name_a,
size_two = fill_textconv(o->repo, textconv_two, two, &data_two); size_two = fill_textconv(o->repo, textconv_two, two, &data_two);


memset(&ecbdata, 0, sizeof(ecbdata)); memset(&ecbdata, 0, sizeof(ecbdata));
ecbdata.color_diff = want_color(o->use_color); ecbdata.color_diff = o->use_color;
ecbdata.ws_rule = whitespace_rule(o->repo->index, name_b); ecbdata.ws_rule = whitespace_rule(o->repo->index, name_b);
ecbdata.opt = o; ecbdata.opt = o;
if (ecbdata.ws_rule & WS_BLANK_AT_EOF) { if (ecbdata.ws_rule & WS_BLANK_AT_EOF) {
@ -2303,7 +2303,7 @@ static void free_diff_words_data(struct emit_callback *ecbdata)
} }
} }


const char *diff_get_color(int diff_use_color, enum color_diff ix) const char *diff_get_color(enum git_colorbool diff_use_color, enum color_diff ix)
{ {
if (want_color(diff_use_color)) if (want_color(diff_use_color))
return diff_colors[ix]; return diff_colors[ix];
@ -3732,7 +3732,7 @@ static void builtin_diff(const char *name_a,
if (o->flags.suppress_diff_headers) if (o->flags.suppress_diff_headers)
lbl[0] = NULL; lbl[0] = NULL;
ecbdata.label_path = lbl; ecbdata.label_path = lbl;
ecbdata.color_diff = want_color(o->use_color); ecbdata.color_diff = o->use_color;
ecbdata.ws_rule = whitespace_rule(o->repo->index, name_b); ecbdata.ws_rule = whitespace_rule(o->repo->index, name_b);
if (ecbdata.ws_rule & WS_BLANK_AT_EOF) if (ecbdata.ws_rule & WS_BLANK_AT_EOF)
check_blank_at_eof(&mf1, &mf2, &ecbdata); check_blank_at_eof(&mf1, &mf2, &ecbdata);
@ -4497,7 +4497,7 @@ static void fill_metainfo(struct strbuf *msg,
struct diff_options *o, struct diff_options *o,
struct diff_filepair *p, struct diff_filepair *p,
int *must_show_header, int *must_show_header,
int use_color) enum git_colorbool use_color)
{ {
const char *set = diff_get_color(use_color, DIFF_METAINFO); const char *set = diff_get_color(use_color, DIFF_METAINFO);
const char *reset = diff_get_color(use_color, DIFF_RESET); const char *reset = diff_get_color(use_color, DIFF_RESET);
@ -4596,7 +4596,7 @@ static void run_diff_cmd(const struct external_diff *pgm,
*/ */
fill_metainfo(msg, name, other, one, two, o, p, fill_metainfo(msg, name, other, one, two, o, p,
&must_show_header, &must_show_header,
want_color(o->use_color) && !pgm); pgm ? GIT_COLOR_NEVER : o->use_color);
xfrm_msg = msg->len ? msg->buf : NULL; xfrm_msg = msg->len ? msg->buf : NULL;
} }


@ -4995,8 +4995,7 @@ void diff_setup_done(struct diff_options *options)
if (options->flags.follow_renames) if (options->flags.follow_renames)
diff_check_follow_pathspec(&options->pathspec, 1); diff_check_follow_pathspec(&options->pathspec, 1);


if (!options->use_color || if (options->flags.allow_external && external_diff())
(options->flags.allow_external && external_diff()))
options->color_moved = 0; options->color_moved = 0;


if (options->filter_not) { if (options->filter_not) {
@ -5278,7 +5277,7 @@ static int diff_opt_color_words(const struct option *opt,
struct diff_options *options = opt->value; struct diff_options *options = opt->value;


BUG_ON_OPT_NEG(unset); BUG_ON_OPT_NEG(unset);
options->use_color = 1; options->use_color = GIT_COLOR_ALWAYS;
options->word_diff = DIFF_WORDS_COLOR; options->word_diff = DIFF_WORDS_COLOR;
options->word_regex = arg; options->word_regex = arg;
return 0; return 0;
@ -5600,7 +5599,7 @@ static int diff_opt_word_diff(const struct option *opt,
if (!strcmp(arg, "plain")) if (!strcmp(arg, "plain"))
options->word_diff = DIFF_WORDS_PLAIN; options->word_diff = DIFF_WORDS_PLAIN;
else if (!strcmp(arg, "color")) { else if (!strcmp(arg, "color")) {
options->use_color = 1; options->use_color = GIT_COLOR_ALWAYS;
options->word_diff = DIFF_WORDS_COLOR; options->word_diff = DIFF_WORDS_COLOR;
} }
else if (!strcmp(arg, "porcelain")) else if (!strcmp(arg, "porcelain"))
@ -6733,7 +6732,7 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)
if (WSEH_NEW & WS_RULE_MASK) if (WSEH_NEW & WS_RULE_MASK)
BUG("WS rules bit mask overlaps with diff symbol flags"); BUG("WS rules bit mask overlaps with diff symbol flags");


if (o->color_moved) if (o->color_moved && want_color(o->use_color))
o->emitted_symbols = &esm; o->emitted_symbols = &esm;


if (o->additional_path_headers) if (o->additional_path_headers)
@ -6746,20 +6745,17 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)
} }


if (o->emitted_symbols) { if (o->emitted_symbols) {
if (o->color_moved) { struct mem_pool entry_pool;
struct mem_pool entry_pool; struct moved_entry_list *entry_list;
struct moved_entry_list *entry_list;


mem_pool_init(&entry_pool, 1024 * 1024); mem_pool_init(&entry_pool, 1024 * 1024);
entry_list = add_lines_to_move_detection(o, entry_list = add_lines_to_move_detection(o, &entry_pool);
&entry_pool); mark_color_as_moved(o, entry_list);
mark_color_as_moved(o, entry_list); if (o->color_moved == COLOR_MOVED_ZEBRA_DIM)
if (o->color_moved == COLOR_MOVED_ZEBRA_DIM) dim_moved_lines(o);
dim_moved_lines(o);


mem_pool_discard(&entry_pool, 0); mem_pool_discard(&entry_pool, 0);
free(entry_list); free(entry_list);
}


for (i = 0; i < esm.nr; i++) for (i = 0; i < esm.nr; i++)
emit_diff_symbol_from_struct(o, &esm.buf[i]); emit_diff_symbol_from_struct(o, &esm.buf[i]);

5
diff.h
View File

@ -7,6 +7,7 @@
#include "hash.h" #include "hash.h"
#include "pathspec.h" #include "pathspec.h"
#include "strbuf.h" #include "strbuf.h"
#include "color.h"


struct oidset; struct oidset;


@ -283,7 +284,7 @@ struct diff_options {
/* diff-filter bits */ /* diff-filter bits */
unsigned int filter, filter_not; unsigned int filter, filter_not;


int use_color; enum git_colorbool use_color;


/* Number of context lines to generate in patch output. */ /* Number of context lines to generate in patch output. */
int context; int context;
@ -469,7 +470,7 @@ enum color_diff {
DIFF_FILE_NEW_BOLD = 22, DIFF_FILE_NEW_BOLD = 22,
}; };


const char *diff_get_color(int diff_use_color, enum color_diff ix); const char *diff_get_color(enum git_colorbool diff_use_color, enum color_diff ix);
#define diff_get_color_opt(o, ix) \ #define diff_get_color_opt(o, ix) \
diff_get_color((o)->use_color, ix) diff_get_color((o)->use_color, ix)



4
grep.c
View File

@ -1263,12 +1263,12 @@ static void show_line(struct grep_opt *opt,
*/ */
show_line_header(opt, name, lno, cno, sign); show_line_header(opt, name, lno, cno, sign);
} }
if (opt->color || opt->only_matching) { if (want_color(opt->color) || opt->only_matching) {
regmatch_t match; regmatch_t match;
enum grep_context ctx = GREP_CONTEXT_BODY; enum grep_context ctx = GREP_CONTEXT_BODY;
int eflags = 0; int eflags = 0;


if (opt->color) { if (want_color(opt->color)) {
if (sign == ':') if (sign == ':')
match_color = opt->colors[GREP_COLOR_MATCH_SELECTED]; match_color = opt->colors[GREP_COLOR_MATCH_SELECTED];
else else

4
grep.h
View File

@ -159,7 +159,7 @@ struct grep_opt {
int pathname; int pathname;
int null_following_name; int null_following_name;
int only_matching; int only_matching;
int color; enum git_colorbool color;
int max_depth; int max_depth;
int funcname; int funcname;
int funcbody; int funcbody;
@ -198,7 +198,7 @@ struct grep_opt {
[GREP_COLOR_SEP] = GIT_COLOR_CYAN, \ [GREP_COLOR_SEP] = GIT_COLOR_CYAN, \
}, \ }, \
.only_matching = 0, \ .only_matching = 0, \
.color = -1, \ .color = GIT_COLOR_UNKNOWN, \
.output = std_output, \ .output = std_output, \
} }



View File

@ -57,7 +57,7 @@ static const char *color_decorate_slots[] = {
[DECORATION_GRAFTED] = "grafted", [DECORATION_GRAFTED] = "grafted",
}; };


static const char *decorate_get_color(int decorate_use_color, enum decoration_type ix) static const char *decorate_get_color(enum git_colorbool decorate_use_color, enum decoration_type ix)
{ {
if (want_color(decorate_use_color)) if (want_color(decorate_use_color))
return decoration_colors[ix]; return decoration_colors[ix];
@ -341,7 +341,7 @@ static void show_name(struct strbuf *sb, const struct name_decoration *decoratio
*/ */
void format_decorations(struct strbuf *sb, void format_decorations(struct strbuf *sb,
const struct commit *commit, const struct commit *commit,
int use_color, enum git_colorbool use_color,
const struct decoration_options *opts) const struct decoration_options *opts)
{ {
const struct name_decoration *decoration; const struct name_decoration *decoration;

View File

@ -1,6 +1,8 @@
#ifndef LOG_TREE_H #ifndef LOG_TREE_H
#define LOG_TREE_H #define LOG_TREE_H


#include "color.h"

struct rev_info; struct rev_info;


struct log_info { struct log_info {
@ -26,7 +28,7 @@ int log_tree_diff_flush(struct rev_info *);
int log_tree_commit(struct rev_info *, struct commit *); int log_tree_commit(struct rev_info *, struct commit *);
void show_log(struct rev_info *opt); void show_log(struct rev_info *opt);
void format_decorations(struct strbuf *sb, const struct commit *commit, void format_decorations(struct strbuf *sb, const struct commit *commit,
int use_color, const struct decoration_options *opts); enum git_colorbool use_color, const struct decoration_options *opts);
void show_decorations(struct rev_info *opt, struct commit *commit); void show_decorations(struct rev_info *opt, struct commit *commit);
void log_write_email_headers(struct rev_info *opt, struct commit *commit, void log_write_email_headers(struct rev_info *opt, struct commit *commit,
char **extra_headers_p, char **extra_headers_p,

View File

@ -50,12 +50,12 @@ int parse_opt_expiry_date_cb(const struct option *opt, const char *arg,
int parse_opt_color_flag_cb(const struct option *opt, const char *arg, int parse_opt_color_flag_cb(const struct option *opt, const char *arg,
int unset) int unset)
{ {
int value; enum git_colorbool value;


if (!arg) if (!arg)
arg = unset ? "never" : (const char *)opt->defval; arg = unset ? "never" : (const char *)opt->defval;
value = git_config_colorbool(NULL, arg); value = git_config_colorbool(NULL, arg);
if (value < 0) if (value == GIT_COLOR_UNKNOWN)
return error(_("option `%s' expects \"always\", \"auto\", or \"never\""), return error(_("option `%s' expects \"always\", \"auto\", or \"never\""),
opt->long_name); opt->long_name);
*(int *)opt->value = value; *(int *)opt->value = value;

View File

@ -470,7 +470,7 @@ static inline void strbuf_add_with_color(struct strbuf *sb, const char *color,


static void append_line_with_color(struct strbuf *sb, struct grep_opt *opt, static void append_line_with_color(struct strbuf *sb, struct grep_opt *opt,
const char *line, size_t linelen, const char *line, size_t linelen,
int color, enum grep_context ctx, enum git_colorbool color, enum grep_context ctx,
enum grep_header_field field) enum grep_header_field field)
{ {
const char *buf, *eol, *line_color, *match_color; const char *buf, *eol, *line_color, *match_color;
@ -899,7 +899,7 @@ struct format_commit_context {
const char *message; const char *message;
char *commit_encoding; char *commit_encoding;
size_t width, indent1, indent2; size_t width, indent1, indent2;
int auto_color; enum git_colorbool auto_color;
int padding; int padding;


/* These offsets are relative to the start of the commit message. */ /* These offsets are relative to the start of the commit message. */
@ -1455,14 +1455,14 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
switch (placeholder[0]) { switch (placeholder[0]) {
case 'C': case 'C':
if (starts_with(placeholder + 1, "(auto)")) { if (starts_with(placeholder + 1, "(auto)")) {
c->auto_color = want_color(c->pretty_ctx->color); c->auto_color = c->pretty_ctx->color;
if (c->auto_color && sb->len) if (want_color(c->auto_color) && sb->len)
strbuf_addstr(sb, GIT_COLOR_RESET); strbuf_addstr(sb, GIT_COLOR_RESET);
return 7; /* consumed 7 bytes, "C(auto)" */ return 7; /* consumed 7 bytes, "C(auto)" */
} else { } else {
int ret = parse_color(sb, placeholder, c); int ret = parse_color(sb, placeholder, c);
if (ret) if (ret)
c->auto_color = 0; c->auto_color = GIT_COLOR_NEVER;
/* /*
* Otherwise, we decided to treat %C<unknown> * Otherwise, we decided to treat %C<unknown>
* as a literal string, and the previous * as a literal string, and the previous
@ -2167,7 +2167,7 @@ static int pp_utf8_width(const char *start, const char *end)
} }


static void strbuf_add_tabexpand(struct strbuf *sb, struct grep_opt *opt, static void strbuf_add_tabexpand(struct strbuf *sb, struct grep_opt *opt,
int color, int tabwidth, const char *line, enum git_colorbool color, int tabwidth, const char *line,
int linelen) int linelen)
{ {
const char *tab; const char *tab;

View File

@ -3,6 +3,7 @@


#include "date.h" #include "date.h"
#include "string-list.h" #include "string-list.h"
#include "color.h"


struct commit; struct commit;
struct repository; struct repository;
@ -46,7 +47,7 @@ struct pretty_print_context {
struct rev_info *rev; struct rev_info *rev;
const char *output_encoding; const char *output_encoding;
struct string_list *mailmap; struct string_list *mailmap;
int color; enum git_colorbool color;
struct ident_split *from_ident; struct ident_split *from_ident;
unsigned encode_email_headers:1; unsigned encode_email_headers:1;
struct pretty_print_describe_status *describe_status; struct pretty_print_describe_status *describe_status;

View File

@ -95,7 +95,7 @@ struct ref_format {
const char *format; const char *format;
const char *rest; const char *rest;
int quote_style; int quote_style;
int use_color; enum git_colorbool use_color;


/* Internal state to ref-filter */ /* Internal state to ref-filter */
int need_color_reset_at_eol; int need_color_reset_at_eol;
@ -111,7 +111,7 @@ struct ref_format {
.exclude = STRVEC_INIT, \ .exclude = STRVEC_INIT, \
} }
#define REF_FORMAT_INIT { \ #define REF_FORMAT_INIT { \
.use_color = -1, \ .use_color = GIT_COLOR_UNKNOWN, \
} }


/* Macros for checking --merged and --no-merged options */ /* Macros for checking --merged and --no-merged options */

View File

@ -27,16 +27,16 @@ static struct keyword_entry keywords[] = {
}; };


/* Returns a color setting (GIT_COLOR_NEVER, etc). */ /* Returns a color setting (GIT_COLOR_NEVER, etc). */
static int use_sideband_colors(void) static enum git_colorbool use_sideband_colors(void)
{ {
static int use_sideband_colors_cached = -1; static enum git_colorbool use_sideband_colors_cached = GIT_COLOR_UNKNOWN;


const char *key = "color.remote"; const char *key = "color.remote";
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
const char *value; const char *value;
int i; int i;


if (use_sideband_colors_cached >= 0) if (use_sideband_colors_cached != GIT_COLOR_UNKNOWN)
return use_sideband_colors_cached; return use_sideband_colors_cached;


if (!repo_config_get_string_tmp(the_repository, key, &value)) if (!repo_config_get_string_tmp(the_repository, key, &value))

View File

@ -30,7 +30,7 @@
#include "color.h" #include "color.h"
#include "bundle-uri.h" #include "bundle-uri.h"


static int transport_use_color = -1; static enum git_colorbool transport_use_color = GIT_COLOR_UNKNOWN;
static char transport_colors[][COLOR_MAXLEN] = { static char transport_colors[][COLOR_MAXLEN] = {
GIT_COLOR_RESET, GIT_COLOR_RESET,
GIT_COLOR_RED /* REJECTED */ GIT_COLOR_RED /* REJECTED */

View File

@ -148,7 +148,7 @@ void wt_status_prepare(struct repository *r, struct wt_status *s)
memcpy(s->color_palette, default_wt_status_colors, memcpy(s->color_palette, default_wt_status_colors,
sizeof(default_wt_status_colors)); sizeof(default_wt_status_colors));
s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES; s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
s->use_color = -1; s->use_color = GIT_COLOR_UNKNOWN;
s->relative_paths = 1; s->relative_paths = 1;
s->branch = refs_resolve_refdup(get_main_ref_store(the_repository), s->branch = refs_resolve_refdup(get_main_ref_store(the_repository),
"HEAD", 0, NULL, NULL); "HEAD", 0, NULL, NULL);
@ -1165,7 +1165,7 @@ static void wt_longstatus_print_verbose(struct wt_status *s)
* before. * before.
*/ */
if (s->fp != stdout) { if (s->fp != stdout) {
rev.diffopt.use_color = 0; rev.diffopt.use_color = GIT_COLOR_NEVER;
wt_status_add_cut_line(s); wt_status_add_cut_line(s);
} }
if (s->verbose > 1 && s->committable) { if (s->verbose > 1 && s->committable) {
@ -2155,7 +2155,7 @@ static void wt_shortstatus_print(struct wt_status *s)


static void wt_porcelain_print(struct wt_status *s) static void wt_porcelain_print(struct wt_status *s)
{ {
s->use_color = 0; s->use_color = GIT_COLOR_NEVER;
s->relative_paths = 0; s->relative_paths = 0;
s->prefix = NULL; s->prefix = NULL;
s->no_gettext = 1; s->no_gettext = 1;

View File

@ -111,7 +111,7 @@ struct wt_status {
int amend; int amend;
enum commit_whence whence; enum commit_whence whence;
int nowarn; int nowarn;
int use_color; enum git_colorbool use_color;
int no_gettext; int no_gettext;
int display_comment_prefix; int display_comment_prefix;
int relative_paths; int relative_paths;