mirror of
https://github.com/git/git.git
synced 2024-11-23 18:05:29 +08:00
Merge branch 'ar/decorate-color'
* ar/decorate-color: Add test for correct coloring of git log --decoration Allow customizable commit decorations colors log --decorate: Colorize commit decorations log-tree.c: Use struct name_decoration's type for classifying decoration commit.h: add 'type' to struct name_decoration
This commit is contained in:
commit
2927a507bf
@ -690,6 +690,11 @@ color.diff.<slot>::
|
||||
(highlighting whitespace errors). The values of these variables may be
|
||||
specified as in color.branch.<slot>.
|
||||
|
||||
color.decorate.<slot>::
|
||||
Use customized color for 'git log --decorate' output. `<slot>` is one
|
||||
of `branch`, `remoteBranch`, `tag`, `stash` or `HEAD` for local
|
||||
branches, remote tracking branches, tags, stash and HEAD, respectively.
|
||||
|
||||
color.grep::
|
||||
When set to `always`, always highlight matches. When `false` (or
|
||||
`never`), never. When set to `true` or `auto`, use color only
|
||||
|
@ -296,6 +296,9 @@ static int git_log_config(const char *var, const char *value, void *cb)
|
||||
default_show_root = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
if (!prefixcmp(var, "color.decorate."))
|
||||
return parse_decorate_color_config(var, 15, value);
|
||||
|
||||
return git_diff_ui_config(var, value, cb);
|
||||
}
|
||||
|
||||
|
1
commit.h
1
commit.h
@ -28,6 +28,7 @@ extern const char *commit_type;
|
||||
extern struct decoration name_decoration;
|
||||
struct name_decoration {
|
||||
struct name_decoration *next;
|
||||
int type;
|
||||
char name[1];
|
||||
};
|
||||
|
||||
|
108
log-tree.c
108
log-tree.c
@ -7,32 +7,113 @@
|
||||
#include "reflog-walk.h"
|
||||
#include "refs.h"
|
||||
#include "string-list.h"
|
||||
#include "color.h"
|
||||
|
||||
struct decoration name_decoration = { "object names" };
|
||||
|
||||
static void add_name_decoration(const char *prefix, const char *name, struct object *obj)
|
||||
enum decoration_type {
|
||||
DECORATION_NONE = 0,
|
||||
DECORATION_REF_LOCAL,
|
||||
DECORATION_REF_REMOTE,
|
||||
DECORATION_REF_TAG,
|
||||
DECORATION_REF_STASH,
|
||||
DECORATION_REF_HEAD,
|
||||
};
|
||||
|
||||
static char decoration_colors[][COLOR_MAXLEN] = {
|
||||
GIT_COLOR_RESET,
|
||||
GIT_COLOR_BOLD_GREEN, /* REF_LOCAL */
|
||||
GIT_COLOR_BOLD_RED, /* REF_REMOTE */
|
||||
GIT_COLOR_BOLD_YELLOW, /* REF_TAG */
|
||||
GIT_COLOR_BOLD_MAGENTA, /* REF_STASH */
|
||||
GIT_COLOR_BOLD_CYAN, /* REF_HEAD */
|
||||
};
|
||||
|
||||
static const char *decorate_get_color(int decorate_use_color, enum decoration_type ix)
|
||||
{
|
||||
if (decorate_use_color)
|
||||
return decoration_colors[ix];
|
||||
return "";
|
||||
}
|
||||
|
||||
static int parse_decorate_color_slot(const char *slot)
|
||||
{
|
||||
/*
|
||||
* We're comparing with 'ignore-case' on
|
||||
* (because config.c sets them all tolower),
|
||||
* but let's match the letters in the literal
|
||||
* string values here with how they are
|
||||
* documented in Documentation/config.txt, for
|
||||
* consistency.
|
||||
*
|
||||
* We love being consistent, don't we?
|
||||
*/
|
||||
if (!strcasecmp(slot, "branch"))
|
||||
return DECORATION_REF_LOCAL;
|
||||
if (!strcasecmp(slot, "remoteBranch"))
|
||||
return DECORATION_REF_REMOTE;
|
||||
if (!strcasecmp(slot, "tag"))
|
||||
return DECORATION_REF_TAG;
|
||||
if (!strcasecmp(slot, "stash"))
|
||||
return DECORATION_REF_STASH;
|
||||
if (!strcasecmp(slot, "HEAD"))
|
||||
return DECORATION_REF_HEAD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int parse_decorate_color_config(const char *var, const int ofs, const char *value)
|
||||
{
|
||||
int slot = parse_decorate_color_slot(var + ofs);
|
||||
if (slot < 0)
|
||||
return 0;
|
||||
if (!value)
|
||||
return config_error_nonbool(var);
|
||||
color_parse(value, var, decoration_colors[slot]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* log-tree.c uses DIFF_OPT_TST for determining whether to use color
|
||||
* for showing the commit sha1, use the same check for --decorate
|
||||
*/
|
||||
#define decorate_get_color_opt(o, ix) \
|
||||
decorate_get_color(DIFF_OPT_TST((o), COLOR_DIFF), ix)
|
||||
|
||||
static void add_name_decoration(enum decoration_type type, const char *name, struct object *obj)
|
||||
{
|
||||
int plen = strlen(prefix);
|
||||
int nlen = strlen(name);
|
||||
struct name_decoration *res = xmalloc(sizeof(struct name_decoration) + plen + nlen);
|
||||
memcpy(res->name, prefix, plen);
|
||||
memcpy(res->name + plen, name, nlen + 1);
|
||||
struct name_decoration *res = xmalloc(sizeof(struct name_decoration) + nlen);
|
||||
memcpy(res->name, name, nlen + 1);
|
||||
res->type = type;
|
||||
res->next = add_decoration(&name_decoration, obj, res);
|
||||
}
|
||||
|
||||
static int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
|
||||
{
|
||||
struct object *obj = parse_object(sha1);
|
||||
enum decoration_type type = DECORATION_NONE;
|
||||
if (!obj)
|
||||
return 0;
|
||||
|
||||
if (!prefixcmp(refname, "refs/heads"))
|
||||
type = DECORATION_REF_LOCAL;
|
||||
else if (!prefixcmp(refname, "refs/remotes"))
|
||||
type = DECORATION_REF_REMOTE;
|
||||
else if (!prefixcmp(refname, "refs/tags"))
|
||||
type = DECORATION_REF_TAG;
|
||||
else if (!prefixcmp(refname, "refs/stash"))
|
||||
type = DECORATION_REF_STASH;
|
||||
else if (!prefixcmp(refname, "HEAD"))
|
||||
type = DECORATION_REF_HEAD;
|
||||
|
||||
if (!cb_data || *(int *)cb_data == DECORATE_SHORT_REFS)
|
||||
refname = prettify_refname(refname);
|
||||
add_name_decoration("", refname, obj);
|
||||
add_name_decoration(type, refname, obj);
|
||||
while (obj->type == OBJ_TAG) {
|
||||
obj = ((struct tag *)obj)->tagged;
|
||||
if (!obj)
|
||||
break;
|
||||
add_name_decoration("tag: ", refname, obj);
|
||||
add_name_decoration(DECORATION_REF_TAG, refname, obj);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -60,6 +141,10 @@ void show_decorations(struct rev_info *opt, struct commit *commit)
|
||||
{
|
||||
const char *prefix;
|
||||
struct name_decoration *decoration;
|
||||
const char *color_commit =
|
||||
diff_get_color_opt(&opt->diffopt, DIFF_COMMIT);
|
||||
const char *color_reset =
|
||||
decorate_get_color_opt(&opt->diffopt, DECORATION_NONE);
|
||||
|
||||
if (opt->show_source && commit->util)
|
||||
printf("\t%s", (char *) commit->util);
|
||||
@ -70,7 +155,14 @@ void show_decorations(struct rev_info *opt, struct commit *commit)
|
||||
return;
|
||||
prefix = " (";
|
||||
while (decoration) {
|
||||
printf("%s%s", prefix, decoration->name);
|
||||
printf("%s", prefix);
|
||||
fputs(decorate_get_color_opt(&opt->diffopt, decoration->type),
|
||||
stdout);
|
||||
if (decoration->type == DECORATION_REF_TAG)
|
||||
fputs("tag: ", stdout);
|
||||
printf("%s", decoration->name);
|
||||
fputs(color_reset, stdout);
|
||||
fputs(color_commit, stdout);
|
||||
prefix = ", ";
|
||||
decoration = decoration->next;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ struct log_info {
|
||||
struct commit *commit, *parent;
|
||||
};
|
||||
|
||||
int parse_decorate_color_config(const char *var, const int ofs, const char *value);
|
||||
void init_log_tree_opt(struct rev_info *);
|
||||
int log_tree_diff_flush(struct rev_info *);
|
||||
int log_tree_commit(struct rev_info *, struct commit *);
|
||||
|
66
t/t4207-log-decoration-colors.sh
Executable file
66
t/t4207-log-decoration-colors.sh
Executable file
@ -0,0 +1,66 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2010 Nazri Ramliy
|
||||
#
|
||||
|
||||
test_description='Test for "git log --decorate" colors'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
get_color ()
|
||||
{
|
||||
git config --get-color no.such.slot "$1"
|
||||
}
|
||||
|
||||
test_expect_success setup '
|
||||
git config diff.color.commit yellow &&
|
||||
git config color.decorate.branch green &&
|
||||
git config color.decorate.remoteBranch red &&
|
||||
git config color.decorate.tag "reverse bold yellow" &&
|
||||
git config color.decorate.stash magenta &&
|
||||
git config color.decorate.HEAD cyan &&
|
||||
|
||||
c_reset=$(get_color reset) &&
|
||||
|
||||
c_commit=$(get_color yellow) &&
|
||||
c_branch=$(get_color green) &&
|
||||
c_remoteBranch=$(get_color red) &&
|
||||
c_tag=$(get_color "reverse bold yellow") &&
|
||||
c_stash=$(get_color magenta) &&
|
||||
c_HEAD=$(get_color cyan) &&
|
||||
|
||||
test_commit A &&
|
||||
git clone . other &&
|
||||
(
|
||||
cd other &&
|
||||
test_commit A1
|
||||
) &&
|
||||
|
||||
git remote add -f other ./other &&
|
||||
test_commit B &&
|
||||
git tag v1.0 &&
|
||||
echo >>A.t &&
|
||||
git stash save Changes to A.t
|
||||
'
|
||||
|
||||
cat >expected <<EOF
|
||||
${c_commit}COMMIT_ID (${c_HEAD}HEAD${c_reset}${c_commit},\
|
||||
${c_tag}tag: v1.0${c_reset}${c_commit},\
|
||||
${c_tag}tag: B${c_reset}${c_commit},\
|
||||
${c_branch}master${c_reset}${c_commit})${c_reset} B
|
||||
${c_commit}COMMIT_ID (${c_tag}tag: A1${c_reset}${c_commit},\
|
||||
${c_remoteBranch}other/master${c_reset}${c_commit})${c_reset} A1
|
||||
${c_commit}COMMIT_ID (${c_stash}refs/stash${c_reset}${c_commit})${c_reset}\
|
||||
On master: Changes to A.t
|
||||
${c_commit}COMMIT_ID (${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
|
||||
EOF
|
||||
|
||||
# We want log to show all, but the second parent to refs/stash is irrelevant
|
||||
# to this test since it does not contain any decoration, hence --first-parent
|
||||
test_expect_success 'Commit Decorations Colored Correctly' '
|
||||
git log --first-parent --abbrev=10 --all --decorate --oneline --color=always |
|
||||
sed "s/[0-9a-f]\{10,10\}/COMMIT_ID/" >out &&
|
||||
test_cmp expected out
|
||||
'
|
||||
|
||||
test_done
|
Loading…
Reference in New Issue
Block a user