Merge branch 'rr/for-each-ref-decoration'
Add a few formatting directives to "git for-each-ref --format=...", to paint them in color, etc. * rr/for-each-ref-decoration: for-each-ref: avoid color leakage for-each-ref: introduce %(color:...) for color for-each-ref: introduce %(upstream:track[short]) for-each-ref: introduce %(HEAD) asterisk marker t6300 (for-each-ref): don't hardcode SHA-1 hexes t6300 (for-each-ref): clearly demarcate setup
This commit is contained in:
@ -9,6 +9,7 @@
|
||||
#include "quote.h"
|
||||
#include "parse-options.h"
|
||||
#include "remote.h"
|
||||
#include "color.h"
|
||||
|
||||
/* Quoting styles */
|
||||
#define QUOTE_NONE 0
|
||||
@ -75,6 +76,8 @@ static struct {
|
||||
{ "upstream" },
|
||||
{ "symref" },
|
||||
{ "flag" },
|
||||
{ "HEAD" },
|
||||
{ "color" },
|
||||
};
|
||||
|
||||
/*
|
||||
@ -90,6 +93,7 @@ static struct {
|
||||
static const char **used_atom;
|
||||
static cmp_type *used_atom_type;
|
||||
static int used_atom_cnt, sort_atom_limit, need_tagged, need_symref;
|
||||
static int need_color_reset_at_eol;
|
||||
|
||||
/*
|
||||
* Used to parse format string and sort specifiers
|
||||
@ -176,13 +180,21 @@ static const char *find_next(const char *cp)
|
||||
static int verify_format(const char *format)
|
||||
{
|
||||
const char *cp, *sp;
|
||||
static const char color_reset[] = "color:reset";
|
||||
|
||||
need_color_reset_at_eol = 0;
|
||||
for (cp = format; *cp && (sp = find_next(cp)); ) {
|
||||
const char *ep = strchr(sp, ')');
|
||||
int at;
|
||||
|
||||
if (!ep)
|
||||
return error("malformed format string %s", sp);
|
||||
/* sp points at "%(" and ep points at the closing ")" */
|
||||
parse_atom(sp + 2, ep);
|
||||
at = parse_atom(sp + 2, ep);
|
||||
cp = ep + 1;
|
||||
|
||||
if (!memcmp(used_atom[at], "color:", 6))
|
||||
need_color_reset_at_eol = !!strcmp(used_atom[at], color_reset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -649,6 +661,7 @@ static void populate_value(struct refinfo *ref)
|
||||
int deref = 0;
|
||||
const char *refname;
|
||||
const char *formatp;
|
||||
struct branch *branch = NULL;
|
||||
|
||||
if (*name == '*') {
|
||||
deref = 1;
|
||||
@ -660,7 +673,6 @@ static void populate_value(struct refinfo *ref)
|
||||
else if (!prefixcmp(name, "symref"))
|
||||
refname = ref->symref ? ref->symref : "";
|
||||
else if (!prefixcmp(name, "upstream")) {
|
||||
struct branch *branch;
|
||||
/* only local branches may have an upstream */
|
||||
if (prefixcmp(ref->refname, "refs/heads/"))
|
||||
continue;
|
||||
@ -670,8 +682,13 @@ static void populate_value(struct refinfo *ref)
|
||||
!branch->merge[0]->dst)
|
||||
continue;
|
||||
refname = branch->merge[0]->dst;
|
||||
}
|
||||
else if (!strcmp(name, "flag")) {
|
||||
} else if (!prefixcmp(name, "color:")) {
|
||||
char color[COLOR_MAXLEN] = "";
|
||||
|
||||
color_parse(name + 6, "--format", color);
|
||||
v->s = xstrdup(color);
|
||||
continue;
|
||||
} else if (!strcmp(name, "flag")) {
|
||||
char buf[256], *cp = buf;
|
||||
if (ref->flag & REF_ISSYMREF)
|
||||
cp = copy_advance(cp, ",symref");
|
||||
@ -684,20 +701,62 @@ static void populate_value(struct refinfo *ref)
|
||||
v->s = xstrdup(buf + 1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (!deref && grab_objectname(name, ref->objectname, v))
|
||||
} else if (!deref && grab_objectname(name, ref->objectname, v)) {
|
||||
continue;
|
||||
else
|
||||
} else if (!strcmp(name, "HEAD")) {
|
||||
const char *head;
|
||||
unsigned char sha1[20];
|
||||
|
||||
head = resolve_ref_unsafe("HEAD", sha1, 1, NULL);
|
||||
if (!strcmp(ref->refname, head))
|
||||
v->s = "*";
|
||||
else
|
||||
v->s = " ";
|
||||
continue;
|
||||
} else
|
||||
continue;
|
||||
|
||||
formatp = strchr(name, ':');
|
||||
/* look for "short" refname format */
|
||||
if (formatp) {
|
||||
int num_ours, num_theirs;
|
||||
|
||||
formatp++;
|
||||
if (!strcmp(formatp, "short"))
|
||||
refname = shorten_unambiguous_ref(refname,
|
||||
warn_ambiguous_refs);
|
||||
else
|
||||
else if (!strcmp(formatp, "track") &&
|
||||
!prefixcmp(name, "upstream")) {
|
||||
char buf[40];
|
||||
|
||||
stat_tracking_info(branch, &num_ours, &num_theirs);
|
||||
if (!num_ours && !num_theirs)
|
||||
v->s = "";
|
||||
else if (!num_ours) {
|
||||
sprintf(buf, "[behind %d]", num_theirs);
|
||||
v->s = xstrdup(buf);
|
||||
} else if (!num_theirs) {
|
||||
sprintf(buf, "[ahead %d]", num_ours);
|
||||
v->s = xstrdup(buf);
|
||||
} else {
|
||||
sprintf(buf, "[ahead %d, behind %d]",
|
||||
num_ours, num_theirs);
|
||||
v->s = xstrdup(buf);
|
||||
}
|
||||
continue;
|
||||
} else if (!strcmp(formatp, "trackshort") &&
|
||||
!prefixcmp(name, "upstream")) {
|
||||
assert(branch);
|
||||
stat_tracking_info(branch, &num_ours, &num_theirs);
|
||||
if (!num_ours && !num_theirs)
|
||||
v->s = "=";
|
||||
else if (!num_ours)
|
||||
v->s = "<";
|
||||
else if (!num_theirs)
|
||||
v->s = ">";
|
||||
else
|
||||
v->s = "<>";
|
||||
continue;
|
||||
} else
|
||||
die("unknown %.*s format %s",
|
||||
(int)(formatp - name), name, formatp);
|
||||
}
|
||||
@ -875,11 +934,9 @@ static void sort_refs(struct ref_sort *sort, struct refinfo **refs, int num_refs
|
||||
qsort(refs, num_refs, sizeof(struct refinfo *), compare_refs);
|
||||
}
|
||||
|
||||
static void print_value(struct refinfo *ref, int atom, int quote_style)
|
||||
static void print_value(struct atom_value *v, int quote_style)
|
||||
{
|
||||
struct atom_value *v;
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
get_value(ref, atom, &v);
|
||||
switch (quote_style) {
|
||||
case QUOTE_NONE:
|
||||
fputs(v->s, stdout);
|
||||
@ -946,15 +1003,26 @@ static void show_ref(struct refinfo *info, const char *format, int quote_style)
|
||||
const char *cp, *sp, *ep;
|
||||
|
||||
for (cp = format; *cp && (sp = find_next(cp)); cp = ep + 1) {
|
||||
struct atom_value *atomv;
|
||||
|
||||
ep = strchr(sp, ')');
|
||||
if (cp < sp)
|
||||
emit(cp, sp);
|
||||
print_value(info, parse_atom(sp + 2, ep), quote_style);
|
||||
get_value(info, parse_atom(sp + 2, ep), &atomv);
|
||||
print_value(atomv, quote_style);
|
||||
}
|
||||
if (*cp) {
|
||||
sp = cp + strlen(cp);
|
||||
emit(cp, sp);
|
||||
}
|
||||
if (need_color_reset_at_eol) {
|
||||
struct atom_value resetv;
|
||||
char color[COLOR_MAXLEN] = "";
|
||||
|
||||
color_parse("reset", "--format", color);
|
||||
resetv.s = color;
|
||||
print_value(&resetv, quote_style);
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user